Reference configs

kubernetes/kubernetes: which verify scripts become rules

In May 2026, make verify ran most of Kubernetes' 50 hack/verify-*.sh scripts on every pull request. This config covers about two thirds of what they check: most of it as rules, and the generators by running Kubernetes' own scripts from alint. This config was written to test alint; Kubernetes doesn't use alint.

What alint found

.alint.yml
extends:
  - alint://bundled/oss-baseline@v1
  - alint://bundled/go@v1
  - alint://bundled/hygiene/no-tracked-artifacts@v1

ℹ︎ info go-sources-final-newline

Six vendored Go files have no final newline, such as vendor/github.com/modern-go/concurrent/log.go. Kubernetes' gofmt check skips vendor/, so nothing else sees them.

ℹ︎ info oss-final-newline

92 Markdown and YAML files have no final newline, 22 of them changelogs. Kubernetes doesn't gate on it.

ℹ︎ info oss-no-trailing-whitespace

Trailing whitespace turns up in 160 Markdown and YAML files, most of them under staging/, vendor/ and test/.

.alint.yml
- id: k8s-file-max-1mb
  kind: file_max_size
  paths:
    include: ["**/*"]
    exclude: ["vendor/**", "**/testdata/**", "docs/**/*.png"]
  max_bytes: 1048576
  level: warning

⚠︎ warning k8s-file-max-1mb

Eight files are over 1 MiB, six of them generated OpenAPI and protobuf files. Kubernetes' own size check looks only at binary files and allows the one binary among these, a kubectl logo; the rule needs the same exclusions.

The config

It extends three bundled rulesets and adds rules for what the verify scripts check: license headers, import restrictions, the files each staging repository carries and the 1 MiB file cap. The scripts that regenerate code, docs or vendor files stay Kubernetes' own; alint runs them and fails when one would change a file.

.alint.yml
- id: k8s-pkg-import-firewall
  kind: import_gate
  language: go
  paths:
    include: ["pkg/**/*.go"]
    exclude: ["pkg/kubemark/**"]
  forbid: '^(k8s\.io/kubernetes/cmd|github\.com/ghodss/yaml|github\.com/ishidawataru/sctp|k8s\.io/kubectl/pkg/scheme)(/.*)?$'
  level: error

import_gate reads Go import blocks. This rule carries pkg/.import-restrictions: nothing under pkg/ may import cmd/ or three banned packages. Two more rules like it carry the most important of the other .import-restrictions files; a full port would need one rule per file, 66 in all.

.alint.yml
- id: k8s-staging-meta-files
  # fixed here: the six files verify-staging-meta-files.sh requires
  kind: for_each_dir
  select: "staging/src/k8s.io/*"
  require:
    - kind: file_exists
      paths: "{path}/OWNERS"
    - kind: file_exists
      paths: "{path}/README.md"
    - kind: file_exists
      paths: "{path}/LICENSE"
    - kind: file_exists
      paths: "{path}/SECURITY_CONTACTS"
    - kind: file_exists
      paths: "{path}/code-of-conduct.md"
    - kind: file_exists
      paths: "{path}/.github/PULL_REQUEST_TEMPLATE.md"
  level: error

Each of the 33 staging repositories under staging/src/k8s.io/ is published on its own and carries the same six files: OWNERS, README, LICENSE, SECURITY_CONTACTS, a code of conduct and a pull request template. One for_each_dir rule checks all of them, the job of verify-staging-meta-files.sh.

.alint.yml
- id: k8s-codegen-fresh
  kind: command_idempotent
  command: ["hack/verify-codegen.sh"]
  timeout: 1800
  level: error

Regenerating code needs Kubernetes' own generators, so this rule runs the existing script and fails if the tree would change. Nine more run the docs, OpenAPI, vendor, metrics, gofmt, golangci-lint, ShellCheck, spelling and OWNERS-format checks the same way.

Speed

In May 2026, the 43 rules that didn't call other tools, from the config as it was then, took 320 ms on a 30,000-file checkout of Kubernetes. The four verify scripts they overlap with took 6.4 s one after another. Three of those scripts check a little differently: verify-file-sizes.sh allows one image and skips text files, where the rule checks every file; verify-pkg-names.sh checks Go import aliases, where the rule checks package declarations; and verify-staging-meta-files.sh checks six files in each staging repository, where the timed rule checked four. The timings are hyperfine means on a machine with 10 logical cores, with alint 0.9.17.

What stays outside alint

Of the 51 checks, 17 stay with Kubernetes' own tools:

  • go vet and the type check, which need Go's type checker;
  • the internal-modules and vendor-cycle checks, which read the module graph;
  • the publishing bot's check of the staging repositories;
  • checks that build binaries or run the e2e suite, such as the dead-code and e2e-image checks;
  • checks that call the network, such as the license check on vendored packages.

alint reads files as text. A command rule can run any of these tools, but alint can't do their work.