Skip to content

feat(agent-actions): cancel in-flight CI runs when a PR is auto-closed for the contributor cap #2462

Description

@JSONbored

Parent: #1936
Related: #2270 (this triggers off the contributor_cap close that issue introduces)

Motivation

#2270 adds a per-contributor open-PR/issue cap with auto-close over the limit. Closing a PR for
being over the cap should also stop burning CI minutes on that PR's in-flight Actions runs — today
nothing in this codebase cancels a GitHub Actions run: there is no call to
POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel (or any equivalent) anywhere in src/.

Important constraint found while scoping this: the GitHub App's default_permissions
(src/selfhost/setup-wizard.ts) currently requests pull_requests, contents, issues, checks,
metadatanot actions. Listing/cancelling workflow runs via the Actions REST API needs
actions: write (and effectively actions: read to list runs for a head SHA first). Adding this
scope means every already-installed self-hosted operator will see a "this app wants additional
permissions" prompt and must re-approve before cancellation works for them — this is a permission
rollout, not just a code change, and installs that haven't re-approved must degrade gracefully
rather than error.

Requirements

  • Config-driven per this project's convention: default disabled, enableable globally (env var)
    or per-repo (.gittensory.yml / repository_settings), independent of (but only meaningful when
    paired with) the feat(agent-actions): configurable per-contributor open PR/issue cap with auto-close over the limit #2270 cap being enabled.
  • Scope to v1: only fires after a deterministic closeKind: "contributor_cap" close (from feat(agent-actions): configurable per-contributor open PR/issue cap with auto-close over the limit #2270)
    succeeds. (Extending to the existing "blacklist" closeKind is a natural follow-up, not v1 here.)
  • On trigger: list in-progress/queued workflow runs for the closed PR's head SHA
    (GET /repos/{owner}/{repo}/actions/runs?head_sha={sha}&status=in_progress plus queued), then
    cancel each (POST .../actions/runs/{run_id}/cancel).
  • Must degrade gracefully when the installation hasn't granted actions: write (a 403/permission
    error from the list/cancel call must be caught, logged via the audit ledger, and must NOT block or
    fail the underlying close action that already succeeded).

Deliverables

  • Add actions: write to default_permissions in the App manifest (src/selfhost/setup-wizard.ts),
    plus operator-facing docs on re-approving the permission bump for existing installs.
  • New GitHub REST wrappers (alongside the existing src/github/app.ts / src/github/pr-actions.ts
    helpers) for listing workflow runs by head SHA and cancelling a run.
  • New settings field (e.g. contributorCapCancelCi?: boolean) threaded through the same
    migration → schema → RepositorySettingsFocusManifestSettings/parseSettingsOverride
    resolveEffectiveSettings chain used for every other per-repo toggle, plus a global env var
    default (e.g. CONTRIBUTOR_CAP_CANCEL_CI_DEFAULT).
  • Hook into the action executor: after a closeKind: "contributor_cap" close executes successfully,
    if enabled, cancel in-flight runs for that PR's head SHA.
  • Audit event (recordAuditEvent) for both outcomes: cancelled (with run count) and skipped/failed
    due to missing permission.
  • Tests: disabled (default) → no cancel attempt; enabled + contributor_cap close → runs cancelled;
    enabled + any other close kind → no cancel attempt; missing actions:write → soft-fails, close
    action itself still reports success.

Acceptance criteria

Expected outcome

Contributor-cap enforcement (#2270) actually saves the CI minutes it's meant to save, without
silently breaking (or requiring a forced upgrade for) self-hosted installs that haven't granted the
new Actions permission.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions