fix(ci): use built-in token for runtime pin PRs (#3365)

This commit is contained in:
Carlos Florêncio
2026-09-04 14:33:41 +00:00
committed by GitHub
parent b557cf442c
commit ed80524e7d
16 changed files with 424 additions and 47 deletions
@@ -10,6 +10,14 @@ REPO_ROOT = Path(__file__).resolve().parents[2]
WORKFLOW = REPO_ROOT / ".github" / "workflows" / "update-agent-runtime-pins.yml"
LINT_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "lint-action-pinning.yml"
SCRIPT = REPO_ROOT / "scripts" / "update-agent-runtime-pins.mjs"
REQUIRED_CHECK_WORKFLOWS = (
"backend-tests.yml",
"frontend-tests.yml",
"e2e-tests.yml",
"architecture-lint.yml",
"lint-action-pinning.yml",
"lint-harness-files.yml",
)
class ManagedRuntimePinWorkflowContractTest(unittest.TestCase):
@@ -21,16 +29,15 @@ class ManagedRuntimePinWorkflowContractTest(unittest.TestCase):
self.assertRegex(self.workflow, r"cron:\s*[\"']?[0-9]+ [0-9]+ \* \* [0-6][\"']?")
self.assertIn("workflow_dispatch:", self.workflow)
def test_workflow_uses_least_privilege_and_dedicated_app_token(self) -> None:
self.assertIn("permissions:\n contents: read", self.workflow)
self.assertIn("permission-contents: write", self.workflow)
self.assertIn("permission-pull-requests: write", self.workflow)
self.assertNotIn("permissions:\n contents: write", self.workflow)
self.assertNotIn("permissions:\n pull-requests: write", self.workflow)
self.assertIn("MANAGED_RUNTIME_PIN_APP_PRIVATE_KEY", self.workflow)
self.assertIn("MANAGED_RUNTIME_PIN_APP_CLIENT_ID", self.workflow)
def test_workflow_uses_least_privilege_and_builtin_token(self) -> None:
self.assertIn(
"permissions:\n contents: write\n pull-requests: write", self.workflow
)
self.assertIn("GH_TOKEN: ${{ github.token }}", self.workflow)
self.assertNotIn("actions/create-github-app-token@", self.workflow)
self.assertNotIn("MANAGED_RUNTIME_PIN_APP_PRIVATE_KEY", self.workflow)
self.assertNotIn("MANAGED_RUNTIME_PIN_APP_CLIENT_ID", self.workflow)
self.assertNotIn("secrets.GITHUB_TOKEN", self.workflow)
self.assertNotIn("GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}", self.workflow)
def test_workflow_groups_one_conventional_commit_pr_on_stable_branch(self) -> None:
self.assertIn("update-managed-runtime-pins", self.workflow)
@@ -47,7 +54,30 @@ class ManagedRuntimePinWorkflowContractTest(unittest.TestCase):
push_start = self.workflow.index("- name: Commit and push one grouped change")
pr_start = self.workflow.index("- name: Create or refresh the single grouped PR")
push_step = self.workflow[push_start:pr_start]
self.assertIn("GH_TOKEN: ${{ steps.app-token.outputs.token }}", push_step)
pr_step = self.workflow[pr_start:]
self.assertIn("GH_TOKEN: ${{ github.token }}", push_step)
self.assertIn("GH_TOKEN: ${{ github.token }}", pr_step)
def test_workflow_dispatches_required_checks_for_builtin_token_prs(self) -> None:
self.assertIn("actions: write", self.workflow)
dispatch_start = self.workflow.index(
"- name: Dispatch required checks for generated PR"
)
dispatch_step = self.workflow[dispatch_start:]
self.assertIn("gh workflow run", dispatch_step)
self.assertIn('--ref "$BOT_BRANCH"', dispatch_step)
self.assertIn('--repo "$GITHUB_REPOSITORY"', dispatch_step)
for workflow_name in REQUIRED_CHECK_WORKFLOWS:
self.assertIn(workflow_name, dispatch_step)
workflow = (REPO_ROOT / ".github" / "workflows" / workflow_name).read_text(
encoding="utf-8"
)
self.assertRegex(
workflow,
r"(?m)^ workflow_dispatch:\s*$",
f"{workflow_name} must accept explicit validation dispatches",
)
def test_workflow_validates_before_any_commit_or_push(self) -> None:
update_pos = self.workflow.index("node scripts/update-agent-runtime-pins.mjs")
+4
View File
@@ -7,6 +7,7 @@ on:
branches: [main]
merge_group:
types: [checks_requested]
workflow_dispatch:
concurrency:
# Pull requests can supersede one another safely. Pushes compare each commit
@@ -57,6 +58,9 @@ jobs:
# group's equivalent of the pull request's base.
merge_group) BASE_REF="${MERGE_GROUP_BASE_SHA}" ;;
push) BASE_REF="${PUSH_BEFORE}" ;;
# The updater dispatches this workflow against its stable bot
# branch, so the main branch fork point is the PR baseline.
workflow_dispatch) BASE_REF="$(git merge-base HEAD origin/main)" ;;
*) BASE_REF="" ;;
esac
+1
View File
@@ -13,6 +13,7 @@ on:
branches: [main]
merge_group:
types: [checks_requested]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
+1
View File
@@ -13,6 +13,7 @@ on:
branches: [main]
merge_group:
types: [checks_requested]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -18,6 +18,7 @@ on:
branches: [main]
merge_group:
types: [checks_requested]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
+1
View File
@@ -18,6 +18,7 @@ on:
branches: [main]
merge_group:
types: [checks_requested]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
+31 -18
View File
@@ -7,11 +7,13 @@ on:
- cron: "17 6 * * 1"
workflow_dispatch:
# The job mints a narrower GitHub App token only after checkout. The default
# workflow token is never used to create the generated PR, so its events retain
# the repository's normal CI behavior.
# The job uses the repository-scoped workflow token for the branch, PR, and
# explicit validation-workflow dispatches. A GITHUB_TOKEN-created push or PR
# does not recursively trigger push/pull_request workflows.
permissions:
contents: read
contents: write
pull-requests: write
actions: write
concurrency:
group: managed-runtime-pin-update
@@ -21,8 +23,6 @@ jobs:
update:
name: Open managed runtime pin PR
runs-on: ubuntu-latest
permissions:
contents: read
env:
BOT_BRANCH: automation/update-managed-runtime-pins
@@ -42,18 +42,9 @@ jobs:
- name: Test pin updater
run: node --test scripts/update-agent-runtime-pins.test.mjs
- name: Create managed runtime pin App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.MANAGED_RUNTIME_PIN_APP_CLIENT_ID }}
private-key: ${{ secrets.MANAGED_RUNTIME_PIN_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
- name: Configure git authentication
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GH_TOKEN: ${{ github.token }}
run: gh auth setup-git
- name: Prepare stable bot branch
@@ -74,7 +65,7 @@ jobs:
- name: Commit and push one grouped change
if: steps.update.outputs.changed == 'true'
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
git config user.name "kandev-runtime-updater[bot]"
@@ -89,7 +80,7 @@ jobs:
- name: Create or refresh the single grouped PR
if: steps.update.outputs.changed == 'true'
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
cat > /tmp/managed-runtime-pin-pr-body.md <<'EOF'
@@ -113,3 +104,25 @@ jobs:
--title "chore: update managed runtime pins" \
--body-file /tmp/managed-runtime-pin-pr-body.md
fi
# GITHUB_TOKEN-created push and pull-request events do not recursively
# start validation workflows. Dispatch the six required checks explicitly
# against the exact bot-branch commit after the PR exists.
- name: Dispatch required checks for generated PR
if: steps.update.outputs.changed == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
for workflow in \
backend-tests.yml \
frontend-tests.yml \
e2e-tests.yml \
architecture-lint.yml \
lint-action-pinning.yml \
lint-harness-files.yml
do
gh workflow run "$workflow" \
--repo "$GITHUB_REPOSITORY" \
--ref "$BOT_BRANCH"
done