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
26 changes: 16 additions & 10 deletions .github/config/super-linter.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ FILTER_REGEX_EXCLUDE=(.*renovate-tracked-deps\.json|CHANGELOG\.md)
IGNORE_GITIGNORED_FILES=true
LOG_LEVEL=ERROR

# Disable linters not relevant for this repository
VALIDATE_CHECKOV=false
VALIDATE_GIT_COMMITLINT=false
VALIDATE_JSCPD=false
# Use Biome instead of Prettier for JSON formatting (Biome uses tabs, Prettier uses spaces)
VALIDATE_JSON_PRETTIER=false
# Use Ruff instead of Black/Pylint/isort for Python
VALIDATE_PYTHON_BLACK=false
VALIDATE_PYTHON_ISORT=false
VALIDATE_PYTHON_PYLINT=false
# Allow-list: only enable linters relevant for this repository
VALIDATE_BASH=true
VALIDATE_BIOME_FORMAT=true
VALIDATE_EDITORCONFIG=true
VALIDATE_ENV=true
VALIDATE_GITHUB_ACTIONS=true
VALIDATE_JSONC=true
VALIDATE_MARKDOWN=true
VALIDATE_MARKDOWN_PRETTIER=true
VALIDATE_NATURAL_LANGUAGE=true
VALIDATE_PYTHON_ISORT=true
VALIDATE_PYTHON_RUFF=true
VALIDATE_PYTHON_RUFF_FORMAT=true
VALIDATE_SHELL_SHFMT=true
VALIDATE_SPELL_CODESPELL=true
VALIDATE_YAML_PRETTIER=true

# Enable auto-fix for relevant linters
FIX_BIOME_FORMAT=true
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.idea
.mise.super-linter-*.toml
52 changes: 50 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ All task scripts follow these conventions:
**`tasks/lint/`** - Linting validators:

- `super-linter.sh`: Runs Super-Linter via Docker/Podman,
auto-detects runtime, handles SELinux on Fedora
auto-detects runtime, handles SELinux on Fedora.
`--native` flag runs a **subset** of linters directly
on the host for fast local feedback (not a full
replacement for the container — CI uses the full set).
`--full` flag lints all files instead of only changed
files (applies to both native and container modes)
- `links.sh`: Runs lychee link checker with two default
checks (all links in modified files + local links in all
files) and a `--full` flag for comprehensive checking
Expand All @@ -51,7 +56,9 @@ All task scripts follow these conventions:

1. **Container runtime detection**: `super-linter.sh` tries
podman first (with SELinux "z" mount flag),
falls back to Docker
falls back to Docker. With `--native`, the container
runtime is bypassed entirely and linters run directly
on the host
2. **AUTOFIX mode**: Lint scripts that support fixing accept
`--autofix` flag and `AUTOFIX` env var for unified fix
workflows:
Expand Down Expand Up @@ -101,14 +108,55 @@ This ensures all files pass CI linting (Biome formatting,
shellcheck, etc.). Review the auto-fixed files before
committing — auto-fixes may produce unexpected results.

A pre-commit hook can automate this — run
`mise run setup:pre-commit-hook` once per clone to install
it. The hook runs native linters with autofix on every
commit.

```bash
# Auto-fix and verify (recommended dev workflow)
mise run fix

# Verify only (same command used in CI)
mise run lint

# Install pre-commit hook (one-time setup)
mise run setup:pre-commit-hook
```

## Native Mode Tips

For faster native linting, consider switching
`super-linter.env` from a deny-list
(`VALIDATE_X=false` for each unwanted linter) to an
allow-list (only `VALIDATE_X=true` for linters you
want). Super-linter's logic — and native mode — treats
any explicit `VALIDATE_*=true` as "only run these".
This avoids noise from linters like `golangci-lint`
running on non-Go repos.

After updating the super-linter version in `mise.toml`,
run `mise run setup:native-lint-tools` on the host to
install matching tool versions. Tools not installed are
skipped with a warning in native mode.

