Skip to content

ci-conformance is SHA-pinned but executes policy and script from main #22

Description

@krisarmstrong

Summary

ci-conformance.yml is consumed by all four repos with a SHA pin and a version comment:

uses: MustardSeedNetworks/.github/.github/workflows/ci-conformance.yml@20eb2935… # v1.3.0

But the job itself checks out this repo at its default branch, with no ref:, and runs the script from that checkout:

- name: Check out the policy repo
  uses: actions/checkout@…
  with:
    repository: MustardSeedNetworks/.github
    path: .conformance
    persist-credentials: false
    # no ref: -> default branch

- name: Check CI conformance
  run: python3 .conformance/scripts/check-ci-conformance.py

So the workflow definition is pinned, while the script and policy files that actually execute are live from main.

Why raise it

Not necessarily a bug — policy/README.md is explicit that these files exist so one place can enforce fleet policy that golangci-lint has no extends for, and needing four PRs to roll out a policy change would defeat that. Live policy may well be the intent.

But the pin currently implies an immutability it does not provide, and that has two concrete consequences:

  1. A commit to main here changes what executes in all four repos on their next CI run, with no review in those repos and no tag bump. A mistake in a policy file reds the entire fleet immediately, including on unrelated PRs.
  2. It cost real sequencing care in Design: two status vocabularies in the fleet — settle one before Step 5 #21's rollout. The status-vocabulary gate had to merge after all three repo migrations for exactly this reason; had it merged first, every unmigrated repo would have gone red on unrelated PRs. That was navigable because it was noticed — the SHA pin suggests otherwise at a glance.

There is also a mild irony: check-ci-conformance.py itself enforces that tool installs are pinned, on the stated grounds that "an unpinned gate can change behaviour with no code change" — which is precisely what the policy checkout does.

Options

  • Document it and move on. Add a note to policy/README.md and to the uses: comment in each repo, so the pin is not read as covering the policy. Cheapest, keeps instant rollout.
  • Pin the policy checkout to the same ref as the workflow. Makes the pin honest and per-repo reviewable, but every policy change then needs four repo PRs plus a tag — which is the friction the shared policy exists to avoid.
  • Split the two. Keep the script pinned (it is code) while leaving the policy .txt files live (they are data). The failure mode this protects against — a script bug breaking all four repos — is the more dangerous half, and policy data changes are the ones worth rolling out instantly.

The third looks like the best trade to me, but this is a fleet-governance call rather than a code fix, so flagging rather than changing.

Related to #21

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions