Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Run bazel-diff tests
env:
USE_BAZEL_VERSION: ${{ matrix.bazel }}
run: ~/go/bin/bazelisk coverage --combined_report=lcov //cli/... //tools:coverage_check_test --enable_bzlmod=true --enable_workspace=false
run: ~/go/bin/bazelisk coverage --combined_report=lcov //cli/... //tools:coverage_check_test //tools/go/... --enable_bzlmod=true --enable_workspace=false
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
Expand All @@ -55,6 +55,15 @@ jobs:
USE_BAZEL_VERSION: ${{ matrix.bazel }}
COVERAGE_THRESHOLD: '90'
run: ~/go/bin/bazelisk run //tools:coverage-check -- --badge-json coverage.json bazel-out/_coverage/_coverage_report.dat
- name: Enforce Go coverage threshold (>= 90% line coverage under tools/go/)
env:
# Must match the `Run bazel-diff tests` step above; see the note on the
# Kotlin enforcement step for why USE_BAZEL_VERSION has to be pinned here.
USE_BAZEL_VERSION: ${{ matrix.bazel }}
# Gate Go independently of the Kotlin overall so thin Go coverage can't hide
# behind well-covered Kotlin (and vice versa). --include scopes the report to
# Go production source only (tools/go/, which excludes tools/coverage_check.py).
run: ~/go/bin/bazelisk run //tools:coverage-check -- --include tools/go/ --threshold 90 bazel-out/_coverage/_coverage_report.dat
- name: Upload test logs
uses: actions/upload-artifact@v4
if: always()
Expand Down
9 changes: 9 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ bazel_dep(name = "rules_nodejs", version = "6.7.3", dev_dependency = True)
bazel_dep(name = "rules_foreign_cc", version = "0.15.1", dev_dependency = True)
bazel_dep(name = "rules_python", version = "1.8.4", dev_dependency = True)

# Go support is internal to building/testing bazel-diff (tooling under tools/go,
# whose line coverage is gated at >=90% in CI). Marked dev_dependency so consumers
# of bazel-diff as a module don't inherit rules_go/gazelle via MVS.
bazel_dep(name = "rules_go", version = "0.60.0", dev_dependency = True)
bazel_dep(name = "gazelle", version = "0.45.0", dev_dependency = True)

go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk", dev_dependency = True)
go_sdk.download(version = "1.23.1")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
name = "bazel_diff_maven",
Expand Down
173 changes: 171 additions & 2 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,21 @@ generate-readme:

.PHONY: coverage
coverage:
bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test
bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test //tools/go/...
bazel run //tools:coverage-check -- bazel-out/_coverage/_coverage_report.dat
bazel run //tools:coverage-check -- --include tools/go/ --threshold 90 bazel-out/_coverage/_coverage_report.dat

.PHONY: coverage-check
coverage-check:
bazel run //tools:coverage-check -- bazel-out/_coverage/_coverage_report.dat
bazel run //tools:coverage-check -- --include tools/go/ --threshold 90 bazel-out/_coverage/_coverage_report.dat

.PHONY: coverage-test
coverage-test:
bazel test //tools:coverage_check_test

.PHONY: coverage-html
coverage-html:
bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test
bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test //tools/go/...
bazel run //tools:coverage-check -- bazel-out/_coverage/_coverage_report.dat --html coverage-html
@echo "Open coverage-html/index.html in a browser to inspect."
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,8 @@ bazel run @bazel-diff//cli:bazel-diff -- bazel-diff -h
<td align="center"><a href="https://github.com/purkhusid"><img src="https://avatars.githubusercontent.com/u/5622403?s=64" width="64" alt="Daniel P. Purkhus"/><br/><sub><b>Daniel P. Purkhus</b></sub></a></td>
<td align="center"><a href="https://github.com/alexeagle"><img src="https://avatars.githubusercontent.com/u/47395?s=64" width="64" alt="Alex Eagle"/><br/><sub><b>Alex Eagle</b></sub></a></td>
<td align="center"><a href="https://github.com/Malinskiy"><img src="https://avatars.githubusercontent.com/u/2089114?s=64" width="64" alt="Anton Malinskiy"/><br/><sub><b>Anton Malinskiy</b></sub></a></td>
<td align="center"><a href="https://github.com/rdark"><img src="https://avatars.githubusercontent.com/u/260691?s=64" width="64" alt="rdark"/><br/><sub><b>rdark</b></sub></a></td>
<td align="center"><a href="https://github.com/github-actions[bot]"><img src="https://avatars.githubusercontent.com/in/15368?s=64" width="64" alt="github-actions[bot]"/><br/><sub><b>github-actions[bot]</b></sub></a></td>
<td align="center"><a href="https://github.com/rdark"><img src="https://avatars.githubusercontent.com/u/260691?s=64" width="64" alt="rdark"/><br/><sub><b>rdark</b></sub></a></td>
<td align="center"><a href="https://github.com/thirtyseven"><img src="https://avatars.githubusercontent.com/u/123678?s=64" width="64" alt="Ted Kaplan"/><br/><sub><b>Ted Kaplan</b></sub></a></td>
</tr>
<tr>
Expand Down Expand Up @@ -536,18 +536,22 @@ bazel test //...

