Opt-in via new 'dependabot-auto-approve' input (mode 'dev-patch-minor'). When enabled, Dependabot PRs are evaluated on pull_request_target opened/reopened and on check_suite completed for dependabot/ branches, and approved + labeled + auto-merged only when ALL gates hold: 1. Author is the real dependabot[bot] app (login AND user id 49699333) 2. Same-repo head on a dependabot/ branch (never forks) 3. Every commit signature-verified and dependabot-authored 4. Changed files a subset of 'dependabot-allowed-files' (exact paths) 5. Every updated dependency direct:development with semver-patch/minor update per Dependabot's commit metadata (missing metadata = no approve) 6. CI green on head SHA: all check runs success/neutral/skipped with at least one non-skipped check, combined status success if any exist 7. PR open, non-draft, conflict-free, not on hold Every gate fails closed, logging the reason to the action log only. Approvals use a distinct marker (slash-commands-dependabot-auto) that push invalidation now dismisses alongside /lgtm approvals; after a human push, gate 3 fails permanently so only /lgtm can accept the PR. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ygNtiNcAaqTRnQjHCDkVS
179 lines
7.6 KiB
YAML
179 lines
7.6 KiB
YAML
name: PR Slash Commands
|
|
description: >-
|
|
Handles /lgtm, /hold, and /stageblog slash commands on PRs. Core maintainers
|
|
can approve via /lgtm (adds an accepted label, submits a bot APPROVE review,
|
|
and enables auto-merge). Core maintainers or CODEOWNERS can block via /hold
|
|
or trigger a blog preview staging workflow via /stageblog. Approval is
|
|
invalidated when new commits are pushed. Optionally auto-approves
|
|
narrowly-scoped Dependabot PRs (dependabot-auto-approve).
|
|
|
|
inputs:
|
|
github-token:
|
|
description: >-
|
|
GitHub App installation token used for all API calls: team-membership
|
|
checks, labels, comments, reactions, reviews, auto-merge, CODEOWNERS
|
|
fetch, and workflow dispatch. Must have Organization Members:read plus
|
|
Repository Pull requests:write and Contents:read (and Actions:write if
|
|
/stageblog is enabled). The default GITHUB_TOKEN will NOT work — it
|
|
lacks read:org and its approvals may not count toward required reviews.
|
|
required: true
|
|
approved-label:
|
|
description: Label added by /lgtm to mark the PR as accepted
|
|
required: false
|
|
default: accepted
|
|
hold-label:
|
|
description: Label added by /hold to block merging
|
|
required: false
|
|
default: do-not-merge/hold
|
|
always-allow-teams:
|
|
description: >-
|
|
Comma-separated team slugs (within the repo's org) whose members may
|
|
/lgtm any PR. Only these teams can /lgtm — CODEOWNERS does not grant
|
|
/lgtm authorization. Members may also /hold and /stageblog any PR.
|
|
required: false
|
|
default: core-maintainers
|
|
force-allow-teams:
|
|
description: >-
|
|
Comma-separated team slugs (within the repo's org) whose members may
|
|
use /lgtm force. This bypasses the self-approval guard and CODEOWNERS —
|
|
only membership in one of these teams grants it.
|
|
required: false
|
|
default: core-maintainers,lead-maintainers
|
|
codeowners-path:
|
|
description: Path to the CODEOWNERS file (fetched from the PR base branch)
|
|
required: false
|
|
default: .github/CODEOWNERS
|
|
invalidate-on-push:
|
|
description: >-
|
|
Remove the approved label and dismiss the bot review when new commits
|
|
are pushed to the PR. Skipped if the label was most recently applied
|
|
manually by a member of always-allow-teams or force-allow-teams (not
|
|
the bot via /lgtm). Set to 'false' to keep approval across pushes
|
|
unconditionally.
|
|
required: false
|
|
default: 'true'
|
|
submit-review:
|
|
description: >-
|
|
Whether to submit a bot APPROVE review alongside the label on /lgtm.
|
|
Set to 'false' to rely on the label alone.
|
|
required: false
|
|
default: 'true'
|
|
enable-auto-merge:
|
|
description: >-
|
|
Enable auto-merge on the PR after a successful /lgtm. The PR will merge
|
|
automatically once all required checks pass. Requires the repo to have
|
|
"Allow auto-merge" enabled in Settings. Disabled on /lgtm cancel and on
|
|
push invalidation.
|
|
required: false
|
|
default: 'true'
|
|
auto-merge-method:
|
|
description: Merge method for auto-merge — one of squash, merge, rebase
|
|
required: false
|
|
default: squash
|
|
remove-labels-on-accept:
|
|
description: >-
|
|
Comma-separated label names to remove from the PR when /lgtm accepts it
|
|
(e.g. in-review,draft,proposal). Missing labels are ignored.
|
|
required: false
|
|
default: ''
|
|
project-number:
|
|
description: >-
|
|
Org-level Project (V2) number to update when /lgtm accepts the PR. Leave
|
|
empty to disable project updates. The PR is added to the project if not
|
|
already present.
|
|
required: false
|
|
default: ''
|
|
project-status-field:
|
|
description: Name of the single-select field to set on accept
|
|
required: false
|
|
default: Status
|
|
project-accepted-option:
|
|
description: Name of the option to set in the status field on accept
|
|
required: false
|
|
default: Accepted
|
|
project-gate-label:
|
|
description: >-
|
|
If set, only update the project status when the PR has this label.
|
|
Leave empty to update the project for every accepted PR.
|
|
required: false
|
|
default: ''
|
|
stageblog-workflow:
|
|
description: >-
|
|
Workflow file name (e.g. stage-blog.yml) to dispatch when /stageblog is
|
|
invoked. Leave empty to disable the command. The workflow must accept
|
|
inputs 'pr_number' and 'head_sha'.
|
|
required: false
|
|
default: ''
|
|
stageblog-paths:
|
|
description: >-
|
|
Comma-separated glob patterns (CODEOWNERS-style: **, *, ?, leading /,
|
|
trailing /) matched against the PR's changed files. /stageblog is refused
|
|
if no file matches.
|
|
required: false
|
|
default: 'blog/**'
|
|
dependabot-auto-approve:
|
|
description: >-
|
|
Opt-in Dependabot auto-approve policy. Empty (default) = disabled.
|
|
'dev-patch-minor' approves + labels + enables auto-merge on Dependabot
|
|
PRs where ALL of these hold: author is the real dependabot[bot] app
|
|
(login and user id), same-repo dependabot/ head branch, every commit is
|
|
signature-verified and dependabot-authored, changed files are a subset
|
|
of dependabot-allowed-files, every updated dependency is
|
|
direct:development with a semver-patch/minor update (per Dependabot's
|
|
commit-message metadata; missing metadata never approves), all check
|
|
runs on the head SHA are green with at least one non-skipped check, and
|
|
the PR is open, non-draft, conflict-free, and not on hold. Requires the
|
|
caller workflow to also trigger on pull_request_target
|
|
[opened, reopened] and check_suite [completed]. Any other value
|
|
disables the mode (fail closed).
|
|
required: false
|
|
default: ''
|
|
dependabot-allowed-files:
|
|
description: >-
|
|
Comma-separated exact file paths a Dependabot PR may touch to qualify
|
|
for auto-approve. A PR changing any other file is never auto-approved.
|
|
required: false
|
|
default: 'package.json,package-lock.json'
|
|
|
|
outputs:
|
|
result:
|
|
description: >-
|
|
One of: lgtm-added, lgtm-forced, lgtm-removed, hold-added, hold-removed,
|
|
invalidated, invalidate-skipped, unauthorized, force-unauthorized,
|
|
self-lgtm-blocked, stageblog-dispatched, stageblog-not-blog,
|
|
stageblog-disabled, dependabot-approved, dependabot-skipped, noop
|
|
value: ${{ steps.handle.outputs.result }}
|
|
actor:
|
|
description: Login of the user who triggered the action (commenter)
|
|
value: ${{ steps.handle.outputs.actor }}
|
|
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Handle slash command
|
|
id: handle
|
|
uses: actions/github-script@v8
|
|
env:
|
|
APPROVED_LABEL: ${{ inputs.approved-label }}
|
|
HOLD_LABEL: ${{ inputs.hold-label }}
|
|
ALWAYS_ALLOW_TEAMS: ${{ inputs.always-allow-teams }}
|
|
FORCE_ALLOW_TEAMS: ${{ inputs.force-allow-teams }}
|
|
CODEOWNERS_PATH: ${{ inputs.codeowners-path }}
|
|
INVALIDATE_ON_PUSH: ${{ inputs.invalidate-on-push }}
|
|
SUBMIT_REVIEW: ${{ inputs.submit-review }}
|
|
ENABLE_AUTO_MERGE: ${{ inputs.enable-auto-merge }}
|
|
AUTO_MERGE_METHOD: ${{ inputs.auto-merge-method }}
|
|
REMOVE_LABELS_ON_ACCEPT: ${{ inputs.remove-labels-on-accept }}
|
|
PROJECT_NUMBER: ${{ inputs.project-number }}
|
|
PROJECT_STATUS_FIELD: ${{ inputs.project-status-field }}
|
|
PROJECT_ACCEPTED_OPTION: ${{ inputs.project-accepted-option }}
|
|
PROJECT_GATE_LABEL: ${{ inputs.project-gate-label }}
|
|
STAGEBLOG_WORKFLOW: ${{ inputs.stageblog-workflow }}
|
|
STAGEBLOG_PATHS: ${{ inputs.stageblog-paths }}
|
|
DEPENDABOT_AUTO_APPROVE: ${{ inputs.dependabot-auto-approve }}
|
|
DEPENDABOT_ALLOWED_FILES: ${{ inputs.dependabot-allowed-files }}
|
|
with:
|
|
github-token: ${{ inputs.github-token }}
|
|
script: |
|
|
const main = require(process.env.GITHUB_ACTION_PATH + '/main.js');
|
|
await main({ github, context, core });
|