Skip to content

Commit d2131ed

Browse files
Priyanshu AgrawalCopilot
authored andcommitted
Add scheduled Dependabot auto-fix workflow using Copilot CLI
Adds .github/workflows/dependabot-autofix.yml that runs weekly (and on workflow_dispatch) to invoke the fix-dependabot-alerts skill via GitHub Copilot CLI, apply fixes, run build + tests, and open a single consolidated PR. Auth model matches existing workflows: - GitHub App (app-id 2740120, POWER_PAGES_PUBLIC_GITHUB_APP_PRIVATE_KEY) is used for checkout, git push, and gh pr create so commits and the PR are authored by github-actions[bot]. - A fine-grained PAT in COPILOT_CLI_PAT is used only for Copilot CLI auth and Dependabot alert enumeration (App tokens cannot authenticate Copilot CLI since Copilot licenses are per-user). Hardening: - Narrow --allow-tool grants; no --allow-all, no --share-gist. - --secret-env-vars redacts the PAT from logs. - --no-ask-user prevents the agent from blocking CI. - --model pinned to claude-sonnet-4.6 for reproducibility. - Agent is instructed to skip push/PR when npm build or tests fail, and to no-op when there are zero open alerts. - concurrency group with cancel-in-progress: false. - Session transcript uploaded as a workflow artifact (14-day retention). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent af89e5e commit d2131ed

1 file changed

Lines changed: 201 additions & 0 deletions

