Repository navigation
The ecosystem roadmap: thirteen profiles and the schema-validation check - #176
Merged
Merged
Conversation
Shell (.sh, .bash, .zsh, .bats, or a script without a suffix whose shebang names a shell) and PowerShell (.ps1, .psm1) are one ecosystem with no build system, judged by the tools CI runs on the scripts: bats, shellspec or shunit2 under kcov, shfmt and shellcheck; Pester with its code coverage and PSScriptAnalyzer. The lints stand for the compiler warnings a shell does not have; shellcheck fails on any finding, so running it treats warnings as errors, and PSScriptAnalyzer does with -EnableExit. Nothing measures branches in a shell, so lines (and for Pester, the commands run) are what coverage requires. The issue's open question, when helper scripts make a project a Shell project: always, like any other source; --auxiliary dials it back. kcov was the Zig profile's and .editorconfig the .NET profile's; each has its second user now, so project_validator/tools/kcov.py (with a launcher, so that the test run under kcov is seen) and project_validator/tools/editorconfig.py hold them. The shell-script expander's shebang reading is a function the profile's probe shares. Closes cpp-best-practices#82. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
Dockerfiles (Dockerfile, Containerfile, Dockerfile.<stage>, <name>.Dockerfile) are a format: not a program, judged for hygiene. The Dockerfile parses (known instructions with arguments, a FROM first after any ARG; continuations, the escape directive and heredocs read as BuildKit reads them), hadolint lints it and its security rules scan it, the misconfiguration scanners (checkov, trivy config, KICS) scan it, and CI audits the image it builds (trivy image, grype, Docker Scout). The build (docker build, docker/build-push-action) shows a job works with the ecosystem. A Dockerfile has no telling suffix, so an ecosystem can now name its sources (Ecosystem.source_names: names or name patterns, each to a language or format), recognised when no suffix is, claimed once, named in --map's signals, and left out of the unrecognised suffixes. The misconfiguration scanners were the Terraform profile's; Dockerfiles are their second user, so project_validator/tools/misconfiguration.py holds them, and the one trivy action (image-ref for an image scan, scan-ref otherwise) replaces the audits' and Terraform's. The data parsers' UTF-8 reading is facts.wellformed.decoded. Closes cpp-best-practices#94. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
Helm charts (Chart.yaml), kustomizations and manifests (YAML with apiVersion, kind and metadata in a directory of them) make a project a Kubernetes one: a format whose files are YAML, the Data format's. helm lint, chart-testing and kube-linter lint it; kube-linter, checkov, trivy config, KICS, polaris, kyverno and kube-score scan it; its tests are helm-unittest's, or the chart's test hooks that helm test and ct install run. Schema validation, Kubernetes versions as an axis and Chart.lock wait for their own checks. A content probe could only add languages; a format ecosystem's probe now adds its format to the project's and the root unit's formats. A chart's templates are Go templates, not YAML, so templates/ is a role of its own and a data file with it is noted as not parsed, rendered before it is read, instead of failing data-wellformed. A kind of test file may say what its files are written in (the chart's tests are YAML), so they are found among another format's sources. Closes cpp-best-practices#95. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
A collection (galaxy.yml), a role (meta/main.yml with galaxy_info), an ansible.cfg, a molecule scenario or a playbook (YAML whose plays name hosts and tasks or roles) makes a project Ansible's: a format whose files are YAML, the Data format's, with its Jinja templates accounted for. ansible-lint lints it and its risky-command and no-log rules scan it, beside checkov and KICS, the misconfiguration scanners that read Ansible; its tests are molecule scenarios, or a collection's integration targets that ansible-test runs. The production profile as warnings as errors, yamllint and the target platforms wait for their own checks. Closes cpp-best-practices#96. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
Flakes (flake.nix) and plain expressions (default.nix, shell.nix) are judged by the checks CI builds (nix flake check), the formatter it runs (nixfmt, alejandra, or the flake's own through nix fmt -- --check), the lints statix and deadnix (errors with deadnix --fail), the systems it builds for (the platform axis: the ones a job names, else the runner's own) and the result symlinks nix build leaves, which must be ignored. What nix runs in turn is followed: nix run nixpkgs#statix -- check . runs statix, nix develop -c and nix shell -c run their command. The shell splitter ended a word at any #, where the shell begins a comment at the start of a word only: nix build .#checks.x86_64-linux was split as nix build . A # inside a word stays. Closes cpp-best-practices#97. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
MkDocs, Sphinx, Docusaurus, mdBook, Hugo and Jekyll sites are one format ecosystem with a format per generator, each recognised by its configuration (prose alone makes no site), so that each one's build, strict switch and output directory are judged on their own: CI builds the site (tests-run), the build fails on a warning (warnings-as-errors: mkdocs build --strict, sphinx-build -W, onBrokenLinks: 'throw', hugo --panicOnWarning, jekyll build --strict_front_matter), the prose is linted (markdownlint, vale), and the built site is ignored and never committed. Link checking waits for a check of its own. The repository stage listed only the project's languages' build outputs as what could be committed, so a format's never were; it lists the formats' too. Closes cpp-best-practices#91. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
A repository whose product is a reusable action (action.yml at its root) is asked that a workflow of its own uses the action (uses: ./, the self-test; the step is expanded into a marker the test runner claims, as GitLab's templates are), that actionlint lints its workflows and that zizmor audits them and the action. Every repository's workflows get ci-lint and action-pinning already; this profile asks more of one whose product is an action. The ecosystem has no CI usage signal of its own: actionlint and zizmor are every repository's hygiene, so a C++ project's lint job stays that project's. Closes cpp-best-practices#98. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
CI validates each format's documents, in each unit, against their schemas: a tool-based check over a new aspect, schema, whose policy fails when no validator runs (a schema nothing is checked against guards nothing); policy/tooling.required is the failing counterpart of advised. JSON Schema, a format recognised by intent (*.schema.json, or a $schema naming a json-schema.org dialect; never plain .json), supplies check-jsonschema, ajv, the jsonschema CLI and jv, and is formatted with prettier or biome; Kubernetes supplies kubeconform, kubeval and helm lint --strict. prettier has its second user, so tools/prettier.py holds it. The other schema practices of cpp-best-practices#85 are not here. Part of cpp-best-practices#85. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
…matted by buf .proto schemas (and the gRPC services they define) are a format: the schemas compile (buf build, or protoc), buf lint runs with the rules buf.yaml sets, and buf format --diff --exit-code fails on a file it would change. bufbuild/buf-action is expanded into the commands it runs unless its inputs turn them off. Breaking changes and buf.lock wait for their own checks. Closes cpp-best-practices#88. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
… their key A YAML or JSON file whose top-level key is openapi (or swagger) or asyncapi is an API description: a format whose files stay the Data format's. CI lints the description against its specification (spectral with a ruleset, redocly, vacuum, swagger-cli, openapi-generator's validate; the AsyncAPI CLI), one tool that validates and analyses at once. The version declared, the examples checked and breaking changes are the other schema practices, not yet built. Part of cpp-best-practices#87. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
…h XSpec XSD, RELAX NG and Schematron schemas (XML Schema) and XSLT stylesheets (XSLT) are two formats recognised from their suffixes; the files stay XML, the Data format's, which gains .rng, .sch and .xspec. CI validates the documents (xmllint with a schema, jing, SchXslt), runs the stylesheets' XSpec suites, and formats both with prettier's XML plugin. Two formats, so that a project of schemas alone is not asked for XSpec. The ecosystem contract reckons a fixture's checks by its languages and formats rather than by ecosystem, for the same reason. Part of cpp-best-practices#86. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
Notebooks (.ipynb) are a format: a notebook is JSON with nbformat and cells, which its parser checks for data-wellformed. CI runs the notebooks (pytest --nbmake or --nbval, jupyter nbconvert --execute, papermill), formats them (ruff format, or nbQA with black or ruff) and lints them (ruff check, or nbQA with a linter), and .ipynb_checkpoints/ is ignored and never committed. Notebooks committed without outputs wait for committed-artifacts. ruff reads notebooks, so the bare fixture's broken one is excluded from the repository's own lint. Closes cpp-best-practices#90. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
LaTeX is recognised by a document (a .tex that declares its class, or a .latexmkrc); its sources count once one is found, so a stray fragment makes no LaTeX project. CI compiles the documents (latexmk, a TeX engine, tectonic, or xu-cheng/latex-action, whose pre- and post-compile scripts are split into their commands), lints them (chktex, lacheck), formats them (latexindent --check), and ignores what compiling leaves. Typst is recognised by .typ sources, compiled with typst compile and formatted with typstyle or typstfmt. Part of cpp-best-practices#92. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt
Add the XML schema profile: schemas validated, stylesheets tested with XSpec
Add the Jupyter notebook profile, a format with a parser of its own
Add the LaTeX and Typst profiles
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #176 +/- ##
==========================================
+ Coverage 99.75% 99.76% +0.01%
==========================================
Files 225 251 +26
Lines 12451 13266 +815
Branches 1413 1474 +61
==========================================
+ Hits 12420 13235 +815
Misses 31 31 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The ecosystem roadmap (#105, #107): thirteen changes, reviewed and merged one by one as a stack on leftibot/project_validator (its PRs #49 to #61), brought here as one. Each landed with every gate green: the full suite, 99% branch coverage, ruff, mypy, lizard, jscpd and the strict self-check.
Profiles
trivy config, KICS;trivy image, grype, Docker Scouthelm lint --strictnix flake check; nixfmt, alejandra,nix fmt -- --check; statix, deadnix; the systems built as the platform axis;resultsymlinksuses: ./); actionlint; zizmorbuf build, protoc;buf lint;buf format --diff --exit-code;bufbuild/buf-actionpytest --nbmake, nbconvert, papermill;ruff format, nbQA;ruff check;.ipynb_checkpoints/xu-cheng/latex-action; chktex; latexindent; the auxiliary files.typst compile; typstyle, typstfmtThe check
schema-validation: CI validates each format's documents against their schemas, a tool-based check over a new aspect (schema), failing when no validator runs. JSON Schema, Kubernetes, Protobuf, OpenAPI and XML supply its tools.What the core gained for them
Ecosystem.source_names: sources recognised by file name or name pattern (Dockerfile,Dockerfile.*), claimed once, named in--map.templaterole: a data file undertemplates/is noted as not parsed, rendered before it is read, instead of failingdata-wellformed(Helm charts, Ansible roles).TestFiles.written_in: a format's tests written in another format (a chart's YAML tests).site/is a committed artifact.#inside a word (nix build .#checks.x86_64-linux.default,nixpkgs#statix).policy/tooling.required, the failing counterpart ofadvised.Conventions
A format's lints are
static-analysis, notcompiler-warnings(documentation sites keepwarnings-as-errors, whose strict build is a real switch). Helper shell scripts make Shell one of a project's languages, like any other source;--auxiliarydials that back. A shared tool records its run for every language it serves, so several fixtures' facts snapshots gained runs for languages they do not have; no result changed for them.Left on the roadmap
Tabular data (#92); the other schema practices of #85 (
schema-declared,schema-examples,schema-compatibility);link-check(#91) andmigration-safety(#92) as new checks; #142 to #149.🤖 Generated with Claude Code
https://claude.ai/code/session_01ByTXNqDWdM7HzezrFtEvQt