Feature/runtime execution engine #73
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 | |
| ;; | |
| 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 " - hotfix/name (→ master)" | |
| echo " - release/yyyy-mm-dd (develop → master)" | |
| exit 1 | |
| ;; | |
| esac | |
| echo "✅ Quiver loves your PR: $SOURCE_BRANCH → $TARGET_BRANCH" | |
| } | |
| validate_branch | |
| # 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 | |
| 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 < 80" | bc -l) -eq 1 ]; then | |
| echo "❌ Overall coverage ${OVERALL_COVERAGE}% is below required 80%" | |
| cat coverage.txt | |
| exit 1 | |
| fi | |
| echo "✅ Overall coverage ${OVERALL_COVERAGE}% meets requirement (≥80%)" | |
| - 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: Run security scan | |
| run: make security | |
| # Final validation - all checks must pass | |
| pr-validation-complete: | |
| name: PR Validation Complete | |
| runs-on: ubuntu-latest | |
| needs: [validate-branch, build, 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 "- 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-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 "- ✅ Overall test coverage ≥ 80%" | |
| echo "- ✅ PR coverage ≥ 80%" | |
| echo "- ✅ Code quality and security checks passed" | |
| echo "" | |
| echo "🎉 This PR is ready for review!" |