Guide
Create a GitHub branch protection rule of the default branch
You should protect the default branch by GitHub branch protection rule. At least, the following settings should be enabled.
Require a pull request before merging
Require status checks to pass before merging
Status checks that are required.
:status-check
The meaning of these settings is simple, changes of the default branch must be tested.
Create a GitHub Actions' dedicated job for status check
Status checks that are required.
is an essential setting.
You can't merge a pull request whose required jobs
fail,
but in other words you can merge a pull request even if jobs other than required jobs
fail. This is undesirable.
If you add jobs to Status checks that are required.
, it is inconvenient when you add a new job to the workflow and Status checks that are required.
or change job names because until you merge a pull request to add a new job to the workflow you can't merge other pull requests.
Futhermore, if you don't have the permission to change GitHub Repository Settings and you have to ask someone to change them, it would be inconvenient.
So you should define a dedicated job and adding only the job to Status checks that are required.
.
We call this job status-check
job.
e.g.
status-check:
# This job is used for main branch's branch protection rule's status check.
# If all dependent jobs succeed or are skipped this job succeeds.
runs-on: ubuntu-latest
needs:
- update-aqua-checksums
- test
- build
- renovate-config-validator
- ghalint
permissions: {}
if: failure()
steps:
- run: exit 1
You can't merge status-check
job and a job to enable auto-merge and approve a pull request.
Example
status-check:
runs-on: ubuntu-latest
needs:
- update-aqua-checksums
- test
- renovate-config-validator
permissions: {}
if: |
! failure() && ! cancelled() && github.event.pull_request.user.login == 'renovate[bot]' && contains(github.event.pull_request.body, ' **Automerge**: Enabled.')
steps:
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@021a2405c7f990db57f5eae5397423dcc554159c # v1
with:
app_id: ${{secrets.gh_app_id}}
private_key: ${{secrets.gh_app_private_key}}
- run: gh -R "$GITHUB_REPOSITORY" pr merge --merge --auto --delete-branch "$PR_NUMBER"
env:
GITHUB_TOKEN: ${{steps.generate_token.outputs.token}} # Use GitHub App to trigger GitHub Actions Workflow by merge commit.
PR_NUMBER: ${{github.event.pull_request.number}}
# ...
The issue of this example is that status-check
is skipped when some of needs jobs fails so you can merge the pull request unexpectedly.
Merge GitHub Actions workflows for pull_request
event to one workfklow for status check
If a workflow is run only when specific files are changed, you can't add the workflow's jobs to Status checks that are required.
, so even if the workflow fails you can merge a pull request. This is undesirable.
To solve the issue, you should merge workflows for pull_request
event to one workflow which is always triggered and add jobs to status-check
job's needes
. We call this workflow one workflow
. And to run jobs only when specific files are changed, you should use dorny/paths-filter or similar action.
e.g.
path-filter:
outputs:
renovate-config-validator: ${{steps.changes.outputs.renovate-config-validator}}
runs-on: ubuntu-latest
steps:
- uses: dorny/paths-filter@v2
id: changes
with:
filters: |
renovate-config-validator:
- renovate.json5
renovate-config-validator:
uses: suzuki-shunsuke/renovate-config-validator-workflow/.github/workflows/validate.yaml@v0.2.0
needs: path-filter
if: needs.path-filter.outputs.renovate-config-validator == 'true'
There are an exception of one workflow
.
actionlint
: A workflow to run actionlint
actionlint should be run in a dedicated workflow because if the workflow gets invalid actionlint isn't run and you can't find the issue.
If you want to trigger the workflow by not only pull_request
event but also other events, please change the workflow to a Reusable Workflow and share the workflow with multiple workflows.
Update dependencies continuously by Renovate
It is important to keep dependencies up-to-date. If you don't update dependencies continuously, you would face the following issues.
- You can't take any support from maintainers
- You can't use new features
- The behaviour of a old tool is different from the latest document
- If you do a big update including a lot of changes, it is hard to check Release Notes, verify the update, solve the upgrading issues, and detect the root cause when any problem occurs after upgrading
- The frequency of big updates is lower than the frequency of continuous updates, so it is difficult to keep the knowledge and improve the procedure
On the other hand, if you keep dependencies up-to-date, you can solve the above issues. Renovate enables the continuous updates.
Renovate is awesome and can be introduced easily, but it isn't enough to just install Renovate. To utilize Renovate fully, you should not only tune Renovate settings but also configure GitHub Repository settings properly and tune GitHub Actions Workflows in accordance with Renovate.
Merge pull requests automatically
Renovate would create many pull requests every day. It would be hard to review and merge all of them manually. You would be exhausted and frustrated, and finally pull requests would tend to be left.
To solve the problem, you should merge pull requests from Renovate automatically. The burden of handling pull requests from Renovate would decrease and you would be able to focus on more essential tasks.
Exclude risky updates from auto-merge
Some updates should not be merged automatically. For example, normally major updates should not be merged automatically (If you know the major update is safe, you would be able merge pull requests automatically). Renovate can enable or disable the auto-merge flexibly.
Spread the target of auto-merge gradually
If you hesitate to enable auto-merge, you can also enable auto-merge against only specific packages. After that, you would understand the benefit of auto-merge and would like to merge more pull requests automatically. Then you can spread the target of auto-merge gradually.
Test dependency updates by CI
Depency updates should be tested by CI. Otherwise, you would miss bugs. Probably you already test updates your application depends on directly, but maybe you don't test other updates.
For example, when a tool for document generation is updated, the tool should be run in CI, and the document should be updated automatically or CI should fail if the document is changed.
Automerge consists of CI's reliability. It is mandatory to test dependency updates by CI in order to enable auto-merge.
Use GitHub auto-merge feature
To merge a pull request safely, you should enable GitHub auto-merge. To use this feature, you have to configure the branch protection rule described above. Renovate supports the auto-merge, but using GitHub native auto-merge feature you can merge pull requests more quickly.
Enable auto-merge by GitHub Actions
Renovate supports platformAutomerge enabling GitHub auto-merge
automatically, but there are some issues.
platformAutomerge
works only when the pull request is initially createdplatformAutomerge
enables auto-merge regardless the result of GitHub Actions Workflows
So you should enable auto-merge by GitHub Actions without platformAutomerge.
You should use GitHub App rather than GITHUB_TOKEN
to enable auto-merge, because GITHUB_TOKEN
doesn't trigger GitHub Actions Workflows.
When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run.
Please see Enable GitHub auto-merge in renovate workflow too.
Split the workflow by reusable workflows for better path filters
Example
.github/workflows/
test.yaml
wc-renovate-config-validator.yaml
wc-ghalint.yaml
.github/workflows/test.yaml
jobs:
path-filter:
# Get changed files to filter jobs
outputs:
renovate-config-validator: ${{steps.changes.outputs.renovate-config-validator}}
ghalint: ${{steps.changes.outputs.ghalint}}
runs-on: ubuntu-latest
permissions: {}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
id: changes
with:
filters: |
renovate-config-validator:
- renovate.json5
- .github/workflows/test.yaml
- .github/workflows/wc-renovate-config-validator.yaml
ghalint:
- .github/workflows/*.yaml
- aqua/aqua.yaml
- aqua/imports/ghalint.yaml
- ghalint.yaml
renovate-config-validator:
uses: ./.github/workflows/wc-renovate-config-validator.yaml
needs: path-filter
if: needs.path-filter.outputs.renovate-config-validator == 'true'
permissions:
contents: read
ghalint:
needs: path-filter
if: needs.path-filter.outputs.ghalint == 'true'
uses: ./.github/workflows/wc-ghalint.yaml
permissions: {}
.github/workflows/wc-renovate-config-validator.yaml
name: renovate-config-validator
on: workflow_call
jobs:
renovate-config-validator:
# Validate Renovate Configuration by renovate-config-validator.
uses: suzuki-shunsuke/renovate-config-validator-workflow/.github/workflows/validate.yaml@1a2fd7b15d99b1c434124b0bd2d8bd55b54ed869 # v0.2.0
permissions:
contents: read
.github/workflows/wc-ghalint.yaml
name: ghalint
on: workflow_call
env:
AQUA_LOG_COLOR: always
jobs:
ghalint:
# Validate GitHub Actions Workflows by ghalint.
runs-on: ubuntu-latest
permissions: {}
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- uses: aquaproj/aqua-installer@294926f94b4233f202a2f03875c604f840cfed70 # v2.1.1
with:
aqua_version: v2.3.6
env:
AQUA_GITHUB_TOKEN: ${{github.token}}
- run: ghalint run
env:
GHALINT_LOG_COLOR: always
AQUA_GITHUB_TOKEN: ${{github.token}}
In the above example, jobs ghalint
and renovate-config-validator
are separated from the workflow file test
.
The benefit of the saparation is the following things.
- Enable jobs to be called by other workflows
- Improve the maintainability by making the workflow file small
- Enable to run only a specific job when the job file is changed
Especially, 3 Enable to run only a specific job when the job file is changed
is important.
If the job is changed the job should be tested.
If the file .github/workflows/wc-renovate-config-validator.yaml
is changed, you can run only the job renovate-config-validator
by path filter. If the file isn't separated, you have to run all jobs in the test
workflow if the job renovate-config-validator
is changed.
For team development
If you maintain a repository with other team members, which means multiple developers have the write permission, some additional settings are required.
Configure a branch protection rule of the default branch to enforce the review
Require a pull request before merging
Require approvals
(1 approval)Dismiss stale pull request approvals when new commits are pushed
Require review from Code Owners
Require approval of the most recent reviewable push
This settings means a pull request must be reviewed by at least one Code Owner.
Configure a branch protection rule of Renovate branches to forbid to add changes without the review
You should create a branch protection rule of Renovate's branches renovate/*
.
renovate/*
Do not allow bypassing the above settings
Restrict who can push to matching branches
Restrict pushes that create matching branches
renovate
- Dedicated GitHub App
Allow deletions
: To allow Renovate to delete branchesAllow force pushes
: To allow Renovate to rebase branchesSpecify who can force push
renovate
You should forbid developers to push a commit to Renovate branches.
Otherwise, developers can push malicious code to a pull request of Renovate and can approve and merge the pull request.
Even if Require approval of the most recent reviewable push
is enabled, developers still can push malicious code.
If you want to add changes to a Renovate pull request, you should create a new pull request. You may feel bothersome, but you have no choice.
Create a dedicated GitHub App to push commits to a Renovate pull request
Sometimes you would like to push a commit to a Renovate pull request automatically. For example, you would like to update a autogenerated document. In that case, you should create a dedicated GitHub App for it. The GitHub App must be dedicated and be able to be used only in the workflow triggered by a pull request from Renovate. Otherwise, developers can push a malicious code to a Renovate pull request using the GitHub App.
GitHub App's private key must be managed with GitHub Environment's Deployment branches and Environment secrets.
approve-and-enable-automerge-renovate:
runs-on: ubuntu-latest
environment: renovate
if: |
github.event.pull_request.user.login == 'renovate[bot]' && contains(github.event.pull_request.body, ' **Automerge**: Enabled.')
steps:
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@021a2405c7f990db57f5eae5397423dcc554159c # v1
with:
app_id: ${{secrets.APP_ID}}
private_key: ${{secrets.APP_PRIVATE_KEY}}
- name: Enable auto-merge
run: gh -R "$GITHUB_REPOSITORY" pr merge --merge --auto --delete-branch "$PR_NUMBER"
env:
# github.token is unavailable, because github.token doesn't have a permission to delete a branch `renovate/*`
GITHUB_TOKEN: ${{steps.generate_token.outputs.token}}
PR_NUMBER: ${{github.event.pull_request.number}}
# https://github.com/cli/cli/issues/6680
# HTTP 401: Personal access tokens with fine grained access do not support the GraphQL API (https://api.github.com/graphql)
# - run: gh -R aquaproj/example-update-checksum pr review -a "$PR_NUMBER"
- name: Approve a pull request
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
"/repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews" \
-f event='APPROVE'
env:
PR_NUMBER: ${{github.event.pull_request.number}}
GITHUB_TOKEN: ${{secrets.GH_TOKEN_APPROVE_RENOVATE_PR}}
(Optional) Update branch of Renovate pull request by comment
Developers can't update branch of Renovate pull requests due to the branch protection rule. Renovate supports rebasing branch but sometimes you would like to update branch. You can update branch of Renovate pull request by adding a GitHub Actions Workflow. This workflow is triggered by pull request comment and updates branch by GitHub API.
We call this workflow update-branch workflow
.
This workflow is optional because Renovate supports rebasing branch.
To use this workflow, you must allow the default branch to access GitHub App Private Key to push commits to Renovate branch because issue_comment event is triggered at the default branch.
💡 Consider self-hosted runner to save money
As we mentioned above, you have to run some additional jobs.
status-check
path-filter
approve-and-enable-automerge-renovate
But maybe you don't want to run these jobs to save the billing for GitHub Actions.
In that case, you should consider self-hosted runner because GitHub Actions usage is free for self-hosted runner.
For public repository
If you maintain a repository yourself and only you have a write permission, the following things are unnecessary.
- a personal access token to approve a pull request
- a dedicated GitHub App to push commits to Renovate branches
- a GitHub Environment for Renovate
- a GitHub Actions Workflows for Renovate
Support pull requests from fork repositories
GitHub Actions workflows should pass even if a pull request is sent from a fork repository.
A pull request from a fork repository can't access GitHub Secrets and GITHUB_TOKEN
has only read permissions,
so steps requiring secrets or write permissions should be skipped or fixed.
Pull request from a fork repository:
if: |
github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork
Other than pull request from a fork repository:
if: |
github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork