repomatic 6.30.0__tar.gz → 7.0.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.
Files changed (160) hide show
  1. {repomatic-6.30.0 → repomatic-7.0.0}/PKG-INFO +7 -6
  2. {repomatic-6.30.0 → repomatic-7.0.0}/pyproject.toml +30 -16
  3. {repomatic-6.30.0 → repomatic-7.0.0}/readme.md +3 -2
  4. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/__init__.py +2 -2
  5. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/changelog.py +14 -1
  6. repomatic-7.0.0/repomatic/checksums.py +127 -0
  7. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/cli.py +496 -220
  8. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/config.py +81 -2
  9. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/_release-engine.yaml +26 -18
  10. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/agent-sphinx-docs.md +1 -1
  11. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/autofix.yaml +212 -66
  12. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/changelog.yaml +18 -18
  13. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/debug.yaml +3 -3
  14. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/docs.yaml +7 -7
  15. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/labeller-content-based.yaml +0 -1
  16. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/labeller-file-based.yaml +0 -1
  17. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/labels.yaml +11 -11
  18. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/lint.yaml +26 -23
  19. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/pytest.toml +0 -4
  20. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/release.yaml +4 -16
  21. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/ruff.toml +7 -0
  22. repomatic-7.0.0/repomatic/data/skill-babysit-ci.md +245 -0
  23. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-repomatic-audit.md +3 -4
  24. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-repomatic-changelog.md +1 -1
  25. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-repomatic-deps.md +2 -2
  26. repomatic-7.0.0/repomatic/data/skill-repomatic-ship.md +150 -0
  27. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/tests.yaml +23 -37
  28. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/unsubscribe.yaml +2 -2
  29. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/zizmor.yaml +1 -1
  30. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/deps_graph.py +180 -77
  31. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/git_ops.py +151 -7
  32. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/matrix.py +1 -1
  33. repomatic-7.0.0/repomatic/github/releases.py +408 -0
  34. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/token.py +12 -47
  35. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/unsubscribe.py +7 -14
  36. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/workflow_sync.py +11 -10
  37. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/init_project.py +13 -103
  38. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/lint_repo.py +67 -7
  39. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/metadata.py +116 -111
  40. repomatic-7.0.0/repomatic/npm.py +89 -0
  41. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/pypi.py +1 -1
  42. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/registry.py +10 -10
  43. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/release_prep.py +25 -75
  44. repomatic-7.0.0/repomatic/sync_ops.py +886 -0
  45. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/fix-changelog.md +3 -0
  46. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/fix-vulnerable-deps.md +7 -0
  47. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-dependabot.md +2 -2
  48. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-token.md +4 -5
  49. repomatic-7.0.0/repomatic/templates/sync-action-pins.md +18 -0
  50. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/sync-repomatic.md +5 -0
  51. repomatic-7.0.0/repomatic/templates/sync-tool-versions.md +18 -0
  52. repomatic-7.0.0/repomatic/templates/sync-workflow-pins.md +18 -0
  53. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/update-docs.md +8 -0
  54. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/test_matrix.py +6 -7
  55. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/tool_runner.py +415 -189
  56. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/uv.py +333 -118
  57. repomatic-7.0.0/repomatic/version_sync.py +482 -0
  58. repomatic-6.30.0/repomatic/checksums.py +0 -181
  59. repomatic-6.30.0/repomatic/data/renovate.json5 +0 -202
  60. repomatic-6.30.0/repomatic/data/renovate.yaml +0 -138
  61. repomatic-6.30.0/repomatic/data/skill-babysit-ci.md +0 -246
  62. repomatic-6.30.0/repomatic/data/skill-repomatic-ship.md +0 -144
  63. repomatic-6.30.0/repomatic/github/releases.py +0 -141
  64. repomatic-6.30.0/repomatic/renovate.py +0 -358
  65. repomatic-6.30.0/repomatic/templates/renovate-migration.md +0 -13
  66. {repomatic-6.30.0 → repomatic-7.0.0}/license +0 -0
  67. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/__main__.py +0 -0
  68. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/binary.py +0 -0
  69. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/broken_links.py +0 -0
  70. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/cache.py +0 -0
  71. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/__init__.py +0 -0
  72. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/action-publish-pypi.yaml +0 -0
  73. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/agent-grunt-qa.md +0 -0
  74. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/agent-qa-engineer.md +0 -0
  75. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/autolock.yaml +0 -0
  76. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/config.yml +0 -0
  77. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/new-link.yaml +0 -0
  78. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/code-of-conduct.md +0 -0
  79. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/contributing.md +0 -0
  80. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/contributing.zh.md +0 -0
  81. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/funding.yml +0 -0
  82. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/.github/pull_request_template.md +0 -0
  83. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/__init__.py +0 -0
  84. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/awesome_template/license +0 -0
  85. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/bumpversion.toml +0 -0
  86. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/cancel-runs.yaml +0 -0
  87. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/codecov.yaml +0 -0
  88. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/labels.toml +0 -0
  89. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/lychee.toml +0 -0
  90. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/mdformat.toml +0 -0
  91. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/mypy.toml +0 -0
  92. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-av-false-positive.md +0 -0
  93. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-awesome-triage.md +0 -0
  94. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-benchmark-update.md +0 -0
  95. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-brand-assets.md +0 -0
  96. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-file-bug-report.md +0 -0
  97. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-repomatic-init.md +0 -0
  98. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-repomatic-topics.md +0 -0
  99. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-sphinx-docs-sync.md +0 -0
  100. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-translation-sync.md +0 -0
  101. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/skill-upstream-audit.md +0 -0
  102. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/typos.toml +0 -0
  103. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/uv.toml +0 -0
  104. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/data/yamllint.yaml +0 -0
  105. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/__init__.py +0 -0
  106. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/actions.py +0 -0
  107. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/advisories.py +0 -0
  108. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/dev_release.py +0 -0
  109. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/gh.py +0 -0
  110. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/issue.py +0 -0
  111. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/pr.py +0 -0
  112. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/pr_body.py +0 -0
  113. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/release_sync.py +0 -0
  114. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/github/status.py +0 -0
  115. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/images.py +0 -0
  116. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/mailmap.py +0 -0
  117. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/myst_converter.py +0 -0
  118. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/myst_docstrings.py +0 -0
  119. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/py.typed +0 -0
  120. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/pyproject.py +0 -0
  121. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/rst_to_myst.py +0 -0
  122. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/sponsor.py +0 -0
  123. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/__init__.py +0 -0
  124. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/available-admonition.md +0 -0
  125. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/broken-links-issue.md +0 -0
  126. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/bump-version.md +0 -0
  127. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/detect-squash-merge.md +0 -0
  128. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/development-warning.md +0 -0
  129. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/fix-typos.md +0 -0
  130. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/format-images.md +0 -0
  131. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/format-json.md +0 -0
  132. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/format-markdown.md +0 -0
  133. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/format-pyproject.md +0 -0
  134. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/format-python.md +0 -0
  135. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/format-shell.md +0 -0
  136. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/generated-footer.md +0 -0
  137. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/github-releases.md +0 -0
  138. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/immutable-releases.md +0 -0
  139. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/pr-metadata.md.noformat +0 -0
  140. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/prepare-release.md +0 -0
  141. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/refresh-tip.md +0 -0
  142. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/release-notes.md +0 -0
  143. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/release-sync-report.md +0 -0
  144. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-branch-ruleset.md +0 -0
  145. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-fork-pr-approval.md +0 -0
  146. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-pages-source.md +0 -0
  147. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-pypi-trusted-publisher.md +0 -0
  148. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-verify.md +0 -0
  149. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide-virustotal.md +0 -0
  150. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/setup-guide.md +0 -0
  151. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/sync-bumpversion.md +0 -0
  152. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/sync-gitignore.md +0 -0
  153. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/sync-mailmap.md +0 -0
  154. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/sync-uv-lock.md +0 -0
  155. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/unavailable-admonition.md +0 -0
  156. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/unsubscribe-phase1.md +0 -0
  157. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/unsubscribe-phase2.md +0 -0
  158. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/update-deps-graph.md +0 -0
  159. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/templates/yanked-admonition.md +0 -0
  160. {repomatic-6.30.0 → repomatic-7.0.0}/repomatic/virustotal.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repomatic
3
- Version: 6.30.0
3
+ Version: 7.0.0
4
4
  Summary: 🏭 Automate repository maintenance, releases, and CI/CD workflows
5
- Keywords: changelog-formatter,dependabot-alternative,github-actions,github-labels,github-workflow,gitignore,mailmap,mypy,nuitka,python-automation,release-automation,renovate,repository-automation,repository-management,reusable-workflows,software-factory,sphinx-doc,typo,uv,workflow-reusable
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
7
7
  Author-email: Kevin Deldycke <kevin@deldycke.com>
8
8
  License-Expression: GPL-2.0-or-later
@@ -43,13 +43,13 @@ Classifier: Topic :: Text Processing :: Markup :: HTML
43
43
  Classifier: Topic :: Text Processing :: Markup :: Markdown
44
44
  Classifier: Topic :: Utilities
45
45
  Classifier: Typing :: Typed
46
+ Requires-Dist: arrow>=1.3
46
47
  Requires-Dist: backports-strenum>=1 ; python_full_version < '3.11'
47
48
  Requires-Dist: boltons>=25
48
49
  Requires-Dist: click-extra>=8.1
49
50
  Requires-Dist: extra-platforms>=12.0.2
50
51
  Requires-Dist: packaging>=17
51
52
  Requires-Dist: py-walk>=0.3.1
