-
Notifications
You must be signed in to change notification settings - Fork 264
feat: add actions-updater agentic workflow #18693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,336 @@ | ||||||||||||||
| --- | ||||||||||||||
| name: Actions Version Updater | ||||||||||||||
| description: Scans .md workflow source files for outdated GitHub Actions and creates issues for each update, similar to Dependabot | ||||||||||||||
| on: | ||||||||||||||
| schedule: | ||||||||||||||
| - cron: '0 6 * * 1' # Weekly on Monday at 6am UTC | ||||||||||||||
| workflow_dispatch: | ||||||||||||||
| inputs: | ||||||||||||||
| repository: | ||||||||||||||
| description: "Repository to scan (format: owner/repo). Defaults to current repo." | ||||||||||||||
| required: false | ||||||||||||||
| type: string | ||||||||||||||
| organization: | ||||||||||||||
| description: "Scan all repos in an organization (overrides repository input)" | ||||||||||||||
| required: false | ||||||||||||||
| type: string | ||||||||||||||
| dry-run: | ||||||||||||||
| description: "Only report outdated actions, don't create issues" | ||||||||||||||
| required: false | ||||||||||||||
| type: boolean | ||||||||||||||
| default: false | ||||||||||||||
|
|
||||||||||||||
| permissions: | ||||||||||||||
| contents: read | ||||||||||||||
| issues: write | ||||||||||||||
| pull-requests: read | ||||||||||||||
|
|
||||||||||||||
| engine: copilot | ||||||||||||||
| timeout-minutes: 15 | ||||||||||||||
| strict: true | ||||||||||||||
|
|
||||||||||||||
| network: | ||||||||||||||
| allowed: | ||||||||||||||
| - defaults | ||||||||||||||
| - github | ||||||||||||||
|
|
||||||||||||||
| tools: | ||||||||||||||
| github: | ||||||||||||||
| read-only: true | ||||||||||||||
| lockdown: true | ||||||||||||||
| toolsets: | ||||||||||||||
| - repos | ||||||||||||||
| - issues | ||||||||||||||
| bash: | ||||||||||||||
| - "find .github/workflows -name '*.md' -type f" | ||||||||||||||
| - "grep -rn 'uses:' .github/workflows/*.md" | ||||||||||||||
| - "cat .github/workflows/*.md" | ||||||||||||||
| - "head -n * .github/workflows/*.md" | ||||||||||||||
| - "gh api repos/*/releases/latest" | ||||||||||||||
| - "gh api repos/*/tags" | ||||||||||||||
| - "gh api repos/*/contents/*" | ||||||||||||||
| - "gh repo list *" | ||||||||||||||
|
|
||||||||||||||
| safe-outputs: | ||||||||||||||
| create-issue: | ||||||||||||||
| expires: 7d | ||||||||||||||
| title-prefix: "[actions-update] " | ||||||||||||||
| labels: [dependencies, automation, github-actions] | ||||||||||||||
| max: 20 | ||||||||||||||
| close-older-issues: true | ||||||||||||||
| missing-tool: | ||||||||||||||
|
|
||||||||||||||
| if: needs.check_outdated.outputs.has_outdated == 'true' | ||||||||||||||
|
|
||||||||||||||
| jobs: | ||||||||||||||
| check_outdated: | ||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||
| permissions: | ||||||||||||||
| contents: read | ||||||||||||||
| outputs: | ||||||||||||||
| has_outdated: ${{ steps.check.outputs.has_outdated }} | ||||||||||||||
| outdated_list: ${{ steps.check.outputs.outdated_list }} | ||||||||||||||
| outdated_count: ${{ steps.check.outputs.outdated_count }} | ||||||||||||||
| steps: | ||||||||||||||
| - name: Checkout repository | ||||||||||||||
| uses: actions/checkout@v6 | ||||||||||||||
| with: | ||||||||||||||
| sparse-checkout: | | ||||||||||||||
| .github/workflows | ||||||||||||||
| persist-credentials: false | ||||||||||||||
|
|
||||||||||||||
| - name: Extract and check action versions | ||||||||||||||
| id: check | ||||||||||||||
| env: | ||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||
| run: | | ||||||||||||||
| # Extract unique action@version pairs from .md workflow files | ||||||||||||||
| grep -rhn 'uses:' .github/workflows/*.md 2>/dev/null \ | ||||||||||||||
|
||||||||||||||
| grep -rhn 'uses:' .github/workflows/*.md 2>/dev/null \ | |
| # Only consider the YAML frontmatter (before the second ---) to avoid prompt/example noise | |
| find .github/workflows -name '*.md' -type f -print0 2>/dev/null \ | |
| | while IFS= read -r -d '' file; do | |
| awk 'BEGIN{d=0} /^---[[:space:]]*$/{d++; if (d>=2) exit} {print}' "$file" | |
| done \ |
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extractor only scans .github/workflows/*.md (non-recursive), so it misses action references in nested source files like .github/workflows/shared/**/*.md that can be imported into workflows. Consider scanning recursively (e.g., grep -r --include='*.md' .github/workflows) so the check covers all .md workflow sources.
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SHA→tag resolution compares the input SHA to git/ref's .object.sha, which is the tag object's SHA for annotated tags (not the commit SHA). This will fail to resolve many real tags. To make this reliable, dereference annotated tags by checking .object.type and, when it's tag, follow up with git/tags/{sha} to compare the underlying commit SHA (or use an endpoint that returns the peeled commit).
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
outdated_list is written to $GITHUB_OUTPUT using name=value, but the value is multi-line (OUTDATED_LIST accumulates \n). Multi-line outputs must use the <<EOF delimiter form; otherwise this can break output parsing and fail the step. Update this to use the documented multi-line output syntax when emitting outdated_list.
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow_dispatch input name dry-run is referenced as ${{ github.event.inputs.dry-run }}. In GitHub Actions expressions, keys with hyphens generally require bracket notation (e.g., github.event.inputs['dry-run']) or using an input name without - (like dry_run). As written, this expression is likely to fail to evaluate and may break the run/compile.
| - **Dry run**: `${{ github.event.inputs.dry-run }}` | |
| - **Dry run**: `${{ github.event.inputs['dry-run'] }}` |
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The agent instructions say to "create a single informational issue" when everything is up to date, but the workflow is gated by if: needs.check_outdated.outputs.has_outdated == 'true', so the agent will never run in the all-up-to-date case. Either remove this instruction, or change the gating/logic so a no-op run can still optionally create that informational issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check_outdatedignores therepositoryandorganizationworkflow_dispatch inputs (it always checks out and scans only the current repo). With the workflow-levelif: needs.check_outdated.outputs.has_outdated == 'true', running the workflow for another repo/org can incorrectly skip the agent even when targets are outdated. Either incorporate the selected target(s) into the deterministic precheck, or change the gating so the agent runs whenrepository/organizationare provided (and the agent does the scanning).