repomatic.release.attestation module

Naming and packing of the sigstore bundles attached to a release.

actions/attest writes every bundle to the same attestation.json basename, whatever it signed, so each release job has to rename its own before the files land in one directory. Three of them did, three different ways: the compiled binaries appended the suffix to the full filename, the man-page tarball dropped its .tar.gz first, and the consumer-declared extra assets were named after the job rather than any file. A release page therefore carried repomatic-manpages.attestation.json next to repomatic-manpages.tar.gz, and repomatic-extra-assets.attestation.json next to repomatic-claude-plugin.zip.

This module holds the one rule instead: a bundle is named after the artifact it attests. The subject list is read back out of the bundle rather than passed in, so the name is derived from what was actually signed and no caller can spell it differently. See bundle_filename() for the multi-subject case.

Note

The signing itself stays in actions/attest: it needs the job’s OIDC token, so it cannot move here. This module runs immediately after it, in the same job.

repomatic.release.attestation.ATTESTATION_SUFFIX: Final[str] = '.attestation.json'

Extension carried by every attestation bundle attached to a release.

Not .sigstore.json (the ecosystem’s own convention) because these files have been published under this name since the first attested release, and a release asset name is part of the surface users script against.

repomatic.release.attestation.bundle_subjects(bundle_path)[source]

Filenames of the artifacts a sigstore bundle attests.

A bundle wraps a DSSE envelope whose base64 payload is an in-toto Statement, and that statement’s subject array names every file signed in the same call. One entry for a single subject-path, several when actions/attest was handed a glob: “If multiple subjects are being attested at the same time, a single attestation will be created with references to each of the supplied subjects.”

Parameters:

bundle_path (Path) – The bundle actions/attest wrote.

Return type:

tuple[str, ...]

Returns:

Subject filenames, in the order the statement lists them.

Raises:

ValueError – If the file is not a bundle carrying a readable in-toto statement, or names a subject that is not a bare filename.

repomatic.release.attestation.bundle_filename(subjects, set_name=None)[source]

Name a bundle after the artifact it attests.

A single subject gives the bundle its own name, suffix appended to the whole filename so the two sort together on a release page listing assets alphabetically (papaya.tar.gz, then papaya.tar.gz.attestation.json).

Several subjects have no such name to borrow, since one bundle covers them all, so set_name is required and should describe the set rather than any member of it. That case only arises when a job hands actions/attest a glob.

Parameters:
Return type:

str

Returns:

The bundle’s filename.

Raises:

ValueError – If subjects is empty, or holds several entries with no set_name to fall back on.

repomatic.release.attestation.pack_attestation(bundle_path, asset_dir, set_name=None)[source]

Name a bundle after its subject and print what to upload with it.

Copies bundle_path into asset_dir under the name bundle_filename() derives, then returns that bundle alongside every artifact it attests, which is exactly the file list the release upload step has to attach for the provenance to be verifiable offline.

Every subject must already sit in asset_dir: a bundle naming a file that is not there means the job attested a different tree than the one it is about to upload, which would publish an asset whose sidecar covers something else. Immutable releases make that unfixable after the fact, so it fails here instead.

Idempotent: re-running copies the same bytes over the same name.

Parameters:
  • bundle_path (Path) – The bundle actions/attest wrote.

  • asset_dir (Path) – Directory holding the attested artifacts.

  • set_name (str | None) – Stem for the multi-subject case, see bundle_filename().

Return type:

list[Path]

Returns:

Sorted paths to upload, the renamed bundle included.

Raises:

ValueError – If a subject is missing from asset_dir.