52
- Requires-Dist: pydriller>=2
53
53
  Requires-Dist: pyproject-metadata>=0.9
54
54
  Requires-Dist: pyyaml>=6.0.3
55
55
  Requires-Dist: tomlrt>=1.7.6
@@ -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/v6.30.0
61
+ Project-URL: Download, https://github.com/kdeldycke/repomatic/releases/tag/v7.0.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
@@ -88,7 +88,8 @@ A Python CLI and `pyproject.toml` configuration that let you **release Python pa
88
88
  - Cross-platform binary compilation (Linux / macOS / Windows, x86_64 / arm64)
89
89
  - Formatting autofix for Python, Markdown, JSON, Shell, and typos
90
90
  - Linting: Python types with mypy, YAML, GitHub Actions, workflow security, URLs, secrets, and Awesome lists
91
- - Synchronization of `uv.lock`, `.gitignore`, `.mailmap`, and Mermaid dependency graph
91
+ - Synchronization of `uv.lock`, GitHub Action pins, workflow version literals, and `repomatic run` tool versions with configurable stabilization cooldowns
92
+ - Synchronization of `.gitignore`, `.mailmap`, and Mermaid dependency graph
92
93
  - Label management with file-based and content-based rules
93
94
  - Inactive issue locking
94
95
  - Static image optimization
