Skip to content

Commit a4b46cb

Browse files
authored
Chore: [AEA-0000] - add workflow to approve dependabot (#1)
## Summary - Routine Change ### Details - add workflow to approve dependabot
1 parent db39aa1 commit a4b46cb

10 files changed

Lines changed: 260 additions & 11 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "eps-account-resources",
2+
"name": "eps-dependabot-approve",
33
"build": {
44
"dockerfile": "Dockerfile",
55
"context": "..",
@@ -39,7 +39,7 @@
3939
"vitest.explorer"
4040
],
4141
"settings": {
42-
"python.defaultInterpreterPath": "/workspaces/electronic-prescription-service-account-resources/.venv/bin/python",
42+
"python.defaultInterpreterPath": "${containerWorkspaceFolder}/.venv/bin/python",
4343
"python.analysis.autoSearchPaths": true,
4444
"python.analysis.extraPaths": [],
4545
"python.testing.unittestEnabled": false,

.gitallowed

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ token: ?"?\$\{\{\s*secrets\.GITHUB_TOKEN\s*\}\}"?
22
github-token: ?"?\$\{\{\s*secrets\.GITHUB_TOKEN\s*\}\}"?
33
token: ?"?\$\{\{\s*secrets\.DEPENDABOT_TOKEN\s*\}\}"?
44
id-token: write
5+
id-token: "write"
56
--token=\$\{\{\s*steps\.generate-token\.outputs\.token\s*\}\}
67
--token=\$GITHUB-TOKEN
78
--token="\$GITHUB-TOKEN"
89
"accountId": "123456789012"
910
accountId: "123456789012"
1011
"AWSAccountId": "123456789012"
1112
poetry.lock
13+
\.gitallowed

.github/config/settings.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TAG_FORMAT: "v${version}"

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches: [main]
6+
permissions: {}
7+
jobs:
8+
get_config_values:
9+
uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
10+
permissions:
11+
attestations: "read"
12+
contents: "read"
13+
packages: "read"
14+
with:
15+
verify_published_from_main_image: true
16+
17+
quality_checks:
18+
uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
19+
needs: [get_config_values]
20+
permissions:
21+
contents: "read"
22+
packages: "read"
23+
id-token: "write"
24+
with:
25+
pinned_image: ${{ needs.get_config_values.outputs.pinned_image }}
26+
secrets:
27+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
28+
29+
tag_release:
30+
needs: [get_config_values]
31+
uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
32+
permissions:
33+
id-token: "write"
34+
contents: "write"
35+
packages: "write"
36+
with:
37+
dry_run: true
38+
pinned_image: ${{ needs.get_config_values.outputs.pinned_image }}
39+
branch_name: main
40+
tag_format: ${{ needs.get_config_values.outputs.tag_format }}

.github/workflows/pull_request.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: pull_request
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
permissions: {}
7+
jobs:
8+
get_config_values:
9+
uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
10+
permissions:
11+
attestations: "read"
12+
contents: "read"
13+
packages: "read"
14+
with:
15+
verify_published_from_main_image: false
16+
17+
dependabot-auto-approve-and-merge:
18+
uses: NHSDigital/eps-common-workflows/.github/workflows/dependabot-auto-approve-and-merge.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
19+
permissions:
20+
contents: "write"
21+
pull-requests: "write"
22+
secrets:
23+
AUTOMERGE_APP_ID: ${{ secrets.AUTOMERGE_APP_ID }}
24+
AUTOMERGE_PEM: ${{ secrets.AUTOMERGE_PEM }}
25+
26+
quality_checks:
27+
uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
28+
needs: [get_config_values]
29+
permissions:
30+
contents: "read"
31+
packages: "read"
32+
id-token: "write"
33+
with:
34+
pinned_image: ${{ needs.get_config_values.outputs.pinned_image }}
35+
secrets:
36+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
37+
38+
pr_title_format_check:
39+
uses: NHSDigital/eps-common-workflows/.github/workflows/pr_title_check.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
40+
permissions:
41+
pull-requests: "write"
42+
43+
tag_release:
44+
needs: [get_config_values]
45+
uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
46+
permissions:
47+
id-token: "write"
48+
contents: "write"
49+
packages: "write"
50+
with:
51+
dry_run: true
52+
pinned_image: ${{ needs.get_config_values.outputs.pinned_image }}
53+
branch_name: ${{ github.event.pull_request.head.ref }}
54+
tag_format: ${{ needs.get_config_values.outputs.tag_format }}

.github/workflows/release.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: release
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "0 8 * * 3"
7+
permissions: {}
8+
jobs:
9+
get_config_values:
10+
uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
11+
permissions:
12+
attestations: "read"
13+
contents: "read"
14+
packages: "read"
15+
with:
16+
verify_published_from_main_image: true
17+
18+
quality_checks:
19+
uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
20+
needs: [get_config_values]
21+
permissions:
22+
contents: "read"
23+
packages: "read"
24+
id-token: "write"
25+
with:
26+
pinned_image: ${{ needs.get_config_values.outputs.pinned_image }}
27+
secrets:
28+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
29+
30+
tag_release:
31+
needs: [get_config_values, quality_checks]
32+
uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929
33+
permissions:
34+
id-token: "write"
35+
contents: "write"
36+
packages: "write"
37+
with:
38+
dry_run: false
39+
pinned_image: ${{ needs.get_config_values.outputs.pinned_image }}
40+
branch_name: main
41+
tag_format: ${{ needs.get_config_values.outputs.tag_format }}

Makefile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ install-hooks: install-python
1515

1616
install: install-python install-hooks
1717
echo "Not implemented yet"
18-
exit 1
1918

2019
install-node:
2120
echo "Not implemented yet"
@@ -27,11 +26,9 @@ compile:
2726

2827
lint:
2928
echo "Not implemented yet"
30-
exit 1
3129

3230
test:
3331
echo "Not implemented yet"
34-
exit 1
3532

3633
# include common targets
3734
%:

README.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,56 @@
1-
# Electronic Prescriptions Service template repo
1+
# Electronic Prescriptions Service dependabot approve
2+
3+
Composite GitHub Action to automatically approve and enable auto-merge for trusted dependency update pull requests.
4+
This will be called from each repo on a scheduled basis
5+
6+
## What this action does
7+
8+
This action:
9+
10+
1. Lists open pull requests in the current repository.
11+
2. Filters pull requests to only include those where:
12+
- the head commit signature is verified, and
13+
- the commit author is either `dependabot[bot]` or `eps-create-pull-request[bot]`.
14+
3. Approves each eligible pull request.
15+
4. Enables auto-merge using squash merge for each eligible pull request.
16+
17+
## Inputs
18+
19+
| Name | Required | Description |
20+
| --- | --- | --- |
21+
| `AUTOMERGE_APP_ID` | Yes | GitHub App ID used to authenticate and approve pull requests. |
22+
| `AUTOMERGE_PEM` | Yes | Private key for the GitHub App in PEM format. |
23+
24+
## Usage
25+
26+
```yaml
27+
name: Auto-approve dependency updates
28+
29+
on:
30+
workflow_dispatch:
31+
schedule:
32+
- cron: '*/30 * * * *'
33+
34+
jobs:
35+
auto-approve-dependabot:
36+
runs-on: ubuntu-22.04
37+
environment: create_pull_request
38+
permissions:
39+
contents: write
40+
pull-requests: write
41+
steps:
42+
- name: Auto approve and enable auto-merge
43+
uses: NHSDigital/eps-dependabot-approve@db39aa18bf6b1ce317219661299a91c572689bb7
44+
with:
45+
AUTOMERGE_APP_ID: ${{ secrets.AUTOMERGE_APP_ID }}
46+
AUTOMERGE_PEM: ${{ secrets.AUTOMERGE_PEM }}
47+
```
48+
49+
## Notes
50+
51+
- Pull requests that do not meet the verification and bot-author checks are skipped.
52+
- If no pull requests are eligible, the action completes without approving or merging anything.
253
3-
# THIS SHOULD BE UPDATED WHEN IT IS USED AS A TEMPLATE FOR A NEW REPO
454
555
## Contributing
656

action.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Auto approve dependabot pull request
2+
description: "Automatically approves dependabot pull requests."
3+
inputs:
4+
AUTOMERGE_APP_ID:
5+
description: "GitHub App ID for approving pull requests"
6+
required: true
7+
AUTOMERGE_PEM:
8+
description: "Private key for the GitHub App in PEM format"
9+
required: true
10+
runs:
11+
using: "composite"
12+
steps:
13+
- name: Create GitHub App Token
14+
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859
15+
id: generate-token
16+
with:
17+
app-id: "${{ inputs.AUTOMERGE_APP_ID }}"
18+
private-key: "${{ inputs.AUTOMERGE_PEM }}"
19+
20+
- name: Find eligible pull requests
21+
id: find-prs
22+
shell: bash
23+
env:
24+
REPO: ${{ github.repository }}
25+
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
26+
run: |
27+
set -euo pipefail
28+
29+
mapfile -t pr_numbers < <(gh pr list --repo "$REPO" --state open --json number --jq '.[].number')
30+
31+
eligible_pr_urls=()
32+
33+
for pr_number in "${pr_numbers[@]}"; do
34+
read -r pr_url head_sha < <(gh pr view "$pr_number" --repo "$REPO" --json url,headRefOid --jq '[.url, .headRefOid] | @tsv')
35+
read -r author_login is_verified is_cross_repository < <(gh api "/repos/$REPO/commits/$head_sha" --jq '[.author.login // "", (.commit.verification.verified // false), (.commit.verification.reason // "")] | @tsv')
36+
37+
if [[ "$is_cross_repository" == "false" ]] && [[ "$is_verified" == "true" ]] && [[ "$author_login" == "dependabot[bot]" || "$author_login" == "eps-create-pull-request[bot]" ]]; then
38+
eligible_pr_urls+=("$pr_url")
39+
fi
40+
done
41+
42+
echo "Found ${#eligible_pr_urls[@]} eligible pull request(s) for approval and merging."
43+
printf '%s\n' "${eligible_pr_urls[@]}"
44+
45+
{
46+
echo "pr_urls<<EOF"
47+
printf '%s\n' "${eligible_pr_urls[@]}"
48+
echo "EOF"
49+
} >> "$GITHUB_OUTPUT"
50+
51+
- name: Approve and merge updates
52+
shell: bash
53+
run: |
54+
set -euo pipefail
55+
56+
while IFS= read -r PR_URL; do
57+
[[ -z "$PR_URL" ]] && continue
58+
59+
gh pr review "$PR_URL" --approve -b "I'm **approving** this pull request"
60+
gh pr merge --auto --squash "$PR_URL"
61+
done <<< "${PR_URLS}"
62+
env:
63+
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
64+
PR_URLS: ${{ steps.find-prs.outputs.pr_urls }}

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
[project]
22
python = "^3.14"
3-
name = "CHANGE_ME"
3+
name = "eps-dependabot-approve"
44

55
[tool.poetry]
6-
name = "CHANGE_ME"
7-
description = "CHANGE_ME"
6+
name = "eps-dependabot-approve"
7+
description = "eps-dependabot-approve"
88
version = "0.0.1-alpha"
99
authors = [
1010
"EPS Team <eps.tem@nhs.net>"
1111
]
1212
readme = "README.md"
1313
license = "MIT"
14-
repository = "https://github.com/NHSDigital/CHANGE_ME"
14+
repository = "https://github.com/NHSDigital/eps-dependabot-approve"
1515
package-mode = false
1616

1717
[tool.poetry.dependencies]

0 commit comments

Comments
 (0)