File tree

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
#
4+
# Dependabot Auto-fix
5+
# ------------------------------------------------------------------------
6+
# Runs the `fix-dependabot-alerts` skill via GitHub Copilot CLI on a weekly
7+
# schedule (and on-demand). Copilot enumerates open Dependabot alerts,
8+
# applies fixes following `.claude/skills/fix-dependabot-alerts/SKILL.md`,
9+
# runs the build + tests, and opens a single consolidated PR.
10+
#
11+
# Required secrets
12+
# ------------------------------------------------------------------------
13+
# POWER_PAGES_PUBLIC_GITHUB_APP_PRIVATE_KEY
14+
# Private key of the existing GitHub App (app-id 2740120) that is
15+
# already used by loc-update.yml / translations-export.yml. The App
16+
# installation on this repo must have:
17+
# - Contents: Read/Write
18+
# - Pull requests: Read/Write
19+
# Commits and the PR are authored as github-actions[bot] via this App.
20+
#
21+
# COPILOT_CLI_PAT
22+
# Fine-grained PAT from a user with a Copilot license. Needed because
23+
# GitHub App tokens cannot authenticate Copilot CLI (Copilot licenses
24+
# are per-user). Required permissions:
25+
# - Account: Copilot Requests: Read
26+
# - Repository: Dependabot alerts: Read (so `gh api .../dependabot/alerts` works)
27+
# The org-level "Copilot CLI" policy must be enabled for this user.
28+
# ------------------------------------------------------------------------
29+
30+
name: Dependabot Auto-fix
31+
32+
on:
33+
schedule:
34+
# Weekly, Mondays 06:00 UTC
35+
- cron: '0 6 * * 1'
36+
workflow_dispatch:
37+
38+
permissions:
39+
contents: read
40+
41+
concurrency:
42+
group: dependabot-autofix
43+
cancel-in-progress: false
44+
45+
jobs:
46+
autofix:
47+
name: Copilot CLI Dependabot Auto-fix
48+
runs-on: ubuntu-latest
49+
timeout-minutes: 45
50+
permissions:
51+
contents: write
52+
pull-requests: write
53+
54+
steps:
55+
- name: Generate GitHub App Token
56+
id: app-token
57+
uses: actions/create-github-app-token@v1
58+
with:
59+
app-id: 2740120
60+
private-key: ${{ secrets.POWER_PAGES_PUBLIC_GITHUB_APP_PRIVATE_KEY }}
61+
62+
- name: Checkout Repository
63+
uses: actions/checkout@v4
64+
with:
65+
fetch-depth: 0
66+
token: ${{ steps.app-token.outputs.token }}
67+
68+
- name: Setup Node.js
69+
uses: actions/setup-node@v4
70+
with:
71+
node-version: '20'
72+
cache: 'npm'
73+
74+
- name: Install dependencies
75+
run: npm ci
76+
77+
- name: Install GitHub Copilot CLI
78+
run: npm install -g @github/copilot
79+
80+
- name: Configure git identity
81+
run: |
82+
git config --local user.name "github-actions[bot]"
83+
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
84+
85+
- name: Create working branch
86+
id: branch
87+
run: |
88+
BRANCH="copilot/dependabot-autofix-${{ github.run_id }}"
89+
git checkout -b "$BRANCH"
90+
echo "name=$BRANCH" >> "$GITHUB_OUTPUT"
91+
92+
- name: Run Copilot CLI (fix-dependabot-alerts)
93+
id: copilot
94+
timeout-minutes: 30
95+
env:
96+
# Copilot CLI auth + Dependabot alerts read. Redacted from logs.
97+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_CLI_PAT }}
98+
# App token used by `gh pr create` and `git push` so the PR
99+
# and commits are authored by github-actions[bot].
100+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
101+
REPO: ${{ github.repository }}
102+
BRANCH: ${{ steps.branch.outputs.name }}
103+
run: |
104+
set -euo pipefail
105+
106+
# Inline the skill so behavior is identical even if Copilot CLI
107+
# on the runner does not auto-load .claude/skills/.
108+
SKILL_BODY="$(cat .claude/skills/fix-dependabot-alerts/SKILL.md)"
109+
110+
PROMPT=$(cat <<PROMPT_EOF
111+
You are running inside a GitHub Actions job. Follow the skill
112+
below to fix ALL currently open Dependabot alerts for the
113+
repository \`${REPO}\` in a SINGLE consolidated pull request.
114+
115+
Environment already set up for you:
116+
- Repository is checked out at the current working directory.
117+
- A working branch named \`${BRANCH}\` is already created and checked out.
118+
- \`npm ci\` has already installed dependencies.
119+
- \`git\` is configured as github-actions[bot].
120+
- \`COPILOT_GITHUB_TOKEN\` is available for \`gh api\` calls that read
121+
Dependabot alerts (e.g. \`gh api repos/${REPO}/dependabot/alerts\`).
122+
- \`GH_TOKEN\` is a GitHub App token with Contents and Pull requests
123+
write access. Use it (it is already in env) for \`git push\` and
124+
\`gh pr create\`.
125+
126+
Mandatory rules:
127+
1. Use \`gh api repos/${REPO}/dependabot/alerts --paginate --jq '.[] | select(.state=="open")'\`
128+
to enumerate open alerts. Authenticate that call with
129+
\`GH_TOKEN=\$COPILOT_GITHUB_TOKEN gh api ...\` since the App token
130+
typically cannot read Dependabot alerts.
131+
2. If there are ZERO open alerts, do not commit, do not push,
132+
do not open a PR. Print "NO_OPEN_ALERTS" and exit.
133+
3. Apply fixes for ALL open alerts on branch \`${BRANCH}\`
134+
following Steps 1-6 of the skill. Produce one logical commit
135+
(or several, your choice) on that branch only.
136+
4. Run \`npm run build\` AND \`npm test\`. If either fails after
137+
your fixes, DO NOT push and DO NOT open a PR. Print
138+
"BUILD_OR_TEST_FAILED" and exit non-zero.
139+
5. When build and tests pass:
140+
- \`git push -u origin ${BRANCH}\` (uses \$GH_TOKEN).
141+
- \`gh pr create --base main --head ${BRANCH} \\\\
142+
--title "chore(deps): auto-fix Dependabot alerts" \\\\
143+
--body "<summary of alerts addressed, per-package old→new versions, CVE IDs, and any overrides added>"\`.
144+
- Print the PR URL.
145+
6. Never manually edit integrity hashes in package-lock.json
146+
(see skill). Use \`npm install\`, \`npm update\`, or a clean
147+
reinstall to let npm compute them.
148+
7. Never use \`--allow-all\` semantics; stick to the tools you
149+
already have permission to use.
150+
151+
----- SKILL START -----
152+
${SKILL_BODY}
153+
----- SKILL END -----
154+
PROMPT_EOF
155+
)
156+
157+
copilot \
158+
-p "$PROMPT" \
159+
--model claude-sonnet-4.6 \
160+
-s \
161+
--no-ask-user \
162+
--allow-tool 'shell(npm:*), shell(npx:*), shell(gh:*), shell(git:*), shell(node:*), write, read' \
163+
--secret-env-vars 'COPILOT_CLI_PAT' \
164+
--share ./copilot-session.md \
165+
| tee copilot-output.txt
166+
167+
- name: Summarize run
168+
if: always()
169+
run: |
170+
{
171+
echo "## Dependabot Auto-fix"
172+
echo ""
173+
echo "- Branch: \`${{ steps.branch.outputs.name }}\`"
174+
if [ -f copilot-output.txt ]; then
175+
if grep -q "NO_OPEN_ALERTS" copilot-output.txt; then
176+
echo "- Result: no open Dependabot alerts; no PR opened."
177+
elif grep -q "BUILD_OR_TEST_FAILED" copilot-output.txt; then
178+
echo "- Result: build or tests failed after fixes; no PR opened."
179+
else
180+
PR_URL=$(grep -Eo 'https://github.com/[^ ]+/pull/[0-9]+' copilot-output.txt | head -n1 || true)
181+
if [ -n "$PR_URL" ]; then
182+
echo "- PR: $PR_URL"
183+
else
184+
echo "- Result: see Copilot session transcript artifact."
185+
fi
186+
fi
187+
else
188+
echo "- Result: Copilot step did not produce output."
189+
fi
190+
} >> "$GITHUB_STEP_SUMMARY"
191+
192+
- name: Upload Copilot session transcript
193+
if: always()
194+
uses: actions/upload-artifact@v4
195+
with:
196+
name: copilot-session-${{ github.run_id }}
197+
path: |
198+
copilot-session.md
199+
copilot-output.txt
200+
retention-days: 14
201+
if-no-files-found: ignore

0 commit comments

Comments
 (0)