feat: test secure image publishing #40
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
| --- | |
| # Test coverage workflow for ComplyBeacon | |
| # Runs tests with coverage for all modules and enforces a | |
| # minimum coverage threshold. Also runs SonarCloud analysis to | |
| # check code quality and compliance. | |
| # | |
| # Features: | |
| # - Tests all modules with coverage | |
| # - Merges coverage profiles from all modules | |
| # - Enforces minimum coverage threshold | |
| # - Runs SonarCloud analysis for code quality and compliance | |
| name: test-coverage | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| types: [opened, synchronize, reopened] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| GOTOOLCHAIN: local | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| jobs: | |
| sonarcloud: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Go | |
| uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 | |
| with: | |
| go-version: '1.25.x' | |
| - name: Install deps | |
| id: install-deps | |
| run: | | |
| set -euxo pipefail | |
| modules=$(git ls-files '**/go.mod' | grep -v '^vendor/' | sed 's#/go\.mod##' | tr '\n' ' ' || true) | |
| echo "modules=$modules" >> "$GITHUB_OUTPUT" | |
| if [ -z "$modules" ]; then | |
| echo "No Go modules found. Skipping dependency installation." | |
| exit 0 | |
| fi | |
| for m in $modules; do | |
| echo "Processing module: $m" | |
| if [ ! -f "$m/go.mod" ]; then | |
| echo "Error: go.mod not found in $m. Skipping." | |
| continue | |
| fi | |
| (cd "$m" && go mod tidy && go mod download) | |
| done | |
| - name: Generate coverage | |
| run: | | |
| set -euxo pipefail | |
| modules="${{ steps.install-deps.outputs.modules }}" | |
| echo "Cleaning up existing coverage files..." | |
| for m in $modules; do | |
| (cd "$m" && rm -f coverage.out) | |
| done | |
| rm -f coverage.out | |
| # Test each module | |
| for m in $modules; do | |
| echo "--- generating coverage for module: $m" | |
| ( | |
| cd "$m" | |
| go test -v -covermode=atomic -coverprofile=coverage.out ./... | |
| go tool cover -func=coverage.out | tail -n1 || true | |
| ) | |
| done | |
| echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | |
| # Create workspace for merged coverage analysis | |
| echo "Setting up go.work for coverage analysis..." | |
| rm -f go.work go.work.sum | |
| go work init | |
| for m in $modules; do | |
| go work use "./$m" | |
| done | |
| go work sync | |
| # Merge coverage files | |
| go install github.com/wadey/gocovmerge@latest | |
| # Collect coverage files using mapfile | |
| mapfile -t covs < <(for m in $modules; do find "$m" -maxdepth 1 -type f -name coverage.out 2>/dev/null; done) | |
| if [ ${#covs[@]} -eq 0 ]; then | |
| echo "No coverage files found; creating empty coverage.out" | |
| echo "mode: atomic" > coverage.out | |
| echo "COVERAGE_PCT=0" >> "$GITHUB_ENV" | |
| else | |
| gocovmerge "${covs[@]}" > coverage.out | |
| echo "Coverage file: coverage.out" | |
| echo "" | |
| echo "=== Total Coverage (all files) ===" | |
| go tool cover -func=coverage.out | tail -n1 | |
| echo "" | |
| echo "=== Filtered Coverage (excluding test/generated/cmd) ===" | |
| cp coverage.out coverage-filtered.out | |
| sed -i -E '/\.gen\.go:|\/cmd\/|_test\.go:/d' coverage-filtered.out | |
| # Extract coverage percentage | |
| pct=$(go tool cover -func=coverage-filtered.out | tail -n1 | grep -oE '[0-9]+\.[0-9]+' | head -1) | |
| if [ -z "$pct" ]; then | |
| echo "WARNING: Could not calculate coverage" | |
| echo "COVERAGE_PCT=0" >> "$GITHUB_ENV" | |
| else | |
| echo "Filtered coverage (excluding test/generated/cmd): $pct%" | |
| echo "COVERAGE_PCT=$pct" >> "$GITHUB_ENV" | |
| fi | |
| fi | |
| # Cleanup workspace | |
| echo "Cleaning up workspace..." | |
| rm -f go.work go.work.sum | |
| - name: Enforce coverage threshold | |
| continue-on-error: true | |
| env: | |
| MIN_COVERAGE: "60.0" | |
| run: | | |
| echo "Coverage threshold check:" | |
| echo " Current: ${COVERAGE_PCT}%" | |
| echo " Required: ${MIN_COVERAGE}%" | |
| if awk -v c="$COVERAGE_PCT" -v m="$MIN_COVERAGE" 'BEGIN{exit !(c<m)}'; then | |
| echo " Status: FAILED - Coverage below threshold" | |
| exit 1 | |
| else | |
| echo " Status: PASSED - Coverage meets threshold" | |
| fi | |
| - name: Sonar Scan | |
| continue-on-error: true | |
| uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 # v7.0.0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| with: | |
| args: > | |
| -Dsonar.go.coverage.reportPaths=coverage.out | |
| -Dsonar.qualitygate.wait=true | |
| -Dsonar.projectKey=rh-psce_complybeacon | |
| -Dsonar.organization=rh-psce |