feat(checks): oci-incompatible-version, for a version that cannot be an OCI tag #22

Merged
mikluko merged 1 commit from mikluko/octant/1725-oci-incompatible into mikluko/octant/1724-semver-compliance 2026-09-06 20:20:33 +00:00
mikluko commented 2026-09-06 20:14:34 +00:00 (Migrated from github.com)

Octant: T1725, on map D1726. Stacked on #21 — merge that first.

Build metadata is valid Semantic Versioning and cannot be an OCI tag. The specification permits 1.2.3+build.1; the OCI tag grammar is [a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}, which has no +. Git ref syntax does permit it, so such a version cuts a tag and is then not a name a registry takes.

Why a check and not a parser rule

parser        is this a version?               the specification decides
this check    can this version be an OCI tag?  the OCI grammar decides

The parser accepts strict SemVer with no exceptions, so the accepted set stays the specification's. A version that will not survive the journey is a finding about that version, not a malformed document.

The explanation rides on the check, so the reason arrives attached to the refusal — in -list-checks and in the generated README table — rather than in a paragraph a reader meets only by going looking.

What it actually checks

The grammar, not the one case. The length bound is checked too: a pre-release run has no bound in SemVer and a tag stops at 128 characters. The finding names the character or the length at fault:

version 1.2.0+build.7 cannot be an OCI tag: an OCI tag holds only letters,
digits, ".", "-" and "_", and this holds "+"

The first check whose subject is outside the document

The other seventeen are about the changelog or about the repository's tags. This one is about what a version can become somewhere else entirely, and the register's description says so rather than pretending otherwise. A repository that publishes no image or chart switches it off in off: and it never fires again — there is a test for exactly that, because the error default leans on it.

The two consequences the ticket asked me to carry

  • The corpus already had the build-metadata forms in its valid set — T1723 wrote it that way, so nothing moved.
  • The compliance section (#21) now names this check as where the action acts on the OCI grammar, keeping the citation and dropping nothing.

One existing test changed: TestLintBuildMetadataIsAReadableVersion asserted no findings at all for a build-metadata document. That was the coupling D1726 predicted — unreadable-version is still silent on it, and this check is what now has the opinion, so the test asserts the pair rather than silence.

Open, and yours: error or warning. Shipped at error per the ticket's own position, which inverts D1629's policy-defaults-to-off rule the same way undated-entry does. The ticket says to decide it rather than default to it, so say the word and I will change it.

Suite green, vet and gofmt clean, README regenerated, document reads valid=true. Eighteen checks.

Octant: [T1725](http://127.0.0.1:9876/T1725), on map [D1726](http://127.0.0.1:9876/D1726). **Stacked on #21** — merge that first. Build metadata is valid Semantic Versioning and cannot be an OCI tag. The specification permits `1.2.3+build.1`; the OCI tag grammar is `[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}`, which has no `+`. Git ref syntax *does* permit it, so such a version cuts a tag and is then not a name a registry takes. ## Why a check and not a parser rule ``` parser is this a version? the specification decides this check can this version be an OCI tag? the OCI grammar decides ``` The parser accepts strict SemVer with no exceptions, so the accepted set stays the specification's. A version that will not survive the journey is a finding *about that version*, not a malformed document. The explanation rides on the check, so the reason arrives attached to the refusal — in `-list-checks` and in the generated README table — rather than in a paragraph a reader meets only by going looking. ## What it actually checks The grammar, not the one case. The length bound is checked too: a pre-release run has no bound in SemVer and a tag stops at 128 characters. The finding names the character or the length at fault: ``` version 1.2.0+build.7 cannot be an OCI tag: an OCI tag holds only letters, digits, ".", "-" and "_", and this holds "+" ``` ## The first check whose subject is outside the document The other seventeen are about the changelog or about the repository's tags. This one is about what a version can become somewhere else entirely, and the register's description says so rather than pretending otherwise. A repository that publishes no image or chart switches it off in `off:` and it never fires again — there is a test for exactly that, because the `error` default leans on it. ## The two consequences the ticket asked me to carry - **The corpus** already had the build-metadata forms in its valid set — T1723 wrote it that way, so nothing moved. - **The compliance section** (#21) now names this check as where the action acts on the OCI grammar, keeping the citation and dropping nothing. One existing test changed: `TestLintBuildMetadataIsAReadableVersion` asserted *no* findings at all for a build-metadata document. That was the coupling D1726 predicted — `unreadable-version` is still silent on it, and this check is what now has the opinion, so the test asserts the pair rather than silence. **Open, and yours: `error` or `warning`.** Shipped at `error` per the ticket's own position, which inverts D1629's policy-defaults-to-off rule the same way `undated-entry` does. The ticket says to decide it rather than default to it, so say the word and I will change it. Suite green, `vet` and `gofmt` clean, README regenerated, document reads `valid=true`. Eighteen checks.
Sign in to join this conversation.
No description provided.