repomatic 7.8.0__tar.gz → 7.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {repomatic-7.8.0 → repomatic-7.9.0}/PKG-INFO +2 -2
- {repomatic-7.8.0 → repomatic-7.9.0}/pyproject.toml +5 -5
- {repomatic-7.8.0 → repomatic-7.9.0}/pyproject.toml.orig +5 -5
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/__init__.py +2 -2
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/cli.py +48 -3
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/config.py +15 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/_release-engine.yaml +147 -21
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/agent-sphinx-docs.md +10 -7
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/autofix.yaml +46 -45
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/autolock.yaml +4 -3
- repomatic-7.9.0/repomatic/data/awesome_template/.github/code-of-conduct.md +43 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/cancel-runs.yaml +5 -4
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/changelog.yaml +18 -17
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/debug.yaml +6 -5
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/docs.yaml +23 -7
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/labels.yaml +10 -9
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/lint.yaml +13 -12
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/release.yaml +23 -5
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/babysit-ci/SKILL.md +3 -3
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/repomatic-deps/SKILL.md +1 -1
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/repomatic-ship/SKILL.md +6 -2
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/tests.yaml +8 -7
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/unsubscribe.yaml +5 -4
- repomatic-7.9.0/repomatic/data/yamllint.yaml +12 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/gh.py +40 -21
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/token.py +16 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/workflow_sync.py +26 -7
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/gitignore.py +38 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/init_project.py +65 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/lint_repo.py +48 -13
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/metadata.py +112 -27
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/prepare_release.py +13 -2
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/setup_guide.py +41 -18
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-token.md +2 -1
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/tool_registry.py +4 -1
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/tool_runner.py +115 -6
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/version_sync.py +8 -1
- repomatic-7.8.0/repomatic/data/awesome_template/.github/code-of-conduct.md +0 -70
- repomatic-7.8.0/repomatic/data/yamllint.yaml +0 -6
- {repomatic-7.8.0 → repomatic-7.9.0}/license +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/readme.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/__main__.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/attestation.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/awesome_toc.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/binaries_page.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/binary.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/broken_links.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/bundle.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/cache.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/changelog.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/checksums.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/compat.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/__init__.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/action-publish-pypi.yaml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/agent-grunt-qa.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/agent-qa-engineer.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/new-link.yaml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/.github/contributing.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/.github/contributing.zh.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/.github/funding.yml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/.github/pull_request_template.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/__init__.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/awesome_template/license +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/bumpversion.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/coverage.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/labeller-content-based.yaml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/labeller-file-based.yaml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/labels.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/lychee.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/mdformat.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/mypy.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/pytest.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/ruff.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/av-false-positive/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/awesome-triage/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/benchmark-update/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/brand-assets/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/file-bug-report/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/github-housekeeping/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/repomatic-audit/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/repomatic-changelog/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/repomatic-init/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/repomatic-topics/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/sphinx-docs-sync/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/translation-sync/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/skills/upstream-audit/SKILL.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/typos.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/uv.toml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/vt-trend-chart.js +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/data/zizmor.yaml +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/dep_graph.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/dep_report.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/dep_sources.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/docs.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/frontmatter.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/git_ops.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/__init__.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/actions.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/dev_release.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/issue.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/matrix.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/pr_body.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/release_sync.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/releases.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/sponsor.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/status.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/github/unsubscribe.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/http.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/humanize.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/images.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/labels.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/mailmap.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/matrix_axes.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/npm.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/plugin.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/py.typed +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/pypi.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/pyproject.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/registry.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/sync_ops.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/__init__.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/available-admonition.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/broken-links-issue.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/bump-version.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/detect-squash-merge.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/development-warning.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/fix-changelog.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/fix-typos.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/fix-vulnerable-deps.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/format-images.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/format-json.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/format-markdown.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/format-pyproject.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/format-python.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/format-shell.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/generated-footer.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/github-releases.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/immutable-releases.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/pr-metadata.md.noformat +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/prepare-release.md.noformat +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/refresh-tip.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/release-notes.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/release-sync-report.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-branch-ruleset.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-dependabot.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-fork-pr-approval.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-notifications-pat.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-pages-source.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-pypi-trusted-publisher.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-sha-pinning-required.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-verify.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide-virustotal.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/setup-guide.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-action-pins.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-bumpversion.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-dep-sources.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-gitignore.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-mailmap.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-repomatic.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-tool-versions.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-uv-lock.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/sync-workflow-pins.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/unavailable-admonition.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/unsubscribe-phase1.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/unsubscribe-phase2.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/update-dep-graph.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/update-docs.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/templates/yanked-admonition.md +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/tool_runner_page.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/uv.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/virustotal.py +0 -0
- {repomatic-7.8.0 → repomatic-7.9.0}/repomatic/vulnerable_deps.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: repomatic
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.9.0
|
|
4
4
|
Summary: 🏭 Automate repository maintenance, releases, and CI/CD workflows
|
|
5
5
|
Keywords: changelog-formatter,dependabot-alternative,github-actions,github-labels,github-workflow,gitignore,mailmap,mypy,nuitka,python-automation,release-automation,repository-automation,repository-management,reusable-workflows,software-factory,sphinx-doc,typo,uv,workflow-reusable
|
|
6
6
|
Author: Kevin Deldycke
|
|
@@ -59,7 +59,7 @@ Requires-Dist: wcmatch>=10
|
|
|
59
59
|
Requires-Python: >=3.10
|
|
60
60
|
Project-URL: Changelog, https://github.com/kdeldycke/repomatic/blob/main/changelog.md
|
|
61
61
|
Project-URL: Documentation, https://kdeldycke.github.io/repomatic
|
|
62
|
-
Project-URL: Download, https://github.com/kdeldycke/repomatic/releases/tag/v7.
|
|
62
|
+
Project-URL: Download, https://github.com/kdeldycke/repomatic/releases/tag/v7.9.0
|
|
63
63
|
Project-URL: Funding, https://github.com/sponsors/kdeldycke
|
|
64
64
|
Project-URL: Homepage, https://github.com/kdeldycke/repomatic
|
|
65
65
|
Project-URL: Issues, https://github.com/kdeldycke/repomatic/issues
|
|
@@ -4,7 +4,7 @@ requires = ["uv-build>=0.8"]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "repomatic"
|
|
7
|
-
version = "7.
|
|
7
|
+
version = "7.9.0"
|
|
8
8
|
description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
|
|
9
9
|
readme = "readme.md"
|
|
10
10
|
keywords = [
|
|
@@ -92,7 +92,7 @@ email = "kevin@deldycke.com"
|
|
|
92
92
|
[project.urls]
|
|
93
93
|
Changelog = "https://github.com/kdeldycke/repomatic/blob/main/changelog.md"
|
|
94
94
|
Documentation = "https://kdeldycke.github.io/repomatic"
|
|
95
|
-
Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.
|
|
95
|
+
Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.9.0"
|
|
96
96
|
Funding = "https://github.com/sponsors/kdeldycke"
|
|
97
97
|
Homepage = "https://github.com/kdeldycke/repomatic"
|
|
98
98
|
Issues = "https://github.com/kdeldycke/repomatic/issues"
|
|
@@ -146,7 +146,7 @@ module-root = ""
|
|
|
146
146
|
[tool.nuitka]
|
|
147
147
|
copyright = "Kevin Deldycke <kevin@deldycke.com> and contributors. Distributed under GPL-2.0-or-later license."
|
|
148
148
|
file-description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
|
|
149
|
-
file-version = "7.
|
|
149
|
+
file-version = "7.9.0"
|
|
150
150
|
include-data-dir = [
|
|
151
151
|
"repomatic/data/awesome_template=repomatic/data/awesome_template",
|
|
152
152
|
"repomatic/data/skills=repomatic/data/skills",
|
|
@@ -156,7 +156,7 @@ include-package-data = ["click_extra"]
|
|
|
156
156
|
linux-icon = "docs/assets/icon.png"
|
|
157
157
|
macos-app-icon = "docs/assets/icon.icns"
|
|
158
158
|
product-name = "Repomatic"
|
|
159
|
-
product-version = "7.
|
|
159
|
+
product-version = "7.9.0"
|
|
160
160
|
windows-icon-from-ico = "docs/assets/icon.ico"
|
|
161
161
|
|
|
162
162
|
[tool.ruff]
|
|
@@ -250,7 +250,7 @@ fail_under = 80
|
|
|
250
250
|
precision = 2
|
|
251
251
|
|
|
252
252
|
[tool.bumpversion]
|
|
253
|
-
current_version = "7.
|
|
253
|
+
current_version = "7.9.0"
|
|
254
254
|
parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.dev(?P<dev>\d+))?'
|
|
255
255
|
serialize = [
|
|
256
256
|
"{major}.{minor}.{patch}.dev{dev}",
|
|
@@ -12,7 +12,7 @@ requires = [ "uv-build>=0.8" ]
|
|
|
12
12
|
[project]
|
|
13
13
|
# Docs: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
|
|
14
14
|
name = "repomatic"
|
|
15
|
-
version = "7.
|
|
15
|
+
version = "7.9.0"
|
|
16
16
|
description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
|
|
17
17
|
readme = "readme.md"
|
|
18
18
|
keywords = [
|
|
@@ -145,7 +145,7 @@ dependencies = [
|
|
|
145
145
|
]
|
|
146
146
|
urls.Changelog = "https://github.com/kdeldycke/repomatic/blob/main/changelog.md"
|
|
147
147
|
urls.Documentation = "https://kdeldycke.github.io/repomatic"
|
|
148
|
-
urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.
|
|
148
|
+
urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.9.0"
|
|
149
149
|
urls.Funding = "https://github.com/sponsors/kdeldycke"
|
|
150
150
|
urls.Homepage = "https://github.com/kdeldycke/repomatic"
|
|
151
151
|
urls.Issues = "https://github.com/kdeldycke/repomatic/issues"
|
|
@@ -250,7 +250,7 @@ copyright = "Kevin Deldycke <kevin@deldycke.com> and contributors. Distributed u
|
|
|
250
250
|
file-description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
|
|
251
251
|
# Numeric only: Nuitka rejects PEP 440 .devN suffixes. Kept in sync with the
|
|
252
252
|
# package version by the dedicated [tool.bumpversion] rule that strips the suffix.
|
|
253
|
-
file-version = "7.
|
|
253
|
+
file-version = "7.9.0"
|
|
254
254
|
include-data-dir = [
|
|
255
255
|
"repomatic/data/awesome_template=repomatic/data/awesome_template",
|
|
256
256
|
"repomatic/data/skills=repomatic/data/skills",
|
|
@@ -269,7 +269,7 @@ include-package-data = [ "click_extra" ]
|
|
|
269
269
|
linux-icon = "docs/assets/icon.png"
|
|
270
270
|
macos-app-icon = "docs/assets/icon.icns"
|
|
271
271
|
product-name = "Repomatic"
|
|
272
|
-
product-version = "7.
|
|
272
|
+
product-version = "7.9.0"
|
|
273
273
|
windows-icon-from-ico = "docs/assets/icon.ico"
|
|
274
274
|
|
|
275
275
|
[tool.ruff]
|
|
@@ -407,7 +407,7 @@ report.fail_under = 80
|
|
|
407
407
|
report.precision = 2
|
|
408
408
|
|
|
409
409
|
[tool.bumpversion]
|
|
410
|
-
current_version = "7.
|
|
410
|
+
current_version = "7.9.0"
|
|
411
411
|
# Parse versions with an optional .devN suffix (PEP 440).
|
|
412
412
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\.dev(?P<dev>\\d+))?"
|
|
413
413
|
serialize = [
|
|
@@ -104,7 +104,12 @@ from .docs import update_docs as _update_docs
|
|
|
104
104
|
from .frontmatter import split_frontmatter
|
|
105
105
|
from .git_ops import commit_and_push_files, create_and_push_tag
|
|
106
106
|
from .github import token as _token_mod, unsubscribe as _unsub_mod
|
|
107
|
-
from .github.actions import
|
|
107
|
+
from .github.actions import (
|
|
108
|
+
AnnotationLevel,
|
|
109
|
+
cancel_superseded_runs,
|
|
110
|
+
emit_annotation,
|
|
111
|
+
format_multiline_output,
|
|
112
|
+
)
|
|
108
113
|
from .github.dev_release import (
|
|
109
114
|
cleanup_dev_releases as _cleanup_dev_releases,
|
|
110
115
|
sync_dev_release as _sync_dev_release,
|
|
@@ -144,7 +149,7 @@ from .github.unsubscribe import (
|
|
|
144
149
|
unsubscribe_threads as _unsubscribe_threads,
|
|
145
150
|
)
|
|
146
151
|
from .github.workflow_sync import run_workflow_lint
|
|
147
|
-
from .gitignore import build_gitignore
|
|
152
|
+
from .gitignore import build_gitignore, orphaned_rules
|
|
148
153
|
from .humanize import format_age, format_file_size
|
|
149
154
|
from .images import (
|
|
150
155
|
DEFAULT_MIN_SAVINGS_BYTES,
|
|
@@ -1244,8 +1249,16 @@ def close_stale_bump_pr(part: str) -> None:
|
|
|
1244
1249
|
default=None,
|
|
1245
1250
|
help=("Output path. Defaults to gitignore-location from [tool.repomatic] config."),
|
|
1246
1251
|
)
|
|
1252
|
+
@option(
|
|
1253
|
+
"--drop-orphans/--no-drop-orphans",
|
|
1254
|
+
default=False,
|
|
1255
|
+
help=(
|
|
1256
|
+
"Overwrite rules found on disk but absent from the generated file, "
|
|
1257
|
+
"instead of refusing to drop them."
|
|
1258
|
+
),
|
|
1259
|
+
)
|
|
1247
1260
|
@pass_context
|
|
1248
|
-
def sync_gitignore(ctx: Context, output_path: Path | None) -> None:
|
|
1261
|
+
def sync_gitignore(ctx: Context, output_path: Path | None, drop_orphans: bool) -> None:
|
|
1249
1262
|
"""Sync a .gitignore file from gitignore.io templates.
|
|
1250
1263
|
|
|
1251
1264
|
Fetches templates for a base set of categories plus any extras from
|
|
@@ -1253,6 +1266,11 @@ def sync_gitignore(ctx: Context, output_path: Path | None) -> None:
|
|
|
1253
1266
|
Writes to the path specified by gitignore-location (default
|
|
1254
1267
|
./.gitignore).
|
|
1255
1268
|
|
|
1269
|
+
The generated file is the whole file: nothing is read back from the copy on
|
|
1270
|
+
disk. A rule added there by hand is therefore dropped on the next sync, so
|
|
1271
|
+
the write aborts when it would lose one. Move the rule into
|
|
1272
|
+
gitignore-extra-content to keep it, or pass --drop-orphans to let it go.
|
|
1273
|
+
|
|
1256
1274
|
\b
|
|
1257
1275
|
Examples:
|
|
1258
1276
|
# Generate .gitignore using config from pyproject.toml
|
|
@@ -1275,6 +1293,32 @@ def sync_gitignore(ctx: Context, output_path: Path | None) -> None:
|
|
|
1275
1293
|
if output_path is None:
|
|
1276
1294
|
output_path = Path(config.gitignore.location)
|
|
1277
1295
|
|
|
1296
|
+
# Compare against what is already there before overwriting it. Skipped for
|
|
1297
|
+
# stdout, which destroys nothing, and for a first run, which has nothing to
|
|
1298
|
+
# destroy.
|
|
1299
|
+
if not drop_orphans and str(output_path) != "-" and output_path.is_file():
|
|
1300
|
+
orphans = orphaned_rules(output_path.read_text(encoding="UTF-8"), content)
|
|
1301
|
+
if orphans:
|
|
1302
|
+
emit_annotation(
|
|
1303
|
+
AnnotationLevel.ERROR,
|
|
1304
|
+
f"{output_path}: sync would drop {len(orphans)} hand-added "
|
|
1305
|
+
f"rule(s): {', '.join(orphans)}",
|
|
1306
|
+
)
|
|
1307
|
+
echo(
|
|
1308
|
+
f"Refusing to overwrite {output_path}: "
|
|
1309
|
+
f"{len(orphans)} rule(s) on disk are absent from the generated "
|
|
1310
|
+
"file and would be lost.",
|
|
1311
|
+
err=True,
|
|
1312
|
+
)
|
|
1313
|
+
for rule in orphans:
|
|
1314
|
+
echo(f" {rule}", err=True)
|
|
1315
|
+
echo(
|
|
1316
|
+
"\nMove them into [tool.repomatic.gitignore] extra-content to "
|
|
1317
|
+
"keep them, or re-run with --drop-orphans to discard them.",
|
|
1318
|
+
err=True,
|
|
1319
|
+
)
|
|
1320
|
+
ctx.exit(1)
|
|
1321
|
+
|
|
1278
1322
|
log_output_target(".gitignore", output_path)
|
|
1279
1323
|
|
|
1280
1324
|
echo(content.rstrip(), file=prep_path(output_path))
|
|
@@ -3166,6 +3210,7 @@ def lint_repo(
|
|
|
3166
3210
|
exit_code = run_repo_lint(
|
|
3167
3211
|
package_name=package_name,
|
|
3168
3212
|
repo_name=repo_name,
|
|
3213
|
+
is_package=metadata.is_python_package,
|
|
3169
3214
|
is_sphinx=is_sphinx,
|
|
3170
3215
|
project_description=project_description,
|
|
3171
3216
|
keywords=keywords,
|
|
@@ -869,6 +869,21 @@ class Config:
|
|
|
869
869
|
PAT with `notifications` scope stored as `REPOMATIC_NOTIFICATIONS_PAT`.
|
|
870
870
|
"""
|
|
871
871
|
|
|
872
|
+
nuitka_dev_targets: list[str] = field(
|
|
873
|
+
default_factory=lambda: ["linux-arm64"],
|
|
874
|
+
metadata={CONFIG_PATH_METADATA_KEY: "nuitka.dev-targets"},
|
|
875
|
+
)
|
|
876
|
+
"""Nuitka build targets compiled on ordinary pushes, as a canary.
|
|
877
|
+
|
|
878
|
+
An ordinary push to the default branch rebuilds binaries only for these
|
|
879
|
+
targets: enough to catch a compilation break early, while freeing runner
|
|
880
|
+
slots the full fleet would occupy on every code push just to refresh the
|
|
881
|
+
rolling dev pre-release (a draft). The full target roster still builds on
|
|
882
|
+
release commits, on the weekly `schedule` trigger, and on
|
|
883
|
+
`workflow_dispatch`. Defaults to `["linux-arm64"]`, the fastest and
|
|
884
|
+
cheapest builder. Set to `[]` to skip dev builds entirely.
|
|
885
|
+
"""
|
|
886
|
+
|
|
872
887
|
nuitka_enabled: bool = field(
|
|
873
888
|
default=True,
|
|
874
889
|
metadata={CONFIG_PATH_METADATA_KEY: "nuitka.enabled"},
|
|
@@ -30,9 +30,10 @@ permissions: {}
|
|
|
30
30
|
# Supply-chain cooldown: no package published within the window can be resolved by
|
|
31
31
|
# any command in this workflow. Set here, not per command, so it also covers the
|
|
32
32
|
# `metadata` bootstrap and any step added later; a workflow-level `env:` cannot
|
|
33
|
-
# reference `needs`, so the window is a literal
|
|
34
|
-
#
|
|
35
|
-
#
|
|
33
|
+
# reference `needs`, so the window is a literal kept equal to `[tool.repomatic]
|
|
34
|
+
# minimum-release-age`. repomatic's own test suite enforces that upstream; a
|
|
35
|
+
# synced copy is kept in step by hand. Deliberate bypasses are per-package CLI
|
|
36
|
+
# flags (`--exclude-newer-package`, `--min-release-age-exclude`).
|
|
36
37
|
# See claude.md for the rationale.
|
|
37
38
|
env:
|
|
38
39
|
NPM_CONFIG_MIN_RELEASE_AGE: 7
|
|
@@ -64,7 +65,7 @@ jobs:
|
|
|
64
65
|
- name: Run repomatic metadata
|
|
65
66
|
id: metadata
|
|
66
67
|
run: >
|
|
67
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
68
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' metadata
|
|
68
69
|
--format github-json --output "$GITHUB_OUTPUT"
|
|
69
70
|
new_commits_matrix release_commits_matrix build_targets nuitka_matrix
|
|
70
71
|
nuitka_extras is_python_project package_name current_version
|
|
@@ -102,10 +103,28 @@ jobs:
|
|
|
102
103
|
container: ${{ matrix.container }}
|
|
103
104
|
# We keep going when a job flagged as not stable fails.
|
|
104
105
|
continue-on-error: ${{ matrix.state == 'unstable' }}
|
|
106
|
+
# Headroom over the slowest measured cold-cache compile job (17.4 min on
|
|
107
|
+
# windows-x64); see docs/nuitka.md § Compile caching for the full table.
|
|
108
|
+
# Without it a hung compile squats a runner-cap slot for the 360-min default.
|
|
109
|
+
timeout-minutes: 45
|
|
105
110
|
permissions:
|
|
106
111
|
id-token: write
|
|
107
112
|
attestations: write
|
|
108
113
|
contents: read
|
|
114
|
+
env:
|
|
115
|
+
# Relocate every Nuitka cache (ccache/clcache objects, downloads,
|
|
116
|
+
# bytecode) under the workspace, so the cache step below and Nuitka
|
|
117
|
+
# agree on one path both on VM jobs and inside the manylinux containers.
|
|
118
|
+
NUITKA_CACHE_DIR: ${{ github.workspace }}/.nuitka-cache
|
|
119
|
+
# Two ccache settings cross-VM hits depend on: hash the compiler
|
|
120
|
+
# binary's content (the default mtime+size check trips on runner VMs,
|
|
121
|
+
# which do not keep stable file timestamps) and tolerate
|
|
122
|
+
# __DATE__/__TIME__ macros. The cache-prep step below also writes both
|
|
123
|
+
# into $CCACHE_DIR/ccache.conf, so whichever channel reaches the
|
|
124
|
+
# wrapper carries the same values. Nuitka's internal clcache on MSVC
|
|
125
|
+
# ignores both settings.
|
|
126
|
+
CCACHE_COMPILERCHECK: content
|
|
127
|
+
CCACHE_SLOPPINESS: time_macros
|
|
109
128
|
steps:
|
|
110
129
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
111
130
|
with:
|
|
@@ -113,6 +132,70 @@ jobs:
|
|
|
113
132
|
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
114
133
|
with:
|
|
115
134
|
version: "0.12.1"
|
|
135
|
+
# Persist the Nuitka compile caches across runs: ccache objects on gcc
|
|
136
|
+
# targets, Nuitka's internal clcache objects on MSVC, plus downloads
|
|
137
|
+
# and demoted-module bytecode. The per-commit key never hits exactly,
|
|
138
|
+
# so every run saves a fresh snapshot and restores the latest previous
|
|
139
|
+
# one via the prefix; ccache/clcache hash compiler, flags and sources
|
|
140
|
+
# themselves, so a stale snapshot degrades to cache misses, never to
|
|
141
|
+
# wrong objects. Two exclusions:
|
|
142
|
+
# - Release commits build cold, on purpose: a cache entry is writable
|
|
143
|
+
# by any code running in any main-ref workflow (the cache API is not
|
|
144
|
+
# gated by `permissions:`), and its restore is a tar extraction into
|
|
145
|
+
# the workspace, so a poisoned entry could reach a signed, published,
|
|
146
|
+
# immutable binary. Skipping restore AND save on release commits
|
|
147
|
+
# keeps every published artifact compiled from source on a fresh VM;
|
|
148
|
+
# canary and weekly runs keep the warm-cache speed.
|
|
149
|
+
# - macOS is excluded entirely: its ccache scored 0/470 cross-VM hits
|
|
150
|
+
# through every configuration channel tried (CCACHE_* env vars, then
|
|
151
|
+
# ccache.conf inside this very cache dir), so persisting it only paid
|
|
152
|
+
# restore/save overhead for entries that never hit. Capture Nuitka's
|
|
153
|
+
# CCACHE_LOGFILE from a scheduled run to diagnose before re-enabling.
|
|
154
|
+
- name: Restore Nuitka compile cache
|
|
155
|
+
if: >-
|
|
156
|
+
matrix.platform_id != 'macos'
|
|
157
|
+
&& !fromJSON(needs.metadata.outputs.metadata).release_commits_matrix
|
|
158
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
159
|
+
with:
|
|
160
|
+
path: .nuitka-cache
|
|
161
|
+
key: nuitka-${{ matrix.target }}-${{ matrix.commit }}
|
|
162
|
+
restore-keys: nuitka-${{ matrix.target }}-
|
|
163
|
+
# Two duties. Trim: Nuitka's clcache has no size cap or pruning (ccache
|
|
164
|
+
# self-prunes at 5 GiB), so left alone a restore-then-save cycle grows
|
|
165
|
+
# the cache without bound; reset past 2 GiB and let the next save start
|
|
166
|
+
# a fresh lineage. Configure: write ccache's settings inside the cache
|
|
167
|
+
# dir itself, the one channel that reliably reaches the wrapper (ccache
|
|
168
|
+
# always reads $CCACHE_DIR/ccache.conf, while the job-level CCACHE_*
|
|
169
|
+
# env vars above die with scons's scrubbed compiler environment).
|
|
170
|
+
- name: Prepare Nuitka cache
|
|
171
|
+
if: >-
|
|
172
|
+
matrix.platform_id != 'macos'
|
|
173
|
+
&& !fromJSON(needs.metadata.outputs.metadata).release_commits_matrix
|
|
174
|
+
shell: bash
|
|
175
|
+
run: |
|
|
176
|
+
if [[ -d .nuitka-cache ]]; then
|
|
177
|
+
size_mb=$(du -sm .nuitka-cache | cut -f1)
|
|
178
|
+
echo "Nuitka cache restored at ${size_mb} MiB."
|
|
179
|
+
if (( size_mb > 2048 )); then
|
|
180
|
+
echo "Cache exceeds 2 GiB, resetting."
|
|
181
|
+
rm -rf .nuitka-cache
|
|
182
|
+
fi
|
|
183
|
+
fi
|
|
184
|
+
mkdir -p .nuitka-cache/ccache
|
|
185
|
+
printf 'compiler_check = content\nsloppiness = time_macros\n' \
|
|
186
|
+
> .nuitka-cache/ccache/ccache.conf
|
|
187
|
+
# The manylinux containers ship no ccache (Nuitka warns and compiles
|
|
188
|
+
# cold), so the canary target pays full C compilation on every push.
|
|
189
|
+
# EPEL is a distro archive, exempt from the install cooldown (see
|
|
190
|
+
# claude.md § Distro archives are out of scope). Non-fatal on mirror
|
|
191
|
+
# hiccups: a release build must not die for a missing cache helper.
|
|
192
|
+
- name: Install ccache in container
|
|
193
|
+
if: matrix.container
|
|
194
|
+
shell: bash
|
|
195
|
+
run: >
|
|
196
|
+
(dnf install --assumeyes --quiet epel-release
|
|
197
|
+
&& dnf install --assumeyes --quiet ccache)
|
|
198
|
+
|| echo "ccache unavailable, building uncached."
|
|
116
199
|
- name: Setup venv
|
|
117
200
|
# --managed-python forces uv's own python-build-standalone interpreter,
|
|
118
201
|
# whose deployment floors are the ones we declare and verify (macOS
|
|
@@ -150,7 +233,7 @@ jobs:
|
|
|
150
233
|
uv --no-progress sync --frozen ${flags}
|
|
151
234
|
- name: Pre-bake build metadata
|
|
152
235
|
if: contains(matrix.current_version, '.dev')
|
|
153
|
-
run: uvx --no-progress 'click-extra==8.8.
|
|
236
|
+
run: uvx --no-progress 'click-extra==8.8.1' prebake all
|
|
154
237
|
- name: Build binary
|
|
155
238
|
id: build-binary
|
|
156
239
|
continue-on-error: true
|
|
@@ -162,6 +245,15 @@ jobs:
|
|
|
162
245
|
# passes as a proper argv, so a plain word-split is enough here.
|
|
163
246
|
env:
|
|
164
247
|
NUITKA_PYTHON_FLAGS: ${{ matrix.nuitka_python_flags }}
|
|
248
|
+
# On macOS Nuitka auto-downloads a ccache binary from nuitka.net,
|
|
249
|
+
# with no checksum at the call site (SconsCaching.py's
|
|
250
|
+
# getCachedDownload passes none). Since the macOS cache is not
|
|
251
|
+
# persisted (0/470 cross-VM hits, see the cache step above), ccache
|
|
252
|
+
# brings zero benefit there and the unchecksummed download is pure
|
|
253
|
+
# supply-chain surface: disable it. Empty (and inert) elsewhere;
|
|
254
|
+
# Linux ccache and MSVC clcache are unaffected.
|
|
255
|
+
NUITKA_CCACHE_FLAG: >-
|
|
256
|
+
${{ matrix.platform_id == 'macos' && '--disable-ccache' || '' }}
|
|
165
257
|
BIN_NAME: ${{ matrix.bin_name }}
|
|
166
258
|
MODULE_PATH: ${{ matrix.module_path }}
|
|
167
259
|
# Pin the macOS floor: without it, compiled objects and processed
|
|
@@ -171,11 +263,11 @@ jobs:
|
|
|
171
263
|
${{ matrix.platform_id == 'macos' && matrix.min_os || '' }}
|
|
172
264
|
shell: bash
|
|
173
265
|
run: |
|
|
174
|
-
# NUITKA_PYTHON_FLAGS
|
|
266
|
+
# NUITKA_PYTHON_FLAGS and NUITKA_CCACHE_FLAG hold optional flags,
|
|
175
267
|
# meant to word-split.
|
|
176
268
|
# shellcheck disable=SC2086
|
|
177
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
178
|
-
${NUITKA_PYTHON_FLAGS} \
|
|
269
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' run nuitka -- \
|
|
270
|
+
${NUITKA_PYTHON_FLAGS} ${NUITKA_CCACHE_FLAG} \
|
|
179
271
|
--output-filename="${BIN_NAME}" "${MODULE_PATH}"
|
|
180
272
|
- name: Upload Nuitka crash report
|
|
181
273
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
@@ -183,6 +275,11 @@ jobs:
|
|
|
183
275
|
name: nuitka-crash-report-${{ matrix.os }}-${{ matrix.short_sha }}.xml
|
|
184
276
|
if-no-files-found: ignore
|
|
185
277
|
path: nuitka-crash-report.xml
|
|
278
|
+
# Sizing signal for the cache strategy: hit/miss counts are in Nuitka's
|
|
279
|
+
# own "Cached C files" log lines above, this step adds what they omit.
|
|
280
|
+
- name: Nuitka cache stats
|
|
281
|
+
shell: bash
|
|
282
|
+
run: du -sm .nuitka-cache/* 2>/dev/null || echo "No Nuitka cache dir."
|
|
186
283
|
- if: steps.build-binary.outcome == 'failure'
|
|
187
284
|
run: |
|
|
188
285
|
echo "Nuitka build failed, skipping the rest of the steps."
|
|
@@ -199,8 +296,27 @@ jobs:
|
|
|
199
296
|
BIN_NAME: ${{ matrix.bin_name }}
|
|
200
297
|
shell: bash
|
|
201
298
|
run: >
|
|
202
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
299
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0'
|
|
203
300
|
verify-binary --target "${TARGET}" --binary "${BIN_NAME}"
|
|
301
|
+
# On a non-release run, exercise the freshly-built binary in place: the
|
|
302
|
+
# standalone test-binaries job only runs for release commits, so canary
|
|
303
|
+
# and weekly-schedule builds still prove the binary works without paying
|
|
304
|
+
# a second runner-queue slot. Env mirrors the test-binaries job; see its
|
|
305
|
+
# comments for the UTF-8 and safe.directory rationale.
|
|
306
|
+
- name: Self-test binary
|
|
307
|
+
if: ${{ !fromJSON(needs.metadata.outputs.metadata).release_commits_matrix }}
|
|
308
|
+
env:
|
|
309
|
+
BIN_NAME: ${{ matrix.bin_name }}
|
|
310
|
+
PYTHONIOENCODING: utf8
|
|
311
|
+
GIT_CONFIG_COUNT: "1"
|
|
312
|
+
GIT_CONFIG_KEY_0: safe.directory
|
|
313
|
+
GIT_CONFIG_VALUE_0: "*"
|
|
314
|
+
shell: bash
|
|
315
|
+
run: >
|
|
316
|
+
uv --no-progress run --frozen --
|
|
317
|
+
click-extra test-suite
|
|
318
|
+
--binary "./${BIN_NAME}"
|
|
319
|
+
--jobs max
|
|
204
320
|
- name: Upload binaries
|
|
205
321
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
206
322
|
with:
|
|
@@ -232,7 +348,7 @@ jobs:
|
|
|
232
348
|
BIN_NAME: ${{ matrix.bin_name }}
|
|
233
349
|
shell: bash
|
|
234
350
|
run: >
|
|
235
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
351
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' run gh --
|
|
236
352
|
attestation verify "${BIN_NAME}"
|
|
237
353
|
--repo "${{ github.repository }}"
|
|
238
354
|
--signer-repo kdeldycke/repomatic
|
|
@@ -248,7 +364,7 @@ jobs:
|
|
|
248
364
|
BUNDLE_PATH: ${{ steps.attest-binary.outputs.bundle-path }}
|
|
249
365
|
shell: bash
|
|
250
366
|
run: >
|
|
251
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
367
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0'
|
|
252
368
|
pack-attestation --bundle "${BUNDLE_PATH}"
|
|
253
369
|
- name: Upload attestation bundle
|
|
254
370
|
# Globbed rather than named, so the filename stays the CLI's to decide.
|
|
@@ -266,10 +382,15 @@ jobs:
|
|
|
266
382
|
needs:
|
|
267
383
|
- metadata
|
|
268
384
|
- compile-binaries
|
|
269
|
-
#
|
|
385
|
+
# Release commits only: non-release builds self-test inside compile-binaries
|
|
386
|
+
# instead of paying a second runner-queue slot per target. This standalone
|
|
387
|
+
# job re-validates the artifact on a pristine VM, through the same
|
|
388
|
+
# upload/download round-trip a user's binary takes. Also skipped for
|
|
389
|
+
# branches that don't affect code (e.g., update-mailmap, format-markdown).
|
|
270
390
|
if: >
|
|
271
391
|
fromJSON(needs.metadata.outputs.metadata).nuitka_matrix
|
|
272
392
|
&& !(fromJSON(needs.metadata.outputs.metadata).skip_binary_build || false)
|
|
393
|
+
&& fromJSON(needs.metadata.outputs.metadata).release_commits_matrix
|
|
273
394
|
strategy:
|
|
274
395
|
# Advisory matrix (default fail-fast): see docs/workflows.md "Matrix fail-fast strategy".
|
|
275
396
|
# Fall back to an empty `{"include":[]}` matrix when nuitka_matrix is null
|
|
@@ -285,6 +406,8 @@ jobs:
|
|
|
285
406
|
container: ${{ matrix.container }}
|
|
286
407
|
# We keep going when a job flagged as not stable fails.
|
|
287
408
|
continue-on-error: ${{ matrix.state == 'unstable' }}
|
|
409
|
+
# The suite runs in ~1-2 min; a hung run must not squat a runner-cap slot.
|
|
410
|
+
timeout-minutes: 10
|
|
288
411
|
steps:
|
|
289
412
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
290
413
|
with:
|
|
@@ -356,7 +479,7 @@ jobs:
|
|
|
356
479
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
357
480
|
COMMIT: ${{ matrix.commit }}
|
|
358
481
|
run: >
|
|
359
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
482
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' git-tag
|
|
360
483
|
--tag "v${CURRENT_VERSION}"
|
|
361
484
|
--commit "${COMMIT}"
|
|
362
485
|
--skip-existing
|
|
@@ -398,7 +521,7 @@ jobs:
|
|
|
398
521
|
continue-on-error: true
|
|
399
522
|
env:
|
|
400
523
|
GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
|
|
401
|
-
run: uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
524
|
+
run: uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' sync-dev-release --live --delete
|
|
402
525
|
- name: Create GitHub release draft
|
|
403
526
|
# Idempotent: skips if release already exists (e.g. workflow re-run).
|
|
404
527
|
# Notes carry the PyPI availability admonition from the start: baking it
|
|
@@ -510,7 +633,7 @@ jobs:
|
|
|
510
633
|
BUNDLE_PATH: ${{ steps.attest-manpages.outputs.bundle-path }}
|
|
511
634
|
GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
|
|
512
635
|
run: |
|
|
513
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
636
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' \
|
|
514
637
|
pack-attestation --bundle "${BUNDLE_PATH}" > upload-list.txt
|
|
515
638
|
xargs gh release upload "v${CURRENT_VERSION}" \
|
|
516
639
|
--repo "${{ github.repository }}" \
|
|
@@ -595,7 +718,7 @@ jobs:
|
|
|
595
718
|
PACKAGE_NAME: ${{ fromJSON(needs.metadata.outputs.metadata).package_name }}
|
|
596
719
|
shell: bash
|
|
597
720
|
run: |
|
|
598
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
721
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' pack-attestation \
|
|
599
722
|
--bundle "${BUNDLE_PATH}" \
|
|
600
723
|
--dir release-assets \
|
|
601
724
|
--name "${PACKAGE_NAME}-extra-assets" > upload-list.txt
|
|
@@ -673,7 +796,7 @@ jobs:
|
|
|
673
796
|
# Python distributions live in the CLI; the shell only feeds the
|
|
674
797
|
# printed list to `gh release upload`.
|
|
675
798
|
run: |
|
|
676
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
799
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' pack-binaries \
|
|
677
800
|
--version "${CURRENT_VERSION}" --dir ./compile-assets > upload-list.txt
|
|
678
801
|
if [[ -s upload-list.txt ]]; then
|
|
679
802
|
xargs gh release upload "v${CURRENT_VERSION}" \
|
|
@@ -706,6 +829,9 @@ jobs:
|
|
|
706
829
|
# (rare) multi-release runs keeps them from racing on the same files.
|
|
707
830
|
max-parallel: 1
|
|
708
831
|
runs-on: ubuntu-slim
|
|
832
|
+
# Upload plus the 600 s --poll-timeout, with margin; a stuck poll must not
|
|
833
|
+
# squat a runner-cap slot for the 360-min default.
|
|
834
|
+
timeout-minutes: 15
|
|
709
835
|
permissions:
|
|
710
836
|
contents: write
|
|
711
837
|
steps:
|
|
@@ -738,7 +864,7 @@ jobs:
|
|
|
738
864
|
VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }}
|
|
739
865
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
740
866
|
run: >
|
|
741
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
867
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' scan-virustotal
|
|
742
868
|
--tag "v${CURRENT_VERSION}"
|
|
743
869
|
--binaries-dir ./binaries
|
|
744
870
|
--poll
|
|
@@ -751,7 +877,7 @@ jobs:
|
|
|
751
877
|
env:
|
|
752
878
|
GH_TOKEN: ${{ github.token }}
|
|
753
879
|
run: >
|
|
754
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
880
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' sync-binaries
|
|
755
881
|
--repo "${{ github.repository }}"
|
|
756
882
|
--page docs/binaries.md
|
|
757
883
|
--records docs/assets/virustotal-scans.json
|
|
@@ -766,7 +892,7 @@ jobs:
|
|
|
766
892
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
767
893
|
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
768
894
|
run: >
|
|
769
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
895
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' git-commit-push
|
|
770
896
|
--message "Record v${CURRENT_VERSION} binaries"
|
|
771
897
|
--branch "${DEFAULT_BRANCH}"
|
|
772
898
|
docs/binaries.md
|
|
@@ -814,5 +940,5 @@ jobs:
|
|
|
814
940
|
env:
|
|
815
941
|
GH_TOKEN: ${{ github.token }}
|
|
816
942
|
run: >
|
|
817
|
-
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.
|
|
943
|
+
uvx --no-progress --exclude-newer-package repomatic=P0D 'repomatic==7.9.0' sync-dev-release --live
|
|
818
944
|
--upload-assets release_assets
|
|
@@ -541,7 +541,7 @@ Hand-written, but with a strict structure that downstream projects should mirror
|
|
|
541
541
|
|
|
542
542
|
5. **Python compatibility matrix** — a `<!-- matrix python -->` / `<!-- matrix-end -->` comment-marker region whose embedded table is regenerated by `click-extra refresh-directives` (the fourth `repomatic update-docs` phase runs it automatically), so it refreshes on every release without manual intervention. click-extra's matrix machinery owns the generation logic: per-tag Python support from classifiers with `requires-python`/Poetry/`setup.py` fallbacks, release-date capping, and range grouping. Keep the marker form (not the live `{matrix}` fence) so the table also renders when browsing the file on GitHub. Rendering conventions the reader relies on: `✅` / `❌` glyph cells, consecutive same-support tags grouped into one row labelled `` `4.25.x` → `6.15.x` ``, newest ranges on top. Tags with no Python declaration at all are out of scope; note the cutoff in a sentence beneath the table rather than padding with blank rows.
|
|
543
543
|
|
|
544
|
-
6. **Executables** table linking to GitHub Release binaries for each platform/architecture.
|
|
544
|
+
6. **Executables** table linking to GitHub Release binaries for each platform/architecture. Its URLs belong to the release freeze (`PrepareRelease.freeze_install_download_urls`), which ratchets them forward to `/releases/download/vX.Y.Z/<package>-X.Y.Z-linux-arm64.bin` on every release: a repo that has shipped once carries versioned URLs permanently, and there is no unfreeze step. A never-released repo starts from the evergreen `releases/latest/download/<package>-linux-arm64.bin` form, which resolves because the release pipeline uploads versionless alias assets alongside the version-stamped ones. Both spellings resolve, so neither is drift: never hand-edit one into the other.
|
|
545
545
|
|
|
546
546
|
7. **Release verification** section showing `gh attestation verify` against the package's own repo, with the `--signer-repo` flag if the release workflow runs as a reusable workflow from another repo. Mirror exactly: a stale flag here breaks reader trust.
|
|
547
547
|
|
|
@@ -549,7 +549,7 @@ Sync rules:
|
|
|
549
549
|
|
|
550
550
|
- Re-check the Repology page on every release. New distros get a new tab; dropped distros get the tab removed.
|
|
551
551
|
- The Python compatibility matrix is auto-generated; never hand-edit it.
|
|
552
|
-
-
|
|
552
|
+
- Download URLs in `install.md` are generated, not hand-maintained, so a version number in one is expected rather than drift. The single manual intervention is the documented repair: when a release's binary lane failed, re-point the table at the last release that actually carries binaries, since the freeze pins the version optimistically before the binaries exist (`lint-repo` reports the gap but never repairs it; see `claude.md` § A published release freezes what is missing from it).
|
|
553
553
|
- The Try it tab-set's `Specific version` tab does carry a pinned version as an example — that's intentional (it teaches the syntax). From repomatic `v7.4.0` on, the prepare-release freeze step bumps it automatically (`freeze_install_cli_version` rewrites `{package}@X.Y.Z` and `{package}==X.Y.Z` pins in `docs/install.md`); hand-bumping is only needed on repos pinned to older release engines.
|
|
554
554
|
|
|
555
555
|
### `packaging.md`: distribution and dependency reference
|
|
@@ -575,9 +575,10 @@ Primary toctree (user-facing), in this order:
|
|
|
575
575
|
05. `tool-runner` — Only when the project ships a `repomatic run`-style tool runner.
|
|
576
576
|
06. `workflows` — Only when the project publishes reusable workflows.
|
|
577
577
|
07. `test-matrix` — Only when the project documents its CI test-matrix composition.
|
|
578
|
-
08. `
|
|
579
|
-
09. `
|
|
580
|
-
10. `
|
|
578
|
+
08. `nuitka` — Only for projects compiling standalone executables through the release engine: the canonical home for build targets, fleet cadence, compile caching and measured build times (the `binaries` page below stays the per-release catalog).
|
|
579
|
+
09. `security` — Optional, and absent by default: a security page with nothing project-specific to say (no real threat model, no attack surface worth describing, no dedicated reporting channel) is boilerplate that dilutes the docs. Add it only when the project has a genuine security consideration. When present, single-source it as `docs/security.md`: GitHub's security tab detects the file in `docs/` as well as `.github/`, so no duplicate copy is needed.
|
|
580
|
+
10. `skills`, `agents` — Only when the project ships Claude Code skills or agents (see § Recipes › skills/agents pages below).
|
|
581
|
+
11. `benchmark` — Optional comparison page; only useful for projects positioning against alternatives. MyST docstring authoring needs no local page: it is canonically documented on the [click-extra MyST docstrings page](https://kdeldycke.github.io/click-extra/myst-docstrings.html), which also covers the `click-extra convert-to-myst` migration command.
|
|
581
582
|
|
|
582
583
|
Development toctree, in this order:
|
|
583
584
|
|
|
@@ -641,6 +642,7 @@ Page-shape rules that apply across the roster:
|
|
|
641
642
|
| `managers.md` | `file-submodule` |
|
|
642
643
|
| `mkdocs.md` | `markdown` |
|
|
643
644
|
| `myst-docstrings.md` | `pencil` |
|
|
645
|
+
| `nuitka.md` | `file-binary` |
|
|
644
646
|
| `operation-contracts.md` | `tasklist` |
|
|
645
647
|
| `overrides.md` | `pin` |
|
|
646
648
|
| `packaging.md` | `package-dependents` |
|
|
@@ -769,8 +771,9 @@ Strictness flags:
|
|
|
769
771
|
|
|
770
772
|
Theme assets and OpenGraph:
|
|
771
773
|
|
|
772
|
-
- `
|
|
773
|
-
- `
|
|
774
|
+
- The sidebar logo is Furo's `light_logo`/`dark_logo` **pair** of theme options, set to `"logo-square-light.png"` and `"logo-square-dark.png"`. Never `html_logo`: Furo performs no dark-mode swap on a single logo, so the light-only `assets/logo-square.svg` keeps its near-black wordmark on the dark theme, where it lands around 1.2:1 against Furo's background. Both options must be set for the pair to render at all, and `html_logo` must be unset, since Furo's `sidebar/brand.html` prefers it and skips the pair when it is present. Furo resolves both names against `_static/`, so each PNG needs its own `html_static_path` entry (that setting accepts individual files, which land at the root of `_static/`; listing `docs/assets/` wholesale would copy every screenshot and report along with them). The two PNGs are same-aspect exports of the same SVG, so the swap holds geometry.
|
|
775
|
+
- `html_favicon = "assets/favicon.svg"` is the canonical path, an SVG since browsers handle SVG favicons natively. The `/brand-assets` skill is the canonical producer of every one of these files: it manages the SVG sources (favicon, square logo, banner, social banner), exports light/dark PNG variants, and wires the new files into `docs/conf.py`. When they are missing or out of date, run `/brand-assets` instead of editing the assets by hand.
|
|
776
|
+
- `ogp_image` must be an **absolute** URL to the committed PNG on the GitHub raw host — `f"https://raw.githubusercontent.com/{github_user}/{project_id}/main/docs/assets/banner-social-light.png"` — never a site-relative `assets/...` path. `docs/assets/` is not copied into the built site (only the two sidebar logos are named in `html_static_path`, and no doc body references the banner, so Sphinx's image collector never picks it up), so a relative `ogp_image` resolves against `ogp_site_url` to a URL that 404s for the social crawlers that only ever see the raw HTML. Set it when the project has a banner asset; without `ogp_image`, `sphinxext.opengraph` falls back to the favicon, which scales poorly. Still define `ogp_site_url = f"https://{github_user}.github.io/{project_id}/"` for the page-level `og:url` tag. The PNG is exported from `assets/banner-social.svg` by the `/brand-assets` skill (which also produces the dark variant for dark-mode social cards on platforms that support them).
|
|
774
777
|
- The Furo `announcement` banner template across this lineage references the same `github_user` constant defined at the top of `conf.py`. Rebuilding the announcement string locally inside `html_theme_options` avoids a per-theme override layer.
|
|
775
778
|
|
|
776
779
|
Pruning checklist before merging any `conf.py` change:
|