Repository navigation
Releases
v0.6.0
Added
- Every tag gets a GitHub release whose notes are the version's CHANGELOG.md section, the engine level and the fleetlint version it needs, the digest pin and the commands that verify the signature, SBOM and provenance (
scripts/release-notes.sh). The signed OCI artifact stays the only asset. Releases for v0.1.0 to v0.5.0 were created after the fact with the same notes.
Changed
- A publish step counts in any workflow not run from a pull request. Every artifact kind is detected in tag-triggered workflows and in workflows run on push, release, schedule, by hand (
workflow_dispatch), oncreate,workflow_run,workflow_callorrepository_dispatch;if:guards on the step are not evaluated, since a step that is there publishes eventually. Before, ten kinds (release-files, npm, pypi, crate, gem, maven, nuget, pub, android-app, apple-app) only looked at tag-triggered workflows and missed release-please, semantic-release and changesets, which publish from a push to main. Rehearsals still do not count:--dry-run(and-nfor cargo and pub), GoReleaserbuild,checkand--snapshot, and Apple builds (xcodebuild -exportArchive, fastlanegym,flutter build ipa) outside a tag-triggered workflow. - CI installs fleetlint v0.8.1 (0.8.0 is a source tag without binaries).
Engine level 7: needs fleetlint 0.8.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:07014623de14509a2f6257b02f3f215ad6f7431e6a29ea0f1eae682b5a7e83c0 }or by tag from git: catalog: { version: v0.6.0 }.
As a Go module: go get github.com/fleetlint/catalog@v0.6.0.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:07014623de14509a2f6257b02f3f215ad6f7431e6a29ea0f1eae682b5a7e83c0 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/fleetlint/catalog@sha256:07014623de14509a2f6257b02f3f215ad6f7431e6a29ea0f1eae682b5a7e83c0 --repo fleetlint/catalog # SLSA build provenanceThe SPDX SBOM of the tree is attested to the same digest (cosign verify-attestation --type spdxjson).
v0.5.0
Engine level 7: needs fleetlint 0.8.0 or newer (published artifacts as named instances, locate:; combine: and artifact_workflows() are gone).
Changed
- Published artifacts are instances with names.
artifacts/image.yaml,helm-chart.yamlandoci-artifact.yamlsay withinstances:what tells one artifact of the kind from another (an image reference, a chart path, a registry reference), so two images in one repository are checked one by one and the report names the one that fails. The release implementations read the current artifact's workflows asartifact.workflowsinstead ofartifact_workflows(kind). - Rules whose finding is about one file say so with
locate:(189 rules), a CEL string expression ('"README.md"', or computed from the task runner or the publishing workflow), so reports and SARIF point at the file. combine:is gone.changelog/generator-configuredis one rule at the root with every generator as a satisfier (the per-stack implementations are aliases of it).release/reproducible-buildis keyed by artifact:release-files(Go-trimpathwithmod_timestamp, Cargo--lockedwith--remap-path-prefix, .NETContinuousIntegrationBuild, orSOURCE_DATE_EPOCH),image(SOURCE_DATE_EPOCHorrewrite-timestamp=true),maven,nuget,pypiandgem;npm,crateandpubare source packages and do not apply,helm-chart,oci-artifact,android-appandapple-appare not checked. The stack-keyed ids are aliases of the capability.
Security
- The publish workflow passes the pushed digest to
cosignthrough the environment instead of interpolating a step output intorun:.
Engine level 7: needs fleetlint 0.8.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:8c5fd99c16db51642b31fce647772e945ef5947b260d3c10fe1820f6a4fe2a57 }or by tag from git: catalog: { version: v0.5.0 }.
As a Go module: go get github.com/fleetlint/catalog@v0.5.0.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:8c5fd99c16db51642b31fce647772e945ef5947b260d3c10fe1820f6a4fe2a57 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/fleetlint/catalog@sha256:8c5fd99c16db51642b31fce647772e945ef5947b260d3c10fe1820f6a4fe2a57 --repo fleetlint/catalog # SLSA build provenanceThe SPDX SBOM of the tree is attested to the same digest (cosign verify-attestation --type spdxjson).
v0.4.0
Engine level 6: needs fleetlint 0.7.0 or newer (typed refs).
Changed
- Every rule names its source with a typed ref. A
refs:entry is a bare URL or{url, kind, section}; the kinds, strongest first, arespec(a language or format specification, or an official tool),guidance(official guidance such as Go Code Review Comments, PEP 8 or GitHub's own docs),style-guide(a public style guide),standard(a process or supply-chain standard: NIST SSDF, SLSA, OpenSSF Scorecard, Keep a Changelog, Conventional Commits, Semantic Versioning, EditorConfig, Reproducible Builds),check(a linter's check,sectionis its id) andconvention(a convention of this catalog with no outside source, pointing at the fleetlint.org baseline page). Implementations carry the stack's own source (the tool's documentation), capabilities the general one; the fleetlint.org page links stay as untyped refs after the typed sources.
Engine level 6: needs fleetlint 0.7.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:f9236c508275124195020520071219d99491a6e2b224ff8457157c61810b3c93 }or by tag from git: catalog: { version: v0.4.0 }.
As a Go module: go get github.com/fleetlint/catalog@v0.4.0.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:f9236c508275124195020520071219d99491a6e2b224ff8457157c61810b3c93 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/fleetlint/catalog@sha256:f9236c508275124195020520071219d99491a6e2b224ff8457157c61810b3c93 --repo fleetlint/catalog # SLSA build provenanceThe SPDX SBOM of the tree is attested to the same digest (cosign verify-attestation --type spdxjson).
v0.3.1
Added
- Artifact kind
oci-artifact: a non-image artifact pushed to a registry withoras push,flux push artifact,cosign upload bloborregctl artifact put, in the workflow step or in a repository script the step runs. Implementations of the four release capabilities for it: signing by digest with cosign or Notation, an SBOM attached withcosign attestororas attach, provenance with actions/attest-build-provenance,cosign attestor the SLSA generic generator; trusted publishing does not apply. - The published catalog version carries an SPDX SBOM (
cosign attest) and SLSA build provenance (actions/attest-build-provenance) on its digest, next to the signature.
Changed
release/checksumsdoes not ask a release that publishes an OCI artifact or a chart for a checksums file: the registry digest is the checksum.- The catalog repository checks itself at tier 1.
- The
imagekind sees GoReleaserdockers_v2:andkos:next todockers:;release/sbom/imageacceptsdockers_v2withsbom: trueand ko's SBOM,release/provenance/imageaccepts adockers_v2build (buildx attaches provenance unlessprovenance: false).
Engine level 5: needs fleetlint 0.6.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:bac517f63c92e26b9269ebc45a89fbd7ecf457598795efd61be94026c656e4f4 }or by tag from git: catalog: { version: v0.3.1 }.
As a Go module: go get github.com/fleetlint/catalog@v0.3.1.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:bac517f63c92e26b9269ebc45a89fbd7ecf457598795efd61be94026c656e4f4 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/fleetlint/catalog@sha256:bac517f63c92e26b9269ebc45a89fbd7ecf457598795efd61be94026c656e4f4 --repo fleetlint/catalog # SLSA build provenanceThe SPDX SBOM of the tree is attested to the same digest (cosign verify-attestation --type spdxjson).
v0.3.0
Engine level 5: needs fleetlint 0.6.0 or newer (artifacts as catalog data, capabilities keyed by artifact, metadata.label).
Added
- Artifacts are catalog data.
artifacts/<id>.yamlsays what a release publishes and how it is detected: a CEL expression returning the workflows that publish it. Twelve kinds:release-files,image,helm-chart,npm,pypi,crate,gem,maven,nuget,pub,android-app,apple-app. A repository pinsfacts: {artifacts: [...]}when detection misses one.
Changed
release/signing,release/sbom,release/provenanceandrelease/trusted-publishingare checked per published artifact (by: artifact), not per stack: a repository that publishes binaries and an npm package must sign both, and the report says which one is not. Each kind has its own implementation (rules/release/<name>/<artifact>.yaml); where a check means nothing for a kind (an SBOM for an npm package, a signature on a crate) the implementation says so and reports not applicable.combine: anyis gone from these capabilities; the stack-keyed ids (release/signing/node, ...) are aliases of the new ones. Images pushed from a push- or schedule-triggered workflow count as published, not only from tag-triggered ones.metadata.layerismetadata.label(the old key is still read).
Engine level 5: needs fleetlint 0.6.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:5cc7a8896f3fd64dfd90f5608dcd5fc6b9ce8fc90ca5cd11c78fbbc3e21f4917 }or by tag from git: catalog: { version: v0.3.0 }.
As a Go module: go get github.com/fleetlint/catalog@v0.3.0.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:5cc7a8896f3fd64dfd90f5608dcd5fc6b9ce8fc90ca5cd11c78fbbc3e21f4917 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comv0.2.1
The rules are those of 0.2.0.
Fixed
- The publish workflow installs the fleetlint that reads engine level 4, so the published artifact is loaded the way a repository pins it before the run passes; 0.2.0 was pushed and signed, but that last check ran the old fleetlint.
Engine level 4: needs fleetlint 0.5.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:d246c2ed1a0cf6082cdbfe6f37bb6e53607afddb8a0b7392dbb4fd1ad046cd20 }or by tag from git: catalog: { version: v0.2.1 }.
As a Go module: go get github.com/fleetlint/catalog@v0.2.1.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:d246c2ed1a0cf6082cdbfe6f37bb6e53607afddb8a0b7392dbb4fd1ad046cd20 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comv0.2.0
Engine level 4: needs fleetlint 0.5.0 or newer (combine: on capabilities, the stack-neutral implementation running where no stack is detected).
Changed
- More capabilities. These rules state the requirement once and check it per stack at
rules/<family>/<name>/<stack>.yaml; overrides, exceptions and policy on the old id reach every implementation:release/signing: cosign, GoReleaser and gpg for every stack (any); the APK/AAB signature and PGP for Maven Central (kotlin), PGP and jarsigner (java), APK signing and Apple code signing (flutter), npm provenance (node), PyPI attestations and sigstore-python (python),nuget signand Authenticode (dotnet), release-gem attestations and signed gems (ruby). A Kotlin or Android release no longer needs cosign.release/sbom: syft, trivy, cdxgen, cyclonedx CLIs, sbom-tool, GoReleaser, BuildKit for every stack; the CycloneDX Gradle task and Maven plugin (kotlin, java; now only when the release runs them),npm sbomand cyclonedx-npm (node), cargo-cyclonedx (rust), CycloneDX .NET (dotnet), the CycloneDX Composer plugin (php).release/provenance: attest action, SLSA generator,cosign attest/attest-blob, BuildKit, GitLab metadata for every stack; npm provenance (node), PyPI attestations (python), release-gem attestations (ruby).release/api-compatibility: each stack decides when its project is a library and names its tool; new for java (japicmp, revapi), flutter (dart_apitool) and dotnet (package validation, ApiCompat), and kotlin also accepts the Kotlin Gradle plugin'sabiValidation.quality/mutation-gate: one tool per stack, new for dotnet (Stryker.NET), php (Infection), ruby (mutant) and cpp (Mull); not applicable to Hugo.quality/duplication-gate: jscpd, Simian, duplo and Sonar for every stack; golangcidupl(go), pylint (python), PMD CPD (java, kotlin). Each stack's code needs a detector: a Go and Python repository that runs only pylint now fails for Go.public/manifest-license: one manifest per stack, new for java and kotlin (POM licenses), ruby (gemspec), php (composer.json), dotnet (PackageLicenseExpression) and cpp (vcpkg.json, conanfile); not applicable to go, flutter and hugo, whose manifests have no license field.deps/forks-documented: one manifest per stack, new for ruby (Gemfilegit:/github:) and php (composer VCS repositories).release/trusted-publishing: one registry per stack (npm, PyPI, crates.io, RubyGems), each with its own publish commands and token variables; not applicable to go, php, java, kotlin, hugo and cpp.ci/sast: CodeQL, Semgrep, GitLab SAST and SonarQube for every stack; Brakeman (ruby) and Psalm taint analysis (php).changelog/generator-configured: the generators' own files for every stack; changesets and semantic-release in package.json (node), git-cliff, commitizen and towncrier in pyproject.toml (python), git-cliff Cargo metadata (rust).
combine: anyon the release capabilities andchangelog/generator-configured: a release and a changelog belong to the repository, so one stack's implementation passing is enough. The others keepcombine: all.- The stack-neutral implementations of
deps/vulnerability-scan,deps/license-checkandquality/coverage-thresholddo not apply without a detected stack (no dependency manifest, no code); the release ones do, so a repository that only releases a container image is checked. lint/configured/kotlinrequires detekt 2 (dev.detekt); a build that still applies detekt 1.x (io.gitlab.arturbosch.detekt, built on Kotlin 2.0, fails on JDK 25) gets a partial with that message. A version-catalog alias counts whengradle/libs.versions.tomlmaps it todev.detekt. The fix names detekt 2 and a convention plugin for multi-module builds.- The
kotlin/detekt.ymltemplate uses detekt 2's configuration keys (allowedLines,allowedComplexity,allowedFunctionsPerFile/PerClass,UnusedPrivateFunction, nobuild.maxIssues), which detekt 2 refused in the old template, and excludes every test source set (commonTest,androidHostTest, ...) from MagicNumber and FunctionNaming and@Composablefunctions from FunctionNaming, MagicNumber and LongParameterList.
Fixed
- The check and release workflow templates install fleetlint from its release archive with a checksum check instead of
go install, which needed Go on non-Go stacks. - The Kotlin and Java workflow templates set
java-version: "25"instead of reading a.java-versionthatfleetlint fixnever writes. - The pre-commit template leaves the generated
gradlewscript to Gradle (no shellcheck or shfmt rewrites) and lets.bat/.cmdfiles keep the CRLF that the.gitattributestemplate asks for.
Engine level 4: needs fleetlint 0.5.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:e98e1d1245f3445ea5bab7438f068a9e7c4f14e6d1110a65d2f848e7d2603b8c }or by tag from git: catalog: { version: v0.2.0 }.
As a Go module: go get github.com/fleetlint/catalog@v0.2.0.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:e98e1d1245f3445ea5bab7438f068a9e7c4f14e6d1110a65d2f848e7d2603b8c \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comv0.1.0
The first release of the catalog on its own. fleetlint 0.3 and older embedded the rules under the ids listed as renamed below.
Added
- The presets
minimal,recommended,slop,strictandoss, the rule library (94 rules and 12 capabilities with 129 per-stack implementations), the stack definitions and the fix templates, moved here from the fleetlint repository. fleetlint embeds this module. - Capabilities. A requirement that every stack meets with its own tools is one capability with an implementation per stack at
rules/<family>/<name>/<stack>.yaml;any.yamlis the stack-neutral implementation, and an implementation withwhen: "false"says the requirement does not apply to its stack. Capabilities:lint/configured,lint/strict,types/strict,format/configured,repo/lockfile-committed,repo/toolchain-pinned,deps/vulnerability-scan,deps/license-check,deps/locked-install,deps/unused-check,quality/coverage-threshold,release/reproducible-build. Selecting, overriding or excepting a capability reaches all its implementations. - Stacks as data.
stacks/<id>.yamlfor cpp, dotnet, flutter, go, hugo, java, kotlin, node, php, python, ruby and rust: detection markers, dev container feature or image, the image targets run in, Renovate lockfile maintenance. - New rules:
ci/no-script-injection,ci/no-pipe-to-shell,ci/checkout-no-persist-credentials,ci/workflow-lint,ci/sast,hooks/revs-pinned,release/trusted-publishing,release/hosted-builder,deps/update-coverage,deps/update-cooldown,slop/forced-unwraps; new capabilitiesformat/configured,types/strict,deps/locked-install,deps/unused-check,release/reproducible-build. - GitLab CI: every rule that reads CI understands
.gitlab-ci.yml(jobs, scripts,timeout:,interruptible, includes pinned to a commit, release pipelines on$CI_COMMIT_TAG); Forgejo Actions workflows are read too. lefthook is understood byhooks/secret-scan,hooks/conventional-commitsandhooks/pre-push-check. - Every tag is published as a signed OCI artifact,
ghcr.io/fleetlint/catalog:<tag>, holding the whole catalog version; a repository pins it withcatalog: {oci: ghcr.io/fleetlint/catalog:<tag>}. The check workflow builds and loads the artifact on every change. aliases.yamlmaps every renamed rule id to the ids that replace it; fleetlint reads an old id in a configuration as those, with a warning.deps/update-automationhas a fix:fleetlint fixwrites a renovate.json with only the settings the repository's stacks need.- Templates for a justfile and a Taskfile next to the Makefile, and workflow fragments that install those runners.
Changed
- Renamed.
lint/<stack>-configislint/configured/<stack>,lint/hugo-strict-buildislint/configured/hugo;lint/go-linters-enabled,lint/python-rules-enabled,lint/rust-lints-deniedandlint/kotlin-detekt-strictarelint/strict/<stack>;lint/node-strict-flagsandlint/flutter-strict-modesaretypes/strict/<stack>, and the tsconfig and mypy parts oflint/node-configandlint/python-configmoved there;quality/no-slop-markersisslop/marketing-words(info, inslop). - Presets.
public/no-agent-filesandpublic/no-ai-attributionmoved fromminimaltoslop.minimaladdsslop/conflict-markers,repo/no-large-filesandpublic/license.recommendedaddsformat/*andtypes/*and lists its public rules.strictalso forbids exceptions onci/no-script-injection,ci/no-pipe-to-shell,hooks/revs-pinnedandrelease/trusted-publishing. Presets stateengine: 3and no version of their own: they take the release tag. - The lint, format and type capabilities apply at tiers 1 and 2; the lint rules before applied at every tier. Lint rules find a configuration in a parent directory, as the tools do, so workspace members inherit the root's.
public/no-ai-attributionmatches AI tool and bot addresses and generator footers, never a person's name.public/no-agent-filesalso coversGEMINI.md,.github/copilot-instructions.md,.cursorrules,.windsurfrules,.clinerules,.aider*and.cursor/.- Vulnerability scanners, license checks and coverage gates count only where they are run: an
echo, a comment or an install line no longer satisfies those rules, and the templates' TODO lines name no tool. hooks/secret-scanneeds a secret scanner (gitleaks, trufflehog, ggshield, detect-secrets, secretlint);detect-private-keyalone is a partial.ci/check-workflowandhooks/pre-push-checkno longer acceptcheck-fast.ci/actions-pinnedneeds a digest fordocker://and a commit for GitLab includes.repo/toolchain-pinnedneeds the tool named with a version (and a JDK pin for Java and Kotlin);repo/lockfile-committedno longer counts an unhashed requirements.txt.release/sbomis a warning and does not apply when a release only publishes to a package registry or when git-cliff is the only release tool.repo/no-tracked-envandrepo/no-tracked-junkrun once at the root. The per-stack capabilities run in every workspace member and nested project, and accept what the repository provides above it: a workspace's root lockfile, a pin in a parent directory, a scanner or coverage gate in the root's CI or task runner.- A Gradle build is
javawhen it applies the Java plugins and neither Kotlin nor Android; every other Gradle build (Kotlin, Android, Kotlin Multiplatform) iskotlin. ci/least-privilegechecks GitHub Actions workflows only: Gitea and Forgejo do not take the token's scope from the workflow file.repo/readme-presentaccepts a heading on running, developing or building the project too.repo/no-tracked-envandrepo/no-tracked-junkpass.envfiles, logs and dependency directories under test and fixture directories: they are test inputs.- A Hugo site's
go.mod(Hugo modules) does not make it a Go project; Go sources next to it do. - Slop heuristics report fewer false positives:
model.eval(),iter().skip(), "Enter your password", mdBook'sSUMMARY.md, pytest'stest_*.py,isNew, versioned API files, Git'sRevert "..."subjects and the initial commit no longer count; conflict markers are found in every file type. - Templates: ESLint flat config with
defineConfig, PHPStan 2 and PHP CS Fixer rule sets, clang-tidy header filter, ruff without a hardcoded target version, current Dart analyzer options,.editorconfigwith tabs for Go and two spaces for Dart,ciandstylecommit types, npm publishing through trusted publishing.
Fixed
ci/concurrency-cancelno longer errors onconcurrencywithoutcancel-in-progress.hooks/conventional-commitsno longer passes onno-commit-to-branch.containers/non-root-userreads the final stage only.slop/focused-testsreads test files only, and looks forfdescribe,fitand.onlyin JavaScript and TypeScript and forsolo: truein Dart; a Go function calledfitwas an error before.repo/no-tracked-envaccepts encrypted environment files (.sops,.enc,.age,.gpg,.asc).- The agent instructions of
ci/least-privilegeandci/concurrency-cancelshowed an escaped\n; they now give the YAML in flow form.
Engine level 3: needs fleetlint 0.4.0 or newer.
Pin this version in .fleetlint.yaml, by digest from the registry:
catalog: { oci: ghcr.io/fleetlint/catalog@sha256:ed48a3fa614a10bdaa520f697cb1d733068a162c6bbf97ce23e73afd5403c894 }or by tag from git: catalog: { version: v0.1.0 }.
As a Go module: go get github.com/fleetlint/catalog@v0.1.0.
Verify the signature of the published artifact:
cosign verify ghcr.io/fleetlint/catalog@sha256:ed48a3fa614a10bdaa520f697cb1d733068a162c6bbf97ce23e73afd5403c894 \
--certificate-identity-regexp '^https://github\.com/fleetlint/catalog/\.github/workflows/publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com