## Code coverage

CI enforces a minimum **90% line coverage** on production sources (`cli/src/main/...`). To
run the same check locally:
CI enforces a minimum **90% line coverage** on production sources. Kotlin
(`cli/src/main/...`) and Go (`tools/go/...`) are gated **independently** at 90% each, so
thin coverage in one language can't hide behind well-covered code in the other. To run the
same checks locally:

```terminal
make coverage
```

This invokes `bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test`
and then runs `//tools:coverage-check` against the resulting LCOV report. The check is a
Python `py_binary` ([`tools/coverage_check.py`](tools/coverage_check.py)) that prints a
This invokes
`bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test //tools/go/...`
and then runs `//tools:coverage-check` twice against the resulting LCOV report — once for
the Kotlin main sources and once scoped to `tools/go/` (`--include tools/go/`). The check is
a Python `py_binary` ([`tools/coverage_check.py`](tools/coverage_check.py)) that prints a
per-file table sorted by coverage (worst first), the overall percentage, and exits
non-zero if main-source coverage is below the threshold.
non-zero if the scoped coverage is below the threshold.

If you've already produced a coverage report and just want to re-check the threshold,
`make coverage-check` runs only the binary against `bazel-out/_coverage/_coverage_report.dat`.
Expand Down
14 changes: 14 additions & 0 deletions tools/go/sample/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
load("@rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "sample",
srcs = ["sample.go"],
importpath = "github.com/Tinder/bazel-diff/tools/go/sample",
visibility = ["//visibility:public"],
)

go_test(
name = "sample_test",
srcs = ["sample_test.go"],
embed = [":sample"],
)
17 changes: 17 additions & 0 deletions tools/go/sample/sample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Package sample is a placeholder that exercises the Go coverage gate
// end-to-end. Replace it with real tooling code -- the >=90% line-coverage
// requirement enforced in CI applies to everything under tools/go/.
package sample

// Add returns the sum of a and b.
func Add(a, b int) int {
return a + b
}

// Max returns the larger of a and b.
func Max(a, b int) int {
if a > b {
return a
}
return b
}
18 changes: 18 additions & 0 deletions tools/go/sample/sample_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package sample

import "testing"

func TestAdd(t *testing.T) {
if got := Add(2, 3); got != 5 {
t.Fatalf("Add(2, 3) = %d, want 5", got)
}
}

func TestMax(t *testing.T) {
if got := Max(2, 3); got != 3 {
t.Fatalf("Max(2, 3) = %d, want 3", got)
}
if got := Max(5, 1); got != 5 {
t.Fatalf("Max(5, 1) = %d, want 5", got)
}
}
16 changes: 10 additions & 6 deletions tools/readme_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,18 +274,22 @@ bazel test //...

## Code coverage

CI enforces a minimum **90% line coverage** on production sources (`cli/src/main/...`). To
run the same check locally:
CI enforces a minimum **90% line coverage** on production sources. Kotlin
(`cli/src/main/...`) and Go (`tools/go/...`) are gated **independently** at 90% each, so
thin coverage in one language can't hide behind well-covered code in the other. To run the
same checks locally:

```terminal
make coverage
```

This invokes `bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test`
and then runs `//tools:coverage-check` against the resulting LCOV report. The check is a
Python `py_binary` ([`tools/coverage_check.py`](tools/coverage_check.py)) that prints a
This invokes
`bazel coverage --combined_report=lcov //cli/... //tools:coverage_check_test //tools/go/...`
and then runs `//tools:coverage-check` twice against the resulting LCOV report — once for
the Kotlin main sources and once scoped to `tools/go/` (`--include tools/go/`). The check is
a Python `py_binary` ([`tools/coverage_check.py`](tools/coverage_check.py)) that prints a
per-file table sorted by coverage (worst first), the overall percentage, and exits
non-zero if main-source coverage is below the threshold.
non-zero if the scoped coverage is below the threshold.

If you've already produced a coverage report and just want to re-check the threshold,
`make coverage-check` runs only the binary against `bazel-out/_coverage/_coverage_report.dat`.
Expand Down
Loading