Skip to content

0.13.0

Choose a tag to compare

@github-actions github-actions released this 01 Aug 13:51
Immutable release. Only release title and notes can be modified.
0.13.0
77cd5f0

Added

  • GitHub Code Quality is now a modelled tier instead of an unattached price
    tag.
    The product existed in the ledger as github-code-quality-transition
    and nowhere else: no capability, no tier doc, no mention in the tier tables —
    so the catalog priced a product it never told adopters how to place. It gets
    catalog/capabilities.yml entry github-code-quality and a tier doc,
    docs/16-code-quality.md.

    It is deliberately not folded into the public tier. Re-verification
    against the billing docs on 2026-08-01 established that visibility does not
    gate the licence: a public repository is billed the same per-active-committer
    rate as a private one, and being public only removes the Actions-minutes
    component. That contradicted docs/01-public-oss-free.md, which promised the
    "entire security and supply-chain suite for free" — a claim that would have
    been false for any adopter who enabled Code Quality on a public repo. The
    three-tier model sorts by visibility and plan; this product obeys neither, so
    it is documented as an orthogonal fourth tier and excluded from both free
    tiers, with the free maintainability substitutes (coverage-gate.yml,
    docs-quality.yml, pr-hygiene.yml, zizmor, the language packs) named
    explicitly.

    Two further billing facts are now recorded because they invert the usual
    cost-control instinct: committers are counted once per organization, so
    enabling one repository already bills the whole active-committer set and a
    "few paid repos, many free repos" split saves nothing unless the committer
    sets actually differ; and the licence is independent of Code Security and
    Secret Protection, so GHAS does not include it and holding both means paying
    two products to drive one CodeQL engine.

    The capability carries workflow: null and example: null, which is the
    honest shape rather than a gap: Code Quality has no Action, no workflow_call
    entrypoint, and no REST or GraphQL API, so enablement is UI-only and cannot be
    pinned by SHA, asserted, or drift-checked from CI. For the same reason the
    merge gate — ruleset rule "Require code quality results", severity threshold,
    check CodeQL - Code Quality — is documented as a UI procedure and not
    encoded in .github/rulesets/: those specs are shaped for
    POST /repos/{owner}/{repo}/rulesets and the rule-type identifier for this
    rule is undocumented. AGENTS.md records the gate so the next contributor does
    not re-derive it, replacing a stale instruction to "refresh that fact" on a
    date that has passed.

  • The library described GitHub's price list, not this estate's receipts.
    Every tier doc reasoned from what GitHub charges a hypothetical adopter, so a
    private NDDev repository was configured as if it were on the free plan while
    the organization was already paying for Enterprise Cloud, Code Security,
    Secret Protection, and Code Quality. docs/17-nddev-tier.md records the
    verified entitlements and the advice that consequently does not apply.

    The concrete loss this closes: docs/02-private-free.md routes private
    releases to release-supply-chain-free.yml because Artifact Attestations
    require Enterprise Cloud on private repos. This estate has Enterprise
    Cloud, so all 26 private repositories were emitting slsa_build_level: null
    and discarding provenance that was already bought. They can use the attested
    release-supply-chain.yml.

    Also recorded, because it inverts the usual cost instinct: these products bill
    per active committer counted once per organization, so with one committer
    the estate pays the same whether one repository or fifty are enabled — partial
    coverage would have cost identically and protected less. examples/nddev/
    joins the aggregate-example allowlist in validate_catalog.py, alongside the
    three existing per-tier security suites.

    The doc is explicit about what is absent too: Copilot Autofix is unavailable
    (Copilot Business provisioned, zero seats assigned), and SHA pinning is
    unenforced at both org and enterprise (sha_pinning_required: false) — flagged
    rather than recommended blindly, since enabling it org-wide would break any
    repository still pinning actions by tag.

