This document describes the CI/CD pipelines and release process for the Kosli CLI.
Runs on every push to every branch:
- Test — lint (golangci-lint), integration tests (full suite), Snyk code and dependency scans
- Docker — builds and pushes
ghcr.io/kosli-dev/cli:<short-sha>(linux/amd64 only), runs Snyk container scan and smoke test - Kosli trail — attestations are reported to the
cliflow (onmainand tags only) - Slack — notifies
#ci-failureson failure (main branch only)
Triggers when files under docs.kosli.com/ change on main (excluding content/client_reference/ and content/helm/):
- Copies the
docs.kosli.com/directory to thedocs-mainbranch usinggit-publish-subdir-action - Preserves generated CLI reference docs and
metadata.jsonfrom the last release (via.clear-files)
Triggers when files under charts/ change on main:
- Lints the Helm chart
- Generates Helm docs (README + docs site content)
- Packages and uploads the chart to the S3-hosted Helm repo (
charts.kosli.com) - Opens a PR to merge the generated Helm docs back into
main
Manually triggered from any branch — deploys docs to staging-docs--kosli-docs.netlify.app for preview.
Run:
make releasePrerequisites:
You need:
- jq, curl installed.
- An Anthropic API key, provided in one of the following ways:
- Via 1Password: The 1Password CLI (
op), access to the shared vault, and the 1Password desktop app linked to the CLI soopcan read secrets. In the 1Password app: Settings → Developer → Integrate with 1Password CLI. See Turn on the 1Password desktop app integration. - Via environment variable: Set
ANTHROPIC_API_KEYdirectly in your environment (no 1Password required).
- Via 1Password: The 1Password CLI (
What happens:
- A script uses Claude to suggest the next semver and draft release notes from the git diff (no commit messages). It reads the API key from 1Password via
opusing a default secret reference (vault/item/field); you can override withOP_ANTHROPIC_API_KEY_REFif your item lives elsewhere. - You see the suggested tag and release notes. You can press Enter to open your editor and edit
dist/release_notes.md, or Enter to skip. - You are prompted: Create tag vX.Y.Z and push? [y/N]. On y, an annotated tag is created with the release notes as the tag body and pushed. The
release.ymlworkflow runs on GitHub; it reads the notes from the tag body and passes them to GoReleaser for the GitHub Release. On n, nothing is pushed.
If you don’t want the AI flow (e.g. 1Password/op not available or the suggest step failed), run:
make release tag=v2.x.yThis checks the branch is up to date, creates an annotated tag (using dist/release_notes.md as the tag body if that file exists, otherwise the version string), and pushes it. No prompt. The release workflow runs as above; if the tag has no body, GoReleaser uses its default changelog on the GitHub Release.
Extracts the tag version and prepares Kosli trail metadata.
Creates a trail on the cli-release flow with the release version as the trail name.
Verifies the "never alone" policy — ensures commits had peer review.
Full test suite (same as the main pipeline): lint, integration tests, Snyk code and dependency scans.
Builds multi-platform binaries (darwin/linux/windows x amd64/arm64/arm) and creates a GitHub Release with:
- Archive files (
.tar.gz,.zipfor Windows) - Linux packages (
.deb,.rpm) - Publishes packages to Gemfury (
push.fury.io/kosli/)
For each binary artifact:
- Generates GitHub Sigstore build provenance attestation
- Generates SBOM (both SPDX and CycloneDX formats)
- Reports artifact + SBOM attestations to Kosli
Builds and pushes ghcr.io/kosli-dev/cli:<tag> (linux/amd64 + linux/arm64):
- GitHub Sigstore build provenance attestation
- SBOM generation and attestation
- Snyk container scan
- Smoke test (verifies the image can connect to Kosli)
- All results attested to Kosli
Opens a PR to Homebrew/homebrew-core to update the kosli-cli formula (skipped for pre-releases).
- Runs
make legacy-ref-docsthenmake cli-docsto generate CLI reference markdown - Writes
metadata.jsonwith the release version - Pushes the full
docs.kosli.com/directory to thedocs-mainbranch (no.clear-files— replaces everything)
Triggers downstream repository workflows to update:
kosli-dev/terraform-aws-evidence-reporter— evidence reporter Lambda packagekosli-dev/terraform-aws-kosli-reporter— environment reporter package- Uploads a new CLI Lambda layer to AWS
Sends a Slack notification to #ci-failures if any job fails.
Tags containing a hyphen (e.g., v2.12.0-rc1) are treated as pre-releases:
- The Homebrew formula PR is skipped
- GoReleaser marks the GitHub Release as a pre-release
The docs site is served from the docs-main branch (likely via Netlify). Content reaches that branch through two paths:
- Static content — pushed on every merge to
mainthat touchesdocs.kosli.com/(preserving generated files) - Generated CLI reference + version metadata — pushed only during a release (full replacement)
make hugo # Build CLI docs + Helm docs + run Hugo dev server (port 1515)
make hugo-local # Build CLI docs only + run Hugo dev server (port 1515)
make cli-docs # Regenerate CLI reference markdown from the built binary
make helm-docs # Regenerate Helm chart docs
make check-links # Build site and check for broken links