This guide describes CI for the markata-go product repository (issue #1487). For site-author deployments, use the [[ci-cd-guide|CI/CD guide]] instead. The policy is specified in CI.md.

Routine validation #

CI runs on pushes and pull requests targeting main/master, daily at 08:23 UTC, and through Actions → CI → Run workflow. Lint, all three Linux race/coverage shards, their aggregate Test (ubuntu-latest, 1.27) check, and macOS/Windows tests remain active. The CLI/search shard smoke-tests its existing binary with version and --help; there is no separate duplicate build.

Specialized checks use job-level changed-file filters on PRs and pushes:

Checks Inputs
Font completeness and determinism scripts/generate_font_manifests.py, internal/fontcatalog/** (catalog, lock, manifests, licenses, font assets), vendor/google-fonts/**
Rendering contract scripts/rendering-contract/**, spec/rendering-contract/**, pkg/renderingcontract/**, pkg/palettes/**, palettes/**, go.mod, go.sum
Helm helm-chart/**, including chart dependencies and chained test scripts
GoReleaser config .goreleaser.yml, go.mod, go.sum

Changes under .github/workflows/** select every specialized check. Scheduled and manual CI runs execute all specialized checks regardless of paths. Docs-only PRs still receive ordinary checks rather than skipping the entire workflow and potentially leaving required checks pending.

The detection job uses dorny/paths-filter@v3: PRs use the changed-files API, including fork PRs, while pushes compare against the previous push commit. Only this job gets pull-requests: read, alongside contents: read. If detection fails, do not interpret skipped specialized jobs as validation. When adding a generator dependency, update its filter in ci.yml.

Spec conformance manifest #

When adding a normative requirement, assign it a stable DOMAIN-NNN ID in spec/conformance/requirements.yaml. Record its specification file, scope, conformance status, and the implementation and test files that support it. Mark incomplete or intentionally different behavior as partial and explain it in notes.

Run go test ./pkg/specconformance to check IDs, allowed values, referenced files, and the evidence required for implemented status. The normal CI test suite runs the same check. See the conformance manifest guide for the field definitions and rollout plan.

Build Lab observation #

The expensive TestBuildLab_LinkedAndFixtureMutationsCharacterizeProduct logs product failures as observations. PR CLI validation skips that test while retaining focused regression tests. Main push and daily/manual CI include it.

For a focused rerun, select Actions → Build Lab characterization → Run workflow and the desired ref. This separate workflow is manual-only because daily CI already runs the observation; a second daily run would duplicate work. It retains harness race detection, but no longer writes unused coverage data. Its success does not mean that every logged product observation passed.

Docker preview publishing #

Minimal and builder images publish automatically only on main pushes and v* tags. Relevant PR changes still build and validate both images without publishing. Tagged builds retain amd64/arm64 images and Trivy scanning.

To publish a feature preview explicitly, select Actions → Docker → Run workflow and choose the feature branch in Use workflow from. Both images publish to GHCR with branch and sha- tags; feature previews do not receive latest. Use the SHA tag when a stable preview reference is needed. Manual dispatch on main follows the existing default-branch tagging policy, and dispatch on a version tag follows the existing semver/multiarch policy.

Performance comparisons #

The initial benchmark sample selects only BenchmarkBuild_EndToEnd and BenchmarkBuild_Incremental. Concurrency keeps its separate three-sample run. Profiling and stage-specific sampling remain unchanged.

For a comparison, manually run Performance Benchmarks with compare_branch. The current checkout remains available for Go version/module setup; its benchmark measurements come from the downloaded current-results artifact. Only the comparison checkout generates a fixture and executes comparison benchmarks. Fixture or benchmark failures fail the job instead of being hidden as a successful comparison.

Scope #

Release tests, signing, SBOM generation, action versions, and repository settings are unchanged. Required-check or remote workflow registry changes are separate maintainer operations, not part of these repository workflows.

The bundled markata-go-site skill was reviewed (entrypoint, build/deployment, and faster-build guidance). No update is needed: these changes govern product maintainer CI, not site-author commands, build behavior, deployment workflows, or benchmarking guidance.

Golangci-lint v2 on Go 1.27 #

Go 1.27 uses golangci-lint v2.15.0, rather than the older v1.64.8 tool which cannot decode the Go 1.27 compiler export format. The migrated .golangci.yml retains all existing configured linters.

The new v2 analyzers also surfaced hundreds of historical findings in untouched files. To keep meaningful merge protection while progressively resolving that debt (tracked in issue #1902), PR and push CI now rejects new findings relative to the PR base or previous main commit. Scheduled CI runs the same new-issue gate plus a full-tree lint audit that reports failures without blocking the daily build. The full audit is deliberately visible, not suppressed.

For local work, run just lint after fetching origin/main to enforce new findings, or just lint-full to inspect all existing diagnostics. just lint-fast uses the supported v2 --fast-only mode. Once issue #1902 is resolved, restoring blocking full-tree lint is the exit criterion.