|
| 1 | +# ADR 0005 — Reusable workflow split between `AzureLocal/.github` and `AzureLocal/platform` |
| 2 | + |
| 3 | +- **Status**: Accepted |
| 4 | +- **Date**: 2026-04-13 |
| 5 | +- **Deciders**: @kristopherjturner |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +Reusable GitHub Actions workflows for the AzureLocal org could plausibly live in either of two existing repos: |
| 10 | + |
| 11 | +- [`AzureLocal/.github`](https://github.com/AzureLocal/.github) — the org's GitHub-metadata repo. Already hosts `reusable-add-to-project.yml`, `reusable-release-please.yml`, `reusable-validate-structure.yml`. |
| 12 | +- [`AzureLocal/platform`](https://github.com/AzureLocal/platform) — the org's developer-tooling repo created by [ADR-0001](./0001-create-platform-repo.md). Hosts standards, testing frameworks, and templates. |
| 13 | + |
| 14 | +Without a written rule, every new reusable workflow becomes a judgement call about where it should live. ADR-0001 deferred this decision; [`docs/reusable-workflows/split-rule.md`](../docs/reusable-workflows/split-rule.md) sketched the rule informally. This ADR formalises it. |
| 15 | + |
| 16 | +The rule has practical consequences: each repo has its own release cadence (`.github` rarely changes, `platform` evolves with frameworks), its own contributor audience, and a different blast radius if a workflow regresses. |
| 17 | + |
| 18 | +## Decision |
| 19 | + |
| 20 | +Adopt the **stack-vs-governance split**: |
| 21 | + |
| 22 | +> **`AzureLocal/.github` owns governance workflows — those that apply to every repo regardless of stack.** |
| 23 | +> |
| 24 | +> **`AzureLocal/platform` owns stack-specific workflows — those that apply only to certain repo types (PS module, TS web app, IaC, MkDocs site, MAPROOM consumer).** |
| 25 | +
|
| 26 | +Plus three corollaries: |
| 27 | + |
| 28 | +1. **Single-consumer workflows are not reusable.** If only one repo uses a workflow, keep it local to that repo. A reusable workflow must have at least two plausible consumers. |
| 29 | +2. **A workflow that's both universal and stack-specific** (e.g., release-please publishing to PSGallery) splits along the seam: the governance half goes to `.github`, the stack-specific half goes to `platform`. |
| 30 | +3. **New universal workflows default to `.github`.** If one ends up in `platform` for convenience, revisit at the next major version. |
| 31 | + |
| 32 | +## Consequences |
| 33 | + |
| 34 | +### Positive |
| 35 | + |
| 36 | +- **Discovery is predictable.** A contributor browsing `AzureLocal/.github` for "how do I contribute" doesn't wade past TypeScript build internals. |
| 37 | +- **Release cadences are decoupled.** `platform` can ship breaking changes to a stack-specific workflow without forcing a `.github` release. |
| 38 | +- **Blast radius is bounded.** A bad governance workflow breaks every repo. A bad stack-specific workflow breaks only the repos in that stack. The split limits the worst case. |
| 39 | +- **Authority is clear for cross-repo conformance.** `Test-RepoConformance` (in `AzureLocal.Common`) only has to check that `deploy-docs.yml` references `AzureLocal/platform/.github/workflows/reusable-mkdocs-deploy.yml@<ref>` — never `.github` — because docs deployment is stack-specific by definition. |
| 40 | + |
| 41 | +### Negative |
| 42 | + |
| 43 | +- **Two repos to track for workflow versions.** Consumers pin two refs separately (`@v1` for `.github`, `@v1` for `platform`). Mitigated by documenting the canonical pin patterns in [`docs/reusable-workflows/consumer-patterns.md`](../docs/reusable-workflows/consumer-patterns.md). |
| 44 | +- **Edge cases require a judgement.** When a workflow blurs the governance/stack line, the corollary in §Decision applies — but applying it correctly requires the maintainer to think carefully. ADR doesn't remove the judgement, only makes it consistent. |
| 45 | +- **Two ADR-required surfaces.** Adding a new reusable workflow to either repo now requires an ADR. Documented overhead, accepted as the cost of explicit decisions. |
| 46 | + |
| 47 | +### Neutral |
| 48 | + |
| 49 | +- The current lineup (`reusable-add-to-project`, `reusable-release-please`, `reusable-validate-structure` in `.github`; the six `reusable-*` workflows in `platform`) already follows the rule. This ADR codifies the existing state, no migration required. |
| 50 | + |
| 51 | +### Affected repos / owners |
| 52 | + |
| 53 | +- **`AzureLocal/.github`**: no change today. Future governance workflows land here. |
| 54 | +- **`AzureLocal/platform`**: no change today. Future stack-specific workflows land here. |
| 55 | +- **All consumer repos**: no change today. Already pin against the correct repos per the rule. |
| 56 | +- **Maintainer**: every new reusable workflow proposal should cite this ADR and state which side of the rule it falls on. |
| 57 | + |
| 58 | +## Alternatives considered |
| 59 | + |
| 60 | +- **Single repo for all reusable workflows** — rejected. Discovery and blast-radius arguments above. The cost of a second repo (already paid — both repos exist) is lower than the cost of mixing governance and stack content. |
| 61 | +- **Per-stack repos** (`AzureLocal/ps-workflows`, `AzureLocal/ts-workflows`, etc.) — rejected. Would multiply the number of repos a consumer pins and the number of major-version axes to track. The current two-repo split is the minimum viable separation. |
| 62 | +- **Live in the consumer repos themselves; share via copy-paste** — rejected. This is the drift problem [ADR-0001](./0001-create-platform-repo.md) and [ADR-0002](./0002-standards-single-source.md) already solved for standards. Rejected on the same grounds. |
| 63 | +- **Keep the rule informal in `docs/reusable-workflows/split-rule.md` only** — rejected. Without an ADR the rule is a documentation note, not a governing decision. ADR makes it citable and reviewable. |
| 64 | + |
| 65 | +## Status |
| 66 | + |
| 67 | +Accepted 2026-04-13. Supersedes the "ADR 0004 — reusable-workflow-split" placeholder referenced in [ADR-0001](./0001-create-platform-repo.md). (ADR-0004 was repurposed for testing-toolset classification.) |
| 68 | + |
| 69 | +The rule is also documented in user-facing form at [`docs/reusable-workflows/split-rule.md`](../docs/reusable-workflows/split-rule.md). When the ADR and the docs page diverge, this ADR wins; update the docs page accordingly. |
0 commit comments