fix(vue): implement dual-linter setup with Biome + ESLint #66
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: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| COVERAGE_THRESHOLD: 80 | |
| jobs: | |
| quality: | |
| name: Code Quality & Tests | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun with cache | |
| uses: ./.github/actions/setup-bun | |
| - name: Type check | |
| run: bun run typecheck | |
| - name: Lint with Biome | |
| run: bun run lint | |
| - name: Lint with Oxlint | |
| run: bun run oxlint | |
| - name: Run tests with coverage | |
| run: bun test tests/ --coverage --coverage-reporter=lcov --coverage-reporter=text | |
| - name: Check coverage threshold | |
| run: | | |
| COVERAGE=$(bun test tests/ --coverage 2>&1 | grep -E "All files" | awk -F'|' '{print $3}' | tr -d ' %') | |
| if [ -z "$COVERAGE" ]; then | |
| echo "::warning::Could not extract coverage percentage" | |
| bun test tests/ --coverage | |
| exit 0 | |
| fi | |
| { | |
| echo "## Coverage Report" | |
| echo "| Metric | Value |" | |
| echo "|--------|-------|" | |
| echo "| Line Coverage | ${COVERAGE}% |" | |
| echo "| Threshold | ${COVERAGE_THRESHOLD}% |" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| COVERAGE_INT=$(echo "$COVERAGE * 100" | bc | cut -d. -f1) | |
| THRESHOLD_INT=$(echo "${COVERAGE_THRESHOLD} * 100" | bc | cut -d. -f1) | |
| if [ "$COVERAGE_INT" -lt "$THRESHOLD_INT" ]; then | |
| echo "| Status | :x: FAILED |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "::error::Coverage ${COVERAGE}% is below threshold ${COVERAGE_THRESHOLD}%" | |
| exit 1 | |
| else | |
| echo "| Status | :white_check_mark: PASSED |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "Coverage ${COVERAGE}% meets threshold ${COVERAGE_THRESHOLD}%" | |
| fi | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: ./coverage/lcov.info | |
| fail_ci_if_error: false | |
| verbose: true | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| lint-actions: | |
| name: Lint GitHub Actions | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Install actionlint | |
| run: | | |
| bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) | |
| - name: Run actionlint | |
| run: ./actionlint | |
| security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| permissions: | |
| security-events: write | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Run Trivy vulnerability scanner (filesystem) | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| trivy-config: trivy.yaml | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| - name: Run Trivy (table output for PR comment) | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| trivy-config: trivy.yaml | |
| format: 'table' | |
| validate-archetypes: | |
| name: Validate Archetypes (Quick) | |
| runs-on: ubuntu-latest | |
| needs: quality | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun with cache | |
| uses: ./.github/actions/setup-bun | |
| - name: Validate archetypes (quick tier) | |
| run: bun run validate:quick | |
| build: | |
| name: Build Check | |
| runs-on: ubuntu-latest | |
| needs: quality | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Setup Bun with cache | |
| uses: ./.github/actions/setup-bun | |
| - name: Build | |
| run: bun run build | |
| - name: Check package exports | |
| run: bun run check:exports | |
| - name: Generate docs | |
| run: bun run docs | |
| - name: Verify CLI runs | |
| run: bun run src/cli.ts --help | |
| - name: Upload docs artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: docs | |
| path: docs/ | |
| docker: | |
| name: Docker Build & Scan | |
| runs-on: ubuntu-latest | |
| needs: quality | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build test image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: test | |
| push: false | |
| load: true | |
| tags: bakery:test | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Run tests in Docker | |
| run: docker compose run --rm test | |
| - name: Run linting in Docker | |
| run: docker compose run --rm lint | |
| - name: Build production image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: production | |
| push: false | |
| load: true | |
| tags: bakery:latest | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Scan Docker image with Trivy | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'bakery:latest' | |
| format: 'table' | |
| exit-code: '1' | |
| ignore-unfixed: true | |
| vuln-type: 'os,library' | |
| severity: 'CRITICAL,HIGH' |