Fixed

  • A grouped action bump could not land on its own. Dependabot updates the
    uses: pins inside the workflows but knows nothing about catalog/tools.yml,
    so validate_catalog.py failed on seven tools whose catalog pin no longer
    matched the workflow that used it, and validate_runtime_coverage.py failed
    because two workflow files changed after the run that proved them. Catalog
    pins and current_version synced for attest, checkout, setup-python,
    setup-go, setup-dotnet, labeler, and markdownlint-cli2-action.
    actionlint.yml is re-proven against the CI run that executed the new bytes —
    this repository's own ci.yml calls it through a relative ref, so the proof is
    real. release-supply-chain.yml is downgraded to static-only: nothing in
    this repository's CI calls it, so no run has executed the new bytes, and the
    ledger's rule is to downgrade rather than carry a stale proof. The next real
    release re-proves it.

  • The catalog recorded four action pins that no workflow used. setup-node,
    setup-java, setup-swift, and checkov-action had drifted a version behind
    the SHA their used_by workflows actually reference — setup-swift by a full
    major (v2.4.0 recorded, v3 shipped). validate_catalog.py checked only the
    pin's shape and that used_by paths existed, never that the pin matched
    reality, so the gate stayed green while the declared source of truth was wrong
    in four places. Pins synced and validate_catalog.py now fails when a
    catalog pin does not appear verbatim in each of its used_by workflows.

  • sql-ci.yml declared a python_version input that nothing read. It was
    the only never-read input across all reusables; the workflow has no
    setup-python step at all and provisions Python through setup-uv. A caller
    passing it got a silently ignored value. Input removed and the header comment
    corrected from "pinned setup-python" to "pinned setup-uv".

  • docs/12-community-dx.md listed five community-health files as still missing;
    all five have shipped. Only the optional .github/FUNDING.yml remains absent.

Added

  • Self-application of the public OSS security suite. This repository shipped
    CodeQL, OSSF Scorecard, Dependency Review, and gitleaks to the estate while
    consuming none of them itself; it self-applied only actionlint, zizmor,
    and release-supply-chain. New self workflows codeql.yml, gitleaks.yml,
    dependency-review.yml, and scorecard.yml call the matching reusables
    through relative refs, with triggers taken from this repository's own
    examples/public-oss/ shapes.

Fixed

  • SELF_WORKFLOWS was duplicated as a literal in three places.
    _workflow_yaml.py held the named constant while validate_catalog.py and
    generate_docs.py each hardcoded {"ci.yml", "release.yml"} again. Both now
    import it. With the constant honoured in only one of the three,
    validate_all.py passed while docs/generated/workflow-inventory.md listed
    the new self workflows as MISSING instead of internal — a green gate over
    wrong generated output.

  • Pinned tools installed into /usr/local/bin, which no correctly isolated
    self-hosted runner allows.
    actionlint.yml and osv-scan.yml placed their
    checksum-verified binaries in a system path. That works on GitHub-hosted
    runners, where the job user may write there, and fails outright on a
    self-hosted runner whose account is unprivileged:
    install: cannot create regular file '/usr/local/bin/actionlint': Permission denied.
    Found by routing a real private-repository job to a self-hosted runner. The
    privilege is not incidental — a runner that can write to system paths shares
    mutable state between jobs — so the destination moved rather than the runner's
    permissions: both now install into "${RUNNER_TEMP}/bin" and prepend it to
    GITHUB_PATH, which is writable on hosted and self-hosted alike and is torn
    down with the job. Checksum verification is unchanged. cpp-ci.yml still uses
    sudo apt-get; that is a different class (system packages, not one pinned
    binary) and remains hosted-only.

Documentation

  • No documented rule for which repositories run where. Private-repository
    minutes are metered and public ones are free, so the cost-optimal routing is
    private → self-hosted, public → GitHub-hosted. docs/05-runners.md gains
    Routing by visibility with that rule, the fork-PR reasoning that makes a
    self-hosted runner on a public repository a security defect rather than a
    saving, and an explicit statement that this repository is public and must
    never route itself to self-hosted or ship a self-hosted default in
    examples/.
  • Two runner settings are invisible to workflow files. CodeQL default
    setup
    and Code Quality scans are scheduled by GitHub, not by a workflow,
    and each carries its own runner control. Missing either leaves a repository
    consuming metered minutes while every caller says otherwise. Both are now
    documented with the exact API call and UI path.
  • AI findings were undocumented. docs/16-code-quality.md gains an
    AI findings section: they are metered separately from the per-committer
    licence with no included allowance (discountAmount: 0.00 on every
    billing line, $0.01/credit), and one repository burned 774.9 credits in about
    twelve days — roughly twice the licence that covers a whole organization. Also
    records why a product budget cannot fence this off, and that the switch is
    absent entirely where CodeQL finds no supported language.
  • docs/17-nddev-tier.md gains the verified per-line cost envelope and a runner
    routing summary, and corrects a stale claim: sha_pinning_required is now
    true at both org and enterprise level, not false.
  • New caller example examples/nddev/security-private-selfhosted.yml — the
    nddev suite with every job pinned to a self-hosted label.