chore(main): release ppc-service 0.4.0 #28
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: PPC Service CI/CD | |
| on: | |
| push: | |
| branches: [main, develop] | |
| paths: | |
| - 'services/ppc/**' | |
| - 'services/shared/**' | |
| - 'gen/**' | |
| - '.github/workflows/ppc-service.yml' | |
| - '.golangci.yml' | |
| pull_request: | |
| branches: [main, develop] | |
| paths: | |
| - 'services/ppc/**' | |
| - 'services/shared/**' | |
| - 'gen/**' | |
| - '.golangci.yml' | |
| workflow_dispatch: | |
| env: | |
| GO_VERSION: '1.24' | |
| GOLANGCI_LINT_VERSION: 'v2.3.0' # NOT the service Makefile's v1.62.2 — v1 cannot parse a `version: "2"` config | |
| SERVICE_NAME: ppc-service | |
| WORKING_DIR: ./services/ppc | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: false # Disable built-in cache, use golangci cache instead | |
| - name: Run golangci-lint | |
| uses: golangci/golangci-lint-action@v8 | |
| with: | |
| version: ${{ env.GOLANGCI_LINT_VERSION }} | |
| working-directory: ${{ env.WORKING_DIR }} | |
| args: --timeout=5m | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| # Runs in parallel with lint job. | |
| # PPC uses neither Redis nor RabbitMQ, so postgres is the only service container. | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_USER: ppc | |
| POSTGRES_PASSWORD: ppc123 | |
| POSTGRES_DB: ppc_db_test | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| cache-dependency-path: '**/go.sum' | |
| - name: Download dependencies | |
| working-directory: ${{ env.WORKING_DIR }} | |
| run: go mod download | |
| # PPC has no `//go:build` tags on any of its 56 test files, so `-short` | |
| # is the only unit/integration separator available. | |
| - name: Run unit tests | |
| working-directory: ${{ env.WORKING_DIR }} | |
| run: | | |
| go test -v -race -short -coverprofile=coverage.out -covermode=atomic ./internal/... | |
| go tool cover -func=coverage.out | tail -1 | |
| - name: Install golang-migrate | |
| run: | | |
| # Install via `go install` (more reliable than the GitHub release | |
| # tarball, which has hit transient redirect failures from CI runners). | |
| go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1 | |
| migrate -version | |
| - name: Run database migrations | |
| working-directory: ${{ env.WORKING_DIR }} | |
| run: | | |
| migrate -path migrations/postgres \ | |
| -database "postgres://ppc:ppc123@localhost:5432/ppc_db_test?sslmode=disable" \ | |
| up | |
| # The 3 INTEGRATION_TEST-gated files all live under internal/infrastructure/postgres. | |
| # TEST_DB_NAME must be set explicitly: the in-code default is `ppc_db`, not `ppc_db_test`. | |
| # TEST_DB_PORT is the mapped host port 5432, not ppc's local-dev 5436. | |
| - name: Run integration tests | |
| working-directory: ${{ env.WORKING_DIR }} | |
| env: | |
| INTEGRATION_TEST: true | |
| TEST_DB_HOST: localhost | |
| TEST_DB_PORT: 5432 | |
| TEST_DB_USER: ppc | |
| TEST_DB_PASSWORD: ppc123 | |
| TEST_DB_NAME: ppc_db_test | |
| run: go test -v -race ./internal/infrastructure/postgres/... | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| file: ${{ env.WORKING_DIR }}/coverage.out | |
| flags: ${{ env.SERVICE_NAME }} | |
| fail_ci_if_error: false | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [lint, test] # Wait for both lint and test to pass | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| cache-dependency-path: '**/go.sum' | |
| - name: Build binary | |
| working-directory: ${{ env.WORKING_DIR }} | |
| run: | | |
| CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ | |
| -ldflags="-s -w -X main.Version=${{ github.sha }}" \ | |
| -o ./bin/${{ env.SERVICE_NAME }} \ | |
| ./cmd/server/main.go | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.SERVICE_NAME }}-binary | |
| path: ${{ env.WORKING_DIR }}/bin/${{ env.SERVICE_NAME }} | |
| retention-days: 7 | |
| docker: | |
| name: Docker Build & Push | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # The bare-SHA tag (`prefix=`) is load-bearing: ArgoCD Image Updater | |
| # matches `allow-tags: regexp:^[a-f0-9]{7,40}$`, so any prefix silently | |
| # breaks auto-deploy. | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/${{ github.repository_owner }}/${{ env.SERVICE_NAME }} | |
| tags: | | |
| type=sha,prefix= | |
| type=ref,event=branch | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| # context is the repo root: the Dockerfile copies gen/ and services/shared/. | |
| - name: Build and push | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ${{ env.WORKING_DIR }}/Dockerfile | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| build-args: | | |
| VERSION=${{ github.sha }} | |
| BUILD_TIME=${{ github.event.head_commit.timestamp }} | |
| # No `e2e` job: services/ppc/tests/e2e/ contains only .gitkeep, so | |
| # `go test ./tests/e2e/...` fails with "no Go files". deploy-staging | |
| # therefore depends on `docker`, not `e2e`. | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: [self-hosted, staging, goapps-runner] | |
| needs: docker | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| environment: | |
| name: staging | |
| url: https://staging-goapps.mutugading.com | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Notify ArgoCD to sync | |
| run: | | |
| echo "Staging deployment triggered via ArgoCD auto-sync" | |
| echo "Image: ghcr.io/mutugading/${{ env.SERVICE_NAME }}:${{ github.sha }}" | |
| # ArgoCD will auto-sync when it detects new image | |
| deploy-production: | |
| name: Deploy to Production | |
| runs-on: [self-hosted, production, goapps-runner] | |
| needs: deploy-staging | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| environment: | |
| name: production | |
| url: https://goapps.mutugading.com | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Trigger Production Deploy via ArgoCD | |
| run: | | |
| echo "Production deployment requires manual ArgoCD sync" | |
| echo "Image: ghcr.io/mutugading/${{ env.SERVICE_NAME }}:${{ github.sha }}" | |
| # Manual sync required in ArgoCD dashboard |