Updating Downstream Repos with Github Actions
The Problem
When working with multiple repositories that depend on shared packages, keeping dependencies updated can become a tedious manual process. Every time you release a new version of your package, you need to update each downstream repository individually. This creates friction in the development process and can lead to repositories using outdated dependencies. I wanted an automated solution that would create pull requests in all downstream repositories whenever a new package version was released.
GitHub Actions
GitHub Actions provides powerful automation capabilities that are perfect for solving this problem. By combining a few key workflows, we can automatically trigger dependency updates across multiple repositories whenever a new package version is published. This automation saves time and ensures consistent dependency management across all projects.
Update Dependency Workflow
First, we need a workflow that can be triggered to update a specific package in a repository. This workflow will:
- Create a new branch
- Update the dependency
- Commit the changes
- Create a pull request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
name: Update Package Dependency
on:
workflow_dispatch:
inputs:
package_name:
description: 'Package name to update'
required: true
package_version:
description: 'Package version to update to'
required: true
permissions:
contents: write
packages: read
id-token: write
pull-requests: write
env:
NODE_AUTH_TOKEN: $
jobs:
update-dependency:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://npm.pkg.github.com'
- name: Configure Git
shell: bash
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
- name: Create branch
shell: bash
run: |
BRANCH_NAME="update-$-$"
git checkout -b $BRANCH_NAME
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
- name: Update dependency
shell: bash
run: |
npm install $@$ --save-exact
- name: Commit changes
shell: bash
run: |
git add .
git commit -m "Update $ to version $"
git push origin $
working-directory: ./service
- name: Create Pull Request
shell: bash
env:
GH_TOKEN: $
run: |
gh pr create \
--title "Update $ to version $" \
--body "Automated PR to update dependency $ to version $" \
--base main \
--head $
This workflow is designed to be triggered externally via the workflow_dispatch
event, which allows us to pass the package name and version as parameters. The workflow then:
- Sets up the necessary permissions and environment
- Checks out the repository and configures Git
- Creates a new branch with a name that reflects the update
- Installs the updated package using NPM
- Commits and pushes the changes
- Creates a pull request for the update
Note that we’re using GitHub’s CLI tool (gh
) to create the pull request, which makes this process seamless. The --save-exact
flag ensures we pin the exact version rather than using a version range.
Trigger Downstream Updates
Now that we have a workflow to update a dependency in a single repository, we need a way to trigger this workflow across multiple repositories whenever a new package version is released. We can add the following steps to the workflow that publishes your package:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- name: Get package version
id: package-version
run: |
echo "version=$(cat package.json | jq -r '.version')" >> $GITHUB_OUTPUT
- name: Trigger downstream repositories
env:
GH_TOKEN: $ # Personal access token with workflow permissions
VERSION: $
run: |
# List of downstream repositories to trigger
REPOS=(
"github/repo"
)
for REPO in "${REPOS[@]}"; do
echo "Triggering workflow in $REPO"
curl -X POST \
-H "Authorization: token $GH_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/$REPO/actions/workflows/update-dependency.yml/dispatches \
-d "{\"ref\":\"main\",\"inputs\":{\"package_name\":\"Package Name here",\"package_version\":\"$VERSION\"}}"
done
This code first extracts the current package version from your package.json
file, then triggers the update dependency workflow in each downstream repository using the GitHub API.
The key components here are:
- Using
jq
to extract the version frompackage.json
- Storing the downstream repository list in an array
- Using
curl
to make API calls to trigger the workflow in each repository - Passing the package name and version as inputs to the workflow
Note that you’ll need a Personal Access Token (PAT) with workflow permissions to trigger workflows in other repositories. This token should be stored as a secret in your repository.
Setting Up The Environment
For this automation to work correctly, you’ll need:
- The “Update Package Dependency” workflow file in each downstream repository
- A PAT with workflow permissions added as a secret (WORKFLOW_DISPATCH_PAT)
- The list of downstream repositories configured in your trigger step
Conclusion
With this GitHub Actions setup, we’ve automated the process of updating dependencies across multiple repositories. Now, whenever we release a new version of our package, pull requests are automatically created in all downstream repositories. This approach:
- Reduces manual work and human error
- Ensures consistent dependency versions across projects
- Creates a clear audit trail through pull requests
- Allows teams to review and test changes before merging
This pattern can be extended to handle more complex scenarios, such as running tests after updates or generating changelogs. By leveraging GitHub Actions for dependency management, we’ve significantly improved our development workflow.