Skip to content

ci: migrate to flint v2 for linting#17759

Draft
zeitlinger wants to merge 10 commits intoopen-telemetry:mainfrom
zeitlinger:flint-v2
Draft

ci: migrate to flint v2 for linting#17759
zeitlinger wants to merge 10 commits intoopen-telemetry:mainfrom
zeitlinger:flint-v2

Conversation

@zeitlinger
Copy link
Copy Markdown
Member

@zeitlinger zeitlinger commented Apr 9, 2026

Blocked by #18114

Summary

  • Replace v1-era remote bash lint tasks with flint v2, a single binary that runs all checks in parallel
  • Add google-java-format and ktlint as fast local checks (Spotless remains authoritative for formatting)
  • Add license-header check for *.java and *.kt files
  • Merge reusable-link-check.yml + reusable-markdown-lint-check.yml into a single reusable-lint-check.yml
  • Add ktlint .editorconfig overrides mirroring the editorConfigOverride() calls in otel.spotless-conventions.gradle.kts

Closes #16815

Spotless coverage

Spotless stays in Gradle and remains the authoritative formatter. Flint provides fast local feedback for changed files only.

One intentional gap: StaticImportFormatter (the custom Spotless step that rewrites qualified references like Objects.requireNonNull(x) into static imports) is not covered by flint's google-java-format check — no standalone tool does this. Gradle CI still enforces it via spotlessCheck. A future flint feature (check_task) would allow a fast regex script to detect violations locally, invoking Gradle only when something actually needs fixing.

Test plan

  • mise run lint passes locally
  • CI passes

zeitlinger added a commit to grafana/flint that referenced this pull request Apr 10, 2026
## Summary

Introduces the `flint` Rust binary: a mise-native lint orchestrator that
replaces the v1 bash task scripts.

**How it works**: reads installed tools from `mise.toml`, maps them to a
built-in check registry, runs checks against changed files (merge-base
diff) in parallel. Special checks (lychee links, renovate-deps) are
implemented in Rust.

## File breakdown

282 files changed — the count is misleading without context:

| Category | Files |
|---|---|
| `tests/` — e2e test fixtures (70 test cases × ~3-4 files each) | 248 |
| `src/` — Rust source | 13 |
| Config, docs, CI, Cargo | 21 |

The 23 linters covered by e2e tests: actionlint, biome, biome-format,
cargo-clippy, cargo-fmt, codespell, dotnet-format, editorconfig-checker,
gofmt, golangci-lint, google-java-format, hadolint, ktlint,
license-header, lychee, markdownlint-cli2, prettier, renovate-deps,
ruff, ruff-format, shellcheck, shfmt, plus general cases.

## What's not in this PR

**Deferred features:**
- `flint hook install` — installs a git pre-commit hook; replaces the
per-repo `mise run setup:pre-commit-hook` task with something
self-contained in the CLI
- `check_task` / `fix_task` in `flint.toml` — allows a fast script (e.g.
regex/Python) as the check with a slow canonical fixer (e.g. Gradle);
motivating use case: javaagent's `StaticImportFormatter`
- Biome config injection — `--config-path` takes a directory, not a
file; needs a directory-injection variant in the registry API

**Low-priority linters** (no consuming repo needs them yet):
- `merge-conflict-markers` — pure-Rust special check
- `dotenv-linter`, `go-mod-tidy`, `xmllint`

**Post-merge:**
- Bash task scripts (`tasks/lint/`) — retire once consumer PRs are
merged
- GitHub release / `github:grafana/flint` registration — cut after this
PR merges; consumer repos switch from branch tracking to a pinned
version

## Consumer migration status

All 7 consumer PRs green — validated across Rust, Go, Java, Kotlin,
Python, .NET, Shell, Dockerfile:

- grafana/mox [#63](grafana/mox#63)
- grafana/oats [#272](grafana/oats#272)
- grafana/otel-checker
[#267](grafana/otel-checker#267)
- grafana/grafana-opentelemetry-java
[#1251](grafana/grafana-opentelemetry-java#1251)
- grafana/docker-otel-lgtm
[#1243](grafana/docker-otel-lgtm#1243)
- prometheus/client_java
[#1988](prometheus/client_java#1988)
- open-telemetry/opentelemetry-java-instrumentation
[#17759](open-telemetry/opentelemetry-java-instrumentation#17759)

## Test plan

- [x] CI passes
- [x] `flint list` shows all registry entries with correct
installed/missing status
- [x] All 7 consumer PRs pass CI

Release-As: 0.20.0

---------

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Replace the v1-era remote bash task and separate markdown lint job with
flint v2, which runs all checks (lychee, markdownlint-cli2,
google-java-format, ktlint, license-header) from a single binary.

- Add flint, google-java-format, ktlint to mise.toml
- Create .github/config/flint.toml with license-header check for
  *.java and *.kt (mirrors spotless config); excludes gradlew,
  spotless.license.java, CHANGELOG.md, licenses/licenses.md
- Add ktlint editorconfig overrides to .editorconfig (mirrors the
  editorConfigOverride() calls in otel.spotless-conventions.gradle.kts)
- Replace reusable-link-check.yml + reusable-markdown-lint-check.yml
  with a single reusable-lint-check.yml running `mise run lint`
- Spotless remains authoritative for formatting; flint provides fast
  local feedback and CI link/markdown/license checking

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant