GitHub Workflows
GitHub Workflows Documentation
This document provides an overview of all GitHub Actions workflows used in the kure project.
Last Updated: 2026-02-27
Workflow Summary
| Workflow | File | Triggers | Purpose |
|---|---|---|---|
| CI | ci.yml | push, PR, schedule, manual | Comprehensive testing, linting, building, security |
| Deploy Docs | deploy-docs.yml | push to main (docs paths), workflow_dispatch | Multi-version docs deployment |
| Manage Docs | manage-docs.yml | workflow_dispatch | Remove, rebuild, or re-point doc versions |
| Auto-Rebase | auto-rebase.yml | push to main | Rebase all open PRs when main is updated |
| Release | release.yml | version tags | GoReleaser-based release with versioned docs deploy |
| Create Release | release-create.yml | workflow_dispatch | Pre-release test gate + tag creation |
| PR Review | pr-review.yml | pull_request | Two-pass AI code review via ccproxy |
CI Workflow
File: .github/workflows/ci.yml
Name: CI
Triggers
- Push to:
main,develop,release/* - Pull requests to:
main,develop - Schedule: 4am UTC daily (catch external changes)
- Manual dispatch
Concurrency
Uses github.sha to avoid duplicate runs:
- Same commit won’t run CI twice (e.g., PR merge → push to main)
- Different commits run independently
concurrency:
group: ci-${{ github.sha }}
cancel-in-progress: falseJob Dependency Graph
┌─────────────────┐
│ lint │ ← Fast checks: go-version, fmt, tidy, vet, lint
└────────┬────────┘
│
┌────┴────┐
▼ ▼
┌───────┐ ┌───────────┐
│ test │ │ security │ ← Tests + govulncheck (parallel)
└───┬───┘ └───────────┘
│
▼
┌───────────────────┐
│ coverage-check │ ← 80% threshold enforcement
└─────────┬─────────┘
│
│
▼
┌───────┐
│ build │ ← Build artifacts
└───┬───┘
│
▼
┌─────────────────────┐
│ cross-platform │ ← Only on main/release branches
└─────────┬───────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ mirror-to-gitlab (main push only, after all checks) │
└─────────────────────────────────────────────────────────────┘
PR-only jobs (parallel, no blocking):
┌──────────────┐ ┌─────────────────┐ ┌────────────┐
│ rebase-check │ │ analyze-changes │ │ docs-check │
└──────────────┘ └─────────────────┘ └────────────┘Jobs Detail
| Job | Check Name | Timeout | Dependencies | Purpose |
|---|---|---|---|---|
validate | lint | 15 min | - | Go version check, fmt, tidy, vet, lint |
test | test | 15 min | validate | Unit tests, race tests, coverage |
security | Security | 10 min | validate | govulncheck, outdated deps, sensitive file check |
coverage-check | Coverage Check | 5 min | test | 80% threshold, Codecov upload, PR comment |
build | build | 10 min | coverage-check | Build kure, kurel, demo |
cross-platform | Cross-Platform Build | 15 min | build | linux/darwin/windows × amd64/arm64 (main/release only) |
rebase-check | rebase-check | 2 min | - | Verify PR branch is rebased on main (PR only) |
analyze-changes | Analyze Changes | 5 min | - | Changed files analysis, breaking change warnings (PR only) |
docs-build | docs-build | 10 min | - | Hugo build validation with versioned config overlay |
docs-check | Docs Check | 5 min | - | API changes need docs check (PR only) |
mirror-to-gitlab | Mirror to GitLab | 5 min | build, security, cross-platform, docs-build | Push main and tags to GitLab mirror; fails on divergence (main only) |
Configuration
- Go Version:
1.26.1 - Golangci-lint Version:
v2.10.1 - Coverage Threshold:
80% - Platforms:
linux/amd64,linux/arm64,darwin/amd64,darwin/arm64,windows/amd64
Features
- gotestfmt - Nice formatted test output
- Fail fast - Jobs depend on validate, so lint failure stops everything
- Artifact sharing - Coverage uploaded as artifact, reused by coverage-check
- PR comments - Coverage report comment on PRs
- Skip draft PRs -
if: github.event.pull_request.draft == false - Sensitive file check - Warn about potential secrets in code
- goimports - Installed as a tool dependency for the formatting check (
goimports -l) - Matrix fail-fast: false - Cross-platform builds continue if one fails
Release Workflow
File: .github/workflows/release.yml
Name: Release
Triggers
- Push tags:
v*(e.g., v1.0.0, v0.1.0-alpha.0)
Jobs
- test - Full test run with race detection
- validate - Strict tag format, changelog, and version progression validation
- goreleaser - Cross-platform builds using GoReleaser v2
- deploy-docs - Trigger versioned docs deployment (stable tags only)
- post-release - Go proxy refresh
Configuration
- Go Version:
1.26.1 - Build Tool: GoReleaser v2
- Platforms:
linux/amd64,linux/arm64,darwin/amd64,darwin/arm64,windows/amd64,windows/arm64 - Tag Format:
^v[0-9]+\.[0-9]+\.[0-9]+(-alpha\.[0-9]+|-beta\.[0-9]+|-rc\.[0-9]+)?$ - Changelog: Required (must have
## v0.1.0section)
CI Status Check
Release workflow verifies CI passed before releasing:
check-ci:
name: Verify CI passed
steps:
- name: Check CI status for this commit
run: |
# Wait up to 5 minutes for CI to complete
for i in {1..30}; do
STATUS=$(gh api repos/.../commits/$COMMIT_SHA/status --jq '.state')
if [ "$STATUS" = "success" ]; then exit 0; fi
if [ "$STATUS" = "failure" ]; then exit 1; fi
sleep 10
doneRelease Management
# Preview release plan locally (dry-run)
make release TYPE=alpha
# Create release via CI:
# Actions > "Create Release" > type=alpha > Run workflowCreate Release Workflow
File: .github/workflows/release-create.yml
Name: Create Release
Triggers
- Manual dispatch with inputs:
type(alpha/beta/rc/stable/bump),scope(minor/major),dry_run
Pre-release Test Gate
The workflow runs a full test suite (with race detection) before creating the tag. This prevents tags from being pushed when tests fail.
workflow_dispatch
→ test job (go test -race ./...)
→ release job (needs: test)
→ release.sh → creates tag + pushes
→ triggers release.yml (tag push)If the pre-release test fails, the release job never runs and no tag is created.
Jobs
- test — Full test run with race detection and CGO enabled (
build-essential+CGO_ENABLED=1) - release — Runs
scripts/release.shto generate changelog, commit, create tag, and push
Authentication
Uses a GitHub App token (RELEASE_APP_ID + RELEASE_APP_PRIVATE_KEY) so that the tag push triggers subsequent workflows (tag-triggered release.yml).
Auto-Rebase Workflow
File: .github/workflows/auto-rebase.yml
Name: Auto-Rebase
Triggers
- Push to
main(runs after every merge to main)
Purpose
Automatically rebases all open PRs targeting main when main is updated. This mirrors the GitLab auto-rebase CI template used in other Wharf repositories.
How It Works
Uses peter-evans/rebase@v4
to:
- Find all open PRs targeting
main - Rebase each PR branch onto the latest
main - Force-push the rebased branch (triggers CI re-run)
- Skip PRs with conflicts (reports them without failing)
Configuration
- Excluded labels:
dependencies(Dependabot manages its own branches) - Excluded drafts: yes (no point rebasing work-in-progress)
- Fork protection: only runs on
go-kure/kure(forks lack the required secret) - Concurrency:
cancel-in-progress: true(newer main state supersedes)
Authentication
Requires AUTO_REBASE_PAT repository secret — a fine-grained PAT with:
- Repository:
go-kure/kureonly - Permissions:
Contents: Read+Write,Pull requests: Read
A PAT is required because pushes made with GITHUB_TOKEN do not trigger subsequent workflow runs. The PAT ensures CI re-runs on rebased branches.
PR Review Workflow
File: .github/workflows/pr-review.yml
Name: PR Review
Triggers
- Pull requests:
opened,synchronize,ready_for_review,reopened - Skips draft PRs and fork PRs (self-hosted runner security)
How It Works
Uses a two-pass AI review system via ccproxy (ported from the GitLab mr-review.yml template):
Pass 1 — Review: Sends the PR diff + project context (
AGENTS.md,.claude/CLAUDE.md) to the review model (default:gpt-5.3-codex). Anti-hallucination rules prevent the model from inventing standards or referencing code not in the diff. The model returns up to 3 findings ranked by severity in a structured table. Posted as a PR comment.Pass 2 — Assessment: If the review found issues (not LGTM), sends the review + diff to an assessment model (default:
claude-sonnet-4-6) which fact-checks each finding against the actual diff and project context. Includes standards verification — claims about “standards violations” are checked against actually-provided standards. Catches hallucinations and false positives. Posted as a second PR comment.
Requirements
- Self-hosted runner: Runs on
autops-kubelabel (ARC runner with in-cluster access) - ccproxy: Reachable at
http://openclaw-ccproxy.openclaw.svc:8000from the runner pod - No API keys needed: ccproxy handles model authentication
Configuration
Configurable via repository variables or workflow env defaults:
| Variable | Default | Purpose |
|---|---|---|
PR_REVIEW_MODEL | gpt-5.3-codex | Model for code review pass |
PR_REVIEW_MAX_DIFF_CHARS | 50000 | Truncation threshold for large diffs |
PR_REVIEW_MAX_TOKENS | 1500 | Max response tokens for review |
PR_REVIEW_CONTEXT | kure project description | Additional system prompt context |
PR_REVIEW_ASSESS_ENABLED | true | Enable/disable assessment pass |
PR_REVIEW_ASSESS_MODEL | claude-sonnet-4-6 | Model for hallucination checking |
PR_REVIEW_ASSESS_MAX_TOKENS | 4096 | Max response tokens for assessment |
PR_REVIEW_AGENTS_FILE | AGENTS.md | Project context file path |
Non-Blocking
The workflow uses continue-on-error: true so review failures never block PR merges.
Deploy Docs Workflow
File: .github/workflows/deploy-docs.yml
Name: Deploy Docs
Triggers
- Push to main (paths:
site/**,docs/**,pkg/**/*.md,examples/**/*.md,README.md,CHANGELOG.md,DEVELOPMENT.md) - Manual dispatch with inputs:
version_slot,version_label,set_latest
How It Works
- Runs
scripts/gen-versions-toml.shto generate a versioned Hugo config overlay - Builds the Hugo site with
--config hugo.toml,versions.toml - Deploys the built site to a subdirectory of
go-kure.github.io
Trigger Matrix
| Event | What Deploys | Path | BaseURL |
|---|---|---|---|
Push to main (docs paths) | Dev docs | /dev/ | www.gokure.dev/dev/ |
workflow_dispatch | Versioned | /vX.Y/ | www.gokure.dev/vX.Y/ |
workflow_dispatch + set_latest=true | Versioned + root | /vX.Y/ + / | Both |
Concurrency
Per-slot concurrency group (deploy-docs-<slot>) prevents race conditions when deploying different versions simultaneously.
Preservation
During deployment, existing version subdirectories (dev/, v*/), CNAME, and .nojekyll are preserved. Only the target slot is replaced.
Manage Docs Workflow
File: .github/workflows/manage-docs.yml
Name: Manage Docs
Triggers
- Manual dispatch only with inputs:
action,version_slot
Actions
| Action | Description | Implementation |
|---|---|---|
remove-version | Delete a version’s docs | Removes /vX.Y/ directory from deploy target |
set-latest | Change root / to a specific version | Triggers deploy-docs.yml with set_latest=true |
rebuild-version | Re-trigger a docs build | Triggers deploy-docs.yml for the specified version |
Common Scenarios
# Roll back latest to an older version:
# Actions > "Manage Docs" > action=set-latest > version_slot=v0.1
# Remove a yanked version:
# Actions > "Manage Docs" > action=remove-version > version_slot=v0.2
# Rebuild after theme or script changes:
# Actions > "Manage Docs" > action=rebuild-version > version_slot=devVersioned Documentation
The docs site supports multiple documentation versions at different URL paths.
URL Structure
| Path | Content | Updated By |
|---|---|---|
/ | Latest stable release | Release workflow (set_latest=true) |
/vX.Y/ | Specific stable version | Release workflow or manual dispatch |
/dev/ | Development (from main) | Every push to main that touches docs |
Version Switcher
The Relearn theme
provides a native version dropdown in the sidebar. It is configured via params.versions entries in versions.toml, which gen-versions-toml.sh generates from git tags.
How gen-versions-toml.sh Works
# Generate config overlay for a dev build:
./scripts/gen-versions-toml.sh --version dev
# Generate for a stable release:
./scripts/gen-versions-toml.sh --version v0.1.0 --latest v0.1.0The script:
- Reads all stable tags (
vX.Y.Zwithout pre-release suffix) from git - Deduplicates to minor level (keeps highest patch per
vX.Y) - Generates
site/versions.tomlwith[params]section and[[params.versions]]entries - Marks the latest version with
isLatest = trueand rootbaseURL - Always includes a “Development” entry pointing to
/dev/
WIP Banner
The development version shows a warning banner linking to the latest stable version (if one exists). Stable versions show no banner.
Test Jobs in CI
| Job | Matrix | Command | Uses Makefile? |
|---|---|---|---|
test | - | go test -json -v ./... | ✅ (deps) |
test | - | make test-race | ✅ |
test | - | make test-coverage | ✅ |
Test Targets in Makefile
| Target | Command | Used in CI? | In precommit? |
|---|---|---|---|
test | go test -timeout 30s ./... | ✅ | ✅ |
test-race | go test -race -timeout 30s ./... | ✅ | - |
test-coverage | go test -coverprofile=... ./... | ✅ | - |
test-integration | go test -tags=integration -timeout 5m ./... | - | - |
vuln | govulncheck ./... | ✅ | - |
CI vs Pre-commit
| Target | Tasks | Use Case |
|---|---|---|
precommit | fmt, tidy, lint, test | Fast local checks (~10s) |
ci | deps, fmt, tidy, lint, vet, test, test-race, test-coverage, test-integration, build, vuln | Comprehensive CI pipeline (~2min) |
Configuration Standards
Go Version
All workflows use Go 1.26.1 consistently, defined via environment variable:
env:
GO_VERSION: '1.26.1'Caching
The actions/setup-go@v6 action has built-in caching enabled by default, but CI
jobs disable it (cache: false) to avoid double-caching with the explicit
actions/cache@v5 steps that follow. Each job uses tuned cache keys and paths:
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ${{ steps.go-version.outputs.version }}
cache: false # explicit actions/cache step below
- name: Cache Go modules
uses: actions/cache@v5
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-Branch Patterns
- Release branches:
release/*(note: notreleases/*) - Development branches:
main,develop
Estimated CI Time
| Scenario | Before (4 workflows) | After (2 workflows) |
|---|---|---|
| PR opened | ~8 min (duplicate work) | ~4 min |
| Push to main | ~5 min | ~4 min |
| PR merge | ~5 min (full re-run) | ~0 min (same SHA, skipped) |
Self-Hosted Runner Requirements
All jobs run on the autops-kube GitHub ARC scale-set, which uses ghcr.io/actions/actions-runner:latest — a minimal Ubuntu image that includes curl and git but not make or wget.
To account for this:
- Every job that calls
makeincludes an explicit install step:sudo apt-get install -y --no-install-recommends make - All
wgetcalls have been replaced withcurl -fsSL -o
Maintenance Notes
- When adding/modifying workflows: Update this document with changes
- Version updates: Run
make sync-go-versionto update Go version in all files - Version check: Run
make check-go-versionto verify consistency - Action versions: Keep GitHub Actions up to date (currently using v3-v6)
- New jobs using
make: Add theInstall build toolsstep (see above) if the job runs onautops-kube
See Also
- Makefile - Local development commands
- mise.toml - Local tool version management
- gen-versions-toml.sh - Versioned docs config generator