Shared CI/CD for the cplieger repos: reusable GitHub Actions workflows,
composite actions, canonical lint/format configs, and a cross-repo governance
audit. One source of truth: consumer repos reference it instead of carrying
duplicate copies.
Pin every reusable-workflow reference to a full commit SHA with a release tag comment, e.g.
@<40-hex-sha> # v2. Renovate tracks the comment and bumps the SHA when the major tag moves. Never pin to a branch.
| Workflow | Purpose |
|---|---|
.github/workflows/ci.yaml |
Meta CI entry point: detects repo surfaces (go.mod / jsr.json / web dir / Dockerfile / scripts) and dispatches the jobs below into one ci / validate gate |
.github/workflows/go-ci.yaml |
Go checks: vet, golangci-lint, race tests, govulncheck, deadcode/punused (apps), wiregen drift, gitleaks |
.github/workflows/ts-ci.yaml |
TS checks: eslint, tsc typecheck, vitest, prettier, knip, version parity, import-map coverage (+ optional web-lint for CSS/HTML) |
.github/workflows/shell-ci.yaml |
Shell/Docker checks: actionlint, shellcheck, shfmt, hadolint, gitleaks |
.github/workflows/release.yaml |
Auto-detects release type (Docker / TS / Go), computes the git-cliff version, publishes (npm + JSR via OIDC), tags + GitHub Release |
.github/workflows/docker-release.yaml |
Multi-arch image build on native runners, Trivy scan, SBOM, cosign signing, release notes (called by release.yaml) |
.github/workflows/coverage.yaml |
Go/TS coverage → shields endpoint badge on the orphan badges branch |
.github/workflows/codeql.yaml |
CodeQL with language auto-detect (public repos) |
.github/workflows/security-scan.yaml |
Trivy repo/config/image scans, advisory only; findings report to the Security tab, never block |
Every other workflow in .github/workflows/ is repo-internal automation
(config sync, tag cutting, the weekly governance audit, scheduled
mutation/fuzz/security runs, staleness-gated image rebuilds, and this repo's
own CI), not for consumers.
Consumer repos do not hand-write these callers: sync.yaml pushes the
workflow templates (.github/workflow-templates/) into every releaseable repo
as PRs. The synced CI caller is a thin shim; all logic stays central:
# .github/workflows/ci.yaml (synced, DO NOT EDIT)
jobs:
ci:
uses: cplieger/ci/.github/workflows/ci.yaml@<sha> # v2# .github/workflows/release.yaml (synced, DO NOT EDIT)
jobs:
release:
uses: cplieger/ci/.github/workflows/release.yaml@<sha> # v2
secrets: inheritrelease.yaml takes no inputs: it auto-detects the release type from the repo
surface (Dockerfile → image, jsr.json → npm + JSR, go.mod → Go tag).
Publishing uses OIDC trusted publishing for npm and JSR (no registry
tokens); the package just needs to be linked to its repo on npmjs.com /
jsr.io. release.yaml declares the id-token: write permission itself.
The Renovate preset lives in cplieger/.github
as default.json, not in this repo. Each consumer repo carries a synced
one-liner renovate.json that extends it (Renovate fetches the preset
natively):
{ "extends": ["github>cplieger/.github"] }Tools without remote-config support get their config pushed to consumers as
PRs by sync.yaml:
| Source (this repo) | Synced to |
|---|---|
.editorconfig, .gitattributes, LICENSE, configs/renovate.json |
all releaseable repos |
.golangci.yaml, configs/gremlins.yaml (→ .gremlins.yaml) |
Go repos |
configs/eslint.config.base.mjs, configs/prettier.json, configs/stylelint.json, configs/htmlvalidate.json |
TS repos (incl. hybrids) |
configs/cliff-stable.toml / configs/cliff-alpha.toml (→ cliff.toml) |
releaseable repos, tier by latest tag (v0.x → alpha) |
configs/ruff.toml (→ ruff.toml) |
Python repos |
configs/image-smoke.sh (→ tests/image-smoke.sh) |
image repos opting in via tests/image-smoke.conf |
The unified-CI group also syncs six workflow files into each consumer repo:
ci.yaml, codeql.yml, security.yml, scorecard.yml, coverage.yml, and
release.yaml. scorecard.yml (OpenSSF Scorecard, self-contained) feeds the
README OpenSSF badge.
See BADGES.md for the canonical badge block per repo type (Go
lib, TS lib, hybrid, Docker image) and the badge principles. The badge row is
per-repo, not synced, because it carries per-repo URLs.
actions/git-cliff-version: installs git-cliff and outputsversion+ areleaseboolean from conventional commits. Used byrelease.yaml; callable directly.actions/publish-badge: writes a shields.io endpoint JSON to the orphanbadgesbranch, preserving sibling badge files. Used bycoverage.yaml,docker-release.yaml(image size), andweekly-gremlins.yaml(mutation score).
ci-local.sh [app-dir]: replays the CI battery locally (mirrors the gate).scripts/install-local-tools.sh: installs the CI-pinned tool versions locally so local lint/scan results match CI.
Issues and PRs are welcome. See CONTRIBUTING.md for the conventions and how to run the checks locally.
This project is built with care and follows security best practices, but it is intended for personal / self-hosted use. No guarantees of fitness for production environments. Use at your own risk.
This project was built with AI-assisted tooling using Claude, GPT, and Kiro. The human maintainer defines architecture, supervises implementation, and makes all final decisions.
GPL-3.0. See LICENSE.