Skip to content

ci: skip pull-request CI while a PR is a draft - #36

Open
seraph-pixelperfect wants to merge 1 commit into
mainfrom
ci/skip-draft-prs
Open

ci: skip pull-request CI while a PR is a draft#36
seraph-pixelperfect wants to merge 1 commit into
mainfrom
ci/skip-draft-prs

Conversation

@seraph-pixelperfect

Copy link
Copy Markdown
Collaborator

Closes #4

What changes

.github/workflows/ci.yml

 on:
   push:
     branches: [main]
   pull_request:
     branches: [main]
+    types: [opened, synchronize, reopened, ready_for_review]

 jobs:
   build-and-test:
+    if: github.event.pull_request.draft == false
     runs-on: ubuntu-latest

.github/PULL_REQUEST_TEMPLATE.md (new) — documents the draft-first contribution sequence: open as draft → iterate silently → mark "Ready for review" to start CI → subsequent pushes run CI as usual.

test/ci-workflow.test.ts (new) — regression coverage: plain string/regex assertions on the workflow YAML (no YAML parser dependency added).

Workflow semantics

Event Behavior
Draft PR opened (opened, draft=true) build-and-test evaluates draft == false → false → job skipped; no runners consumed
Draft PR pushed to (synchronize, draft=true) same guard → skipped
Marked ready (ready_for_review, draft=false) guard passes → CI runs on the exact commit already pushed — no new "trigger CI" commit needed. This is why ready_for_review must be in types:: the default activity types don't include it, so without the subscription the ready transition would fire no workflow at all
Non-draft PR opened/reopened/pushed guard passes → CI runs as before
Push to main unchanged. Note the guard uses loose equality == false deliberately: on push events github.event.pull_request is null, and GitHub's expression caster maps null→0 and false→0 for ==, so the guard evaluates true on pushes. A stricter form (e.g. != null && checks or !== true) would silently skip main-push CI

Why packed-tarball is not separately guarded

packed-tarball has needs: build-and-test and no if: override. Under GitHub Actions' default if: success() gate, a job whose needs dependency was skipped is itself skipped (skipped is treated as non-success). So the draft guard transitively skips packed-tarball — adding a duplicate guard would be redundant. The test pins this invariant: it asserts needs: build-and-test is present and that no if: always() / failure() / cancelled() escape hatch exists that would defeat the transitive skip.

Edge case the issue didn't spell out (flagged rather than silently chosen)

The issue says "do not run pull-request CI jobs while draft is true" but doesn't address ready_for_review needing explicit subscription — without adding it to types:, the default type list (opened, synchronize, reopened) would leave a PR marked ready with stale or absent CI until the next push. This PR subscribes to all four types explicitly. Also, as shown by the issue's own evidence (draft PR #8 ran build-and-test on open), the prior pull_request: trigger with no types: filter used the defaults, which fire on drafts.

Local verification (real output, from the worktree at commit ace8d06)

$ pnpm build
$ tsc
[build exit: 0]

$ pnpm lint
$ eslint .
[lint exit: 0]

$ pnpm run build:skill -- --check
$ tsx scripts/build-skill.ts -- --check
skills/linear-axi/SKILL.md is up to date.
[build:skill exit: 0]

$ pnpm test
$ vitest run

 RUN  v3.2.7 /Users/seraph/workspace/linear-axi-wt/ci-skip-draft

 ✓ test/ci-workflow.test.ts (4 tests) 2ms
 ✓ test/format.test.ts (4 tests) 1ms
 ✓ test/toon.test.ts (7 tests) 3ms
 ✓ test/errors.test.ts (7 tests) 2ms
 ✓ test/args.test.ts (7 tests) 3ms
 ✓ test/fields.test.ts (4 tests) 2ms
 ✓ test/config.test.ts (12 tests) 7ms

 Test Files  7 passed (7)
      Tests  45 passed (45)

[test exit: 0]

Baseline on main was 41 tests in 6 files; this adds 4 tests in 1 new file (test/ci-workflow.test.ts) → 45 tests, 7 files, all passing. Tests are pure file reads — no network, no Linear API.

Formatting: format:check is red on main already (18 pre-existing files flagged by prettier 3.9.6; CI does not run format:check). Verified by diffing the flagged-file list before/after this change: identical 18 files, no new flags. The new/changed files pass prettier --check individually.

CI quota-block caveat (known in this org)

Some Actions jobs in this org get rejected pre-execution with a billing/spending-limit message, and gh pr checks reports that as a failure. If a check here is red, inspect gh run view <run-id> for the billing annotation, or gh api repos/apexcloudwise/linear-axi/actions/runs/<id>/jobs — an empty steps array with ~3-4s duration means quota-blocked, not broken. If that happens, this PR relies on the local output above as evidence; the job will not be retried. This PR is opened ready (not draft) precisely so CI runs — ironic given the topic, but required for validation.

Identity note

This PR was opened by an automated agent dispatch authenticated as GitHub user seraph-pixelperfect, for human review. It is not self-approved; merge is a human decision.

- subscribe pull_request to ready_for_review (plus opened/synchronize/
  reopened) so marking a PR ready triggers CI without a new commit
- guard build-and-test with if: github.event.pull_request.draft == false;
  packed-tarball is transitively skipped via its plain needs: dependency
- add .github/PULL_REQUEST_TEMPLATE.md documenting the draft-first
  contribution sequence
- add test/ci-workflow.test.ts regression coverage for the trigger types,
  draft guard, untouched push-on-main trigger, and the packed-tarball
  transitive-skip invariant

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Skip pull-request CI while a PR is draft

1 participant