refactor: make invalid states unrepresentable #463
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Cross-platform test (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # The coverage job runs the complete suite on Linux. | |
| os: [macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - run: go test -short -p=8 -parallel=8 ./... | |
| validate-agents-md: | |
| name: Validate AGENTS.md | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - run: make docs-check | |
| formatting: | |
| name: Go formatting | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Check formatting | |
| run: make fmt-check | |
| golangci-lint: | |
| name: Go linters | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - uses: golangci/golangci-lint-action@v7 | |
| with: | |
| version: v2.12.2 | |
| args: --timeout=5m | |
| check-large-files: | |
| name: Check file sizes | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Prevent growth of oversized Go files | |
| shell: bash | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_BASE: ${{ github.event.pull_request.base.sha }} | |
| PUSH_BEFORE: ${{ github.event.before }} | |
| run: | | |
| base=$PUSH_BEFORE | |
| if [[ $EVENT_NAME == pull_request ]]; then | |
| base=$PR_BASE | |
| fi | |
| if [[ -z $base || $base =~ ^0+$ ]] || ! git cat-file -e "$base^{commit}"; then | |
| base=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| errors=0 | |
| while IFS= read -r file; do | |
| [[ -z $file || ! -f $file ]] && continue | |
| current_lines=$(wc -l < "$file") | |
| base_lines=0 | |
| if git cat-file -e "$base:$file" 2>/dev/null; then | |
| base_lines=$(git show "$base:$file" | wc -l) | |
| fi | |
| if (( current_lines > 800 && current_lines > base_lines )); then | |
| echo "::error file=$file::$file grew from $base_lines to $current_lines lines; oversized Go files may not grow" | |
| errors=$((errors + 1)) | |
| elif (( current_lines > 800 )); then | |
| echo "::warning file=$file::$file remains oversized at $current_lines lines (baseline: $base_lines)" | |
| fi | |
| done < <(git diff --name-only --diff-filter=ACMR "$base"...HEAD -- '*.go') | |
| if (( errors > 0 )); then | |
| exit 1 | |
| fi | |
| echo "No changed oversized Go file grew" | |
| coverage: | |
| name: Test coverage | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Install gotestsum | |
| run: go install gotest.tools/gotestsum@latest | |
| - name: Run tests with timing and flaky detection | |
| run: | | |
| gotestsum --junitfile test-results.xml --rerun-fails=2 --rerun-fails-max-failures=5 --packages="./..." -- \ | |
| -short -p=8 -parallel=8 \ | |
| -coverprofile=coverage.out \ | |
| -covermode=set \ | |
| -coverpkg=./internal/... \ | |
| -timeout 180s | |
| - name: Check coverage threshold | |
| run: | | |
| coverage=$(go tool cover -func=coverage.out | tail -n1 | awk '{print $NF}' | tr -d '%') | |
| awk -v coverage="$coverage" 'BEGIN { if (coverage < 70) exit 1 }' || { \ | |
| echo "Coverage $coverage% is below 70% threshold"; \ | |
| exit 1; \ | |
| } | |
| echo "Coverage: $coverage% (passes 70% threshold)" | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-results | |
| path: test-results.xml | |
| - name: Upload coverage artifact | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage | |
| path: coverage.out | |
| race: | |
| name: Focused race tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - run: make test-race | |
| integration: | |
| name: Integration tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - run: make test-integration | |
| tidy: | |
| name: Module tidy check | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Check go.mod is tidy | |
| run: make tidy-check | |
| generated: | |
| name: Generated outputs | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - run: make generate-check | |
| security: | |
| name: Security scan | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v3 | |
| with: | |
| languages: go | |
| - name: Build | |
| run: go build ./... | |
| - name: Perform CodeQL analysis | |
| uses: github/codeql-action/analyze@v3 | |
| npm: | |
| name: npm launcher and package metadata | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: 22 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - run: npm run test:npm | |
| - run: npm run test:e2e | |
| - run: npm pack --dry-run |