Skip to content

feat(rollout): plan and prepare the move to the PR workflow - #21

Merged
boeboe merged 1 commit into
mainfrom
feat/pr-workflow-rollout
Nov 14, 2026
Merged

boeboe merged 1 commit into
mainfrom
feat/pr-workflow-rollout

Conversation

@boeboe

@boeboe boeboe commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Builds on #20 (merged as 6c23fd3): the pull requests this tool prepares call pr-changes.yml and required-gate. Rebased onto main; one commit.

What it does

scripts/rollout/pr-workflow.py is Stage I of Phase 1 (PR-only CI). It uses the standard library only.

  • plan <workspace> reads every clone in a workspace, made with engineering's scripts/audit-inventory.sh. It reports each repository's profile from .otfabric/policy.yaml and a status: migrated, ready, manual with reasons, no-ci, or excepted. It also suggests code-paths: Markdown that Go code reads or embeds. Output is Markdown or --format json, with --profile to filter.
  • apply <repo> is a dry run unless given --write. It rewrites the on: blocks of the heavy workflows to workflow_call + workflow_dispatch, and keeps the docs workflow on push to the default branch. It writes pr.yml with changes, every peer, and the OT Fabric Required Checks gate.
    • Permissions are copied from each workflow. secrets: inherit is passed only to workflows that use secrets.
    • It is idempotent: a second run reports migrated and changes nothing.
    • It exits 3 and writes nothing when a workflow needs a person: other triggers, dispatch inputs, paths: filters, its own concurrency group, or expressions reading github.ref / github.event*.
  • Never automatic. It does not commit, push, open pull requests, or touch a ruleset. scripts/rollout/README.md has the procedure: pilot per profile, one reviewed pull request per repository, the ruleset only after the gate has reported, and rollback.
  • exceptions.txt lists repositories the plan leaves alone. Today that is only .github itself: Selftest is path-filtered by design (AGENTS.md rule 6).

The generator was checked against the two hand-made pilots, otfabric/go-mms#43 and otfabric/go-iec61850#90. It reproduces their on: blocks exactly and an equivalent pr.yml, including the README.md code path that go-iec61850's TestREADMESnippets needs.

Files

  • scripts/rollout/pr-workflow.py, scripts/rollout/README.md, scripts/rollout/exceptions.txt: new.
  • scripts/selftest/rollout.sh and the fixtures testdata/rollout/{ready,manual}: new.
  • .github/workflows/selftest.yml: adds scripts/rollout/** to the pull request paths, and a new rollout-cases job.
  • AGENTS.md (Commands row), README.md (directory row).

No shared workflow, input, default, job name or permission changes. Callers are unaffected.

Checks run

  • scripts/selftest/rollout.sh, which covers:
    • a dry run writes nothing;
    • only the on: blocks change;
    • pr.yml has the gate, every job, the conditions and the permissions;
    • a second run changes nothing;
    • a manual repository is refused and left untouched;
    • plan counts.
  • The other selftest scripts (pr-changes, required-gate, policy, release-notes, go-version, docs-check) pass locally on this branch.
  • otfabric-policy check . reports compliant: 0 must-fail and 0 should-fail.
  • Selftest on this pull request: see the checks.
  • Not run: actionlint.

Plan on the local workspace (82 clones, possibly stale)

Profile migrated ready manual no-ci
application 0 0 5 0
cli 0 18 1 0
foundational-transport 0 3 0 0
information-model 0 0 2 0
infrastructure 0 1 1 1
interoperability 0 3 15 0
protocol-library 2 7 15 0
unknown 0 0 2 6

The two migrated repositories are the pilot branches checked out locally. Nothing is merged.

Limitations

  • manual is broad on purpose. Most *-interop repositories have their own concurrency groups or tag-push releases mixed into CI; those need a person.
  • code-paths suggestions only find .md string literals and go:embed. A reviewer still checks them.
  • The plan is only as fresh as the workspace.

🤖 Generated with Claude Code

Base automatically changed from feat/pr-required-gate to main November 14, 2026 01:06
scripts/rollout/pr-workflow.py plans the move of every repository in a
workspace to the PR workflow (pr-changes.yml and the required-gate action)
and prepares one repository at a time: it rewrites the triggers of the heavy
workflows to workflow_call + workflow_dispatch, keeps the docs workflow on
the push to the default branch, and writes pr.yml with the gate. Dry run by
default, idempotent, and it refuses (exit 3) a repository whose workflows
need a person: other triggers, dispatch inputs, path filters, their own
concurrency group, or expressions that read the event or ref.

It never commits, pushes, opens a pull request or touches a ruleset.
scripts/selftest/rollout.sh runs it on two fixtures in testdata/rollout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@boeboe
boeboe force-pushed the feat/pr-workflow-rollout branch from d656dfa to 2b3fd3a Compare November 14, 2026 01:07
@boeboe
boeboe marked this pull request as ready for review November 14, 2026 01:13
@boeboe
boeboe merged commit 6334e54 into main Nov 14, 2026
43 checks passed
@boeboe
boeboe deleted the feat/pr-workflow-rollout branch November 14, 2026 01:13
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.

1 participant