Release Process
skret uses Python Semantic Release (PSR) for automated versioning and GoReleaser for cross-platform binary builds.
How It Works
Section titled “How It Works”- Version bump – PSR analyzes commit messages (
feat:/fix:) to determine the next version - Tag creation – PSR creates a git tag (
v0.1.0) and updatesCHANGELOG.md - Binary build – GoReleaser builds binaries for all 6 platforms and publishes to GitHub Releases
- Package updates – Homebrew tap and Scoop bucket are updated automatically
Triggering a Release
Section titled “Triggering a Release”Releases are triggered via workflow_dispatch on the cd.yml workflow:
# Stable releasegh workflow run cd.yml -f release_type=stable
# Beta/prereleasegh workflow run cd.yml -f release_type=betaNever create tags manually. Always use the workflow.
Release Types
Section titled “Release Types”| Type | Version Example | Use Case |
|---|---|---|
| Stable | v0.2.0 |
Production-ready release |
| Beta | v0.3.0-beta.1 |
Testing before stable |
Beta to Stable Promotion
Section titled “Beta to Stable Promotion”- Release a beta:
gh workflow run cd.yml -f release_type=beta - Test the beta build
- If passing, release stable:
gh workflow run cd.yml -f release_type=stable
PSR automatically determines the version number from commits since the last release.
Commit Impact on Versions
Section titled “Commit Impact on Versions”| Commit Prefix | Version Bump |
|---|---|
fix: |
Patch (1.12.0 -> 1.12.1) |
feat: |
Minor (1.12.0 -> 1.13.0) |
semantic-release.toml sets major_on_zero = false, so unlike the PSR
default, this project never treated 0.x minor bumps as safe for breaking
changes – a breaking-change commit bumps the major version regardless
of whether the project is pre- or post-1.0. The project has been on v1.x
since early 2026; there is no active v0.x phase to describe.
CI/CD Pipeline
Section titled “CI/CD Pipeline”push to main -> ci.yml (lint, test, build)
workflow_dispatch (cd.yml: "release" job) -> PSR: analyze commits, bump version, update CHANGELOG, create + push tag -> cd.yml: "goreleaser" job (same run, needs: release) -> GoReleaser: build 6 binaries, create GitHub Release -> Docker: push ghcr.io/n24q02m/skret:<version> as one linux/amd64 + linux/arm64 manifest; :latest moves only on a stable release -> Homebrew: update tap formula -> Scoop: update bucket manifest -> Cosign: sign artifacts (keyless, GitHub OIDC) -> Syft: generate SBOM
(a raw `git tag vX.Y.Z && git push --tags` also triggers cd.yml's"goreleaser" job directly, without the "release" job -- recovery path,not routine use; see "Never create tags manually" above)Build Targets
Section titled “Build Targets”GoReleaser produces binaries for:
| OS | Architecture | Artifact |
|---|---|---|
| Linux | amd64 | skret_VERSION_linux_amd64.tar.gz |
| Linux | arm64 | skret_VERSION_linux_arm64.tar.gz |
| macOS | amd64 | skret_VERSION_darwin_amd64.tar.gz |
| macOS | arm64 | skret_VERSION_darwin_arm64.tar.gz |
| Windows | amd64 | skret_VERSION_windows_amd64.zip |
| Windows | arm64 | skret_VERSION_windows_arm64.zip |
The container image reuses the two Linux binaries above rather than rebuilding
them, so docker pull ghcr.io/n24q02m/skret resolves on both architectures.
CHANGELOG
Section titled “CHANGELOG”CHANGELOG.md is managed entirely by PSR. Do not edit it manually.
Each release entry includes:
- Version number and date
- Grouped changes under
feat:andfix:headings - Links to commits and compare URLs
CHANGELOG.md uses PSR’s update mode: new release sections are spliced in right below the
<!-- version list --> marker near the top of the file on every release. Do not remove that marker
— without it, PSR silently leaves the file unchanged (by design, not an error) instead of appending
new content. Do not switch to init mode either — that regenerates the whole file from full git
history on every run.
Verifying a Release
Section titled “Verifying a Release”After a release completes:
The signature covers checksums.txt, not each archive individually — .goreleaser.yaml
signs with artifacts: checksum. So verification is two steps: check the signature on
checksums.txt, then check your archive against that now-trusted file. There are no
per-archive .cert / .sig files to download; the one signature artifact is
checksums.txt.bundle.
# Check the latest releasegh release view --repo n24q02m/skret
# Download the archive plus the two files needed to verify itgh release download vVERSION --repo n24q02m/skret \ -p 'skret_VERSION_linux_amd64.tar.gz' -p 'checksums.txt' -p 'checksums.txt.bundle'
# 1. Verify the signature on checksums.txt.# The identity is the CD workflow at the ref it ran from, which differs between a# stable release (refs/tags/vVERSION) and a prerelease cut by workflow_dispatch# (refs/heads/main) -- the regexp below accepts either.cosign verify-blob \ --bundle checksums.txt.bundle \ --certificate-identity-regexp="https://github.com/n24q02m/skret" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ checksums.txt
# 2. Verify the archive against the checksums file you just proved authentic.# --ignore-missing skips the entries for artifacts you did not download.sha256sum --check --ignore-missing checksums.txt