**Config files:** Native mode requires linter configs at
standard locations (project root), not in
`.github/linters/` (super-linter's convention). The
script errors if `.github/linters/` exists. All
supported linters auto-discover their config:
`shellcheck`→`.shellcheckrc`,
`markdownlint`→`.markdownlint.json`,
`editorconfig-checker`→`.ecrc`,
`actionlint`→`.github/actionlint.yml`,
`hadolint`→`.hadolint.yaml`,
`golangci-lint`→`.golangci.yml`,
`ruff`→`ruff.toml`/`pyproject.toml`,
`codespell`→`.codespellrc`/`pyproject.toml`,
`biome`→`biome.json`,
`prettier`→`.prettierrc`,
`shfmt`→`.editorconfig`.

## Adding New Linters

When adding new lint scripts, follow these patterns:
Expand Down
73 changes: 65 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,45 @@ Docker versioning).
| Flag | Description |
| ----------- | ------------------------------------------------------------ |
| `--autofix` | Enable autofix mode (enables `FIX_*` vars from the env file) |
Comment thread
zeitlinger marked this conversation as resolved.
| `--native` | Run linters natively instead of via container |
| `--full` | Lint all files instead of only changed files |

When autofix is not enabled, all `FIX_*` lines are filtered out of
the env file before running Super-Linter.

**Native mode:**

The `--native` flag runs a **subset** of linters directly on
the host for fast local feedback. It is not a full replacement
for the Super-Linter container — CI should always use the
container for comprehensive checks.

Native mode reads the same `super-linter.env` file and follows
Super-Linter's default logic for determining which linters are
enabled: if any `VALIDATE_*=true` is set, only those linters run;
otherwise all linters run unless explicitly `VALIDATE_*=false`.
`FILTER_REGEX_EXCLUDE` is respected. `FIX_*` variables are honored
when `--autofix` is also set.

Supported native linters (subset of super-linter):

- `actionlint`
- `biome`
- `codespell`
- `editorconfig-checker`
- `golangci-lint`
- `hadolint`
- `markdownlint`
- `prettier`
- `ruff`
- `shellcheck`
- `shfmt`

Tools must be installed separately (e.g., via
`mise run setup:native-lint-tools`). Missing tools and unsupported
`VALIDATE_*` flags are skipped with a warning. Linter configs must
be at standard project-root locations (not `.github/linters/`).

**Environment variables:**

<!-- editorconfig-checker-disable -->
Expand Down Expand Up @@ -396,6 +431,35 @@ mise run lint:renovate-deps --autofix # Regenerate tracked deps
Linters that don't support autofix (like lychee link checker)
silently ignore the `AUTOFIX` environment variable.

## Pre-commit hook

Flint provides a `pre-commit` task that runs native linters with
autofix on every commit — fast feedback without the container
overhead. To set it up:

```bash
mise run setup:pre-commit-hook
```

This generates a `.git/hooks/pre-commit` that runs
`mise run pre-commit`, which uses `--native --autofix` to fix
formatting issues before the commit completes.

**For consuming repos**, add these tasks to your `mise.toml`:

```toml
[tasks.pre-commit]
description = "Pre-commit hook: native lint with autofix"
depends = ["setup:native-lint-tools"]
run = "mise run lint:super-linter -- --native --autofix"

[tasks."setup:pre-commit-hook"]
description = "Install git pre-commit hook"
run = "mise generate git-pre-commit --write --task=pre-commit"
```

Then run `mise run setup:pre-commit-hook` once per clone.

## Automatic version updates with Renovate

