Overview
check-image uses GitHub Actions for continuous integration and automated releases. All workflows are defined in.github/workflows/.
Workflows
ci.yml - Continuous Integration
Triggers:- Every push to
main - Every pull request
Jobs
1. validate-pr (PRs only)
Validates PR titles follow Conventional Commits format. Steps:- Uses
amannn/action-semantic-pull-request@v6 - Checks PR title matches:
<type>: <Description> - Verifies description starts with uppercase letter
- Allowed types:
feat,fix,docs,chore,refactor,test,style,perf,ci,build,revert
2. test
Runs tests on multiple operating systems. Matrix:ubuntu-latest(Linux)macos-latest(macOS)windows-latest(Windows)
- Checkout code
- Set up Go 1.26 with caching
- Download dependencies:
go mod download - Verify dependencies:
go mod verify - Run tests:
- Unix:
go test ./... -race -coverprofile=coverage.out -covermode=atomic - Windows:
go test ./... -race(no coverage file)
- Unix:
- Upload coverage to Codecov (Ubuntu only)
- Race detection enabled (
-race) - Coverage tracked on Linux
- Fail-fast disabled (all platforms tested even if one fails)
3. lint
Enforces code quality standards. Steps:- Checkout code
- Set up Go 1.26 with caching
- Run
golangci-lintwith config from.golangci.yml - Check formatting:
- Run
go vet ./... - Verify
go.modis tidy:
.golangci.yml for the complete configuration:
errcheck: Unchecked errorsgosimple: Simplification suggestionsgovet: Suspicious constructsineffassign: Ineffective assignmentsstaticcheck: Static analysistypecheck: Type errorsunused: Unused codegosec: Security issues (warning only in pre-commit)
4. build
Verifies cross-compilation for all supported platforms. Matrix:| OS | Architecture |
|---|---|
| linux | amd64 |
| linux | arm64 |
| darwin | amd64 |
| darwin | arm64 |
| windows | amd64 |
- On Linux amd64: run
./check-image versionand./check-image --help - Other platforms: build verification only
codeql.yml - Security Analysis
Triggers:- Every push to
main - Every pull request to
main - Weekly schedule (Monday at 06:00 UTC)
- Checkout code
- Set up Go 1.26 with caching
- Initialize CodeQL with
security-extendedqueries - Build:
go build ./... - Perform analysis
- Upload results to GitHub Security tab
- Detects security vulnerabilities
- Finds potential bugs
- Suggests best practices
- Weekly scans catch new issues
release-please.yml - Release Pipeline
Triggers:- Every push to
main
Jobs
1. release-please
Manages versioning and release PRs. Steps:- Run
googleapis/release-please-action@v4 - Analyze commits since last release
- Calculate next version based on commit types
- Create or update Release PR with:
- Updated
CHANGELOG.md - Updated version in
README.mdandaction.yml - Updated
.github/release-please-manifest.json
- Updated
releases_created:trueif Release PR was mergedtag_name: Git tag created (e.g.,v0.20.0)
- Creates git tag
- Creates GitHub Release with changelog
- Triggers downstream jobs
2. goreleaser
Condition:needs.release-please.outputs.releases_created == 'true'
Steps:
- Checkout tagged commit
- Set up Go 1.26 with caching
- Run
goreleaser/goreleaser-action@v7:go mod tidygo test ./...- Build binaries for all platforms
- Inject version via ldflags
- Create archives
- Generate checksums
- Upload to GitHub Release (
mode: append) - Update Homebrew tap
GITHUB_TOKEN: For GitHub Release uploadsHOMEBREW_TAP_GITHUB_TOKEN: For Homebrew tap updates
check-imagebinaryLICENSEREADME.mdCHANGELOG.mdconfig/*sample files
3. docker
Condition:needs.release-please.outputs.releases_created == 'true'Dependencies:
release-please, goreleaser
Why depend on goreleaser? The dogfooding step uses the GitHub Action, which downloads the binary from the release.
Steps:
- Checkout tagged commit
-
Lint Dockerfile:
-
Set up build tools:
- QEMU for multi-arch builds
- Docker Buildx
-
Extract build metadata:
-
Build single-arch image for scanning:
-
Run Trivy security scan:
-
Validate with check-image (dogfooding):
Validates:
- Image < 20MB
- Runs as non-root
- No unauthorized ports
- No secrets detected
-
Log in to GHCR:
-
Generate Docker metadata:
-
Build and push multi-arch image:
test-action.yml - GitHub Action Testing
Triggers:- Pull requests that modify
action.ymlorentrypoint.sh
- Checkout code
- Test action with real images:
- Binary download from releases
- Input-to-CLI mapping
- Output capture (JSON and exit code)
- Step summary generation
Workflow Dependencies
CI Workflow (parallel)
Release Workflow (sequential)
release-pleasemust create the tag firstgoreleaserbuilds binaries and uploads to releasedockerneeds binaries uploaded (for dogfooding step)
Environment Variables
Secrets
| Secret | Usage | Where Set |
|---|---|---|
GITHUB_TOKEN | Automatic, scoped to repo | GitHub Actions |
CODECOV_TOKEN | Upload coverage | Repository secret |
HOMEBREW_TAP_GITHUB_TOKEN | Update Homebrew tap | Repository secret |
Automatic Variables
| Variable | Value | Usage |
|---|---|---|
GITHUB_SHA | Commit hash | Version injection in CI builds |
GITHUB_REF | Branch/tag ref | Conditional logic |
GITHUB_ACTOR | Username | GHCR login |
RUNNER_OS | OS name | Platform detection |
RUNNER_ARCH | Architecture | Platform detection |
Caching
Go Module Cache
All workflows use Go module caching:- Faster dependency downloads
- Faster builds
- Reduced CI time
Docker Build Cache
Docker builds use GitHub Actions cache:- Reuses layers between builds
- Faster image builds
- Shared across workflow runs
CI Checks Summary
Before merging a PR, all these checks must pass:Automated Checks
✅ PR title follows Conventional Commits✅ Tests pass on Linux, macOS, Windows
✅ Coverage maintained or improved
✅ Linting passes (golangci-lint)
✅ Formatting correct (gofmt)
✅ go vet passes
✅ go.mod is tidy
✅ Builds succeed on all platforms
✅ CodeQL security analysis passes
Manual Review
👤 Code review approved by maintainer👤 Documentation updated (README.md, CLAUDE.md)
👤 Tests cover new functionality
Troubleshooting
CI Failure: Test
Check:- Run tests locally:
go test ./... -race - Review test output in GitHub Actions logs
- Check for platform-specific issues
CI Failure: Lint
Check:- Run linter locally:
golangci-lint run - Format code:
gofmt -s -w . - Check vet:
go vet ./... - Tidy modules:
go mod tidy
CI Failure: Build
Check:- Cross-compile locally:
- Review compiler errors in logs
Release Failure: GoReleaser
Check:- Homebrew token is valid (check expiration)
- Tests pass:
go test ./... - GoReleaser config is valid:
goreleaser check
Release Failure: Docker
Check:- Dockerfile lints:
hadolint Dockerfile - Build succeeds locally:
- Trivy scan passes:
- Image validates:
Best Practices
For Contributors
-
Run pre-commit hooks before pushing:
-
Test locally before PR:
- Use conventional commits for PR title
- Wait for CI before requesting review
For Maintainers
- Review CI logs even if checks pass
- Check coverage changes in Codecov report
- Verify documentation updates
- Squash merge PRs to maintain clean commit history
- Monitor release workflows for failures
Monitoring
GitHub Actions Dashboard
View workflow runs:Codecov Dashboard
View coverage trends:GitHub Security
View CodeQL alerts:Next Steps
Release Process
Learn how releases are automated
Contributing
Back to contributing overview