Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The required behaviors, organized by domain. Each is a **MUST**, and its `Output

`GOVERNANCE.md` "Workflow YAML Conventions" names the tool D9.1 excepts and states the suffix rules D9.2 requires.

- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a version comment (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin.
- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a comment naming the release tag at that SHA, spelled as the referenced repository publishes it (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin, `$/` being GitHub's syntax, in a workflow file, for a path in the repository holding that file, resolved at that file's own commit.
- **D9.2** File/workflow/job/step names follow the suffix rules. A ruleset-bound job's `name:` equals its ruleset `context:` (renamed together).
- **D9.3** Multi-line bash `run:` blocks start `set -Eeuo pipefail`. Multi-line `if:` uses `>-`.
- **D9.4** Docker layer cache targets a registry tag, not `type=gha`. `cache-to` writes only the built branch's `<repo>:buildcache-<branch>` and only on push, while `cache-from` reads both branches. A multi-image repo varies the cache **repository** rather than the tag, `<image>:buildcache-<branch>` per image, the tag alone being unable to distinguish two images.
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
c73871a551034ae2
4fd3a739a2fc09e2
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The required behaviors, organized by domain. Each is a **MUST**, and its `Output

`GOVERNANCE.md` "Workflow YAML Conventions" names the tool D9.1 excepts and states the suffix rules D9.2 requires.

- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a version comment (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin.
- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a comment naming the release tag at that SHA, spelled as the referenced repository publishes it (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin, `$/` being GitHub's syntax, in a workflow file, for a path in the repository holding that file, resolved at that file's own commit.
- **D9.2** File/workflow/job/step names follow the suffix rules. A ruleset-bound job's `name:` equals its ruleset `context:` (renamed together).
- **D9.3** Multi-line bash `run:` blocks start `set -Eeuo pipefail`. Multi-line `if:` uses `>-`.
- **D9.4** Docker layer cache targets a registry tag, not `type=gha`. `cache-to` writes only the built branch's `<repo>:buildcache-<branch>` and only on push, while `cache-from` reads both branches. A multi-image repo varies the cache **repository** rather than the tag, `<image>:buildcache-<branch>` per image, the tag alone being unable to distinguish two images.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The required behaviors, organized by domain. Each is a **MUST**, and its `Output

`GOVERNANCE.md` "Workflow YAML Conventions" names the tool D9.1 excepts and states the suffix rules D9.2 requires.

- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a version comment (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin.
- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a comment naming the release tag at that SHA, spelled as the referenced repository publishes it (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin, `$/` being GitHub's syntax, in a workflow file, for a path in the repository holding that file, resolved at that file's own commit.
- **D9.2** File/workflow/job/step names follow the suffix rules. A ruleset-bound job's `name:` equals its ruleset `context:` (renamed together).
- **D9.3** Multi-line bash `run:` blocks start `set -Eeuo pipefail`. Multi-line `if:` uses `>-`.
- **D9.4** Docker layer cache targets a registry tag, not `type=gha`. `cache-to` writes only the built branch's `<repo>:buildcache-<branch>` and only on push, while `cache-from` reads both branches. A multi-image repo varies the cache **repository** rather than the tag, `<image>:buildcache-<branch>` per image, the tag alone being unable to distinguish two images.
Expand Down
2 changes: 1 addition & 1 deletion GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ These conventions bind every workflow. Several of them [`WORKFLOW.md`](./WORKFLO

An overlap with `WORKFLOW.md` resolves **by subject**, never by blanket precedence. This section keeps the full style rules and wins on them, stating each in more detail than the guarantee that carries it, while `WORKFLOW.md` wins on the architecture, the contract, and the test methodology. `WORKFLOW.md` section 2 points at this section rather than restating it. Throughout, a job is named by its id and a step by its `name:`. The `workflow-ci-contract` Skill at `.agents/skills/workflow-ci-contract/SKILL.md` in the hub, not a repo-relative link since that path is hub-local and not carried into every fleet repo, surfaces it.

- **Action pinning**: pin **every** action, first-party (`actions/*`) and third-party alike, to a commit SHA with a trailing `# vX.Y.Z` comment, so Renovate / Dependabot can still bump it but a tag swap can't change the executed code. This binds a `uses:` wherever it appears, in a workflow and in a composite action under `.github/actions/**` alike, except a local (`./`) or self-repository (`$/`) reference, which names no ref to pin. Use `# vX` (major-only) only when the upstream's floating major tag doesn't correspond to a specific patch/minor release SHA, since pinning to the floating-tag SHA still gives the SHA guarantee, the version comment just records the major line. Documented exception (no SHA pin at all): `dotnet/nbgv` is consumed via `@master` because the upstream tag stream lags `master` substantially and Dependabot's tag-tracking would propose a downgrade. **This applies to repo-owned build-layer leaves too**, since a leaf owning its build specifics is not a reason to use floating tags, and Dependabot still bumps SHA pins (updating the SHA + version comment).
- **Action pinning**: pin **every** action, first-party (`actions/*`) and third-party alike, to a commit SHA with a trailing comment naming the release tag at that SHA, so Renovate / Dependabot can still bump it but a tag swap can't change the executed code. The comment spells the tag exactly as the referenced repository publishes it, `# vX.Y.Z` where its tags carry a `v` and the bare tag, such as `# 1.4.2`, where they do not, so the comment never names a tag that does not exist. This binds a `uses:` wherever it appears, in a workflow and in a composite action under `.github/actions/**` alike, except a local (`./`) reference or a self-repository (`$/`) one, which names no ref to pin. In a workflow file, `$/` is GitHub's syntax for a path in the repository holding that file, resolved at that file's own commit. Use a major-only comment, `# vX` or the bare `# X` by the same spelling rule, only when the upstream's floating major tag doesn't correspond to a specific patch/minor release SHA, since pinning to the floating-tag SHA still gives the SHA guarantee, the version comment just records the major line. Documented exception (no SHA pin at all): `dotnet/nbgv` is consumed via `@master` because the upstream tag stream lags `master` substantially and Dependabot's tag-tracking would propose a downgrade. **This applies to repo-owned build-layer leaves too**, since a leaf owning its build specifics is not a reason to use floating tags, and Dependabot still bumps SHA pins (updating the SHA + version comment).
- **Filename**: a workflow declaring `on: workflow_call` ends in `-task.yml`, **whatever else it is also triggered by**, since that is the half the suffix is about. A workflow without `workflow_call` is an entry point (`push`, `pull_request`, `pull_request_target`, `schedule`, `workflow_dispatch`) and takes no `-task` suffix, ending instead with what it does: `-pull-request.yml`, `-release.yml`. The suffix says the file is meant to be `uses:`-d, which stays true of a file that is also dispatchable. Composite actions are named by their path (`.github/actions/<name>/action.yml`), so these suffix rules do not reach them.
- **Workflow `name:`** (the top-level `name:` field): a workflow declaring `workflow_call` takes a name ending in **"task"** (e.g. `Build project release task`), matching the filename rule above and covering a file that is also dispatchable, and every other workflow takes one ending in **"action"** (e.g. `Publish project release action`, `Test pull request action`). The suffix tells an orchestrator from a callee while reading the source tree, and on the runs list for an entry point. It does not do that in the Actions UI for a callee: a called reusable workflow's jobs appear nested inside the caller's run as `<caller job> / <callee job>`, and the runs list shows the caller's workflow name rather than the callee's own.
- **Job and step `name:` suffixes**: every job's `name:` ends in **"job"** and every step's `name:` ends in **"step"**, including the PR-gate aggregator, whose `name:` is a required-status-check `context:` in a branch ruleset (`Check pull request workflow status job` in `test-pull-request.yml`). A trailing parenthetical qualifier after the suffix is allowed and is the only exception (`Upload coverage to Codecov step (Python)`), and nothing enforces the rule mechanically. A ruleset-bound job's `name:` and its ruleset `context:` are the **same string**: rename them **together**, or required-status-check enforcement silently breaks. Every surface whose staleness breaks that enforcement moves in the same change, never one without the others. In a repository the surfaces are the live ruleset and its own workflow. A rename of the fleet-wide string additionally moves the hub's `repo-config/` payloads, its `spec/files.json` `requiredCheckName`, and each adopter-facing stub in its `catalog/` and `docs/reusable-workflows.md`, which exist only in the hub. Prose naming the old string goes stale rather than breaking, and follows behind.
Expand Down
2 changes: 1 addition & 1 deletion WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ The required behaviors, organized by domain. Each is a **MUST**, and its `Output

`GOVERNANCE.md` "Workflow YAML Conventions" names the tool D9.1 excepts and states the suffix rules D9.2 requires.

- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a version comment (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin.
- **D9.1** Every action or reusable workflow referenced from another repository is SHA-pinned with a comment naming the release tag at that SHA, spelled as the referenced repository publishes it (sole exception: the documented lagging-tag tool). A local (`./`) or self-repository (`$/`) reference names no ref and takes no pin, `$/` being GitHub's syntax, in a workflow file, for a path in the repository holding that file, resolved at that file's own commit.
- **D9.2** File/workflow/job/step names follow the suffix rules. A ruleset-bound job's `name:` equals its ruleset `context:` (renamed together).
- **D9.3** Multi-line bash `run:` blocks start `set -Eeuo pipefail`. Multi-line `if:` uses `>-`.
- **D9.4** Docker layer cache targets a registry tag, not `type=gha`. `cache-to` writes only the built branch's `<repo>:buildcache-<branch>` and only on push, while `cache-from` reads both branches. A multi-image repo varies the cache **repository** rather than the tag, `<image>:buildcache-<branch>` per image, the tag alone being unable to distinguish two images.
Expand Down
2 changes: 1 addition & 1 deletion scripts/tests/test_prose_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,7 @@ def test_css_has_block_comments_only(self) -> None:
self.assertEqual(["comment-wrap"], self.flag("a.css", "/* One thing. Another thing. */\n"))

def test_a_version_pin_is_machinery_rather_than_prose(self) -> None:
"""The action-pinning rule requires a trailing `# vX.Y.Z`, which is a label, not a sentence."""
"""The action-pinning rule requires a trailing release-tag comment such as `# vX.Y.Z`, which is a label, not a sentence."""
self.assertEqual([], self.flag("a.yml", " uses: x@sha # v7.0.0\n"))
self.assertEqual([], self.flag("a.yml", " uses: x@sha # v3\n"))

Expand Down
Loading