ingestr v1.1.50 - Immutable GitHub Release Attestations


ingestr v1.1.50 was published on 8 September 2026. The release notes contain one item, pull request 1173: publish the five platform archives as one immutable GitHub release and let GitHub attest that release. Ingestion behavior is absent from the notes. The pull request says CDC code and tests are unchanged.

The full release notes and downloads are on the GitHub release page. The compare from the previous tag is v1.1.49 to v1.1.50. This tag is not a prerelease.

Most of the diff is .github/workflows/release.yml. In .goreleaser.yaml the release block is draft: true and make_latest: false. Darwin and Linux still call goreleaser/goreleaser-cross-pro:v1.23 with release --clean --split --verbose. Windows still runs GoReleaser with release --clean --split. The caches of dist/darwin and dist/linux are gone. Each prepare job uploads artifacts for github.run_attempt and sets if-no-files-found: error.

publish-release creates the GitHub release. Default permissions are contents: read. Only this job sets contents: write. It downloads archives-*-${{ github.run_attempt }} with merge-multiple: true. It checks that the repository is bruin-data/ingestr and that the tag resolves to GITHUB_SHA. Then it runs gh release create with --verify-tag, --latest, --title, and --generate-notes. The five files are ingestr_Darwin_x86_64.tar.gz, ingestr_Darwin_arm64.tar.gz, ingestr_Linux_x86_64.tar.gz, ingestr_Linux_arm64.tar.gz, and ingestr_Windows_x86_64.zip. The CLI uploads them to an internal draft, then publishes once. GitHub attests the release when immutability is enabled. No custom signing script, manifest, bundle, attestation action, or checksum file is published.

release-unix (goreleaser continue --merge), the Windows svenstaro/upload-release-action upload, and the final softprops/action-gh-release latest flip are gone. Concurrency is release-${{ github.ref }} with cancel-in-progress: false.

The release page labels v1.1.50 immutable. Only the title and notes can change. The workflow file does not enable that repo flag. The pull request recorded a 403 from the settings endpoint during review, so confirm the flag outside the YAML.

preflight allows only ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$. The trigger is v*, which is wider. v1.2.3-rc1 and a two part tag start the run and then fail the regex. Preflight also lists releases, drafts included, and exits when the tag is already present. The text is Release already exists; use a new version or explicitly recover the unpublished draft.

smoke-archives runs after the three prepare jobs. It extracts each archive on a native runner and requires --version to equal ingestr version plus the tag, with carriage returns stripped. The pairs are ingestr_Linux_x86_64.tar.gz on ubuntu-24.04, ingestr_Linux_arm64.tar.gz on ubuntu-24.04-arm, ingestr_Darwin_x86_64.tar.gz on macos-15-intel, ingestr_Darwin_arm64.tar.gz on macos-15, and ingestr_Windows_x86_64.zip on windows-2022.

publish-release waits on smoke-archives, integration-tests, and docker-test. Integration tests still run make for test-full, test-integration, and test-integration-nodocker, with TEST_CONCURRENCY set to 1, and they now wait on preflight. The image test on depot-ubuntu-latest and ubuntu-24.04-arm used to ignore the text of ingestr --version. It now requires the version string. A failed image test blocks the GitHub release. It does not unpush the image: docker-build pushes ghcr.io/bruin-data/ingestr before docker-test runs.

Installer jobs stay after publication because they need a public URL. Linux and Windows still allow 3 attempts, sleeping attempt * 15 seconds between tries, and they now require the same version string. They do not block release-pip.

After create, the same step runs gh release verify and gh release verify-asset on each local archive. The script uses set -euo pipefail. A failure fails publish-release, which skips the wheel job and both installers. The release is already public and already latest. docs/release-signing.md says to investigate rather than republish that tag.

A passing verify shows membership in that immutable release. It does not name the build workflow, and it does not prove a rebuild from source. Older mutable tags do not gain attestations later. Nothing in this publish replaces a checksum file. The doc says not to fall back to an unsigned checksum or to latest.

The digest embed in release-pip is the previous logic, now gated on publish-release instead of the old upload jobs. It reads release asset metadata, keeps names that start with ingestr_ and end in .tar.gz or .zip, requires a sha256: digest, and writes ARCHIVE_SHA256 into ingestr/_checksums.py. That file is for the Python package. It is not a client running gh release verify. Consumer attestation checks, a trusted verifier bootstrap, and the public installer are left for later.

The pull request reports make format, make lint, make test, and actionlint (Depot runner labels excluded). A mock published five archives and verified five. That text says a live immutable publish had not run yet.

The sample in docs/release-signing.md uses a placeholder tag. For this release, use v1.1.50.

TAG=v1.2.3 # the exact user-requested version
gh release verify "$TAG" --repo bruin-data/ingestr
gh release verify-asset "$TAG" ./ingestr_Linux_x86_64.tar.gz --repo bruin-data/ingestr

Treat v1.1.50 as frozen. Do not replace ingestr_Linux_x86_64.tar.gz or the other four archives. Cut a new version. If verify fails after create, preflight rejects a rerun because the release exists. Rerun only when publish never happened. A leftover draft must be recovered, or you move to a new version.

release-pip is skipped when publish-release fails. An installer failure does not skip the wheel. Both installer jobs depend only on publish, so a bad install script can sit beside a published wheel. v1.2.3-rc1 matches v* and dies in preflight.