Skip to content

[quality] Automation PRs bypass the lint gate: ci.yml never runs on GITHUB_TOKEN-authored PRs #739

Description

@hivecommons-hive

Finding

.github/workflows/ci.yml — the Validate repository and Lint repository
jobs — triggers on pull_request. All three scheduled automation workflows open
their pull request with peter-evans/create-pull-request and pass no explicit
token: input
, so the PR is authored with the default GITHUB_TOKEN:

  • .github/workflows/import-architectures.yml (line 38)
  • .github/workflows/refresh-community-people.yml (line 29)
  • .github/workflows/refresh-radar-reports.yml (line 31)

GitHub does not start workflow runs for events raised by GITHUB_TOKEN, so
ci.yml never runs on any automation/* PR.

Evidence. PR #681 (automation/import-architectures, opened
2026-09-27T02:42Z) has exactly one entry in its status-check rollup — DCO,
which is a GitHub App and not Actions. Neither Validate repository nor
Lint repository appears, and mergeStateStatus is BLOCKED because the
required checks never arrive.

Consequence, measured. Against main at b54cf81 with npm ci:

$ git checkout origin/automation/import-architectures
$ npx prettier --check $(git diff --name-only origin/main...HEAD)
...
[warn] Code style issues found in 16 files. Run Prettier with --write to fix.

$ git checkout main
$ npx prettier --check .     # exit 0, no warnings

The import emits 16 files that violate npm run check:format — including
data/members.json, seven data/architectures/records/*.json, and six
docs/architectures/*.md — while main is currently prettier-clean. Merging an
import PR therefore re-breaks npm run check (and so npm test) on main,
which is the same drift class that PR #510 had to clean up wholesale.

npx -p markdownlint-cli markdownlint -c .markdownlint.yaml docs/architectures/*.md
and npx cspell --no-progress -c .cspell.yml docs both pass on the imported
content, and npx prettier --write on the changed files restores a repo-wide
clean prettier --check .. So normalising formatting inside the workflow, then
gating on markdown and spelling, is sufficient and introduces no flakiness.

Recommendation

Run the lint gate inside each automation workflow, immediately before the
peter-evans/create-pull-request step, so the generated diff is normalised and
verified on the one path that does execute.

1. .github/workflows/import-architectures.yml — insert three steps between
the existing - run: npm run build (line 37) and
- uses: peter-evans/create-pull-request@... (line 38):

      - run: npm run build
      - run: npm run fix:format
      - run: npm run check:markdown
      - run: npm run check:spelling
      - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1

2. .github/workflows/refresh-community-people.yml — same insertion between
- run: npm run build (line 28) and the create-pull-request step (line 29):

      - run: npm run build
      - run: npm run fix:format
      - run: npm run check:markdown
      - run: npm run check:spelling
      - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1

3. .github/workflows/refresh-radar-reports.yml — same insertion between
- run: npm run build (line 30) and the create-pull-request step (line 31):

      - run: npm run build
      - run: npm run fix:format
      - run: npm run check:markdown
      - run: npm run check:spelling
      - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11

npm run check:links is deliberately left out: it is network-bound and would
make the nightly import flaky. npm run check:format is not used directly
because the generator's output is not prettier-clean today; npm run fix:format
normalises it so the committed diff is clean, and a later change to the
generator can tighten this to check:format.

4. Regression guard — add this test to tests/workflow-scripts.test.mjs, which
already holds the workflow/package.json contract suite. It fails today and goes
green only once steps 1–3 land, so it must be part of the same change:

test('every workflow that opens a pull request lints the diff it commits', () => {
  const required = ['fix:format', 'check:markdown', 'check:spelling'];
  for (const [name, workflow] of workflows()) {
    for (const job of Object.values(workflow.jobs ?? {})) {
      const steps = job.steps ?? [];
      const prStep = steps.findIndex((step) =>
        String(step.uses ?? '').startsWith('peter-evans/create-pull-request@'),
      );
      if (prStep === -1) continue;
      const before = steps
        .slice(0, prStep)
        .map((step) => String(step.run ?? '').trim());
      for (const script of required) {
        assert.ok(
          before.includes(`npm run ${script}`),
          `${name} opens a pull request without first running \`npm run ${script}\`; ` +
            'ci.yml never runs on GITHUB_TOKEN-authored PRs, so this is the only gate.',
        );
      }
    }
  }
});

Adjust workflows() to whatever accessor that suite already uses to enumerate
parsed workflow YAML (see every workflow parses as YAML and declares at least one job, line 48).

Why there is no pull request attached

The substantive fix is entirely inside .github/workflows/**. The agent that
found this runs with a token tier that has no workflows permission, so GitHub
rejects any push whose diff touches that directory — there is nothing it could
push that would contain the change. The regression guard in step 4 does live
outside .github/workflows/, but it is red until steps 1–3 land, so it cannot
be shipped separately either.

This change needs a human maintainer, or an agent with workflow-write
permission, to land.
All four parts should go in one pull request.

Priority

  • Impact: high — the repository's entire PR validation gate is inert for the
    automation lane, and an import PR is open right now that re-breaks
    npm run check on main if merged.
  • Effort: low — three identical three-line insertions plus one test.

🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: b54cf81

— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/qualityApproved by a Hive merger/owner for auto-merge on green CIhive/hosted-available-lke648397-260827-5n31Approved by a Hive merger/owner for auto-merge on green CIqualityApproved by a Hive merger/owner for auto-merge on green CItestingApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions