Skip to content

feat(ci): add comprehensive documentation validation workflow (#27) #185

feat(ci): add comprehensive documentation validation workflow (#27)

feat(ci): add comprehensive documentation validation workflow (#27) #185

Workflow file for this run

name: CI
on:
workflow_dispatch:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
- 'specs/**'
- '.specify/**'
- 'CLAUDE.md'
- 'CONTRIBUTING.md'
- 'LICENSE'
- '.gitignore'
pull_request:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
- 'specs/**'
- '.specify/**'
- 'CLAUDE.md'
- 'CONTRIBUTING.md'
- 'LICENSE'
- '.gitignore'
permissions:
contents: read
security-events: write # For SARIF upload
jobs:
check-changes:
name: Detect Code Changes
runs-on: ubuntu-latest
outputs:
code-changed: ${{ steps.filter.outputs.code-files }}
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Check for code changes
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
code-files:
- '**/*.go'
- 'go.mod'
- 'go.sum'
- '.golangci.yml'
lint:
name: Lint
runs-on: ubuntu-latest
needs: check-changes
steps:
- name: Skip if no code changes
if: needs.check-changes.outputs.code-changed != 'true'
run: |
echo "No code changes detected, skipping lint"
exit 0
- name: Checkout code
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/checkout@v5
- name: Set up Go
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: true
cache-dependency-path: go.sum
- name: Cache golangci-lint
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/cache@v4
with:
path: ~/.cache/golangci-lint
key: ${{ runner.os }}-golangci-lint-${{ hashFiles('.golangci.yml') }}
restore-keys: |
${{ runner.os }}-golangci-lint-
- name: Run golangci-lint
if: needs.check-changes.outputs.code-changed == 'true'
uses: golangci/golangci-lint-action@v9
with:
version: v2.5
args: --timeout=3m --build-tags integration
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
needs: check-changes
steps:
- name: Skip if no code changes
if: needs.check-changes.outputs.code-changed != 'true'
run: |
echo "No code changes detected, skipping unit tests"
exit 0
- name: Checkout code
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/checkout@v5
- name: Set up Go
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: true
cache-dependency-path: go.sum
- name: Run unit tests
if: needs.check-changes.outputs.code-changed == 'true'
run: go test -v -coverprofile=coverage.txt -covermode=atomic ./...
shell: bash
- name: Upload coverage to Codecov
if: needs.check-changes.outputs.code-changed == 'true'
uses: codecov/codecov-action@v5
with:
files: ./coverage.txt
flags: unittests
name: codecov-ubuntu
continue-on-error: true
integration-tests:
name: Integration Tests (${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: check-changes
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Skip if no code changes
if: needs.check-changes.outputs.code-changed != 'true'
run: |
echo "No code changes detected, skipping integration tests"
exit 0
- name: Checkout code
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/checkout@v5
- name: Set up Go
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: true
cache-dependency-path: go.sum
- name: Run integration tests
if: needs.check-changes.outputs.code-changed == 'true'
run: go test -v -tags=integration -timeout 4m ./test
shell: bash
- name: Check for TODO-skipped tests
if: needs.check-changes.outputs.code-changed == 'true'
run: |
if grep -r 't.Skip("TODO:' test/; then
echo "ERROR: Found TODO-skipped tests"
exit 1
fi
shell: bash
security:
name: Security Scan
runs-on: ubuntu-latest
needs: check-changes
steps:
- name: Skip if no code changes
if: needs.check-changes.outputs.code-changed != 'true'
run: |
echo "No code changes detected, skipping security scan"
exit 0
- name: Checkout code
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/checkout@v5
- name: Set up Go
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: true
cache-dependency-path: go.sum
- name: Run Gosec Security Scanner
if: needs.check-changes.outputs.code-changed == 'true'
uses: securego/gosec@master
with:
args: '-no-fail -fmt sarif -out results.sarif ./...'
- name: Fix SARIF format
if: needs.check-changes.outputs.code-changed == 'true'
run: |
jq '.runs[].results[] |= if .fixes then .fixes |= map(select(.artifactChanges and (.artifactChanges | type == "array" and length > 0))) else . end' results.sarif > results-fixed.sarif
mv results-fixed.sarif results.sarif
- name: Upload SARIF file
if: needs.check-changes.outputs.code-changed == 'true'
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
continue-on-error: true
build:
name: Build
runs-on: ubuntu-latest
needs: [check-changes, unit-tests, integration-tests, security]
steps:
- name: Skip if no code changes
if: needs.check-changes.outputs.code-changed != 'true'
run: |
echo "No code changes detected, skipping build"
exit 0
- name: Checkout code
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up Go
if: needs.check-changes.outputs.code-changed == 'true'
uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: true
cache-dependency-path: go.sum
- name: Run GoReleaser (snapshot)
if: needs.check-changes.outputs.code-changed == 'true'
uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: build --snapshot --clean