Skip to content

🔄 synced file(s) with PaddleHQ/go-library-template #86

🔄 synced file(s) with PaddleHQ/go-library-template

🔄 synced file(s) with PaddleHQ/go-library-template #86

Workflow file for this run

# DO NOT EDIT: This file should only be modified in the `go-library-template` repo.
name: Run tests and validate coverage
on:
pull_request:
env:
TARGET_COVERAGE_DIFF: 5
# Required to enable support for synctest.Run
# This will be removed once we update to go 1.25
GOEXPERIMENT: synctest
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
actions: write # required for `workflow-dispatch` to trigger the automerge workflow
jobs:
test:
name: Run tests and validate coverage
runs-on: ubuntu-24.04
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Set up Go
uses: ./.github/actions/setup-go
with:
owner: ${{ github.repository_owner }}
private: ${{ github.event.repository.private }}
private-key: ${{ secrets.PRIVATE_GO_CI_PRIVATE_KEY }}
- name: Download external dependencies
run: |
yq '.externalDependencies | @tsv' < build-config.yaml | # Read build config
tail -n +2 | # Remove header row
while IFS=$'\t' read -r source target; do # Read each line
echo "Copying from ${source} to ${target}" # Log action
mkdir -p $(dirname "$target") # Ensure target directory exists
curl -L -o "${target}" "${source}" # Copy the file
done
- name: Cache test results
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-test-${{ hashFiles('**/go.sum') }}-${{ hashFiles('**/*.go') }}
restore-keys: |
${{ runner.os }}-go-test-${{ hashFiles('**/go.sum') }}-
${{ runner.os }}-go-test-
- name: Install test dependencies
run: |
go install gotest.tools/[email protected]
go install github.com/ctrf-io/go-ctrf-json-reporter/cmd/[email protected]
- name: Setup test databases
uses: ./.github/actions/setup-databases
- name: Setup Env
run: |
yq '.env | to_entries | @tsv' < build-config.yaml |
tail -n +2 |
while IFS=$'\t' read -r source target; do
echo "${source}=${target}" >> $GITHUB_ENV
done
- name: Run tests with coverage
timeout-minutes: 20
env:
ENVIRONMENT: ci
run: |
gotestsum \
--format testname \
--jsonfile test-report.json \
-- \
-v \
-coverprofile=cover.out \
-covermode=atomic \
-coverpkg ./... \
-race \
-buildvcs=true \
-shuffle=on \
./...
- name: Convert test reports to CTRF
if: always()
run: |
cat test-report.json | go-ctrf-json-reporter -quiet -output test-ctrf-report.json || true
- name: Publish Test Report
if: always()
uses: ctrf-io/github-test-reporter@024bc4b64d997ca9da86833c6b9548c55c620e40 # v1.0.26
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
report-path: test-ctrf-report.json
pull-request-report: true
overwrite-comment: true
comment-tag: '${{ github.workflow }}-${{ github.event.pull_request.number }}'
- name: Remove mocks from coverage
run: grep -v -e ".\.pb\.go" -e "/mocks" cover.out > cover.filtered.out
- name: Get total coverage
run: |
echo "TOTAL_COVERAGE=`go tool cover -func cover.filtered.out | tail -n 1 | awk '{print substr($3, 1, length($3)-3)}'`" \
>> $GITHUB_ENV
- name: Read build config
id: build_config
uses: pietrobolcato/action-read-yaml@9f13718d61111b69f30ab4ac683e67a56d254e1d # 1.1.0
with:
config: ${{ github.workspace }}/build-config.yaml
- name: Calculate target coverage
run: |
echo "TARGET_COVERAGE=$(( \
${{ steps.build_config.outputs['requiredCoverage'] || 100 }} \
+ \
${{ env.TARGET_COVERAGE_DIFF }} \
))" >> $GITHUB_ENV
- name: Ensure coverage is good
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3
with:
comment-tag: build_coverage
mode: ${{ fromJSON(env.TOTAL_COVERAGE) < (steps.build_config.outputs['requiredCoverage'] || 100) && 'upsert' || 'delete' }}
message: |
> [!CAUTION]
> ## :cry: Coverage is too low :cry:
> Total coverage is `${{ env.TOTAL_COVERAGE }}%` but the required coverage is `${{ steps.build_config.outputs['requiredCoverage'] || 100 }}%`.
Please add additional tests to increase coverage.
- name: Fail if coverage is too low
if: fromJSON(env.TOTAL_COVERAGE) < (steps.build_config.outputs['requiredCoverage'] || 100)
run: exit 1
- name: Comment PR to update build coverage
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3
with:
comment-tag: build_coverage
mode: ${{ fromJSON(env.TOTAL_COVERAGE) > fromJSON(env.TARGET_COVERAGE) && 'upsert' || 'delete' }}
message: |
> [!TIP]
> ## :heart_eyes: Coverage has improved :heart_eyes:
> You may want to update the coverage configuration in `./build-config.yaml` to:
`requiredCoverage: ${{ env.TOTAL_COVERAGE }}`
```diff
diff --git a/build-config.yaml b/build-config.yaml
--- a/build-config.yaml
+++ b/build-config.yaml
@@ -1,1 +1,1 @@
-requiredCoverage: ${{ steps.build_config.outputs['requiredCoverage'] || 100 }}
+requiredCoverage: ${{ env.TOTAL_COVERAGE }}
```
- name: Automerge
uses: ./.github/actions/trigger-automerge
with:
event: ${{ toJSON(github.event) }}
hasAutoApproverPrivateKey: ${{ secrets.AUTO_APPROVER_PRIVATE_KEY != '' }}