diff --git a/.github/workflows/gh-aw-dependency-review.lock.yml b/.github/workflows/gh-aw-dependency-review.lock.yml index 3a2c7d52..108468cb 100644 --- a/.github/workflows/gh-aw-dependency-review.lock.yml +++ b/.github/workflows/gh-aw-dependency-review.lock.yml @@ -36,7 +36,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"bdf54e6b91e8ceef7b8203a6dfddc18e2cadb8d5b514ba5a91ca3950569551f9"} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"1220b4a345844709c33fe207dc47c680e8e00d0c7f0a4806e52631f4de0cb241"} name: "Dependency Review" "on": @@ -52,6 +52,11 @@ name: "Dependency Review" description: Allowlisted bot actor usernames (comma-separated) required: false type: string + classification-labels: + default: "" + description: Comma-separated list of labels the agent may apply (e.g. 'needs-human-review,higher-risk,merge-ready'). If empty, no labels are applied. Define label semantics in additional-instructions. + required: false + type: string messages-footer: default: "" description: Footer appended to all agent comments and reviews @@ -161,6 +166,7 @@ jobs: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GH_AW_EXPR_23557367: ${{ inputs.target-pr-number || github.event.pull_request.number }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_9AD6B038: ${{ inputs.classification-labels }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} @@ -438,19 +444,13 @@ jobs: ### Step 4: Determine Labels - Based on the analysis, determine if labels should be applied: - - - **`needs-human-review`**: Apply when ANY of these conditions are met: - - A dependency update introduces breaking changes that affect this repo's usage - - A GitHub Actions commit SHA is not verified - - A Buildkite plugin moves from SHA-pinned to mutable tag, or between mutable tags - - The changelog indicates breaking changes - - A major version bump in any ecosystem (e.g. v1 → v2 in Go, major semver in npm/Python/Java) + Based on the analysis, determine if any labels from the configured `classification-labels` set should be applied: - - **`higher-risk`**: Apply when: - - The updated dependency is used only in workflows triggered by push-to-main, release, schedule, or workflow_dispatch (cannot be validated in PR context) - - Only apply `needs-human-review` and `higher-risk` labels. + - **Allowed classification labels**: `__GH_AW_EXPR_9AD6B038__` + - Parse `__GH_AW_EXPR_9AD6B038__` as a comma-separated list and treat that list as the only valid labels for this step. + - If `__GH_AW_EXPR_9AD6B038__` is empty, skip this step entirely. + - Use `__GH_AW_EXPR_49B959F1__` to understand what each label means and when to apply it. + - Never apply a label that is not in the parsed classification label list. ### Step 5: Post Analysis Comment @@ -512,6 +512,7 @@ jobs: GH_AW_GITHUB_EVENT_PULL_REQUEST_TITLE: ${{ github.event.pull_request.title }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_9AD6B038: ${{ inputs.classification-labels }} GH_AW_EXPR_23557367: ${{ inputs.target-pr-number || github.event.pull_request.number }} with: script: | @@ -525,6 +526,7 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_EXPR_23557367: ${{ inputs.target-pr-number || github.event.pull_request.number }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_9AD6B038: ${{ inputs.classification-labels }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} @@ -548,6 +550,7 @@ jobs: substitutions: { GH_AW_EXPR_23557367: process.env.GH_AW_EXPR_23557367, GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_9AD6B038: process.env.GH_AW_EXPR_9AD6B038, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, @@ -726,7 +729,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"add_comment":{"max":1,"target":"${{ inputs.target-pr-number || 'triggering' }}"},"add_labels":{"allowed":["needs-human-review","higher-risk"],"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1,"target":"${{ inputs.target-pr-number || 'triggering' }}"},"add_labels":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' [ @@ -768,7 +771,7 @@ jobs: "name": "add_comment" }, { - "description": "Add labels to an existing GitHub issue or pull request for categorization and filtering. Labels must already exist in the repository. For creating new issues with labels, use create_issue with the labels property instead. CONSTRAINTS: Maximum 3 label(s) can be added. Only these labels are allowed: [\"needs-human-review\" \"higher-risk\"].", + "description": "Add labels to an existing GitHub issue or pull request for categorization and filtering. Labels must already exist in the repository. For creating new issues with labels, use create_issue with the labels property instead. CONSTRAINTS: Maximum 3 label(s) can be added.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1564,6 +1567,55 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs/ find "/tmp/gh-aw/safeoutputs/" -type f -print echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Pre-sanitize labels from input allowlist + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + env: + CLASSIFICATION_LABELS: ${{ inputs.classification-labels }} + with: + script: | + const fs = require('fs'); + const outputPath = process.env.GH_AW_AGENT_OUTPUT; + if (!outputPath || !fs.existsSync(outputPath)) { + core.info('No GH_AW_AGENT_OUTPUT file found; skipping.'); + return; + } + const doc = JSON.parse(fs.readFileSync(outputPath, 'utf8')); + if (!Array.isArray(doc.items)) { + core.warning('agent output has no items array; skipping.'); + return; + } + const allowed = new Set( + String(process.env.CLASSIFICATION_LABELS || '') + .split(',') + .map((s) => s.trim()) + .filter(Boolean) + ); + if (allowed.size === 0) { + const before = doc.items.length; + doc.items = doc.items.filter((item) => item?.type !== 'add_labels'); + fs.writeFileSync(outputPath, JSON.stringify(doc)); + core.info(`No allowed labels provided; removed ${before - doc.items.length} add_labels operations.`); + return; + } + let removed = 0; + let dropped = 0; + doc.items = doc.items.filter((item) => { + if (item?.type !== 'add_labels' || !Array.isArray(item.labels)) { + return true; + } + const before = item.labels.length; + item.labels = item.labels + .map((v) => String(v).trim()) + .filter((v) => v && allowed.has(v)); + removed += Math.max(0, before - item.labels.length); + if (item.labels.length === 0) { + dropped++; + return false; + } + return true; + }); + fs.writeFileSync(outputPath, JSON.stringify(doc)); + core.info(`Sanitized label ops: removed=${removed}, dropped_messages=${dropped}`); - name: Process Safe Outputs id: process_safe_outputs uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 @@ -1572,7 +1624,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ inputs.target-pr-number || 'triggering' }}\"},\"add_labels\":{\"allowed\":[\"needs-human-review\",\"higher-risk\"],\"max\":3},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ inputs.target-pr-number || 'triggering' }}\"},\"add_labels\":{\"max\":3},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-dependency-review.md b/.github/workflows/gh-aw-dependency-review.md index cf552fd3..4974bb9c 100644 --- a/.github/workflows/gh-aw-dependency-review.md +++ b/.github/workflows/gh-aw-dependency-review.md @@ -44,6 +44,11 @@ on: type: string required: false default: "github-actions[bot]" + classification-labels: + description: "Comma-separated list of labels the agent may apply (e.g. 'needs-human-review,higher-risk,merge-ready'). If empty, no labels are applied. Define label semantics in additional-instructions." + type: string + required: false + default: "" messages-footer: description: "Footer appended to all agent comments and reviews" type: string @@ -74,9 +79,56 @@ safe-outputs: activation-comments: false add-labels: max: 3 - allowed: - - "needs-human-review" - - "higher-risk" + steps: + - name: Pre-sanitize labels from input allowlist + uses: actions/github-script@v7 + env: + CLASSIFICATION_LABELS: ${{ inputs.classification-labels }} + with: + script: | + const fs = require('fs'); + const outputPath = process.env.GH_AW_AGENT_OUTPUT; + if (!outputPath || !fs.existsSync(outputPath)) { + core.info('No GH_AW_AGENT_OUTPUT file found; skipping.'); + return; + } + const doc = JSON.parse(fs.readFileSync(outputPath, 'utf8')); + if (!Array.isArray(doc.items)) { + core.warning('agent output has no items array; skipping.'); + return; + } + const allowed = new Set( + String(process.env.CLASSIFICATION_LABELS || '') + .split(',') + .map((s) => s.trim()) + .filter(Boolean) + ); + if (allowed.size === 0) { + const before = doc.items.length; + doc.items = doc.items.filter((item) => item?.type !== 'add_labels'); + fs.writeFileSync(outputPath, JSON.stringify(doc)); + core.info(`No allowed labels provided; removed ${before - doc.items.length} add_labels operations.`); + return; + } + let removed = 0; + let dropped = 0; + doc.items = doc.items.filter((item) => { + if (item?.type !== 'add_labels' || !Array.isArray(item.labels)) { + return true; + } + const before = item.labels.length; + item.labels = item.labels + .map((v) => String(v).trim()) + .filter((v) => v && allowed.has(v)); + removed += Math.max(0, before - item.labels.length); + if (item.labels.length === 0) { + dropped++; + return false; + } + return true; + }); + fs.writeFileSync(outputPath, JSON.stringify(doc)); + core.info(`Sanitized label ops: removed=${removed}, dropped_messages=${dropped}`); strict: false timeout-minutes: 60 steps: @@ -224,19 +276,13 @@ Apply the following additional checks based on the dependency ecosystem: ### Step 4: Determine Labels -Based on the analysis, determine if labels should be applied: - -- **`needs-human-review`**: Apply when ANY of these conditions are met: - - A dependency update introduces breaking changes that affect this repo's usage - - A GitHub Actions commit SHA is not verified - - A Buildkite plugin moves from SHA-pinned to mutable tag, or between mutable tags - - The changelog indicates breaking changes - - A major version bump in any ecosystem (e.g. v1 → v2 in Go, major semver in npm/Python/Java) - -- **`higher-risk`**: Apply when: - - The updated dependency is used only in workflows triggered by push-to-main, release, schedule, or workflow_dispatch (cannot be validated in PR context) +Based on the analysis, determine if any labels from the configured `classification-labels` set should be applied: -Only apply `needs-human-review` and `higher-risk` labels. +- **Allowed classification labels**: `${{ inputs.classification-labels }}` +- Parse `${{ inputs.classification-labels }}` as a comma-separated list and treat that list as the only valid labels for this step. +- If `${{ inputs.classification-labels }}` is empty, skip this step entirely. +- Use `${{ inputs.additional-instructions }}` to understand what each label means and when to apply it. +- Never apply a label that is not in the parsed classification label list. ### Step 5: Post Analysis Comment diff --git a/.github/workflows/trigger-dependency-review.yml b/.github/workflows/trigger-dependency-review.yml index 1d3ef754..aacb6f2f 100644 --- a/.github/workflows/trigger-dependency-review.yml +++ b/.github/workflows/trigger-dependency-review.yml @@ -18,8 +18,14 @@ jobs: github.event.pull_request.user.login == 'renovate[bot]' || startsWith(github.head_ref, 'updatecli') uses: ./.github/workflows/gh-aw-dependency-review.lock.yml - # For updatecli: uncomment and set your repo's updatecli bot actor (it varies per repo). # with: - # allowed-bot-users: "github-actions[bot]" + # Configure which labels the agent may apply and define their semantics in additional-instructions. + # classification-labels: "needs-human-review,higher-risk,merge-ready" + # additional-instructions: | + # - `needs-human-review`: Apply when breaking changes are found, a major version bump, unverified SHA, or mutable tag move. + # - `higher-risk`: Apply when the dependency is only used in push/release/schedule/dispatch workflows. + # - `merge-ready`: Apply when all dependency updates are safe to merge without human review. + # For updatecli: uncomment and set your repo's updatecli bot actor (it varies per repo). + # allowed-bot-users: "github-actions[bot]" secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/dependency-review/README.md b/gh-agent-workflows/dependency-review/README.md index 9708ee72..b9e8c671 100644 --- a/gh-agent-workflows/dependency-review/README.md +++ b/gh-agent-workflows/dependency-review/README.md @@ -4,7 +4,7 @@ Analyze Dependabot, Renovate, and Updatecli dependency update PRs. ## How it works -Triggered when Dependabot, Renovate, or Updatecli opens or updates a PR. Classifies each dependency by ecosystem (GitHub Actions, Go, npm, Python, Java, Buildkite, etc.), runs shared checks (changelog, usage analysis, compatibility, testability), and applies ecosystem-specific checks where relevant. Posts a structured analysis comment and optionally labels the PR `needs-human-review` or `higher-risk`. +Triggered when Dependabot, Renovate, or Updatecli opens or updates a PR. Classifies each dependency by ecosystem (GitHub Actions, Go, npm, Python, Java, Buildkite, etc.), runs shared checks (changelog, usage analysis, compatibility, testability), and applies ecosystem-specific checks where relevant. Posts a structured analysis comment and optionally labels the PR. ## Quick Install @@ -26,14 +26,15 @@ See [example.yml](example.yml) for the full workflow file. | Input | Description | Required | Default | | --- | --- | --- | --- | -| `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt. Use this to define label semantics for `classification-labels`. | No | `""` | | `setup-commands` | Shell commands run before the agent starts | No | `""` | | `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated). For Updatecli, add your repo's updatecli bot actor here (e.g. `github-actions[bot]` or a custom app bot). | No | `github-actions[bot]` | +| `classification-labels` | Comma-separated list of labels the agent may apply (e.g. `needs-human-review,higher-risk,merge-ready`). If empty, no labels are applied. Define label semantics in `additional-instructions`. | No | `""` | ## Safe Outputs - `add-comment` — post an analysis comment on the PR (max 1) -- `add-labels` — label the PR when human review or higher risk is detected (max 3) +- `add-labels` — apply labels from the configured `classification-labels` allowlist (max 3); semantics defined via `additional-instructions` ## Manual usage with mention-in-pr diff --git a/gh-agent-workflows/dependency-review/example.yml b/gh-agent-workflows/dependency-review/example.yml index 3978c01a..7b31802c 100644 --- a/gh-agent-workflows/dependency-review/example.yml +++ b/gh-agent-workflows/dependency-review/example.yml @@ -16,8 +16,14 @@ jobs: github.event.pull_request.user.login == 'renovate[bot]' || startsWith(github.head_ref, 'updatecli') uses: elastic/ai-github-actions/.github/workflows/gh-aw-dependency-review.lock.yml@v0 - # For updatecli: uncomment and set your repo's updatecli bot actor (it varies per repo). # with: - # allowed-bot-users: "github-actions[bot]" + # Configure which labels the agent may apply and define their semantics in additional-instructions. + # classification-labels: "needs-human-review,higher-risk,merge-ready" + # additional-instructions: | + # - `needs-human-review`: Apply when breaking changes are found, a major version bump, unverified SHA, or mutable tag move. + # - `higher-risk`: Apply when the dependency is only used in push/release/schedule/dispatch workflows. + # - `merge-ready`: Apply when all dependency updates are safe to merge without human review. + # For updatecli: uncomment and set your repo's updatecli bot actor (it varies per repo). + # allowed-bot-users: "github-actions[bot]" secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}