Skip to content

Migrate documentation build from MkDocs to Zensical - #8848

Merged
nvuillam merged 11 commits into
mainfrom
docs/migrate-to-zensical
Aug 31, 2026
Merged

Migrate documentation build from MkDocs to Zensical#8848
nvuillam merged 11 commits into
mainfrom
docs/migrate-to-zensical

Conversation

@nvuillam

Copy link
Copy Markdown
Member

Migrates the documentation build from mkdocs + mkdocs-material to Zensical, squidfunk's Material successor, keeping every capability of the current site — versioning included.

mkdocs.yml stays the configuration file (Zensical reads it indefinitely), so .automation/build.py's marker-comment nav generation is untouched.

Commits

Commit
fix(docs) Remove the dead {% block disqus %} override
fix(docs) Self-host Satoshi so it actually renders
feat(docs) mkdocs → zensical: deps, emoji namespace, build.sh, hatch scripts, mike fork
feat(docs) OX Security palette + light/dark toggle
ci(docs) test-mkdocs.ymltest-docs.yml, broadened trigger, zensical build
chore(deps) Renovate custom manager for the git-pinned mike fork
docs Contributor documentation, cspell, CHANGELOG
feat(docs) Restore comments with Giscus

Versioning is preserved

Zensical has no native versioning; it documents a Zensical-compatible fork of mike, installed from GitHub and pinned to a commit SHA, watched by a new Renovate custom manager.

mike deploy 9 was rehearsed on a throwaway local clone (nothing pushed):

  • versions.json came back intact, all 40 existing versions preserved
  • 721 files written under 9/
  • the deployed pages carry the same "version":{"default":"latest","provider":"mike"} config the live site uses, and javascripts/version-mike.js still loads

Three pre-existing bugs fixed along the way

All three predate this work and are independent of Zensical:

  1. Comments never rendered. docs/overrides/main.html overrode {% block disqus %}, a block the theme does not define, so Jinja silently never invoked it. Verified absent from the live site.
  2. Satoshi never applied. theme.font.text: Satoshi, sans-serif emitted --md-text-font: "Satoshi, sans-serif" — one quoted family name matching nothing — and the theme requested it from Google Fonts, which does not host Satoshi. Now self-hosted from docs/assets/fonts/.
  3. h1[content~=Home] { display: none; } never matched: h1 has no content attribute. Rule removed.

Regression checks against a 403-page mkdocs baseline

Check Result
Page paths 399 pages, path set identical — permalinks preserved
<img> tags 12 482 = 12 482, exact
Lists and tables (mdx_truly_sane_lists) 0 differing pages
Snippets (--8<--) contributing / license / CHANGELOG identical
Nav anchors, mermaid, footer Identical
Broken-link warnings Same 10 as the mkdocs baseline, no new ones

Judgement calls worth reviewing

  • No --strict in CI. It was in the plan, but main already emits 10 broken-link warnings (missing licenses/spectral.md, licenses/tofu-fmt.md, ../CLAUDE.md…), so the new check would have been red on day one. Zensical also prints "Strict mode is currently unsupported" for the flag today. Fix the 10 links, then turn it on.
  • Comments are site-wide, matching the intent of the utteranc.es block being replaced. A page opts out with comments: false in its front matter; narrowing this to hand-written pages is a one-line change in the partial.
  • glightbox is now lazy-loaded from unpkg.com/glightbox@3 instead of being self-hosted — that is Zensical's built-in behaviour, and it adds a third-party CDN at runtime.
  • Page <h1> source changed. Zensical derives page.title from front matter where mkdocs used the nav entry, so 57 descriptor pages now show spectral configuration in MegaLinter instead of spectral. Cosmetic, and consistent with the <title> tag. The home page rendered as "Index" and is fixed with title: Home front matter, generated by build.py.

Rollback

gh-pages tip before this change: c3dfe2d0aa84f03a42346ae5d3d7f5f101017112

Restore with git push --force-with-lease origin c3dfe2d0aa84f03a42346ae5d3d7f5f101017112:gh-pages.

Merging fires the beta deploy only; latest and the version aliases stay untouched until the next release, which makes that window a natural soak period.

Requires

The Giscus GitHub App installed on oxsecurity/megalinter — already done and verified.

The override targeted `{% block disqus %}`, which no longer exists in
mkdocs-material's base.html. Jinja never invokes an undefined block, so
the script tag never reached the rendered pages and no comments widget
has been displayed on megalinter.io for some time.

Verified absent from the served HTML of /latest/, /latest/quick-start/,
/latest/config-file/ and /beta/.

