name: CI description: Runs Go tests, race detection, vulnerability scanning, and frontend quality checks. on: push: branches: - main - develop pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword POSTGRES_DB: mydb jobs: vet: name: Build & Vet runs-on: ubuntu-latest defaults: run: shell: sh steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.26" cache: false - name: Cache Go modules uses: actions/cache@v4 with: path: | ~/go/pkg/mod ~/.cache/go-build key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}-vet restore-keys: | ${{ runner.os }}-go- - name: Fix node toolcache path for Post-step cleanup run: | mkdir -p /opt/hostedtoolcache/node/22.23.1/x64/bin ln -sf /usr/local/bin/node /opt/hostedtoolcache/node/22.23.1/x64/bin/node - name: Build run: go build ./... working-directory: backend - name: Vet (dev tags) run: go vet -tags "test,dev" ./... working-directory: backend - name: Vet (prod tags) run: go vet -tags "test,!dev" ./... working-directory: backend test: name: Tests (${{ matrix.label }}) needs: [vet, vulns] runs-on: ubuntu-latest defaults: run: shell: sh services: postgres: image: postgres:16-alpine env: POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword POSTGRES_DB: mydb options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: matrix: include: - label: dev gotags: test,dev verbose: -v - label: prod gotags: test,!dev verbose: "" steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.26" cache: false - name: Cache Go modules uses: actions/cache@v4 with: path: | ~/go/pkg/mod ~/.cache/go-build key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}-test-${{ matrix.label }} restore-keys: | ${{ runner.os }}-go- - name: Fix node toolcache path for Post-step cleanup run: | mkdir -p /opt/hostedtoolcache/node/22.23.1/x64/bin ln -sf /usr/local/bin/node /opt/hostedtoolcache/node/22.23.1/x64/bin/node - name: Install psql client run: apk add --no-cache postgresql-client - name: Wait for Postgres run: | for i in $(seq 1 30); do pg_isready -h postgres -U myuser && break sleep 1 done - name: Create test database run: PGPASSWORD=mypassword psql -h postgres -U myuser -d mydb -c "CREATE DATABASE crussell_test_db;" 2>/dev/null || true - name: Run tests working-directory: backend run: go test -tags "${{ matrix.gotags }}" -count=1 ${{ matrix.verbose }} ./... env: POSTGRES_HOST: postgres TEST_DB_HOST: postgres race: name: Race (${{ matrix.label }}) needs: [vet, vulns] runs-on: ubuntu-latest defaults: run: shell: sh services: postgres: image: postgres:16-alpine env: POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword POSTGRES_DB: mydb options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: matrix: include: - label: dev gotags: test,dev - label: prod gotags: test,!dev steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.26" cache: false - name: Cache Go modules uses: actions/cache@v4 with: path: | ~/go/pkg/mod ~/.cache/go-build key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}-race-${{ matrix.label }} restore-keys: | ${{ runner.os }}-go- - name: Fix node toolcache path for Post-step cleanup run: | mkdir -p /opt/hostedtoolcache/node/22.23.1/x64/bin ln -sf /usr/local/bin/node /opt/hostedtoolcache/node/22.23.1/x64/bin/node - name: Install psql + build-base run: apk add --no-cache postgresql-client build-base - name: Wait for Postgres run: | for i in $(seq 1 30); do pg_isready -h postgres -U myuser && break sleep 1 done - name: Create test database run: PGPASSWORD=mypassword psql -h postgres -U myuser -d mydb -c "CREATE DATABASE crussell_test_db;" 2>/dev/null || true - name: Run race detector working-directory: backend run: go test -tags "${{ matrix.gotags }}" -race -count=1 ./... env: POSTGRES_HOST: postgres TEST_DB_HOST: postgres CGO_ENABLED: "1" vulns: name: Go vulnerabilities runs-on: ubuntu-latest defaults: run: shell: sh steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.26" cache: false - name: Cache Go modules uses: actions/cache@v4 with: path: | ~/go/pkg/mod ~/.cache/go-build key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}-vulns restore-keys: | ${{ runner.os }}-go- - name: Fix node toolcache path for Post-step cleanup run: | mkdir -p /opt/hostedtoolcache/node/22.23.1/x64/bin ln -sf /usr/local/bin/node /opt/hostedtoolcache/node/22.23.1/x64/bin/node - name: Go vulnerability scan working-directory: backend run: | go install golang.org/x/vuln/cmd/govulncheck@latest govulncheck ./... frontend-build: name: Frontend build (gate) runs-on: ubuntu-latest defaults: run: shell: sh steps: - uses: actions/checkout@v4 - name: Fix node toolcache path for Post-step cleanup run: | mkdir -p /opt/hostedtoolcache/node/22.23.1/x64/bin ln -sf /usr/local/bin/node /opt/hostedtoolcache/node/22.23.1/x64/bin/node - name: Cache npm dependencies uses: actions/cache@v4 with: path: | ~/.npm frontend/node_modules key: ${{ runner.os }}-npm-${{ hashFiles('frontend/package-lock.json') }} restore-keys: | ${{ runner.os }}-npm- - name: Install dependencies run: cd frontend && npm ci - name: Build run: cd frontend && npm run build frontend-qc: name: Frontend QC (${{ matrix.task }}) needs: [frontend-build] runs-on: ubuntu-latest defaults: run: shell: sh strategy: matrix: include: - task: typecheck cmd: npm run check - task: lint cmd: npm run lint - task: audit cmd: npm audit --audit-level=info steps: - uses: actions/checkout@v4 - name: Fix node toolcache path for Post-step cleanup run: | mkdir -p /opt/hostedtoolcache/node/22.23.1/x64/bin ln -sf /usr/local/bin/node /opt/hostedtoolcache/node/22.23.1/x64/bin/node - name: Restore npm dependencies uses: actions/cache@v4 with: path: | ~/.npm frontend/node_modules key: ${{ runner.os }}-npm-${{ hashFiles('frontend/package-lock.json') }} restore-keys: | ${{ runner.os }}-npm- - name: Install dependencies run: cd frontend && npm ci - name: Run QC task run: cd frontend && ${{ matrix.cmd }}