chore: apply copilot suggestion #2
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: Pull Request | ||
|
Check failure on line 1 in .github/workflows/go_app_pull_requests.yml
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| GH_CI_USER: | ||
| description: 'User for GitHub auth' | ||
| required: true | ||
| type: string | ||
| GOPRIVATE: | ||
| description: 'GOPRIVATE env for go commands' | ||
| required: false | ||
| type: string | ||
| GO_TEST_UNIT_TAGS: | ||
| description: "The tags flag for the unit test go test call. Include -tags flag. Example -tags=unit" | ||
| type: string | ||
| required: false | ||
| default: "" | ||
| GO_TEST_INTEGRATION_ENABLED: | ||
| type: boolean | ||
| default: false | ||
| GO_TEST_INTEGRATION_TAGS: | ||
| description: "The tags flag for the integration test go test call. Include -tags flag. Example -tags=integration" | ||
| type: string | ||
| default: "-tags=integration" | ||
| GO_TEST_INTEGRATION_TIMEOUT: | ||
| description: "The duration before tests are stopped" | ||
| type: string | ||
| default: "10m" | ||
| DOCKER_CACHE_IMAGES: | ||
| description: "Comma-separated list of Docker images to pre-pull and cache for integration tests" | ||
| type: string | ||
| required: false | ||
| default: "" | ||
| secrets: | ||
| GH_CI_PAT: | ||
| description: 'Token password for GitHub auth' | ||
| required: true | ||
| CODECOV_TOKEN: | ||
| description: 'Token for Codecov' | ||
| required: true | ||
| ARTIFACT_REGISTRY: | ||
| description: 'Artifact Registry address to which to publish (leave blank to not publish)' | ||
| required: false | ||
| ARTIFACT_REGISTRY_JSON_KEY: | ||
| description: 'Key for publishing to Artifact Registry' | ||
| required: false | ||
| env: | ||
| GOPRIVATE: ${{ inputs.GOPRIVATE }} | ||
| jobs: | ||
| commitlint: | ||
| # | ||
| # ensures commit messages follow conventional commits | ||
| # | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| # checkout the commits to lint. | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| # setup node, needed to lint commits. | ||
| - uses: actions/setup-node@v1 | ||
| with: | ||
| node-version: 18 | ||
| # Install needed libraries to lint commits. | ||
| - run: npm install --save-dev @commitlint/{config-conventional@v18.6.0,cli} | ||
| # Lint the commits. | ||
| - run: npx commitlint --from=${{ github.event.pull_request.base.sha }} | ||
| lint: | ||
| # | ||
| # runs golangci-lint | ||
| # | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| # Checkout code to build. | ||
| - name: Checkout repo | ||
| uses: actions/checkout@v4 | ||
| # Setup Go. | ||
| - name: Setup Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: '^1' | ||
| # Use auth to get access to private Git repos for Go code dependencies. | ||
| - name: Configure git for private modules | ||
| env: | ||
| TOKEN: ${{ secrets.GH_CI_PAT }} | ||
| GITHUB_USERNAME: kochava-ci | ||
| run: git config --global url."https://${GITHUB_USERNAME}:${TOKEN}@github.com".insteadOf | ||
| "https://github.com" | ||
| - name: Run golangci-lint | ||
| uses: golangci/golangci-lint-action@v6 | ||
| with: | ||
| version: latest | ||
| args: --timeout=5m --enable=bodyclose | ||
| test: | ||
| # | ||
| # ensure go standards and tests pass | ||
| # | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| # List of go versions to test on. | ||
| go: ['^1'] | ||
| steps: | ||
| # Checkout go code to test. | ||
| - name: Checkout repo | ||
| uses: actions/checkout@v4 | ||
| # Setup Go for each version in the matrix. | ||
| - name: Setup Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: ${{ matrix.go }} | ||
| - name: Login to Artifact Registry | ||
| env: | ||
| ARTIFACT_REGISTRY_JSON_KEY: ${{ secrets.ARTIFACT_REGISTRY_JSON_KEY }} | ||
| if: ${{ env.ARTIFACT_REGISTRY_JSON_KEY }} | ||
| uses: docker/login-action@v2 | ||
| with: | ||
| registry: ${{ secrets.ARTIFACT_REGISTRY }} | ||
| username: _json_key | ||
| password: ${{ secrets.ARTIFACT_REGISTRY_JSON_KEY }} | ||
| - name: Configure git for private modules | ||
| env: | ||
| TOKEN: ${{ secrets.GH_CI_PAT }} | ||
| GITHUB_USERNAME: ${{ inputs.GH_CI_USER }} | ||
| run: | ||
| git config --global url."https://${GITHUB_USERNAME}:${TOKEN}@github.com".insteadOf | ||
| "https://github.com" | ||
| # Vendor Go code needed to build app. | ||
| - name: go mod vendor | ||
| run: go mod vendor | ||
| # Go vet every Go module. | ||
| - name: go vet | ||
| run: | ||
| find . -name vendor -prune -o -name go.mod -print | xargs -n1 dirname | xargs -n1 -I{} bash -c "pushd {}; go vet ./..." | ||
| # Install go-junit-report to format test results. | ||
| - name: Install go-junit-report | ||
| run: go install github.com/jstemmer/go-junit-report/v2@v2.1.0 | ||
| # Free up disk space before integration tests (removes ~25GB of unused tools) | ||
| - name: Free disk space | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| run: | | ||
| echo "Disk space before cleanup:" | ||
| df -h | ||
| # Remove unnecessary tools and SDKs (preserve Go and Docker) | ||
| sudo rm -rf /usr/share/dotnet | ||
| sudo rm -rf /usr/local/lib/android | ||
| sudo rm -rf /opt/ghc | ||
| sudo rm -rf /opt/hostedtoolcache/CodeQL | ||
| echo "Disk space after cleanup:" | ||
| df -h | ||
| # Run unit test for every Go module. | ||
| - name: build coverage output directories | ||
| run: | | ||
| mkdir -p coverage/unit | ||
| mkdir -p coverage/int | ||
| - name: go test | ||
| run: | ||
| find . -name vendor -prune -o -name go.mod -print | xargs -n1 dirname | xargs -n1 -I{} bash -c "pushd {}; go test -cover --race -v ${{ inputs.GO_TEST_UNIT_TAGS }} ./... -args -test.gocoverdir=\"${{ github.workspace }}/coverage/unit\"" | ||
| | tee unit_test_output.txt | ||
| - name: Build Unit Test Junit report | ||
| run: | ||
| go-junit-report -in unit_test_output.txt -set-exit-code > junit_report.xml || true | ||
| - name: Unit Test Report | ||
| uses: dorny/test-reporter@v1 | ||
| if: success() || failure() | ||
| with: | ||
| name: Unit Test Report | ||
| path: junit_report.xml | ||
| reporter: java-junit | ||
| - name: Upload unit test coverage results to Codecov | ||
| uses: codecov/test-results-action@v1 | ||
| with: | ||
| fail_ci_if_error: true # optional (default = false) | ||
| files: ./junit_report.xml | ||
| name: junit-report | ||
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| # Get the digest of the latest integrations-testsuite image | ||
| - name: Get integrations-testsuite image digest | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| id: image-digest | ||
| env: | ||
| ARTIFACT_REGISTRY: ${{ secrets.ARTIFACT_REGISTRY }} | ||
| run: | | ||
| IMAGE="${ARTIFACT_REGISTRY}/kochava/integrations-testsuite:latest" | ||
| # Get digest without pulling the full image (only manifest) | ||
| DIGEST=$(docker manifest inspect ${IMAGE} | sha256sum | cut -d' ' -f1) | ||
| echo "digest=${DIGEST}" >> $GITHUB_OUTPUT | ||
| # Cache Docker images for integration tests | ||
| - name: Cache integrations-testsuite Docker image | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: /tmp/.integrations-testsuite-cache | ||
| key: docker-integrations-testsuite-${{ runner.os }}-${{ steps.image-digest.outputs.digest }} | ||
| restore-keys: | | ||
| docker-integrations-testsuite-${{ runner.os }}- | ||
| # Pre-pull integrations-testsuite image before running tests | ||
| - name: Load or pull integrations-testsuite Docker image | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| env: | ||
| ARTIFACT_REGISTRY: ${{ secrets.ARTIFACT_REGISTRY }} | ||
| run: | | ||
| # Full image path with repository namespace | ||
| IMAGE="${ARTIFACT_REGISTRY}/kochava/integrations-testsuite:latest" | ||
| # Try to load from cache first | ||
| if [ -f /tmp/.integrations-testsuite-cache/image.tar ]; then | ||
| echo "Loading integrations-testsuite from cache..." | ||
| if docker load -i /tmp/.integrations-testsuite-cache/image.tar; then | ||
| echo "✓ Successfully loaded from cache" | ||
| else | ||
| echo "✗ Cache corrupted, pulling ${IMAGE}..." | ||
| docker pull ${IMAGE} | ||
| mkdir -p /tmp/.integrations-testsuite-cache | ||
| docker save ${IMAGE} -o /tmp/.integrations-testsuite-cache/image.tar | ||
| fi | ||
| else | ||
| echo "Cache miss, pulling ${IMAGE}..." | ||
| docker pull ${IMAGE} | ||
| # Save for next time | ||
| mkdir -p /tmp/.integrations-testsuite-cache | ||
| docker save ${IMAGE} -o /tmp/.integrations-testsuite-cache/image.tar | ||
| fi | ||
| # Verify image is available | ||
| if ! docker images | grep -q integrations-testsuite; then | ||
| echo "Error: integrations-testsuite image not found after load/pull" | ||
| exit 1 | ||
| fi | ||
| echo "✅ integrations-testsuite image verified" | ||
| # Cache custom Docker images (specified by caller) | ||
| - name: Cache custom Docker images | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED && inputs.DOCKER_CACHE_IMAGES != '' }} | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: /tmp/.custom-docker-cache | ||
| key: docker-custom-images-${{ runner.os }}-${{ github.run_number / 20 }}-v1 | ||
| restore-keys: | | ||
| docker-custom-images-${{ runner.os }}- | ||
| # Pre-pull custom Docker images before running tests | ||
| - name: Load or pull custom Docker images | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED && inputs.DOCKER_CACHE_IMAGES != '' }} | ||
| env: | ||
| IMAGES_LIST: ${{ inputs.DOCKER_CACHE_IMAGES }} | ||
| run: | | ||
| echo "Processing custom Docker images: $IMAGES_LIST" | ||
| # Convert comma-separated string to array | ||
| IFS=',' read -ra IMAGES <<< "$IMAGES_LIST" | ||
| mkdir -p /tmp/.custom-docker-cache | ||
| for image in "${IMAGES[@]}"; do | ||
| # Trim whitespace | ||
| image=$(echo "$image" | xargs) | ||
| if [ -z "$image" ]; then | ||
| continue | ||
| fi | ||
| filename=$(echo "$image" | tr '/:' '_') | ||
| if [ -f "/tmp/.custom-docker-cache/${filename}.tar" ]; then | ||
| echo "Loading $image from cache..." | ||
| if docker load -i "/tmp/.custom-docker-cache/${filename}.tar"; then | ||
| echo "✓ Successfully loaded $image from cache" | ||
| else | ||
| echo "✗ Cache corrupted, pulling $image..." | ||
| docker pull "$image" | ||
| docker save "$image" -o "/tmp/.custom-docker-cache/${filename}.tar" || echo "Warning: failed to cache $image" | ||
| fi | ||
| else | ||
| echo "Cache miss, pulling $image..." | ||
| docker pull "$image" | ||
| # Save for next time | ||
| docker save "$image" -o "/tmp/.custom-docker-cache/${filename}.tar" || echo "Warning: failed to cache $image" | ||
| fi | ||
| done | ||
| echo "✅ Custom Docker images ready" | ||
| docker images | ||
| # relies on the tests themselves compiling the binary with `-cover` and setting GOCOVERDIR to /coverage/int | ||
| # to separate out any integration tests | ||
| - name: integration tests | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| run: go test -v ${{ inputs.GO_TEST_INTEGRATION_TAGS }} -timeout ${{ inputs.GO_TEST_INTEGRATION_TIMEOUT }} ./... | ||
| | tee integration_test_output.txt | ||
| - name: Build Integration Test Junit report | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| run: go-junit-report -in integration_test_output.txt -set-exit-code > junit_integration_report.xml || true | ||
| - name: Integration Test Report | ||
| uses: dorny/test-reporter@v1 | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| with: | ||
| name: Integration Test Report | ||
| path: junit_integration_report.xml | ||
| reporter: java-junit | ||
| - name: Upload integration test results to Codecov | ||
| if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} | ||
| uses: codecov/test-results-action@v1 | ||
| with: | ||
| fail_ci_if_error: true # optional (default = false) | ||
| files: ./junit_integration_report.xml | ||
| name: junit-integration-report | ||
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| - name: show coverage output directories | ||
| run: | | ||
| ls ./coverage/unit | ||
| ls ./coverage/int | ||
| - name: build coverage.txt | ||
| run: go tool covdata textfmt -i=./coverage/int,./coverage/unit -o coverage.txt | ||
| - name: Upload test coverage results to Codecov | ||
| uses: codecov/codecov-action@v4 | ||
| with: | ||
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| files: ./coverage.txt | ||
| verbose: true | ||
| fail_ci_if_error: true # optional (default = false) | ||
| docker-build: | ||
| # | ||
| # ensures the docker image will build without pushing to the registry | ||
| # uses the git sha for the most recent commit for the version | ||
| # | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| # Checkout code to build. | ||
| - name: Checkout repo | ||
| uses: actions/checkout@v4 | ||
| # Setup Go. | ||
| - name: Setup Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: '^1' | ||
| # Use auth to get access to private Git repos for Go code dependencies. | ||
| - name: Configure git for private modules | ||
| env: | ||
| TOKEN: ${{ secrets.GH_CI_PAT }} | ||
| GITHUB_USERNAME: ${{ inputs.GH_CI_USER }} | ||
| run: git config --global url."https://${GITHUB_USERNAME}:${TOKEN}@github.com".insteadOf | ||
| "https://github.com" | ||
| # Vendor Go code needed to build app. | ||
| - name: go mod vendor | ||
| run: go mod vendor | ||
| # Setup docker build arguments. | ||
| - name: Docker release meta | ||
| id: release | ||
| uses: docker/metadata-action@v4 | ||
| with: | ||
| images: | | ||
| ${{ github.repository }} | ||
| tags: | | ||
| type=sha | ||
| # Setup Docker builder to do build. | ||
| - name: Setup Docker Buildx | ||
| id: buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
| # Build the app. | ||
| - name: Build | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| push: false | ||
| provenance: false | ||
| context: . | ||
| file: Dockerfile | ||
| platforms: linux/amd64 | ||
| tags: ${{ steps.release.outputs.tags }} | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||