Removing the dead code; a working comment system is added separately.
`theme.font.text` was set to "Satoshi, sans-serif", which the theme
emits as `--md-text-font: "Satoshi, sans-serif"` — a single quoted
family name that matches nothing. The theme also requests the family
from Google Fonts, which does not host Satoshi (it is an Indian Type
Foundry face distributed via Fontshare), so the site has been falling
back to the browser default rather than rendering in Satoshi.

Ship the four weights in use (400/500/700/900) under docs/assets/fonts,
declare them with @font-face, and set --md-text-font to a single family
name. `font: false` stops the theme requesting a family Google Fonts
cannot serve.
Replace mkdocs + mkdocs-material with zensical, which reads the existing
mkdocs.yml unchanged. Versioning keeps working through the Zensical-compatible
mike fork, pinned to a commit SHA.

- Swap mkdocs/mkdocs-material/mkdocs-glightbox for zensical in requirements
  and in the hatch docs env
- Point mike at squidfunk/mike (Zensical-compatible fork), SHA-pinned
- Use zensical.extensions.emoji for the pymdownx.emoji namespace
- Drop the search_index.json prettify step: Zensical emits site/search.json
- Replace the purple palette with the OX Security colors: navy #061C37 /
  #07224A, indigo #3F11F7, lime #C6F43C, off-white #F7F7FF
- Add a light/dark palette toggle; dark mode uses a navy slate scheme and
  the lime accent, which stays readable on navy
- Scope the color variables per scheme, so the light overrides no longer
  win over the slate ones by cascade order
- Title the home page "Home" again through front matter: the doc engine
  derives page titles from the file name when the page has no h1
- Drop the h1[content~=Home] rule: h1 has no content attribute, so it
  never matched
- Rename the workflow to "Check documentation generation" and its file to
  test-docs.yml (it was not a required status check)
