Skip to content

chore: apply copilot suggestion #2

chore: apply copilot suggestion

chore: apply copilot suggestion #2

name: Pull Request

Check failure on line 1 in .github/workflows/go_app_pull_requests.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/go_app_pull_requests.yml

Invalid workflow file

(Line: 240, Col: 16): Unexpected symbol: '/'. Located at position 19 within expression: github.run_number / 20
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