# Releasing Open Print

An Open Print release is a small collection of files that another person can
inspect without trusting the machine that built them. The package tarball is
the main artifact. It travels with a dependency inventory, a plain JSON
manifest, and SHA-256 checksums.

The local commands in this guide do not publish anything. Pushing a release tag
runs the GitHub workflow and creates a draft release. A person still has to
review and publish that draft.

## Before making a tag

Use Node.js 22 and Python 3.9 or newer. Start from a clean checkout, make sure
the package version and changelog agree, then run:

```bash
npm ci
npm run check
npm run release:verify
npm run release:artifacts
```

`release:verify` copies the release sources into two temporary directories. It
installs the locked dependencies in each directory, builds both packages, and
compares every shipped file and the final tarball byte for byte. Temporary
directories are removed when it finishes.

`release:artifacts` replaces the ignored local `release/` directory with:

- `open-print-core-<version>.tgz`, the installable npm package;
- `open-print-core-<version>.sbom.cdx.json`, a CycloneDX inventory of runtime
  dependencies;
- `RELEASE-MANIFEST.json`, which ties the package version and files to a source
  commit;
- `SHA256SUMS`, which covers the tarball, SBOM, and manifest.

The SBOM generator normally adds a fresh UUID and timestamp on every run. Open
Print removes those two run-specific fields and sorts JSON object keys. The
dependency names, versions, licenses, package URLs, and hashes are left intact.
The manifest labels a local build as `dirty` when the checkout contains changes
that are not in its recorded commit. CI refuses to build release artifacts from
such a checkout.

Inspect the tarball before tagging:

```bash
npm pack --dry-run
cd release
shasum -a 256 --check SHA256SUMS
```

## Make the release tag

Release tags must be annotated and signed. For version `1.0.0`, the normal
sequence is:

```bash
git tag -s v1.0.0 -m "Open Print 1.0.0"
git push origin HEAD
git push origin v1.0.0
```

The workflow checks that GitHub recognizes the tag signature and that the tag
points to the commit being built. A lightweight tag or an unverified signature
stops the release.

## What CI does

The tag workflow repeats the tests and reproducibility check on a clean Linux
runner. It creates the four release files, checks their digests, and asks
GitHub to sign two attestations: build provenance for the tarball and a
CycloneDX SBOM attestation for that same tarball. It then saves the files as a
workflow artifact and opens a draft GitHub release.

Artifact attestations are available to public repositories on current GitHub
plans. A private repository needs a GitHub plan that supports private artifact
attestations. Open Print should be public before its first public release.

Nothing in this workflow runs `npm publish`. Registry publication should only
be added after the package name and maintainers are settled, using npm's
trusted publishing or provenance support from CI rather than a long-lived
token on a developer machine.

## Review and publish

Download the workflow artifact or draft-release assets and check them on a
second machine:

```bash
cd release
shasum -a 256 --check SHA256SUMS
gh attestation verify open-print-core-1.0.0.tgz \
  --repo OWNER/open-print
```

Also open the SBOM and confirm that every runtime dependency is expected. Once
the security review is complete and the draft contains the exact files that
were reviewed, publish the GitHub release manually. Enable GitHub's immutable
release setting before the final `1.0.0` release so the published tag and
assets cannot be replaced later.

If any file changes after the tag, delete the draft, fix the source, bump the
version, and make a new signed tag. Do not reuse a release tag.
