repomatic 7.2.0__tar.gz → 7.3.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.2.0 → repomatic-7.3.0}/PKG-INFO +3 -3
- {repomatic-7.2.0 → repomatic-7.3.0}/pyproject.toml +18 -11
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/__init__.py +2 -2
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/binaries_page.py +21 -2
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/changelog.py +5 -2
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/cli.py +13 -87
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/config.py +9 -18
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/_release-engine.yaml +36 -12
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/agent-sphinx-docs.md +19 -21
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/autofix.yaml +41 -41
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/cancel-runs.yaml +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/changelog.yaml +14 -14
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/debug.yaml +2 -2
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/docs.yaml +9 -3
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/labels.yaml +6 -6
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/lint.yaml +9 -9
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/ruff.toml +6 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-babysit-ci.md +4 -4
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-repomatic-changelog.md +3 -3
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-repomatic-ship.md +9 -9
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-sphinx-docs-sync.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/tests.yaml +56 -3
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/unsubscribe.yaml +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/docs.py +17 -11
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/sync_ops.py +17 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/fix-changelog.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/fix-vulnerable-deps.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-action-pins.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-bumpversion.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-dep-sources.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-gitignore.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-mailmap.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-repomatic.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-tool-versions.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-uv-lock.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/sync-workflow-pins.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/update-deps-graph.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/update-docs.md +1 -1
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/tool_runner.py +11 -11
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/uv.py +24 -9
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/version_sync.py +1 -1
- repomatic-7.2.0/repomatic/myst_converter.py +0 -292
- repomatic-7.2.0/repomatic/myst_docstrings.py +0 -307
- repomatic-7.2.0/repomatic/rst_to_myst.py +0 -156
- {repomatic-7.2.0 → repomatic-7.3.0}/license +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/readme.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/__main__.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/binary.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/broken_links.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/cache.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/checksums.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/__init__.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/action-publish-pypi.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/agent-grunt-qa.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/agent-qa-engineer.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/autolock.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/new-link.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/code-of-conduct.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/contributing.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/contributing.zh.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/funding.yml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/.github/pull_request_template.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/__init__.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/awesome_template/license +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/bumpversion.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/codecov.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/labeller-content-based.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/labeller-file-based.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/labels.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/lychee.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/mdformat.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/mypy.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/pytest.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/release.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-av-false-positive.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-awesome-triage.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-benchmark-update.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-brand-assets.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-file-bug-report.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-repomatic-audit.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-repomatic-deps.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-repomatic-init.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-repomatic-topics.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-translation-sync.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/skill-upstream-audit.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/typos.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/uv.toml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/yamllint.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/data/zizmor.yaml +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/dep_sources.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/deps_graph.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/git_ops.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/__init__.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/actions.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/dev_release.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/gh.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/issue.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/matrix.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/pr.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/pr_body.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/release_sync.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/releases.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/sponsor.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/status.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/token.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/unsubscribe.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/github/workflow_sync.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/gitignore.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/http.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/images.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/init_project.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/lint_repo.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/mailmap.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/metadata.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/npm.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/prepare_release.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/py.typed +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/pypi.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/pyproject.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/registry.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/setup_guide.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/__init__.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/available-admonition.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/broken-links-issue.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/bump-version.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/detect-squash-merge.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/development-warning.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/fix-typos.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/format-images.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/format-json.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/format-markdown.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/format-pyproject.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/format-python.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/format-shell.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/generated-footer.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/github-releases.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/immutable-releases.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/pr-metadata.md.noformat +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/prepare-release.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/refresh-tip.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/release-notes.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/release-sync-report.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-branch-ruleset.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-dependabot.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-fork-pr-approval.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-notifications-pat.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-pages-source.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-pypi-trusted-publisher.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-token.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-verify.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide-virustotal.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/setup-guide.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/unavailable-admonition.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/unsubscribe-phase1.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/unsubscribe-phase2.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/templates/yanked-admonition.md +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/test_matrix.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/tool_runner_page.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.0}/repomatic/virustotal.py +0 -0
- {repomatic-7.2.0 → repomatic-7.3.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.3.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
|
|
@@ -46,7 +46,7 @@ Classifier: Typing :: Typed
|
|
|
46
46
|
Requires-Dist: arrow>=1.3
|
|
47
47
|
Requires-Dist: backports-strenum>=1 ; python_full_version < '3.11'
|
|
48
48
|
Requires-Dist: boltons>=25
|
|
49
|
-
Requires-Dist: click-extra>=8.
|
|
49
|
+
Requires-Dist: click-extra>=8.5
|
|
50
50
|
Requires-Dist: extra-platforms>=12.0.2
|
|
51
51
|
Requires-Dist: packaging>=17
|
|
52
52
|
Requires-Dist: py-walk>=0.3.1
|
|
@@ -58,7 +58,7 @@ Requires-Dist: wcmatch>=10
|
|
|
58
58
|
Requires-Python: >=3.10
|
|
59
59
|
Project-URL: Changelog, https://github.com/kdeldycke/repomatic/blob/main/changelog.md
|
|
60
60
|
Project-URL: Documentation, https://kdeldycke.github.io/repomatic
|
|
61
|
-
Project-URL: Download, https://github.com/kdeldycke/repomatic/releases/tag/v7.
|
|
61
|
+
Project-URL: Download, https://github.com/kdeldycke/repomatic/releases/tag/v7.3.0
|
|
62
62
|
Project-URL: Funding, https://github.com/sponsors/kdeldycke
|
|
63
63
|
Project-URL: Homepage, https://github.com/kdeldycke/repomatic
|
|
64
64
|
Project-URL: Issues, https://github.com/kdeldycke/repomatic/issues
|
|
@@ -5,7 +5,7 @@ requires = [ "uv-build>=0.9,<0.12" ]
|
|
|
5
5
|
[project]
|
|
6
6
|
# Docs: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
|
|
7
7
|
name = "repomatic"
|
|
8
|
-
version = "7.
|
|
8
|
+
version = "7.3.0"
|
|
9
9
|
description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
|
|
10
10
|
readme = "readme.md"
|
|
11
11
|
keywords = [
|
|
@@ -84,10 +84,16 @@ dependencies = [
|
|
|
84
84
|
"backports-strenum>=1; python_version<'3.11'",
|
|
85
85
|
# boltons 25.0.0 dropped Python 3.9, matching our requires-python >= 3.10.
|
|
86
86
|
"boltons>=25",
|
|
87
|
-
# click-extra 8.
|
|
88
|
-
# `
|
|
89
|
-
# `
|
|
90
|
-
|
|
87
|
+
# click-extra 8.5 ships the `python:render` `:mirror:` regions and extends
|
|
88
|
+
# `refresh-directives` to refresh them (update_mirror_blocks), with the
|
|
89
|
+
# fence-aware scanner that stops `update-docs` phase 4 from rewriting
|
|
90
|
+
# examples nested in code fences. 8.5 also carries the
|
|
91
|
+
# `make_schema_callable(warn_unknown=...)` unknown-key warning
|
|
92
|
+
# `load_repomatic_config` opts into, and the `click_extra.sphinx.
|
|
93
|
+
# myst_docstrings` extension `docs/conf.py` loads (absorbed from
|
|
94
|
+
# `repomatic.myst_docstrings`). (8.3 brought the `click:config` directive
|
|
95
|
+
# and `schema_field_infos()` that `configuration.md` and `show-config` use.)
|
|
96
|
+
"click-extra>=8.5",
|
|
91
97
|
# extra-platforms 12.0.2 reimplemented is_macos() with sys.platform, avoiding
|
|
92
98
|
# the platform.platform() shell-out to ``cmd /c ver`` on Windows that broke
|
|
93
99
|
# under patched subprocess in tests and triggered a CPython 3.10.x bug.
|
|
@@ -122,7 +128,7 @@ dependencies = [
|
|
|
122
128
|
]
|
|
123
129
|
urls.Changelog = "https://github.com/kdeldycke/repomatic/blob/main/changelog.md"
|
|
124
130
|
urls.Documentation = "https://kdeldycke.github.io/repomatic"
|
|
125
|
-
urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.
|
|
131
|
+
urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.3.0"
|
|
126
132
|
urls.Funding = "https://github.com/sponsors/kdeldycke"
|
|
127
133
|
urls.Homepage = "https://github.com/kdeldycke/repomatic"
|
|
128
134
|
urls.Issues = "https://github.com/kdeldycke/repomatic/issues"
|
|
@@ -206,7 +212,7 @@ exclude-newer = "1 week"
|
|
|
206
212
|
# `exclude-newer`, returning the package to the normal cooldown. repomatic is
|
|
207
213
|
# pinned to git main (no PyPI release to freeze), so it keeps a permanent
|
|
208
214
|
# "0 day" span.
|
|
209
|
-
exclude-newer-package = { repomatic = "0 day" }
|
|
215
|
+
exclude-newer-package = { click-extra = "2026-07-24T00:00:00Z", repomatic = "0 day" }
|
|
210
216
|
# Package is at root level, not in "./src/".
|
|
211
217
|
build-backend.module-root = ""
|
|
212
218
|
|
|
@@ -219,7 +225,7 @@ copyright = "Kevin Deldycke <kevin@deldycke.com> and contributors. Distributed u
|
|
|
219
225
|
file-description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
|
|
220
226
|
# Numeric only: Nuitka rejects PEP 440 .devN suffixes. Kept in sync with the
|
|
221
227
|
# package version by the dedicated [tool.bumpversion] rule that strips the suffix.
|
|
222
|
-
file-version = "7.
|
|
228
|
+
file-version = "7.3.0"
|
|
223
229
|
include-data-dir = [
|
|
224
230
|
"repomatic/data/awesome_template=repomatic/data/awesome_template",
|
|
225
231
|
]
|
|
@@ -237,13 +243,14 @@ include-package-data = [ "click_extra" ]
|
|
|
237
243
|
linux-icon = "docs/assets/icon.png"
|
|
238
244
|
macos-app-icon = "docs/assets/icon.icns"
|
|
239
245
|
product-name = "Repomatic"
|
|
240
|
-
product-version = "7.
|
|
246
|
+
product-version = "7.3.0"
|
|
241
247
|
windows-icon-from-ico = "docs/assets/icon.ico"
|
|
242
248
|
|
|
243
249
|
[tool.ruff]
|
|
244
250
|
preview = true
|
|
245
251
|
fix = true
|
|
246
|
-
|
|
252
|
+
# Disabled for the reasons documented in the bundled repomatic/data/ruff.toml.
|
|
253
|
+
unsafe-fixes = false
|
|
247
254
|
show-fixes = true
|
|
248
255
|
# Enable reformatting of code snippets in docstrings.
|
|
249
256
|
# https://docs.astral.sh/ruff/formatter/#docstring-formatting
|
|
@@ -351,7 +358,7 @@ run.source = [ "repomatic" ]
|
|
|
351
358
|
report.precision = 2
|
|
352
359
|
|
|
353
360
|
[tool.bumpversion]
|
|
354
|
-
current_version = "7.
|
|
361
|
+
current_version = "7.3.0"
|
|
355
362
|
# Parse versions with an optional .devN suffix (PEP 440).
|
|
356
363
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\.dev(?P<dev>\\d+))?"
|
|
357
364
|
serialize = [
|
|
@@ -164,9 +164,28 @@ def _release_version(tag: str) -> Version | None:
|
|
|
164
164
|
|
|
165
165
|
|
|
166
166
|
def _binary_assets(release: ReleaseWithAssets) -> list[ReleaseAsset]:
|
|
167
|
-
"""Return the release's compiled binaries, sorted by filename.
|
|
167
|
+
"""Return the release's compiled binaries, sorted by filename.
|
|
168
|
+
|
|
169
|
+
Releases also carry versionless alias copies of each binary, backing the
|
|
170
|
+
stable ``releases/latest/download`` URLs (see the upload step in
|
|
171
|
+
``_release-engine.yaml``). An alias shares its digest with its versioned
|
|
172
|
+
sibling: collapse each digest group onto its longest name (the versioned
|
|
173
|
+
one, since the alias is that same name minus the version segment) so the
|
|
174
|
+
catalog lists each binary once. Assets without a recorded digest
|
|
175
|
+
(uploaded before GitHub started recording them, mid-2025) predate the
|
|
176
|
+
aliases and are kept as-is.
|
|
177
|
+
"""
|
|
178
|
+
binaries = [a for a in release.assets if a.name.endswith(BINARY_ASSET_SUFFIXES)]
|
|
179
|
+
digest_groups: dict[str, list[ReleaseAsset]] = {}
|
|
180
|
+
for asset in binaries:
|
|
181
|
+
if asset.sha256:
|
|
182
|
+
digest_groups.setdefault(asset.sha256, []).append(asset)
|
|
183
|
+
aliases: set[str] = set()
|
|
184
|
+
for group in digest_groups.values():
|
|
185
|
+
canonical = max(group, key=lambda asset: (len(asset.name), asset.name))
|
|
186
|
+
aliases.update(asset.name for asset in group if asset.name != canonical.name)
|
|
168
187
|
return sorted(
|
|
169
|
-
(a for a in
|
|
188
|
+
(a for a in binaries if a.name not in aliases),
|
|
170
189
|
key=lambda asset: asset.name,
|
|
171
190
|
)
|
|
172
191
|
|
|
@@ -762,7 +762,8 @@ def warn_on_long_bullets(changelog: Changelog, threshold: int) -> None:
|
|
|
762
762
|
"""Warn about over-long bullets in the unreleased section, non-fatally.
|
|
763
763
|
|
|
764
764
|
A changelog entry is a release note, not a commit message: one short
|
|
765
|
-
sentence stating what changed
|
|
765
|
+
sentence stating what changed. Canonical guideline:
|
|
766
|
+
https://github.com/kdeldycke/repomatic/blob/main/claude.md#changelog-entry-length
|
|
766
767
|
Each unreleased bullet longer than `threshold` words emits a
|
|
767
768
|
{data}`logging.WARNING` and a GitHub Actions warning annotation, without
|
|
768
769
|
affecting the lint exit code.
|
|
@@ -792,7 +793,9 @@ def warn_on_long_bullets(changelog: Changelog, threshold: int) -> None:
|
|
|
792
793
|
f"Changelog entry {index} for {version} runs {words} words, "
|
|
793
794
|
f"over the {threshold}-word guideline. A changelog entry is "
|
|
794
795
|
f"a release note, not a commit message: keep it to one short "
|
|
795
|
-
f"sentence
|
|
796
|
+
f"sentence, per the canonical guideline "
|
|
797
|
+
f"https://github.com/kdeldycke/repomatic/blob/main/claude.md"
|
|
798
|
+
f"#changelog-entry-length",
|
|
796
799
|
)
|
|
797
800
|
|
|
798
801
|
|
|
@@ -29,7 +29,6 @@ from pathlib import Path
|
|
|
29
29
|
|
|
30
30
|
import tomlrt
|
|
31
31
|
from click_extra import (
|
|
32
|
-
DEFAULT_JOBS,
|
|
33
32
|
UNPROCESSED,
|
|
34
33
|
Choice,
|
|
35
34
|
ClickException,
|
|
@@ -336,13 +335,7 @@ def _require_token(module, attr):
|
|
|
336
335
|
# names (e.g., "setup-guide" is both a config key and a subcommand). Config
|
|
337
336
|
# access goes exclusively through config_schema + get_tool_config().
|
|
338
337
|
@group(config_schema=Config, schema_strict=False, included_params=())
|
|
339
|
-
|
|
340
|
-
# keyword) so JobCount.convert() never emits its sequential-execution warning
|
|
341
|
-
# for a value the user never set: on 1-CPU hosts (ubuntu-slim CI runners, docs
|
|
342
|
-
# builders) that warning fires on every bare invocation and leaks into the
|
|
343
|
-
# merged output captured by `{click:run}` doc renders and CliRunner tests.
|
|
344
|
-
# show_default restores the machine-independent "auto" label in help screens.
|
|
345
|
-
@jobs_option(default=DEFAULT_JOBS, show_default="auto")
|
|
338
|
+
@jobs_option()
|
|
346
339
|
def repomatic():
|
|
347
340
|
pass
|
|
348
341
|
|
|
@@ -734,15 +727,6 @@ init_project.help = init_project.help.format(
|
|
|
734
727
|
)
|
|
735
728
|
|
|
736
729
|
|
|
737
|
-
def _table_headers(header_defs: tuple[tuple[str, str], ...]) -> tuple[str, ...]:
|
|
738
|
-
"""Return the column labels from `(label, column_id)` header definitions.
|
|
739
|
-
|
|
740
|
-
`ctx.print_table` takes `(table_data, headers)`; the column IDs drive
|
|
741
|
-
`--sort-by` through the matching `SortByOption`, not the rendered header row.
|
|
742
|
-
"""
|
|
743
|
-
return tuple(label for label, _ in header_defs)
|
|
744
|
-
|
|
745
|
-
|
|
746
730
|
_metadata_sort = SortByOption(*METADATA_KEYS_HEADER_DEFS, default="key")
|
|
747
731
|
|
|
748
732
|
|
|
@@ -793,9 +777,7 @@ def metadata(ctx, format, overwrite, output, list_keys, keys):
|
|
|
793
777
|
current_version is_python_project
|
|
794
778
|
"""
|
|
795
779
|
if list_keys:
|
|
796
|
-
ctx.print_table(
|
|
797
|
-
metadata_keys_reference(), _table_headers(METADATA_KEYS_HEADER_DEFS)
|
|
798
|
-
)
|
|
780
|
+
ctx.print_table(metadata_keys_reference(), METADATA_KEYS_HEADER_DEFS)
|
|
799
781
|
ctx.exit(0)
|
|
800
782
|
|
|
801
783
|
# Validate requested keys.
|
|
@@ -873,7 +855,7 @@ def show_config(ctx):
|
|
|
873
855
|
(option, escape_type_for_gfm_table(ftype), default, desc)
|
|
874
856
|
for option, ftype, default, desc in config_reference()
|
|
875
857
|
]
|
|
876
|
-
ctx.print_table(rows,
|
|
858
|
+
ctx.print_table(rows, CONFIG_REFERENCE_HEADER_DEFS)
|
|
877
859
|
|
|
878
860
|
|
|
879
861
|
TEST_MATRIX_STATE_DISPLAY = {
|
|
@@ -924,7 +906,7 @@ def show_test_matrix(ctx, emoji, matrix_name):
|
|
|
924
906
|
(row[0], *(TEST_MATRIX_STATE_DISPLAY.get(cell, cell) for cell in row[1:]))
|
|
925
907
|
for row in rows
|
|
926
908
|
)
|
|
927
|
-
ctx.
|
|
909
|
+
ctx.print_table(rows, headers)
|
|
928
910
|
|
|
929
911
|
|
|
930
912
|
@repomatic.command(
|
|
@@ -1806,69 +1788,15 @@ def update_docs() -> None:
|
|
|
1806
1788
|
with ``{eval-rst}`` blocks.
|
|
1807
1789
|
3. Run the project-specific `docs/docs_update.py` script (if present)
|
|
1808
1790
|
to generate dynamic content.
|
|
1809
|
-
4. Refresh self-updating
|
|
1810
|
-
|
|
1811
|
-
`click-extra refresh-directives`.
|
|
1791
|
+
4. Refresh self-updating blocks (`{matrix}` compatibility tables and
|
|
1792
|
+
`python:render` `:mirror:` regions) found in `docs/` pages and
|
|
1793
|
+
`readme.md`, via `click-extra refresh-directives`.
|
|
1812
1794
|
|
|
1813
1795
|
Configuration is read from `[tool.repomatic]` in `pyproject.toml`.
|
|
1814
1796
|
"""
|
|
1815
1797
|
_update_docs(get_tool_config())
|
|
1816
1798
|
|
|
1817
1799
|
|
|
1818
|
-
@repomatic.command(
|
|
1819
|
-
name="convert-to-myst",
|
|
1820
|
-
short_help="Convert reST docstrings to MyST in Python files",
|
|
1821
|
-
section=_section_setup,
|
|
1822
|
-
)
|
|
1823
|
-
@argument("directory", required=False, default=None)
|
|
1824
|
-
def convert_to_myst(directory: str | None) -> None:
|
|
1825
|
-
"""Convert reST docstrings to MyST markdown in Python source files.
|
|
1826
|
-
|
|
1827
|
-
Transforms reST markup in docstrings and `#:` comment blocks to MyST.
|
|
1828
|
-
The companion Sphinx extension `repomatic.myst_docstrings` converts
|
|
1829
|
-
the MyST back to reST at build time, so `sphinx.ext.autodoc` still
|
|
1830
|
-
works.
|
|
1831
|
-
|
|
1832
|
-
If DIRECTORY is not specified, auto-detects the source package directory
|
|
1833
|
-
from the project's script entry points in `pyproject.toml`.
|
|
1834
|
-
|
|
1835
|
-
Safe to re-run: already-converted MyST syntax does not match the reST
|
|
1836
|
-
patterns, so the conversion is idempotent.
|
|
1837
|
-
"""
|
|
1838
|
-
from .metadata import Metadata
|
|
1839
|
-
from .myst_converter import convert_directory
|
|
1840
|
-
|
|
1841
|
-
if directory:
|
|
1842
|
-
root = Path(directory)
|
|
1843
|
-
else:
|
|
1844
|
-
# Auto-detect source directory from project metadata.
|
|
1845
|
-
meta = Metadata()
|
|
1846
|
-
source_dirs: set[str] = set()
|
|
1847
|
-
for _cli_id, module_id, _callable_id in meta.script_entries:
|
|
1848
|
-
source_dirs.add(module_id.split(".")[0])
|
|
1849
|
-
|
|
1850
|
-
if not source_dirs:
|
|
1851
|
-
raise ClickException(
|
|
1852
|
-
"Cannot auto-detect source directory. "
|
|
1853
|
-
"Specify a directory argument or add script entry points "
|
|
1854
|
-
"to pyproject.toml."
|
|
1855
|
-
)
|
|
1856
|
-
if len(source_dirs) > 1:
|
|
1857
|
-
raise ClickException(
|
|
1858
|
-
f"Multiple source packages detected: {sorted(source_dirs)}. "
|
|
1859
|
-
"Specify a directory argument."
|
|
1860
|
-
)
|
|
1861
|
-
root = Path(source_dirs.pop())
|
|
1862
|
-
|
|
1863
|
-
if not root.is_dir():
|
|
1864
|
-
raise ClickException(f"Not a directory: {root}")
|
|
1865
|
-
|
|
1866
|
-
changed = convert_directory(root)
|
|
1867
|
-
for filepath in changed:
|
|
1868
|
-
echo(f" Converted: {filepath}")
|
|
1869
|
-
echo(f"\n{len(changed)} file(s) converted.")
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
1800
|
@repomatic.command(
|
|
1873
1801
|
short_help="Manage broken links issue lifecycle", section=_section_github
|
|
1874
1802
|
)
|
|
@@ -2312,9 +2240,7 @@ def audit(
|
|
|
2312
2240
|
)
|
|
2313
2241
|
for v in vulns
|
|
2314
2242
|
]
|
|
2315
|
-
ctx.print_table(
|
|
2316
|
-
rows, _table_headers(AUDIT_HEADER_DEFS)
|
|
2317
|
-
)
|
|
2243
|
+
ctx.print_table(rows, AUDIT_HEADER_DEFS)
|
|
2318
2244
|
|
|
2319
2245
|
if output:
|
|
2320
2246
|
markdown = format_vulnerability_table(vulns)
|
|
@@ -2644,7 +2570,7 @@ def _print_sync_table(
|
|
|
2644
2570
|
if show_released:
|
|
2645
2571
|
row = (*row, format_released(dates.get(name, ""), reference_date))
|
|
2646
2572
|
rows.append(row)
|
|
2647
|
-
ctx.
|
|
2573
|
+
ctx.print_table(rows, headers)
|
|
2648
2574
|
|
|
2649
2575
|
|
|
2650
2576
|
def _print_held_back_table(
|
|
@@ -2671,7 +2597,7 @@ def _print_held_back_table(
|
|
|
2671
2597
|
)
|
|
2672
2598
|
for pkg in held_back
|
|
2673
2599
|
]
|
|
2674
|
-
ctx.
|
|
2600
|
+
ctx.print_table(rows, headers)
|
|
2675
2601
|
|
|
2676
2602
|
|
|
2677
2603
|
def _print_bypass_table(ctx: Context, forecasts: list[BypassForecast]) -> None:
|
|
@@ -2687,7 +2613,7 @@ def _print_bypass_table(ctx: Context, forecasts: list[BypassForecast]) -> None:
|
|
|
2687
2613
|
(forecast.name, forecast.held_version, forecast.expires)
|
|
2688
2614
|
for forecast in forecasts
|
|
2689
2615
|
]
|
|
2690
|
-
ctx.
|
|
2616
|
+
ctx.print_table(rows, headers)
|
|
2691
2617
|
|
|
2692
2618
|
|
|
2693
2619
|
def _emit_version_sync_report(
|
|
@@ -3571,7 +3497,7 @@ def run_cmd(
|
|
|
3571
3497
|
(spec.name, spec.version, resolve_config_source(spec))
|
|
3572
3498
|
for spec in TOOL_REGISTRY.values()
|
|
3573
3499
|
]
|
|
3574
|
-
ctx.print_table(rows,
|
|
3500
|
+
ctx.print_table(rows, TOOL_LIST_HEADER_DEFS)
|
|
3575
3501
|
ctx.exit(0)
|
|
3576
3502
|
|
|
3577
3503
|
if tool_name is None:
|
|
@@ -3664,7 +3590,7 @@ def show(ctx):
|
|
|
3664
3590
|
_format_age(cfg_entry.mtime),
|
|
3665
3591
|
))
|
|
3666
3592
|
|
|
3667
|
-
ctx.print_table(rows,
|
|
3593
|
+
ctx.print_table(rows, CACHE_LIST_HEADER_DEFS)
|
|
3668
3594
|
total_count = len(bin_entries) + len(http_entries) + len(cfg_entries)
|
|
3669
3595
|
echo(f"\nTotal: {total_count} file(s), {format_file_size(total_size)}")
|
|
3670
3596
|
|
|
@@ -23,7 +23,6 @@ Defines the `Config` dataclass, its TOML serialization helpers, and the
|
|
|
23
23
|
|
|
24
24
|
from __future__ import annotations
|
|
25
25
|
|
|
26
|
-
import logging
|
|
27
26
|
from dataclasses import dataclass, field
|
|
28
27
|
from textwrap import dedent
|
|
29
28
|
|
|
@@ -631,8 +630,8 @@ class Config:
|
|
|
631
630
|
exclude: list[str] = field(default_factory=list)
|
|
632
631
|
"""Additional components and files to exclude from repomatic operations.
|
|
633
632
|
|
|
634
|
-
Additive to the default exclusions (`labels`, `skills`). Bare
|
|
635
|
-
exclude an entire component (e.g., `"workflows"`). Qualified
|
|
633
|
+
Additive to the default exclusions (`agents`, `labels`, `skills`). Bare
|
|
634
|
+
names exclude an entire component (e.g., `"workflows"`). Qualified
|
|
636
635
|
`component/identifier` entries exclude a specific file within a component
|
|
637
636
|
(e.g., `"workflows/debug.yaml"`, `"skills/repomatic-audit"`,
|
|
638
637
|
`"labels/labeller-content-based.yaml"`).
|
|
@@ -650,9 +649,9 @@ class Config:
|
|
|
650
649
|
include: list[str] = field(default_factory=list)
|
|
651
650
|
"""Components and files to force-include, overriding default exclusions.
|
|
652
651
|
|
|
653
|
-
Use this to opt into components that are excluded by default (`
|
|
654
|
-
`skills`). Each entry is subtracted from the effective exclude
|
|
655
|
-
(defaults + user `exclude`) and bypasses `RepoScope` filtering, so
|
|
652
|
+
Use this to opt into components that are excluded by default (`agents`,
|
|
653
|
+
`labels`, `skills`). Each entry is subtracted from the effective exclude
|
|
654
|
+
set (defaults + user `exclude`) and bypasses `RepoScope` filtering, so
|
|
656
655
|
scope-restricted components (like awesome-only skills or Python-only
|
|
657
656
|
`publish-pypi-action`) are included regardless of repository type.
|
|
658
657
|
Qualified entries (`component/file`) implicitly select the parent
|
|
@@ -1000,18 +999,10 @@ def load_repomatic_config(
|
|
|
1000
999
|
tool_section = pyproject_data.get("tool", {})
|
|
1001
1000
|
user_config: dict[str, Any] = tool_section.get("repomatic", {})
|
|
1002
1001
|
|
|
1003
|
-
#
|
|
1004
|
-
#
|
|
1005
|
-
#
|
|
1006
|
-
|
|
1007
|
-
for key in user_config:
|
|
1008
|
-
if key.replace("_", "-") not in known_keys:
|
|
1009
|
-
logging.warning(
|
|
1010
|
-
"Unknown [tool.repomatic] option: %s (ignored).",
|
|
1011
|
-
key,
|
|
1012
|
-
)
|
|
1013
|
-
|
|
1014
|
-
schema_callable = make_schema_callable(Config, strict=False)
|
|
1002
|
+
# The [tool.repomatic] section is schema-only (the CLI group runs with
|
|
1003
|
+
# included_params=()), so warn_unknown flags any key the schema does not
|
|
1004
|
+
# know as a typo, nested tables included.
|
|
1005
|
+
schema_callable = make_schema_callable(Config, strict=False, warn_unknown=True)
|
|
1015
1006
|
assert schema_callable is not None
|
|
1016
1007
|
config: Config = schema_callable(user_config)
|
|
1017
1008
|
return config
|
|
@@ -51,7 +51,7 @@ jobs:
|
|
|
51
51
|
- name: Run repomatic metadata
|
|
52
52
|
id: metadata
|
|
53
53
|
run: >
|
|
54
|
-
uvx --no-progress 'repomatic==7.
|
|
54
|
+
uvx --no-progress 'repomatic==7.3.0' metadata
|
|
55
55
|
--format github-json --output "$GITHUB_OUTPUT"
|
|
56
56
|
new_commits_matrix release_commits_matrix build_targets nuitka_matrix
|
|
57
57
|
nuitka_extras is_python_project package_name current_version
|
|
@@ -132,7 +132,7 @@ jobs:
|
|
|
132
132
|
# NUITKA_PYTHON_FLAGS holds the entry point's --python-flag (if any),
|
|
133
133
|
# meant to word-split.
|
|
134
134
|
# shellcheck disable=SC2086
|
|
135
|
-
uvx --no-progress 'repomatic==7.
|
|
135
|
+
uvx --no-progress 'repomatic==7.3.0' run nuitka -- \
|
|
136
136
|
${NUITKA_PYTHON_FLAGS} \
|
|
137
137
|
--output-filename="${BIN_NAME}" "${MODULE_PATH}"
|
|
138
138
|
- name: Upload Nuitka crash report
|
|
@@ -154,8 +154,18 @@ jobs:
|
|
|
154
154
|
- name: Install exiftool - Windows
|
|
155
155
|
if: runner.os == 'Windows'
|
|
156
156
|
shell: pwsh
|
|
157
|
+
# choco's --retry-count retries back-to-back, too fast to outlive a community-feed
|
|
158
|
+
# outage (406/504 responses): space three step-level attempts a minute apart.
|
|
157
159
|
run: |
|
|
158
|
-
|
|
160
|
+
$attempts = 3
|
|
161
|
+
foreach ($try in 1..$attempts) {
|
|
162
|
+
choco install exiftool --no-progress --yes --retry-count=3
|
|
163
|
+
if ($LASTEXITCODE -eq 0) { break }
|
|
164
|
+
if ($try -lt $attempts) {
|
|
165
|
+
Write-Warning "choco install exiftool failed (attempt ${try}/${attempts}), retrying in 60 seconds."
|
|
166
|
+
Start-Sleep -Seconds 60
|
|
167
|
+
}
|
|
168
|
+
}
|
|
159
169
|
if (-not (Get-Command exiftool -ErrorAction SilentlyContinue)) {
|
|
160
170
|
Write-Error "exiftool not found on PATH after choco install"
|
|
161
171
|
exit 1
|
|
@@ -166,7 +176,7 @@ jobs:
|
|
|
166
176
|
BIN_NAME: ${{ matrix.bin_name }}
|
|
167
177
|
shell: bash
|
|
168
178
|
run: >
|
|
169
|
-
uvx --no-progress 'repomatic==7.
|
|
179
|
+
uvx --no-progress 'repomatic==7.3.0'
|
|
170
180
|
verify-binary --target "${TARGET}" --binary "${BIN_NAME}"
|
|
171
181
|
- name: Upload binaries
|
|
172
182
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
@@ -285,7 +295,7 @@ jobs:
|
|
|
285
295
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
286
296
|
COMMIT: ${{ matrix.commit }}
|
|
287
297
|
run: >
|
|
288
|
-
uvx --no-progress 'repomatic==7.
|
|
298
|
+
uvx --no-progress 'repomatic==7.3.0' git-tag
|
|
289
299
|
--tag "v${CURRENT_VERSION}"
|
|
290
300
|
--commit "${COMMIT}"
|
|
291
301
|
--skip-existing
|
|
@@ -326,7 +336,7 @@ jobs:
|
|
|
326
336
|
continue-on-error: true
|
|
327
337
|
env:
|
|
328
338
|
GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
|
|
329
|
-
run: uvx --no-progress 'repomatic==7.
|
|
339
|
+
run: uvx --no-progress 'repomatic==7.3.0' sync-dev-release --live --delete
|
|
330
340
|
- name: Create GitHub release draft
|
|
331
341
|
# Idempotent: skips if release already exists (e.g. workflow re-run).
|
|
332
342
|
# Notes carry the PyPI availability admonition from the start: baking it
|
|
@@ -446,6 +456,12 @@ jobs:
|
|
|
446
456
|
merge-multiple: true
|
|
447
457
|
- name: Upload binaries and attestation bundles to release
|
|
448
458
|
# Exclude Python packages (.tar.gz, .whl) already uploaded by create-release.
|
|
459
|
+
# Each versioned binary is also uploaded under a versionless alias
|
|
460
|
+
# (name-<version>-<target>.<ext> duplicated as name-<target>.<ext>), so the
|
|
461
|
+
# stable releases/latest/download URLs always resolve. Aliases are
|
|
462
|
+
# byte-identical copies: artifact attestations verify them unchanged
|
|
463
|
+
# (digest-based), and the catalog recorder collapses them onto their
|
|
464
|
+
# versioned sibling (see repomatic/binaries_page.py).
|
|
449
465
|
if: needs.compile-binaries.result != 'skipped'
|
|
450
466
|
env:
|
|
451
467
|
GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
|
|
@@ -454,6 +470,11 @@ jobs:
|
|
|
454
470
|
run: |
|
|
455
471
|
shopt -s nullglob extglob
|
|
456
472
|
files=(./compile-assets/!(*.tar.gz|*.whl))
|
|
473
|
+
for binary in ./compile-assets/*-"${CURRENT_VERSION}"-*.@(bin|exe); do
|
|
474
|
+
versionless="${binary/-"${CURRENT_VERSION}"-/-}"
|
|
475
|
+
cp "${binary}" "${versionless}"
|
|
476
|
+
files+=("${versionless}")
|
|
477
|
+
done
|
|
457
478
|
if [[ ${#files[@]} -gt 0 ]]; then
|
|
458
479
|
gh release upload "v${CURRENT_VERSION}" \
|
|
459
480
|
"${files[@]}" \
|
|
@@ -500,21 +521,24 @@ jobs:
|
|
|
500
521
|
with:
|
|
501
522
|
enable-cache: false
|
|
502
523
|
- name: Download release binaries
|
|
524
|
+
# Versioned patterns leave out the versionless alias copies, which
|
|
525
|
+
# share their digest with a versioned sibling and would only submit
|
|
526
|
+
# duplicate scans.
|
|
503
527
|
env:
|
|
504
528
|
GH_TOKEN: ${{ github.token }}
|
|
505
529
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
506
530
|
run: >
|
|
507
531
|
gh release download "v${CURRENT_VERSION}"
|
|
508
532
|
--repo "${{ github.repository }}"
|
|
509
|
-
--pattern "
|
|
510
|
-
--pattern "
|
|
533
|
+
--pattern "*-${CURRENT_VERSION}-*.bin"
|
|
534
|
+
--pattern "*-${CURRENT_VERSION}-*.exe"
|
|
511
535
|
--dir ./binaries
|
|
512
536
|
- name: Upload to VirusTotal and record detections
|
|
513
537
|
env:
|
|
514
538
|
VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }}
|
|
515
539
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
516
540
|
run: >
|
|
517
|
-
uvx --no-progress 'repomatic==7.
|
|
541
|
+
uvx --no-progress 'repomatic==7.3.0' scan-virustotal
|
|
518
542
|
--tag "v${CURRENT_VERSION}"
|
|
519
543
|
--binaries-dir ./binaries
|
|
520
544
|
--poll
|
|
@@ -527,7 +551,7 @@ jobs:
|
|
|
527
551
|
env:
|
|
528
552
|
GH_TOKEN: ${{ github.token }}
|
|
529
553
|
run: >
|
|
530
|
-
uvx --no-progress 'repomatic==7.
|
|
554
|
+
uvx --no-progress 'repomatic==7.3.0' sync-binaries
|
|
531
555
|
--repo "${{ github.repository }}"
|
|
532
556
|
--page docs/binaries.md
|
|
533
557
|
--records docs/assets/virustotal-scans.json
|
|
@@ -542,7 +566,7 @@ jobs:
|
|
|
542
566
|
CURRENT_VERSION: ${{ matrix.current_version }}
|
|
543
567
|
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
544
568
|
run: >
|
|
545
|
-
uvx --no-progress 'repomatic==7.
|
|
569
|
+
uvx --no-progress 'repomatic==7.3.0' git-commit-push
|
|
546
570
|
--message "Record v${CURRENT_VERSION} binaries"
|
|
547
571
|
--branch "${DEFAULT_BRANCH}"
|
|
548
572
|
docs/binaries.md
|
|
@@ -578,5 +602,5 @@ jobs:
|
|
|
578
602
|
env:
|
|
579
603
|
GH_TOKEN: ${{ github.token }}
|
|
580
604
|
run: >
|
|
581
|
-
uvx --no-progress 'repomatic==7.
|
|
605
|
+
uvx --no-progress 'repomatic==7.3.0' sync-dev-release --live
|
|
582
606
|
--upload-assets release_assets
|