diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af0017d8..d6606743 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,6 @@ on: env: TAGS: "-tags=ci" - COVERAGE: "-coverpkg=github.com/go-python/gopy/..." # Init() in main_test will make sure all backends are available if # GOPY_TRAVIS_CI is set GOPY_TRAVIS_CI: 1 @@ -27,6 +26,10 @@ jobs: platform: [ubuntu-latest, windows-latest, macos-15] python-version: ['3.11', '3.12'] runs-on: ${{ matrix.platform }} + env: + # Coverage is measured on exactly one matrix leg, so the numbers stay + # comparable from commit to commit. + COVERAGE_LEG: ${{ matrix.platform == 'ubuntu-latest' && matrix.go-version == '1.25.x' && matrix.python-version == '3.12' }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -72,9 +75,34 @@ jobs: run: | make - name: Test Linux - if: matrix.platform == 'ubuntu-latest' + if: matrix.platform == 'ubuntu-latest' && env.COVERAGE_LEG != 'true' run: | make test + - name: Test Linux (with coverage) + if: env.COVERAGE_LEG == 'true' + run: | + make cover + - name: Coverage summary + if: env.COVERAGE_LEG == 'true' + run: | + { + echo "## Test coverage" + echo + echo "Commit \`${GITHUB_SHA}\`: **$(go tool cover -func=coverage.out | tail -n 1 | awk '{print $NF}')** of statements" + echo + echo "
Per-function coverage" + echo + echo '```' + go tool cover -func=coverage.out + echo '```' + echo "
" + } >> "$GITHUB_STEP_SUMMARY" + - name: Upload coverage profile + if: env.COVERAGE_LEG == 'true' + uses: actions/upload-artifact@v4 + with: + name: coverage + path: coverage.out - name: Build-macOS if: startsWith(matrix.platform, 'macos-') @@ -93,6 +121,14 @@ jobs: if: matrix.platform == 'windows-latest' run: | go test -v ./... + # Long-term history/trends. Needs a CODECOV_TOKEN repo secret (or + # tokenless uploads enabled for the org on codecov.io); without one this + # step only warns, and the step summary + artifact above still work. - name: Upload-Coverage - if: matrix.platform == 'ubuntu-latest' - uses: codecov/codecov-action@v4 + if: env.COVERAGE_LEG == 'true' + uses: codecov/codecov-action@v5 + with: + files: coverage.out + disable_search: true + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false diff --git a/.gitignore b/.gitignore index d5791e7f..b14a673d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ # goreleaser build output /dist/ + +# 'make cover' output +/coverage.out diff --git a/Makefile b/Makefile index e4cdd8b0..f4a9d3a1 100644 --- a/Makefile +++ b/Makefile @@ -21,10 +21,19 @@ build: @echo "GO111MODULE = $(value GO111MODULE)" $(GOBUILD) -v -ldflags "$(LDFLAGS)" $(DIRS) -test: +test: @echo "GO111MODULE = $(value GO111MODULE)" $(GOTEST) -v $(DIRS) +# Same as 'test', but records statement coverage of every gopy package +# (-coverpkg), since most of bind/ is only exercised via main_test.go. +COVERPROFILE=coverage.out + +cover: + @echo "GO111MODULE = $(value GO111MODULE)" + $(GOTEST) -v -coverpkg=./... -coverprofile=$(COVERPROFILE) $(DIRS) + $(GOCMD) tool cover -func=$(COVERPROFILE) | tail -n 1 + clean: @echo "GO111MODULE = $(value GO111MODULE)" $(GOCLEAN) ./... diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..5ce677e1 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ +# Coverage is tracked over time, not enforced: Codecov reports changes on +# PRs but never fails a check because of them. +coverage: + status: + project: + default: + informational: true + patch: + default: + informational: true