- Also trigger it on docs/** and on the docs requirements file, so a broken
  page is caught before it reaches the deploy workflow
- Build with zensical instead of mkdocs
- Drop the two dead "mkdocs gh-deploy" comments from the deploy workflows
Add a custom manager that reads "# renovate: datasource=git-refs depName=<url>
branch=<branch>" annotations above "pkg @ git+<url>@<sha>" requirements, so the
SHA-pinned Zensical-compatible mike fork gets update PRs like any other pin.
Replace the mkdocs-material references in CLAUDE.md, the .claude rules, agents
and skills with Zensical, document the docs commands and the mike fork, add
zensical and Fontshare to the cspell dictionary, and add the CHANGELOG entries.
Comments are rendered by overriding the theme comments partial, so they appear
at the bottom of every page and follow the light/dark palette toggle. Threads
are GitHub Discussions of oxsecurity/megalinter, created lazily in the
Announcements category and matched on the page path. A page can opt out with
"comments: false" in its front matter.

Requires the Giscus GitHub App to be installed on oxsecurity/megalinter.
@echoix

echoix commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Nice work

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

⚠️MegaLinter analysis: Success with warnings

⚠️ PYTHON / bandit - 197 errors
hell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: ./megalinter/utils_reporter.py:406:18
405	    try:
406	        process = subprocess.run(
407	            sarif_fmt_command,
408	            stdout=subprocess.PIPE,
409	            stderr=subprocess.STDOUT,
410	            text=True,
411	            input=sarif_in + "\n",
412	            env=config.build_env(request_id),
413	        )
414	        return_code = process.returncode

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Call to requests without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b113_request_without_timeout.html
   Location: ./megalinter/utils_reporter.py:572:19
571	    try:
572	        response = requests.post(
573	            hook_url,
574	            headers=build_webhook_headers(reporter.master.request_id),
575	            json=payload,
576	        )
577	        if 200 <= response.status_code < 299:

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./megalinter/utils_sarif.py:156:61
155	                        rule["id"] = (
156	                            rule["id"] + "_DUPLICATE_" + str(random.randint(1, 99999))
157	                        )

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:122:4
121	    )
122	    assert os.path.isdir(config.get(request_id, "DEFAULT_WORKSPACE")), (
123	        "DEFAULT_WORKSPACE "
124	        + config.get(request_id, "DEFAULT_WORKSPACE")
125	        + " is not a valid folder"
126	    )
127	

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:167:4
166	    tmp_report_folder = tempfile.gettempdir() + os.path.sep + str(uuid.uuid4())
167	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
168	    linter_name = linter.linter_name

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:241:4
240	    tmp_report_folder = tempfile.gettempdir() + os.path.sep + str(uuid.uuid4())
241	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
242	    if os.path.isfile(workspace + os.path.sep + "no_test_failure"):

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:490:4
489	    )
490	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
491	    expected_file_name = ""

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:590:4
589	        workspace += os.path.sep + "bad"
590	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
591	    # Call linter

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:690:4
689	        workspace = workspace + os.path.sep + "fix"
690	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
691	

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:796:12
795	            ]
796	            assert (len(list(diffs))) > 0, f"No changes in the {file} file"
797	

--------------------------------------------------
>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.
   Severity: Medium   Confidence: Medium
   CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html
   Location: ./server/server.py:81:42
80	    if item.fileUploadId:
81	        uploaded_file_path = os.path.join("/tmp/server-files", item.fileUploadId)
82	        if not os.path.isdir(uploaded_file_path):

--------------------------------------------------
>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.
   Severity: Medium   Confidence: Medium
   CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html
   Location: ./server/server.py:103:38
102	    file_upload_id = "FILE_" + str(uuid1())
103	    uploaded_file_path = os.path.join("/tmp/server-files", file_upload_id)
104	    os.makedirs(uploaded_file_path)

--------------------------------------------------
>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.
   Severity: Medium   Confidence: Medium
   CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html
   Location: ./server/server_worker.py:102:34
101	        temp_dir = self.create_temp_dir()
102	        upload_dir = os.path.join("/tmp/server-files", file_upload_id)
103	        if os.path.exists(upload_dir):

--------------------------------------------------

Code scanned:
	Total lines of code: 30464
	Total lines skipped (#nosec): 0
	Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 130
		Medium: 59
		High: 8
	Total issues (by confidence):
		Undefined: 0
		Low: 44
		Medium: 40
		High: 113
Files skipped (0):

(Truncated to last 8000 characters out of 136301)
⚠️ SPELL / lychee - 55 errors
er/descriptors/html.megalinter-descriptor.yml
[404] https://htmlhint.com/_astro/htmlhint.DIRCoA_t_Z1czEXa.webp (at 88:23) | Rejected status code: 404 Not Found
[404] https://htmlhint.com/docs/user-guide/list-rules (at 87:23) | Rejected status code: 404 Not Found

Errors in megalinter/descriptors/java.megalinter-descriptor.yml
[403] https://pmd.sourceforge.io/pmd-6.55.0/pmd_userdocs_tools_ci.html (at 136:32) | Rejected status code: 403 Forbidden

Errors in megalinter/descriptors/jsx.megalinter-descriptor.yml
[404] https://eslint-react.xyz/docs/getting-started/installation (at 80:37) | Error (cached)

Errors in megalinter/descriptors/kotlin.megalinter-descriptor.yml
[404] https://pinterest.github.io/ktlint/latest/api/custom-rule-set/ (at 69:15) | Rejected status code: 404 Not Found
[404] https://pinterest.github.io/ktlint/latest/faq/#how-do-i-suppress-errors-for-a-lineblockfile (at 38:38) | Rejected status code: 404 Not Found
[404] https://pinterest.github.io/ktlint/latest/rules/configuration-ktlint/ (at 37:37) | Rejected status code: 404 Not Found

Errors in megalinter/descriptors/kubernetes.megalinter-descriptor.yml
[404] https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/%7B%7B.Group%7D%7D/%7B%7B.ResourceKind%7D%7D_%7B%7B.ResourceAPIVersion%7D%7D.json (at 72:22) | Rejected status code: 404 Not Found

Errors in megalinter/descriptors/markdown.megalinter-descriptor.yml
[404] https://github.com/rvben/rumdl/blob/main/docs/RULES.md (at 166:23) | Rejected status code: 404 Not Found
[403] https://www.npmjs.com/package/markdown-table-formatter (at 103:17) | Rejected status code: 403 Forbidden

Errors in megalinter/descriptors/repository.megalinter-descriptor.yml
[404] https://raw.githubusercontent.com/oxsecurity/megalinter/main/docs/assets/icons/linters/betterleaks.png (at 297:26) | Rejected status code: 404 Not Found

Errors in megalinter/descriptors/rst.megalinter-descriptor.yml
[403] https://docutils.sourceforge.io/docs/ref/rst/directives.html#raw-data-pass-through (at 34:38) | Rejected status code: 403 Forbidden

Errors in megalinter/descriptors/salesforce.megalinter-descriptor.yml
[403] https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config.html (at 374:37) | Rejected status code: 403 Forbidden
[403] https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/engine-flow.html (at 371:17) | Rejected status code: 403 Forbidden
[403] https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/get-started.html (at 176:17) | Error (cached)
[403] https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/get-started.html (at 276:17) | Error (cached)
[403] https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/get-started.html (at 74:17) | Rejected status code: 403 Forbidden
[403] https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/rules-flow.html (at 373:23) | Rejected status code: 403 Forbidden

Errors in megalinter/descriptors/shared/biome.megalinter-linter.yml
[404] https://biomejs.dev/linter/rules/ (at 21:19) | Rejected status code: 404 Not Found

Errors in megalinter/descriptors/shared/cppcheck.megalinter-linter.yml
[403] https://cppcheck.sourceforge.io/ (at 3:13) | Rejected status code: 403 Forbidden
[403] https://cppcheck.sourceforge.io/ (at 4:14) | Rejected status code: 403 Forbidden
[403] https://cppcheck.sourceforge.io/manual.html#configuration (at 8:33) | Rejected status code: 403 Forbidden

Errors in megalinter/descriptors/spell.megalinter-descriptor.yml
[404] https://vale.sh/docs/topics/vocab/ (at 190:38) | Rejected status code: 404 Not Found | Followed 2 redirects. Redirects: https://vale.sh/docs/topics/vocab/ --[301]--> https://docs.vale.sh/topics/vocab/ --[302]--> https://docs.vale.sh/topics/vocab
[404] https://vale.sh/docs/vale-cli/structure/ (at 183:95) | Rejected status code: 404 Not Found | Followed 2 redirects. Redirects: https://vale.sh/docs/vale-cli/structure/ --[301]--> https://docs.vale.sh/vale-cli/structure/ --[302]--> https://docs.vale.sh/vale-cli/structure

Errors in megalinter/descriptors/terraform.megalinter-descriptor.yml
[404] https://github.com/gruntwork-io/terragrunt/blob/master/docs/assets/img/favicon/ms-icon-310x310.png (at 124:23) | Rejected status code: 404 Not Found | Followed 1 redirect. Redirects: https://github.com/gruntwork-io/terragrunt/blob/master/docs/assets/img/favicon/ms-icon-310x310.png --[302]--> https://github.com/gruntwork-io/terragrunt/blob/main/docs/assets/img/favicon/ms-icon-310x310.png

Errors in megalinter/descriptors/tsx.megalinter-descriptor.yml
[404] https://eslint-react.xyz/docs/getting-started/installation (at 81:37) | Rejected status code: 404 Not Found

Errors in megalinter/descriptors/xml.megalinter-descriptor.yml
[406] https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home (at 38:17) | Rejected status code: 406 Not Acceptable

Errors in README.md
[ERROR] https://ampcode.com/ (at 248:1) | HTTP/2 protocol error. Server may not support HTTP/2 properly
[301] https://future-architect.github.io/authors/%E5%AE%AE%E6%B0%B8%E5%B4%87%E5%8F%B2 (at 2034:104) | Rejected status code: 301 Moved Permanently
[TIMEOUT] https://generated.at/ (at 1370:301) | Request timed out
[404] https://github.com/oxsecurity/megalinter/stargazers (at 2200:3) | Rejected status code: 404 Not Found
[404] https://github.com/oxsecurity/megalinter/stargazers/ (at 23:1) | Error (cached)
[403] https://javascript.plainenglish.io/node-js-coding-standard-tools-with-megalinter-on-gitlab-ci-a43b55915811 (at 2017:3) | Rejected status code: 403 Forbidden
[403] https://medium.com/@caodanju/30-seconds-to-setup-megalinter-your-go-to-tool-for-automated-code-quality-and-iac-security-969d90a5a99c (at 2002:3) | Rejected status code: 403 Forbidden
[403] https://medium.com/@RunningMattress (at 2011:255) | Rejected status code: 403 Forbidden
[403] https://medium.com/@RunningMattress/level-up-your-unity-packages-with-ci-cd-9498d2791211 (at 2011:3) | Rejected status code: 403 Forbidden
[403] https://medium.com/@SeasonedDeveloper (at 1998:255) | Rejected status code: 403 Forbidden
[403] https://medium.com/@SeasonedDeveloper/looking-for-the-best-ci-cd-pipeline-linting-tool-try-megalinter-d89c9eba850d (at 1998:3) | Rejected status code: 403 Forbidden
[403] https://medium.com/datamindedbe/integrating-megalinter-to-automate-linting-across-multiple-codebases-a-technical-description-a200bb235b71 (at 1999:3) | Rejected status code: 403 Forbidden
[403] https://nicolas.vuillamy.fr/improve-uniformize-and-secure-your-code-base-with-megalinter-62ebab422c1 (at 2020:3) | Rejected status code: 403 Forbidden
[403] https://nicolas.vuillamy.fr/megalinter-sells-his-soul-and-joins-ox-security-2a91a0027628 (at 2019:3) | Rejected status code: 403 Forbidden
[403] https://nklya.medium.com/ (at 2016:255) | Rejected status code: 403 Forbidden
[403] https://nklya.medium.com/hot-to-linter-basic-things-like-trailing-whitespaces-and-newlines-7b40da8f688d (at 2016:3) | Rejected status code: 403 Forbidden
[403] https://npmjs.org/package/mega-linter-runner (at 1285:1) | Error (cached)
[403] https://npmjs.org/package/mega-linter-runner (at 1286:1) | Error (cached)
[403] https://npmjs.org/package/mega-linter-runner (at 1287:1) | Error (cached)
[403] https://npmjs.org/package/mega-linter-runner (at 21:1) | Error (cached)
[403] https://openai.com/codex/ (at 240:1) | Rejected status code: 403 Forbidden
[403] https://pmd.sourceforge.io/pmd-6.55.0/pmd_userdocs_tools_ci.html (at 2105:3) | Error (cached)
[403] https://www.npmjs.com/package/@downatthebottomofthemolehole/megalinter-mcp-server (at 1976:354) | Rejected status code: 403 Forbidden

Hint: Followed 787 redirects. You might want to consider replacing redirecting URLs with the resolved URLs. Use verbose mode (`-v`/`-vv`) to see redirection details.
Hint: Rejected redirectional status codes. This means some redirects were not followed. You might want to increase the limit for `-m`/`--max-redirects`.

(Truncated to last 8000 characters out of 32933)
⚠️ MARKDOWN / markdownlint - 353 errors
in the same document [Context: "Docker container"]
docs/install-drone.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Drone CI"]
docs/install-github.md:10 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "GitHub Action"]
docs/install-gitlab.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "GitLab CI"]
docs/install-jenkins.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Jenkins"]
docs/install-jenkins.md:40 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "PR Comment Reporting from Jenk..."]
docs/install-locally.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Run MegaLinter locally"]
docs/install-version.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Which version to use ?"]
docs/license-explanations.md:7 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Why AGPL V3 License ?"]
docs/mega-linter-vs-super-linter.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "MegaLinter vs Super-Linter"]
docs/plugins.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Plugins"]
docs/quick-start.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Quick Start"]
docs/removed-linters.md:9 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Removed linters"]
docs/reporters.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Reporters"]
docs/reporters/AzureCommentReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Azure Comment Reporter"]
docs/reporters/BitbucketCommentReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Bitbucket Comment Reporter"]
docs/reporters/ConfigReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "IDE Configuration Reporter"]
docs/reporters/ConsoleReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Console Reporter"]
docs/reporters/EmailReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "E-mail Reporter"]
docs/reporters/FileIoReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "File.io Reporter"]
docs/reporters/GitHubCommentReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "GitHub Comment Reporter"]
docs/reporters/GitHubCommentReporter.md:27:196 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:27:46 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:27:174 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:27:196 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:28:179 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:28:46 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:28:160 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:28:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:29:159 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:29:48 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:29:143 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:29:159 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:30:171 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:30:46 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:30:152 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:30:171 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubStatusReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "GitHub Status Reporter"]
docs/reporters/GitlabCommentReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Gitlab Comment Reporter"]
docs/reporters/JsonReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "JSON Reporter"]
docs/reporters/MarkdownSummaryReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Markdown Summary Reporter"]
docs/reporters/SarifReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "SARIF Reporter (beta)"]
docs/reporters/TapReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "TAP Reporter"]
docs/reporters/TextReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Text Reporter"]
docs/reporters/UpdatedSourcesReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Updated Sources Reporter"]
docs/special-thanks.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Special thanks"]
docs/special-thanks.md:23:3 error MD045/no-alt-text Images should have alternate text (alt text)
docs/sponsor.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Sponsoring"]
docs/supported-linters.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Supported Linters"]
mega-linter-runner/README.md:27:274 error MD051/link-fragments Link fragments should be valid [Context: "[**apply formatting and auto-fixes**](#apply-fixes)"]
mega-linter-runner/README.md:27:217 error MD051/link-fragments Link fragments should be valid [Context: "[**reports in several formats**](#reports)"]
README.md:220:127 error MD051/link-fragments Link fragments should be valid [Context: "[many additional features](#mega-linter-vs-super-linter)"]
README.md:2227:3 error MD045/no-alt-text Images should have alternate text (alt text)
skills/megalinter-check/performance.md:27:601 error MD013/line-length Line length [Expected: 600; Actual: 713]
skills/megalinter-setup/agents/megalinter-runner.md:33:601 error MD013/line-length Line length [Expected: 600; Actual: 620]

(Truncated to last 8000 characters out of 46725)
⚠️ YAML / prettier - 14 errors
proselint/Hedging.yml 2ms (unchanged)
.github/linters/valestyles/proselint/Hyperbole.yml 3ms (unchanged)
.github/linters/valestyles/proselint/Jargon.yml 1ms (unchanged)
.github/linters/valestyles/proselint/LGBTOffensive.yml 2ms (unchanged)
.github/linters/valestyles/proselint/LGBTTerms.yml 2ms (unchanged)
.github/linters/valestyles/proselint/Malapropisms.yml 1ms (unchanged)
.github/linters/valestyles/proselint/Needless.yml 42ms (unchanged)
.github/linters/valestyles/proselint/Nonwords.yml 6ms (unchanged)
.github/linters/valestyles/proselint/Oxymorons.yml 5ms (unchanged)
.github/linters/valestyles/proselint/P-Value.yml 2ms (unchanged)
.github/linters/valestyles/proselint/RASSyndrome.yml 5ms (unchanged)
.github/linters/valestyles/proselint/Skunked.yml 2ms (unchanged)
.github/linters/valestyles/proselint/Spelling.yml 4ms (unchanged)
.github/linters/valestyles/proselint/Typography.yml 3ms (unchanged)
.github/linters/valestyles/proselint/Uncomparables.yml 4ms (unchanged)
.github/linters/valestyles/proselint/Very.yml 1ms (unchanged)
.github/release-drafter.yml 13ms (unchanged)
.grype.yaml 3ms (unchanged)
.mega-linter.yml 11ms (unchanged)
.pre-commit-hooks.yaml 9ms (unchanged)
action.yml 3ms (unchanged)
codecov.yml 1ms (unchanged)
mega-linter-runner/.eslintrc.yml 4ms (unchanged)
mega-linter-runner/.mega-linter.yml 8ms (unchanged)
mega-linter-runner/generators/mega-linter-custom-flavor/templates/action.yml 4ms (unchanged)
mega-linter-runner/generators/mega-linter-custom-flavor/templates/check-new-megalinter-version.yml 15ms (unchanged)
mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor-builder.yml 17ms (unchanged)
[error] mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor.yml: SyntaxError: Implicit map keys need to be followed by map values (6:1)
[error]   4 | label: <%= CUSTOM_FLAVOR_LABEL %>
[error]   5 | linters:
[error] > 6 | <%= CUSTOM_FLAVOR_LINTERS %>
[error]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]   7 |
mega-linter-runner/generators/mega-linter-custom-flavor/templates/zizmor.yml 2ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/.drone.yml 5ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/.gitlab-ci.yml 13ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/azure-pipelines.yml 3ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/bitbucket-pipelines.yml 4ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/concourse-task.yml 2ms (unchanged)
[error] mega-linter-runner/generators/mega-linter/templates/mega-linter.yml: SyntaxError: Implicit map keys need to be followed by map values (67:11)
[error]   65 |           # Only define `secrets.PAT` if you fully understand the trade-off.
[error]   66 |           token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }}
[error] > 67 |           <%- PERSIST_CREDENTIALS %>
[error]      |           ^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]   68 |
[error]   69 |           # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to
[error]   70 |           # improve performance
megalinter/descriptors/action.megalinter-descriptor.yml 14ms (unchanged)
megalinter/descriptors/ansible.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/api.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/arm.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/bash.megalinter-descriptor.yml 20ms (unchanged)
megalinter/descriptors/bicep.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/c.megalinter-descriptor.yml 3ms (unchanged)
megalinter/descriptors/clojure.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/cloudformation.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/coffee.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/copypaste.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/cpp.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/csharp.megalinter-descriptor.yml 11ms (unchanged)
megalinter/descriptors/css.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/dart.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/dockerfile.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/editorconfig.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/env.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/gherkin.megalinter-descriptor.yml 3ms (unchanged)
megalinter/descriptors/go.megalinter-descriptor.yml 11ms (unchanged)
megalinter/descriptors/graphql.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/groovy.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/html.megalinter-descriptor.yml 13ms (unchanged)
megalinter/descriptors/java.megalinter-descriptor.yml 19ms (unchanged)
megalinter/descriptors/javascript.megalinter-descriptor.yml 17ms (unchanged)
megalinter/descriptors/json.megalinter-descriptor.yml 13ms (unchanged)
megalinter/descriptors/jsx.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/kotlin.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/kubernetes.megalinter-descriptor.yml 19ms (unchanged)
megalinter/descriptors/latex.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/lua.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/markdown.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/perl.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/php.megalinter-descriptor.yml 21ms (unchanged)
megalinter/descriptors/powershell.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/protobuf.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/python.megalinter-descriptor.yml 98ms (unchanged)
megalinter/descriptors/r.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/raku.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/repository.megalinter-descriptor.yml 115ms (unchanged)
megalinter/descriptors/robotframework.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/rst.megalinter-descriptor.yml 11ms (unchanged)
megalinter/descriptors/ruby.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/rust.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/salesforce.megalinter-descriptor.yml 34ms (unchanged)
megalinter/descriptors/scala.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/shared/biome.megalinter-linter.yml 5ms (unchanged)
megalinter/descriptors/shared/clang-format.megalinter-linter.yml 4ms (unchanged)
megalinter/descriptors/shared/cppcheck.megalinter-linter.yml 6ms (unchanged)
megalinter/descriptors/shared/cpplint.megalinter-linter.yml 3ms (unchanged)
megalinter/descriptors/shared/dotnet-format.megalinter-linter.yml 3ms (unchanged)
megalinter/descriptors/shared/eslint.megalinter-linter.yml 9ms (unchanged)
megalinter/descriptors/shared/prettier.megalinter-linter.yml 5ms (unchanged)
megalinter/descriptors/shared/v8r.megalinter-linter.yml 3ms (unchanged)
megalinter/descriptors/snakemake.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/spell.megalinter-descriptor.yml 27ms (unchanged)
megalinter/descriptors/sql.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/swift.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/tekton.megalinter-descriptor.yml 3ms (unchanged)
megalinter/descriptors/terraform.megalinter-descriptor.yml 71ms (unchanged)
megalinter/descriptors/tsx.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/typescript.megalinter-descriptor.yml 19ms (unchanged)
megalinter/descriptors/vbdotnet.megalinter-descriptor.yml 3ms (unchanged)
megalinter/descriptors/xml.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/yaml.megalinter-descriptor.yml 9ms (unchanged)
server/docker-compose-dev.yml 4ms (unchanged)
server/docker-compose.yml 3ms (unchanged)
trivy-secret.yaml 2ms (unchanged)
zizmor.yml 2ms (unchanged)

(Truncated to last 8000 characters out of 12553)
⚠️ YAML / yamllint - 50 errors
.grype.yaml
  6:1       warning  missing document start "---"  (document-start)

mega-linter-runner/.eslintrc.yml
  11:9      warning  too few spaces inside empty braces  (braces)

mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor-builder.yml
  48:15     warning  too few spaces inside empty braces  (braces)

mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor.yml
  7:1       error    syntax error: could not find expected ':' (syntax)

mega-linter-runner/generators/mega-linter/templates/mega-linter.yml
  38:15     warning  too few spaces inside empty braces  (braces)
  69:11     error    syntax error: could not find expected ':' (syntax)

megalinter/descriptors/copypaste.megalinter-descriptor.yml
  19:301    warning  line too long (313 > 300 characters)  (line-length)
  25:301    warning  line too long (384 > 300 characters)  (line-length)

megalinter/descriptors/javascript.megalinter-descriptor.yml
  52:301    warning  line too long (475 > 300 characters)  (line-length)
  328:301   warning  line too long (307 > 300 characters)  (line-length)
  354:301   warning  line too long (315 > 300 characters)  (line-length)

megalinter/descriptors/json.megalinter-descriptor.yml
  112:301   warning  line too long (315 > 300 characters)  (line-length)

megalinter/descriptors/jsx.megalinter-descriptor.yml
  29:301    warning  line too long (475 > 300 characters)  (line-length)

megalinter/descriptors/perl.megalinter-descriptor.yml
  25:301    warning  line too long (310 > 300 characters)  (line-length)

megalinter/descriptors/php.megalinter-descriptor.yml
  200:301   warning  line too long (389 > 300 characters)  (line-length)
  214:301   warning  line too long (302 > 300 characters)  (line-length)

megalinter/descriptors/repository.megalinter-descriptor.yml
  27:301    warning  line too long (666 > 300 characters)  (line-length)
  193:301   warning  line too long (408 > 300 characters)  (line-length)
  299:301   warning  line too long (345 > 300 characters)  (line-length)
  537:301   warning  line too long (306 > 300 characters)  (line-length)
  616:301   warning  line too long (374 > 300 characters)  (line-length)
  701:301   warning  line too long (316 > 300 characters)  (line-length)
  1038:301  warning  line too long (1263 > 300 characters)  (line-length)
  1135:301  warning  line too long (879 > 300 characters)  (line-length)
  1149:301  warning  line too long (358 > 300 characters)  (line-length)
  1212:301  warning  line too long (346 > 300 characters)  (line-length)
  1219:301  warning  line too long (307 > 300 characters)  (line-length)

megalinter/descriptors/salesforce.megalinter-descriptor.yml
  54:301    warning  line too long (359 > 300 characters)  (line-length)

megalinter/descriptors/spell.megalinter-descriptor.yml
  181:301   warning  line too long (315 > 300 characters)  (line-length)

megalinter/descriptors/sql.megalinter-descriptor.yml
  27:301    warning  line too long (403 > 300 characters)  (line-length)

megalinter/descriptors/terraform.megalinter-descriptor.yml
  28:301    warning  line too long (330 > 300 characters)  (line-length)
  43:301    warning  line too long (330 > 300 characters)  (line-length)
  97:301    warning  line too long (346 > 300 characters)  (line-length)
  164:301   warning  line too long (328 > 300 characters)  (line-length)
  239:301   warning  line too long (307 > 300 characters)  (line-length)
  250:301   warning  line too long (386 > 300 characters)  (line-length)
  304:301   warning  line too long (302 > 300 characters)  (line-length)
  319:301   warning  line too long (334 > 300 characters)  (line-length)
  329:301   warning  line too long (525 > 300 characters)  (line-length)
  339:301   warning  line too long (315 > 300 characters)  (line-length)
  343:301   warning  line too long (436 > 300 characters)  (line-length)

megalinter/descriptors/tsx.megalinter-descriptor.yml
  29:301    warning  line too long (475 > 300 characters)  (line-length)

megalinter/descriptors/typescript.megalinter-descriptor.yml
  39:301    warning  line too long (475 > 300 characters)  (line-length)
  318:301   warning  line too long (314 > 300 characters)  (line-length)
  344:301   warning  line too long (315 > 300 characters)  (line-length)

megalinter/descriptors/yaml.megalinter-descriptor.yml
  38:301    warning  line too long (315 > 300 characters)  (line-length)

mkdocs.yml
  8:301     warning  line too long (590 > 300 characters)  (line-length)
  86:5      warning  wrong indentation: expected 6 but found 4  (indentation)
  100:5     warning  wrong indentation: expected 6 but found 4  (indentation)

zizmor.yml
  1:1       warning  missing document start "---"  (document-start)

✅ Linters with no issues

actionlint, bash-exec, betterleaks, black, checkov, cspell, flake8, git_diff, grype, hadolint, isort, jscpd, jsonlint, markdown-table-formatter, mypy, npm-groovy-lint, osv-scanner, pylint, ruff, secretlint, shellcheck, shfmt, spectral, syft, trivy, trivy-sbom, trufflehog, v8r, v8r, xmllint, zizmor

See detailed reports in MegaLinter artifacts

MegaLinter is provided by OX Security
Show us your support by starring ⭐ the repository

The CHANGELOG entry naming the removed template block was the only
blocking cspell error.
markdownlint --fix strips the significant trailing space from the
error-format regexes in skills/megalinter-fix/linters/*.md (MD038). That
corrupted the documented regex and left the tree dirty, so the auto-fix
commit step aborted its checkout on every pull request. Those files are
generated and already excluded from cspell and lychee.
The good and bad fixtures were identical except for a basic-auth
credential on the-internet.herokuapp.com: trufflehog reported the bad one
only after authenticating against that site, so the tests failed whenever
the runner could not reach it, as happened on this branch.

The fixtures now differ by what is detected rather than by what verifies,
and pre_test drops --only-verified, which stays the production default.
The .wireit poison gains a private key so the excluded-directories
forwarding guard fires instead of being vacuous.

Validated offline with trufflehog 3.97.0: good 0 findings, good with
.wireit kept 1, bad 4.
@nvuillam
nvuillam merged commit 6681060 into main Aug 31, 2026
152 of 153 checks passed
@nvuillam
nvuillam deleted the docs/migrate-to-zensical branch August 31, 2026 18:22
nvuillam added a commit that referenced this pull request Sep 5, 2026
build.sh builds the documentation site with `zensical build` since the
MkDocs to Zensical migration (#8848), but entrypoint.sh still installed
the MkDocs stack (mike, mkdocs-material, mkdocs-glightbox) before running
it. The Auto-Update Linters job has therefore failed with
`build.sh: line 20: zensical: command not found` (exit code 127) on every
run since 2026-09-04, after the linter versions and the docs had already
been regenerated, so no update pull request was ever created.

Swap the three unused MkDocs packages for zensical, keeping the list in
sync with .config/python/dev/requirements.txt as its header asks.
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.

2 participants