@@ -100,7 +101,7 @@ A Python CLI and `pyproject.toml` configuration that let you **release Python pa
100
101
  - [18 third-party GitHub Actions replaced](https://kdeldycke.github.io/repomatic/security.html#third-party-action-minimization) by internal CLI commands and SHA-256-verified binary downloads, keeping the supply chain attack surface minimal
101
102
  - [8 Python linters and formatters](https://kdeldycke.github.io/repomatic/security.html#ruff-consolidation) (pylint, black, isort, pyupgrade, pydocstyle, pycln, docformatter, blacken-docs) consolidated into ruff
102
103
  - [5 packaging and install tools](https://kdeldycke.github.io/repomatic/security.html#uv-consolidation) (poetry, build, twine, check-wheel-contents, pip-audit) consolidated into uv
103
- - All `uses:` references [pinned to full commit SHAs](https://kdeldycke.github.io/repomatic/security.html#supply-chain-security) via Renovate, with stabilization windows before adopting new versions
104
+ - All `uses:` references [pinned to full commit SHAs](https://kdeldycke.github.io/repomatic/security.html#supply-chain-security) with stabilization windows before adopting new versions, managed entirely by self-hosted sync jobs
104
105
  - [SLSA provenance attestations](https://kdeldycke.github.io/repomatic/security.html#supply-chain-security) on every release artifact (wheels and compiled binaries)
105
106
  - [VirusTotal scanning](https://kdeldycke.github.io/repomatic/security.html#av-false-positive-submissions) of compiled binaries to seed AV vendor databases and reduce false positives
106
107
  - [Trusted Publishing](https://kdeldycke.github.io/repomatic/workflows.html#github-workflows-release-yaml-jobs) for PyPI uploads: no long-lived tokens stored as secrets
@@ -5,7 +5,7 @@ requires = [ "uv-build>=0.9" ]
5
5
  [project]
6
6
  # Docs: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
7
7
  name = "repomatic"
8
- version = "6.30.0"
8
+ version = "7.0.0"
9
9
  description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
10
10
  readme = "readme.md"
11
11
  keywords = [
@@ -20,7 +20,6 @@ keywords = [
20
20
  "nuitka",
21
21
  "python-automation",
22
22
  "release-automation",
23
- "renovate",
24
23
  "repository-automation",
25
24
  "repository-management",
26
25
  "reusable-workflows",
@@ -75,14 +74,19 @@ classifiers = [
75
74
  "Typing :: Typed",
76
75
  ]
77
76
  dependencies = [
77
+ # arrow parses the RFC 3339 timestamps uv emits (nanosecond fractional seconds
78
+ # + a Z suffix, which Python 3.10's stdlib fromisoformat rejects) and renders the
79
+ # relative-time hints in sync-uv-lock tables and the unsubscribe report through
80
+ # its .humanize(). whenever was the prior parser but has no humanizer; switch back
81
+ # to it once one lands: https://github.com/ariebovenberg/whenever/discussions/277
82
+ "arrow>=1.3",
78
83
  # Provides enum.StrEnum for Python < 3.11; all versions expose the class.
79
84
  "backports-strenum>=1; python_version<'3.11'",
80
85
  # boltons 25.0.0 dropped Python 3.9, matching our requires-python >= 3.10.
81
86
  "boltons>=25",
82
87
  # 8.1.0 is the first release carrying the APIs repomatic uses: the `test-suite`
83
- # engine (renamed from `test-plan`), the `CONFIG_PATH_METADATA_KEY` /
84
- # `NORMALIZE_KEYS_METADATA_KEY` schema-metadata constants, and the
85
- # `@sort_by_option` / `ColumnSpec` `columns=` table registry.
88
+ # engine (renamed from `test-plan`) and the `CONFIG_PATH_METADATA_KEY` /
89
+ # `NORMALIZE_KEYS_METADATA_KEY` schema-metadata constants.
86
90
  "click-extra>=8.1",
87
91
  # extra-platforms 12.0.2 reimplemented is_macos() with sys.platform, avoiding
88
92
  # the platform.platform() shell-out to ``cmd /c ver`` on Windows that broke
@@ -95,8 +99,6 @@ dependencies = [
95
99
  # XXX Replace py-walk with wcmatch once the latter supports gitignore files:
96
100
  # https://github.com/facelessuser/wcmatch/issues/226
97
101
  "py-walk>=0.3.1",
98
- # pydriller 2.0 redesigned the API; Git, Commit, and Repository are core 2.x classes.
99
- "pydriller>=2",
100
102
  # pyproject-metadata 0.9 added PEP 639 (license expressions) and PEP 685 (extras
101
103
  # normalization); our StandardMetadata.from_pyproject() call benefits from these.
102
104
  "pyproject-metadata>=0.9",
@@ -120,7 +122,7 @@ dependencies = [
120
122
  ]
121
123
  urls.Changelog = "https://github.com/kdeldycke/repomatic/blob/main/changelog.md"
122
124
  urls.Documentation = "https://kdeldycke.github.io/repomatic"
123
- urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v6.30.0"
125
+ urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v7.0.0"
124
126
  urls.Funding = "https://github.com/sponsors/kdeldycke"
125
127
  urls.Homepage = "https://github.com/kdeldycke/repomatic"
126
128
  urls.Issues = "https://github.com/kdeldycke/repomatic/issues"
@@ -201,7 +203,7 @@ exclude-newer = "1 week"
201
203
  # "0 day" span. click-extra is held at its 8.1.0 release date so the lock adopts
202
204
  # it before the 1-week cooldown elapses; sync-uv-lock prunes this entry once
203
205
  # 8.1.0 ages past `exclude-newer`.
204
- exclude-newer-package = { click-extra = "2026-06-25T00:00:00Z", repomatic = "0 day" }
206
+ exclude-newer-package = { repomatic = "0 day" }
205
207
  # Package is at root level, not in "./src/".
206
208
  build-backend.module-root = ""
207
209
 
@@ -214,7 +216,7 @@ copyright = "Kevin Deldycke <kevin@deldycke.com> and contributors. Distributed u
214
216
  file-description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
215
217
  # Numeric only: Nuitka rejects PEP 440 .devN suffixes. Kept in sync with the
216
218
  # package version by the dedicated [tool.bumpversion] rule that strips the suffix.
217
- file-version = "6.30.0"
219
+ file-version = "7.0.0"
218
220
  include-data-dir = [
219
221
  "repomatic/data/awesome_template=repomatic/data/awesome_template",
220
222
  ]
@@ -232,7 +234,7 @@ include-package-data = [ "click_extra" ]
232
234
  linux-icon = "docs/assets/icon.png"
233
235
  macos-app-icon = "docs/assets/icon.icns"
234
236
  product-name = "Repomatic"
235
- product-version = "6.30.0"
237
+ product-version = "7.0.0"
236
238
  windows-icon-from-ico = "docs/assets/icon.ico"
237
239
 
238
240
  [tool.ruff]
@@ -243,6 +245,13 @@ show-fixes = true
243
245
  # Enable reformatting of code snippets in docstrings.
244
246
  # https://docs.astral.sh/ruff/formatter/#docstring-formatting
245
247
  format.docstring-code-format = true
248
+ # PLW1514: `open` and friends called without an explicit `encoding` argument.
249
+ # Windows defaults text I/O to cp1252, so a bare `open()`, `read_text()` or
250
+ # `write_text()` breaks on non-ASCII content, and only on Windows runners.
251
+ # Preview rule; its type inference misses unannotated `Path` locals, so
252
+ # PEP 597's `PYTHONWARNDEFAULTENCODING=1` remains the complete runtime net.
253
+ # See: https://docs.astral.sh/ruff/rules/unspecified-encoding/
254
+ lint.extend-select = [ "PLW1514" ]
246
255
  # D400: First line should end with a period.
247
256
  # Allows docstrings to end up with any punctuation, not just a period.
248
257
  # See: https://github.com/astral-sh/ruff/issues/1858#issuecomment-1382640623
@@ -305,10 +314,7 @@ pretty = true
305
314
  warn_unused_configs = true
306
315
  overrides = [
307
316
  { module = [
308
- "bumpversion.*",
309
- "gitdb.*",
310
317
  "py_walk.*",
311
- "pydriller.*",
312
318
  "vt",
313
319
  ], ignore_missing_imports = true },
314
320
  ]
@@ -319,7 +325,6 @@ addopts = [
319
325
  "--cov",
320
326
  "--cov-report=term",
321
327
  "--numprocesses=auto",
322
- "--dist=loadgroup",
323
328
  ]
324
329
  # https://docs.pytest.org/en/latest/customize.html#pyproject-toml
325
330
  markers = [
@@ -335,7 +340,7 @@ run.source = [ "repomatic" ]
335
340
  report.precision = 2
336
341
 
337
342
  [tool.bumpversion]
338
- current_version = "6.30.0"
343
+ current_version = "7.0.0"
339
344
  # Parse versions with an optional .devN suffix (PEP 440).
340
345
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\.dev(?P<dev>\\d+))?"
341
346
  serialize = [
@@ -419,6 +424,14 @@ exclude = [
419
424
  "^https://www\\.npmjs\\.com/package/.*$",
420
425
  # star-history.com fragments are JS-rendered and invisible to lychee.
421
426
  "^https://star-history\\.com/.*$",
427
+ # githubstatus.com returns 405 to HEAD requests from bots.
428
+ "githubstatus\\.com",
429
+ # Local intra-docs heading fragments are Sphinx cross-references, validated
430
+ # at doc build time via `myst_heading_anchors`. Lychee's GitHub-style slugger
431
+ # strips dots (`cache.dir` → `cachedir`) and cannot see MyST `(target)=`
432
+ # anchors, so it would false-positive links that resolve fine in the rendered
433
+ # docs. Anchored to `file://` so external `.../docs/*.md#` URLs stay checked.
434
+ "^file://.*/docs/[\\w.-]+\\.md#",
422
435
  ]
423
436
  exclude_path = [
424
437
  # Template files contain $variable placeholders that are not real URLs.
@@ -435,5 +448,6 @@ abandoned-versions = [
435
448
  "6.0.0",
436
449
  "6.18.0",
437
450
  ]
451
+ changelog.archive-location = "./docs/changelog-archive.md"
438
452
  exclude = [ "workflows" ]
439
453
  pypi-package-history = [ "gha-utils", "repokit" ]
@@ -21,7 +21,8 @@ A Python CLI and `pyproject.toml` configuration that let you **release Python pa
21
21
  - Cross-platform binary compilation (Linux / macOS / Windows, x86_64 / arm64)
22
22
  - Formatting autofix for Python, Markdown, JSON, Shell, and typos
23
23
  - Linting: Python types with mypy, YAML, GitHub Actions, workflow security, URLs, secrets, and Awesome lists
24
- - Synchronization of `uv.lock`, `.gitignore`, `.mailmap`, and Mermaid dependency graph
24
+ - Synchronization of `uv.lock`, GitHub Action pins, workflow version literals, and `repomatic run` tool versions with configurable stabilization cooldowns
25
+ - Synchronization of `.gitignore`, `.mailmap`, and Mermaid dependency graph
25
26
  - Label management with file-based and content-based rules
26
27
  - Inactive issue locking
27
28
  - Static image optimization
@@ -33,7 +34,7 @@ A Python CLI and `pyproject.toml` configuration that let you **release Python pa
33
34
  - [18 third-party GitHub Actions replaced](https://kdeldycke.github.io/repomatic/security.html#third-party-action-minimization) by internal CLI commands and SHA-256-verified binary downloads, keeping the supply chain attack surface minimal
34
35
  - [8 Python linters and formatters](https://kdeldycke.github.io/repomatic/security.html#ruff-consolidation) (pylint, black, isort, pyupgrade, pydocstyle, pycln, docformatter, blacken-docs) consolidated into ruff
35
36
  - [5 packaging and install tools](https://kdeldycke.github.io/repomatic/security.html#uv-consolidation) (poetry, build, twine, check-wheel-contents, pip-audit) consolidated into uv
36
- - All `uses:` references [pinned to full commit SHAs](https://kdeldycke.github.io/repomatic/security.html#supply-chain-security) via Renovate, with stabilization windows before adopting new versions
37
+ - All `uses:` references [pinned to full commit SHAs](https://kdeldycke.github.io/repomatic/security.html#supply-chain-security) with stabilization windows before adopting new versions, managed entirely by self-hosted sync jobs
37
38
  - [SLSA provenance attestations](https://kdeldycke.github.io/repomatic/security.html#supply-chain-security) on every release artifact (wheels and compiled binaries)
38
39
  - [VirusTotal scanning](https://kdeldycke.github.io/repomatic/security.html#av-false-positive-submissions) of compiled binaries to seed AV vendor databases and reduce false positives
39
40
  - [Trusted Publishing](https://kdeldycke.github.io/repomatic/workflows.html#github-workflows-release-yaml-jobs) for PyPI uploads: no long-lived tokens stored as secrets
@@ -17,5 +17,5 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = "6.30.0"
21
- __git_tag_sha__ = "e8e1f6c651ed0c51dd6622cf316f3f7f591ed3dc"
20
+ __version__ = "7.0.0"
21
+ __git_tag_sha__ = "36523e5a56f287e814210042ca7b852147a95498"
@@ -812,6 +812,7 @@ def lint_changelog_dates(
812
812
  changelog_path: Path,
813
813
  package: str | None = None,
814
814
  *,
815
+ archive_path: Path | None = None,
815
816
  fix: bool = False,
816
817
  pypi_package_history: Sequence[str] = (),
817
818
  abandoned_versions: Sequence[str] = (),
@@ -853,6 +854,10 @@ def lint_changelog_dates(
853
854
  linking to adjacent versions.
854
855
 
855
856
  :param changelog_path: Path to the changelog file.
857
+ :param archive_path: Optional path to a frozen changelog archive. Versions
858
+ documented there are treated as present, suppressing false-positive
859
+ orphan detection (and re-insertion under `fix`) for entries split out
860
+ of the live changelog. Archived dates are not re-validated.
856
861
  :param package: PyPI package name. If `None`, auto-detected from
857
862
  `pyproject.toml`. If detection fails, falls back to git tags.
858
863
  :param fix: If True, fix dates and add admonitions to the file.
@@ -955,8 +960,16 @@ def lint_changelog_dates(
955
960
  # from the changelog.
956
961
  tag_versions = get_all_version_tags()
957
962
  changelog_headings = changelog.extract_all_version_headings()
963
+ # Versions documented in the frozen archive count as present, so entries
964
+ # split out of the live changelog are neither flagged nor re-inserted as
965
+ # orphans.
966
+ archive_headings: set[str] = set()
967
+ if archive_path and archive_path.exists():
968
+ archive_headings = Changelog(
969
+ archive_path.read_text(encoding="UTF-8")
970
+ ).extract_all_version_headings()
958
971
  all_known = set(pypi_data) | set(github_releases) | set(tag_versions)
959
- orphans = all_known - changelog_headings
972
+ orphans = all_known - changelog_headings - archive_headings
960
973
  if orphans:
961
974
  for orphan in sorted(orphans, key=Version):
962
975
  logging.warning(
@@ -0,0 +1,127 @@
1
+ # Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
2
+ #
3
+ # This program is Free Software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU General Public License
5
+ # as published by the Free Software Foundation; either version 2
6
+ # of the License, or (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software
15
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
+
17
+ """Recompute SHA-256 checksums for the binary tool registry.
18
+
19
+ Iterates every `TOOL_REGISTRY` entry with a `binary` spec, downloads each
20
+ platform's release artifact, and rewrites stale hashes in-place in
21
+ `tool_runner.py` (alongside the `VERSIONS` stamps). Driven by
22
+ `repomatic update-checksums` and, with a version override, by
23
+ `sync-tool-versions` so a version bump and its matching checksums land in one
24
+ pass.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import hashlib
30
+ import logging
31
+ import re
32
+ import sys
33
+ from pathlib import Path
34
+ from urllib.request import Request, urlopen
35
+
36
+ from click_extra import progressbar
37
+
38
+ from .tool_runner import TOOL_REGISTRY
39
+
40
+
41
+ def _download_sha256(url: str) -> str:
42
+ """Download a URL and return its SHA-256 hex digest.
43
+
44
+ :param url: The URL to download.
45
+ :return: Lowercase hex SHA-256 digest of the response body.
46
+ """
47
+ request = Request(url)
48
+ with urlopen(request) as response:
49
+ digest = hashlib.sha256(response.read()).hexdigest()
50
+ logging.debug(f"SHA-256 of {url}: {digest}")
51
+ return digest
52
+
53
+
54
+ def update_registry_checksums(
55
+ tool_runner_path: Path,
56
+ version_overrides: dict[str, str] | None = None,
57
+ ) -> list[tuple[str, str, str]]:
58
+ """Recompute binary checksums and version stamps in `tool_runner.py`.
59
+
60
+ Iterates every `TOOL_REGISTRY` entry with a `binary` spec, downloads each
61
+ platform URL, computes its SHA-256, and replaces stale hashes in-place.
62
+ Also reconciles each tool's `VERSIONS` stamp with the version the checksums
63
+ were computed for, the basis of the offline staleness test.
64
+
65
+ :param tool_runner_path: Path to `tool_runner.py`.
66
+ :param version_overrides: Optional mapping of tool name to a version to
67
+ download instead of the in-memory `ToolSpec.version`. `sync-tool-versions`
68
+ passes this so it can bump the version in the source and refresh the
69
+ checksums in a single process: the in-memory registry still holds the
70
+ pre-bump version because the file was edited, not reimported.
71
+ :return: List of `(url, old_hash, new_hash)` for each updated checksum.
72
+ Empty if all checksums are already correct.
73
+ """
74
+ overrides = version_overrides or {}
75
+ original = tool_runner_path.read_text(encoding="UTF-8")
76
+ content = original
77
+ updated: list[tuple[str, str, str]] = []
78
+
79
+ # Flatten all binary platform entries for progress tracking, resolving each
80
+ # download URL against the override version when one is supplied.
81
+ entries = [
82
+ (
83
+ spec,
84
+ pk,
85
+ tmpl.format(version=overrides.get(spec.name, spec.version)),
86
+ spec.binary.checksums[pk],
87
+ )
88
+ for spec in TOOL_REGISTRY.values()
89
+ if spec.binary is not None
90
+ for pk, tmpl in spec.binary.urls.items()
91
+ ]
92
+
93
+ with progressbar(
94
+ entries,
95
+ label="Verifying checksums",
96
+ file=sys.stderr,
97
+ ) as items:
98
+ for spec, platform_key, url, old_hash in items:
99
+ logging.info(
100
+ f"Verifying registry checksum for {spec.name} ({platform_key})"
101
+ )
102
+ new_hash = _download_sha256(url)
103
+
104
+ if old_hash != new_hash:
105
+ content = content.replace(old_hash, new_hash)
106
+ updated.append((url, old_hash, new_hash))
107
+ logging.info(f"Updated checksum: {old_hash} -> {new_hash}")
108
+ else:
109
+ logging.info("Checksum unchanged.")
110
+
111
+ # Reconcile each tool's VERSIONS stamp with its target version (idempotent).
112
+ # The key pattern only matches the quoted-string values in `VERSIONS`, never
113
+ # the `ToolSpec(` registry entries or the tuple-keyed `CHECKSUMS` entries.
114
+ for spec in TOOL_REGISTRY.values():
115
+ if spec.binary is None:
116
+ continue
117
+ target = overrides.get(spec.name, spec.version)
118
+ content = re.sub(
119
+ rf'("{re.escape(spec.name)}":\s*)"[^"]*"',
120
+ rf'\g<1>"{target}"',
121
+ content,
122
+ )
123
+
124
+ if content != original:
125
+ tool_runner_path.write_text(content, encoding="UTF-8")
126
+
127
+ return updated