Flint provides a [Renovate shareable preset](https://docs.renovatebot.com/config-presets/)
Expand Down Expand Up @@ -448,13 +512,6 @@ find the commit SHA for a release tag, run

## Releasing

Releases are automated via
[Release Please](https://github.com/googleapis/release-please).
When conventional commits land on `main`, Release Please opens
(or updates) a release PR with a changelog.

> **Note:** CI checks don't trigger automatically on release-please
> PRs because they are created with `GITHUB_TOKEN`. To run CI,
> either click **Update branch** or **close and reopen** the PR.
See [RELEASING.md](RELEASING.md).

[stf]: https://developer.mozilla.org/en-US/docs/Web/URI/Fragment/Text_fragments
25 changes: 25 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Releasing

Releases are automated via
[Release Please](https://github.com/googleapis/release-please).
When conventional commits land on `main`, Release Please opens
(or updates) a release PR with a changelog.

> **Note:** CI checks don't trigger automatically on release-please
> PRs because they are created with `GITHUB_TOKEN`. To run CI,
> either click **Update branch** or **close and reopen** the PR.

## Post-release: regenerate version mapping

After merging a release that bumps `SUPER_LINTER_VERSION`,
regenerate the native lint tool version mapping:

```bash
mise run setup:update-super-linter-versions
git add super-linter-versions/
git commit -m "chore: regenerate super-linter version mapping"
```

<!-- TODO: automate this via Renovate postUpgradeTasks once
grafana/grafana-renovate-config supports `mise run` commands
(see https://github.com/grafana/grafana-renovate-config/pull/65) -->
22 changes: 22 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ SUPER_LINTER_VERSION="slim-v8.4.0@sha256:8421cd4687937ac32a829539d03de51a147c164
description = "Run Super-Linter on the repository"
file = "tasks/lint/super-linter.sh"

[tasks."lint:super-linter-native"]
description = "Run linters natively (fast, for local dev)"
depends = ["setup:native-lint-tools"]
run = "mise run lint:super-linter -- --native"

[tasks."setup:native-lint-tools"]
description = "Install native lint tools matching the pinned super-linter version"
file = "tasks/setup/native-lint-tools.sh"

[tasks."setup:update-super-linter-versions"]
description = "Generate super-linter version mapping from the super-linter repo"
file = "tasks/setup/update-super-linter-versions.sh"

[tasks."lint:links"]
description = "Check for broken links in changed files + all local links"
file = "tasks/lint/links.sh"
Expand All @@ -28,3 +41,12 @@ depends = ["lint:super-linter", "lint:links", "lint:renovate-deps"]
[tasks.fix]
description = "Auto-fix lint issues and regenerate tracked deps"
run = "AUTOFIX=true mise run lint"

[tasks.pre-commit]
description = "Pre-commit hook: native lint with autofix"
depends = ["setup:native-lint-tools"]
run = "mise run lint:super-linter -- --native --autofix"

[tasks."setup:pre-commit-hook"]
description = "Install git pre-commit hook that runs native linting"
run = "mise generate git-pre-commit --write --task=pre-commit"
19 changes: 19 additions & 0 deletions super-linter-versions/v8.4.0.toml
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will renovate keep this file fresh?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a generate-super-linter-versions.yml workflow that triggers on Renovate branch pushes when mise.toml changes. It checks if SUPER_LINTER_VERSION was bumped, regenerates the version mapping, and commits it back to the branch — same pattern as generate-protobuf.yml in client_java.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Tool versions matching super-linter v8.4.0
# Source: https://github.com/super-linter/super-linter/tree/v8.4.0
#
# Auto-generated by tasks/setup/update-super-linter-versions.sh
# Dockerfile multi-stage builds pin exact versions for compiled tools.
# npm and python versions come from lock files in dependencies/.

[tools]
shellcheck = "v0.11.0"
shfmt = "v3.12.0"
actionlint = "1.7.10"
hadolint = "v2.14.0"
"npm:markdownlint-cli" = "0.47.0"
"npm:prettier" = "3.8.1"
"npm:@biomejs/biome" = "2.3.13"
"pipx:ruff" = "0.14.14"
"pipx:codespell" = "2.4.1"
editorconfig-checker = "v3.6.0"
golangci-lint = "v2.8.0"
Loading
Loading