Remove Terminal UI and streamline codebase for API-only architecture #78
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: | |
| branches: [ master, develop ] | |
| types: [ opened, synchronize, reopened ] | |
| env: | |
| GO_VERSION: '1.24.2' | |
| jobs: | |
| # Branch validation - ensures PR follows branching model | |
| validate-branch: | |
| name: Validate Branch Model | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Validate branching model | |
| run: | | |
| SOURCE_BRANCH="${{ github.head_ref }}" | |
| TARGET_BRANCH="${{ github.base_ref }}" | |
| echo "Source branch: $SOURCE_BRANCH" | |
| echo "Target branch: $TARGET_BRANCH" | |
| # Define validation function | |
| validate_branch() { | |
| case "$SOURCE_BRANCH" in | |
| enhancement/*) | |
| if [ "$TARGET_BRANCH" != "develop" ]; then | |
| echo "❌ Enhancement branches can only target 'develop', not '$TARGET_BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| feature/*) | |
| if [ "$TARGET_BRANCH" != "develop" ]; then | |
| echo "❌ Feature branches can only target 'develop', not '$TARGET_BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| fix/*) | |
| if [ "$TARGET_BRANCH" != "develop" ]; then | |
| echo "❌ Fix branches can only target 'develop', not '$TARGET_BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| refactor/*) | |
| if [ "$TARGET_BRANCH" != "develop" ]; then | |
| echo "❌ Refactor branches can only target 'develop', not '$TARGET_BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| hotfix/*) | |
| if [ "$TARGET_BRANCH" != "master" ]; then | |
| echo "❌ Hotfix branches can only target 'master', not '$TARGET_BRANCH'" | |
| exit 1 | |
| fi | |
| ;; | |
| release/*) | |
| if [ "$TARGET_BRANCH" != "master" ]; then | |
| echo "❌ Release branches can only target 'master', not '$TARGET_BRANCH'" | |
| exit 1 | |
| fi | |
| # Additional check: release branches should come from develop | |
| MERGE_BASE=$(git merge-base origin/develop HEAD) | |
| DEVELOP_HEAD=$(git rev-parse origin/develop) | |
| if [ "$MERGE_BASE" != "$DEVELOP_HEAD" ]; then | |
| echo "❌ Release branches must be created from the latest 'develop' branch" | |
| exit 1 | |
| fi | |
| ;; | |
| *) | |
| echo "❌ Invalid branch name '$SOURCE_BRANCH'. Must follow pattern:" | |
| echo " - enhancement/name (→ develop)" | |
| echo " - feature/name (→ develop)" | |
| echo " - fix/name (→ develop)" | |
| echo " - refactor/name (→ develop)" | |
| echo " - hotfix/name (→ master)" | |
| echo " - release/yyyy-mm-dd (develop → master)" | |
| exit 1 | |
| ;; | |
| esac | |
| echo "✅ Quiver loves your PR: $SOURCE_BRANCH → $TARGET_BRANCH" | |
| } | |
| validate_branch | |
| # Multi-platform testing - tests on Linux, macOS, and Windows | |
| test-multi-platform: | |
| name: Test (${{ matrix.os }} / Go ${{ matrix.go-version }}) | |
| runs-on: ${{ matrix.os }} | |
| needs: validate-branch | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| go-version: ['1.24.2'] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v4 | |
| with: | |
| go-version: ${{ matrix.go-version }} | |
| - name: Cache Go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go-${{ matrix.go-version }}- | |
| ${{ runner.os }}-go- | |
| - name: Download dependencies | |
| run: go mod download | |
| - name: Run tests with race detector | |
| run: go test -race -v ./... | |
| - name: Run OS-specific runtime tests | |
| run: go test -v ./internal/infrastructure/runtime/... | |
| # Build validation - ensures code compiles | |
| build: | |
| name: Build Validation | |
| runs-on: ubuntu-latest | |
| needs: validate-branch | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v4 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Cache Go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go- | |
| - name: Download dependencies | |
| run: make deps | |
| - name: Format check | |
| run: | | |
| make fmt | |
| if [ -n "$(git diff --name-only)" ]; then | |
| echo "❌ Code is not properly formatted. Please run 'make fmt'" | |
| git diff | |
| exit 1 | |
| fi | |
| echo "✅ Code formatting is correct" | |
| - name: Vet check | |
| run: make vet | |
| - name: Build application | |
| run: make build | |
| - name: Verify binary | |
| run: | | |
| if [ ! -f "bin/quiver" ]; then | |
| echo "❌ Binary not found after build" | |
| exit 1 | |
| fi | |
| echo "✅ Binary built successfully" | |
| ls -la bin/ | |
| # Docker-based testing with coverage | |
| test-coverage: | |
| name: Test Coverage (Docker) | |
| runs-on: ubuntu-latest | |
| needs: validate-branch | |
| permissions: | |
| pull-requests: write | |
| issues: write | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Run tests with coverage in Docker | |
| run: | | |
| docker run --rm \ | |
| -v ${{ github.workspace }}:/app \ | |
| -w /app \ | |
| golang:${{ env.GO_VERSION }}-alpine \ | |
| sh -c " | |
| apk add --no-cache git make bc gcc musl-dev && | |
| go mod download && | |
| CGO_ENABLED=1 go test -race -coverprofile=coverage.out -covermode=atomic ./... && | |
| go tool cover -func=coverage.out > coverage.txt && | |
| go tool cover -html=coverage.out -o coverage.html | |
| " | |
| - name: Check overall coverage | |
| run: | | |
| if [ ! -f "coverage.txt" ]; then | |
| echo "❌ Coverage file not found" | |
| exit 1 | |
| fi | |
| OVERALL_COVERAGE=$(grep "total:" coverage.txt | awk '{print $3}' | sed 's/%//') | |
| echo "Overall coverage: ${OVERALL_COVERAGE}%" | |
| if [ $(echo "$OVERALL_COVERAGE < 90" | bc -l) -eq 1 ]; then | |
| echo "❌ Overall coverage ${OVERALL_COVERAGE}% is below required 90%" | |
| cat coverage.txt | |
| exit 1 | |
| fi | |
| echo "✅ Overall coverage ${OVERALL_COVERAGE}% meets requirement (≥90%)" | |
| - name: Comment coverage on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const coverage = fs.readFileSync('coverage.txt', 'utf8'); | |
| const match = coverage.match(/total:.*?(\d+\.\d+)%/); | |
| const total = match ? match[1] : 'unknown'; | |
| const threshold = 90; | |
| const passed = parseFloat(total) >= threshold; | |
| const icon = passed ? '✅' : '❌'; | |
| const body = `## 📊 Test Coverage Report\n\n` + | |
| `${icon} **Total Coverage:** ${total}%\n` + | |
| `**Threshold:** ${threshold}%\n` + | |
| `**Status:** ${passed ? 'PASSED' : 'FAILED'}\n\n` + | |
| `<details><summary>📋 View Detailed Report</summary>\n\n` + | |
| `\`\`\`\n${coverage}\n\`\`\`\n</details>`; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }); | |
| - name: Upload coverage reports | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-reports | |
| path: | | |
| coverage.out | |
| coverage.html | |
| coverage.txt | |
| retention-days: 7 | |
| # Security and linting checks | |
| code-quality: | |
| name: Code Quality & Security | |
| runs-on: ubuntu-latest | |
| needs: validate-branch | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v4 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Cache Go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go- | |
| - name: Download dependencies | |
| run: make deps | |
| - name: Run linting checks | |
| run: make lint | |
| - name: Install gosec | |
| run: go install github.com/securego/gosec/v2/cmd/gosec@latest | |
| - name: Run security scan with gosec | |
| run: | | |
| gosec -fmt=json -out=gosec-results.json -no-fail ./... | |
| gosec ./... | |
| - name: Upload security scan results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: gosec-results | |
| path: gosec-results.json | |
| retention-days: 7 | |
| # Final validation - all checks must pass | |
| pr-validation-complete: | |
| name: PR Validation Complete | |
| runs-on: ubuntu-latest | |
| needs: [validate-branch, build, test-multi-platform, test-coverage, code-quality] | |
| if: always() | |
| steps: | |
| - name: Check all jobs status | |
| run: | | |
| echo "Validation results:" | |
| echo "- Branch validation: ${{ needs.validate-branch.result }}" | |
| echo "- Build validation: ${{ needs.build.result }}" | |
| echo "- Multi-platform tests: ${{ needs.test-multi-platform.result }}" | |
| echo "- Test coverage: ${{ needs.test-coverage.result }}" | |
| echo "- Code quality: ${{ needs.code-quality.result }}" | |
| if [ "${{ needs.validate-branch.result }}" != "success" ] || \ | |
| [ "${{ needs.build.result }}" != "success" ] || \ | |
| [ "${{ needs.test-multi-platform.result }}" != "success" ] || \ | |
| [ "${{ needs.test-coverage.result }}" != "success" ] || \ | |
| [ "${{ needs.code-quality.result }}" != "success" ]; then | |
| echo "❌ Some checks failed. Please review and fix the issues." | |
| exit 1 | |
| fi | |
| echo "✅ All PR validation checks passed successfully!" | |
| echo "" | |
| echo "📋 Summary:" | |
| echo "- ✅ Branch follows the defined branching model" | |
| echo "- ✅ Code compiles successfully" | |
| echo "- ✅ Tests pass on Linux, macOS, and Windows" | |
| echo "- ✅ Overall test coverage ≥ 90%" | |
| echo "- ✅ Code quality and security checks passed" | |
| echo "" | |
| echo "🎉 This PR is ready for review!" |