repomatic 6.27.0__tar.gz → 6.28.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 (150) hide show
  1. {repomatic-6.27.0 → repomatic-6.28.0}/PKG-INFO +2 -2
  2. {repomatic-6.27.0 → repomatic-6.28.0}/pyproject.toml +6 -6
  3. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/__init__.py +2 -2
  4. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/cli.py +82 -12
  5. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/config.py +24 -0
  6. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/_release-engine.yaml +9 -9
  7. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/autofix.yaml +39 -35
  8. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/changelog.yaml +14 -14
  9. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/debug.yaml +1 -1
  10. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/docs.yaml +3 -3
  11. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/labels.yaml +5 -5
  12. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/lint.yaml +7 -7
  13. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/renovate.json5 +2 -2
  14. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/renovate.yaml +3 -3
  15. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/tests.yaml +6 -3
  16. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/unsubscribe.yaml +1 -1
  17. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/matrix.py +9 -6
  18. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/metadata.py +53 -10
  19. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/test_matrix.py +29 -4
  20. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/test_plan.py +59 -2
  21. {repomatic-6.27.0 → repomatic-6.28.0}/license +0 -0
  22. {repomatic-6.27.0 → repomatic-6.28.0}/readme.md +0 -0
  23. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/__main__.py +0 -0
  24. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/binary.py +0 -0
  25. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/broken_links.py +0 -0
  26. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/cache.py +0 -0
  27. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/changelog.py +0 -0
  28. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/checksums.py +0 -0
  29. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/__init__.py +0 -0
  30. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/action-publish-pypi.yaml +0 -0
  31. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/agent-grunt-qa.md +0 -0
  32. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/agent-qa-engineer.md +0 -0
  33. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/agent-sphinx-docs.md +0 -0
  34. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/autolock.yaml +0 -0
  35. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/config.yml +0 -0
  36. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/ISSUE_TEMPLATE/new-link.yaml +0 -0
  37. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/code-of-conduct.md +0 -0
  38. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/contributing.md +0 -0
  39. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/contributing.zh.md +0 -0
  40. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/funding.yml +0 -0
  41. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/.github/pull_request_template.md +0 -0
  42. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/__init__.py +0 -0
  43. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/awesome_template/license +0 -0
  44. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/bumpversion.toml +0 -0
  45. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/cancel-runs.yaml +0 -0
  46. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/codecov.yaml +0 -0
  47. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/labeller-content-based.yaml +0 -0
  48. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/labeller-file-based.yaml +0 -0
  49. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/labels.toml +0 -0
  50. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/lychee.toml +0 -0
  51. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/mdformat.toml +0 -0
  52. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/mypy.toml +0 -0
  53. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/pytest.toml +0 -0
  54. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/release.yaml +0 -0
  55. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/ruff.toml +0 -0
  56. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-av-false-positive.md +0 -0
  57. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-awesome-triage.md +0 -0
  58. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-babysit-ci.md +0 -0
  59. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-benchmark-update.md +0 -0
  60. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-brand-assets.md +0 -0
  61. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-file-bug-report.md +0 -0
  62. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-repomatic-audit.md +0 -0
  63. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-repomatic-changelog.md +0 -0
  64. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-repomatic-deps.md +0 -0
  65. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-repomatic-init.md +0 -0
  66. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-repomatic-ship.md +0 -0
  67. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-repomatic-topics.md +0 -0
  68. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-sphinx-docs-sync.md +0 -0
  69. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-translation-sync.md +0 -0
  70. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/skill-upstream-audit.md +0 -0
  71. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/typos.toml +0 -0
  72. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/yamllint.yaml +0 -0
  73. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/data/zizmor.yaml +0 -0
  74. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/deps_graph.py +0 -0
  75. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/git_ops.py +0 -0
  76. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/__init__.py +0 -0
  77. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/actions.py +0 -0
  78. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/advisories.py +0 -0
  79. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/dev_release.py +0 -0
  80. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/gh.py +0 -0
  81. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/issue.py +0 -0
  82. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/pr.py +0 -0
  83. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/pr_body.py +0 -0
  84. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/release_sync.py +0 -0
  85. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/releases.py +0 -0
  86. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/status.py +0 -0
  87. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/token.py +0 -0
  88. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/unsubscribe.py +0 -0
  89. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/github/workflow_sync.py +0 -0
  90. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/images.py +0 -0
  91. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/init_project.py +0 -0
  92. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/lint_repo.py +0 -0
  93. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/mailmap.py +0 -0
  94. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/myst_converter.py +0 -0
  95. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/myst_docstrings.py +0 -0
  96. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/py.typed +0 -0
  97. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/pypi.py +0 -0
  98. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/pyproject.py +0 -0
  99. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/registry.py +0 -0
  100. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/release_prep.py +0 -0
  101. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/renovate.py +0 -0
  102. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/rst_to_myst.py +0 -0
  103. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/sponsor.py +0 -0
  104. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/__init__.py +0 -0
  105. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/available-admonition.md +0 -0
  106. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/broken-links-issue.md +0 -0
  107. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/bump-version.md +0 -0
  108. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/detect-squash-merge.md +0 -0
  109. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/development-warning.md +0 -0
  110. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/fix-changelog.md +0 -0
  111. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/fix-typos.md +0 -0
  112. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/fix-vulnerable-deps.md +0 -0
  113. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/format-images.md +0 -0
  114. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/format-json.md +0 -0
  115. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/format-markdown.md +0 -0
  116. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/format-pyproject.md +0 -0
  117. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/format-python.md +0 -0
  118. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/format-shell.md +0 -0
  119. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/generated-footer.md +0 -0
  120. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/github-releases.md +0 -0
  121. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/immutable-releases.md +0 -0
  122. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/pr-metadata.md.noformat +0 -0
  123. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/prepare-release.md +0 -0
  124. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/refresh-tip.md +0 -0
  125. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/release-notes.md +0 -0
  126. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/release-sync-report.md +0 -0
  127. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/renovate-migration.md +0 -0
  128. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-branch-ruleset.md +0 -0
  129. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-dependabot.md +0 -0
  130. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-fork-pr-approval.md +0 -0
  131. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-pages-source.md +0 -0
  132. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-pypi-trusted-publisher.md +0 -0
  133. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-token.md +0 -0
  134. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-verify.md +0 -0
  135. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide-virustotal.md +0 -0
  136. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/setup-guide.md +0 -0
  137. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/sync-bumpversion.md +0 -0
  138. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/sync-gitignore.md +0 -0
  139. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/sync-mailmap.md +0 -0
  140. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/sync-repomatic.md +0 -0
  141. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/sync-uv-lock.md +0 -0
  142. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/unavailable-admonition.md +0 -0
  143. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/unsubscribe-phase1.md +0 -0
  144. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/unsubscribe-phase2.md +0 -0
  145. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/update-deps-graph.md +0 -0
  146. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/update-docs.md +0 -0
  147. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/templates/yanked-admonition.md +0 -0
  148. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/tool_runner.py +0 -0
  149. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/uv.py +0 -0
  150. {repomatic-6.27.0 → repomatic-6.28.0}/repomatic/virustotal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repomatic
3
- Version: 6.27.0
3
+ Version: 6.28.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,renovate,repository-automation,repository-management,reusable-workflows,software-factory,sphinx-doc,typo,uv,workflow-reusable
6
6
  Author: Kevin Deldycke
@@ -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.27.0
61
+ Project-URL: Download, https://github.com/kdeldycke/repomatic/releases/tag/v6.28.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" ]
5
5
  [project]
6
6
  # Docs: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
7
7
  name = "repomatic"
8
- version = "6.27.0"
8
+ version = "6.28.0"
9
9
  description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
10
10
  readme = "readme.md"
11
11
  keywords = [
@@ -118,7 +118,7 @@ dependencies = [
118
118
  ]
119
119
  urls.Changelog = "https://github.com/kdeldycke/repomatic/blob/main/changelog.md"
120
120
  urls.Documentation = "https://kdeldycke.github.io/repomatic"
121
- urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v6.27.0"
121
+ urls.Download = "https://github.com/kdeldycke/repomatic/releases/tag/v6.28.0"
122
122
  urls.Funding = "https://github.com/sponsors/kdeldycke"
123
123
  urls.Homepage = "https://github.com/kdeldycke/repomatic"
124
124
  urls.Issues = "https://github.com/kdeldycke/repomatic/issues"
@@ -190,7 +190,7 @@ exclude-newer = "1 week"
190
190
  # pinned to git main (no PyPI release to freeze), so it keeps a permanent
191
191
  # "0 day" span. click-extra is held at 7.19.0 (manpages `--output-dir` flag);
192
192
  # tomlrt is held at 1.8.2.
193
- exclude-newer-package = { click-extra = "2026-06-14T00:00:00Z", repomatic = "0 day", tomlrt = "2026-06-16T00:00:00Z" }
193
+ exclude-newer-package = { repomatic = "0 day", tomlrt = "2026-06-16T00:00:00Z" }
194
194
  # Package is at root level, not in "./src/".
195
195
  build-backend.module-root = ""
196
196
 
@@ -203,7 +203,7 @@ copyright = "Kevin Deldycke <kevin@deldycke.com> and contributors. Distributed u
203
203
  file-description = "🏭 Automate repository maintenance, releases, and CI/CD workflows"
204
204
  # Numeric only: Nuitka rejects PEP 440 .devN suffixes. Kept in sync with the
205
205
  # package version by the dedicated [tool.bumpversion] rule that strips the suffix.
206
- file-version = "6.27.0"
206
+ file-version = "6.28.0"
207
207
  include-data-dir = [
208
208
  "repomatic/data/awesome_template=repomatic/data/awesome_template",
209
209
  ]
@@ -221,7 +221,7 @@ include-package-data = [ "click_extra" ]
221
221
  linux-icon = "docs/assets/icon.png"
222
222
  macos-app-icon = "docs/assets/icon.icns"
223
223
  product-name = "Repomatic"
224
- product-version = "6.27.0"
224
+ product-version = "6.28.0"
225
225
  windows-icon-from-ico = "docs/assets/icon.ico"
226
226
 
227
227
  [tool.ruff]
@@ -324,7 +324,7 @@ run.source = [ "repomatic" ]
324
324
  report.precision = 2
325
325
 
326
326
  [tool.bumpversion]
327
- current_version = "6.27.0"
327
+ current_version = "6.28.0"
328
328
  # Parse versions with an optional .devN suffix (PEP 440).
329
329
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\.dev(?P<dev>\\d+))?"
330
330
  serialize = [
@@ -17,5 +17,5 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = "6.27.0"
21
- __git_tag_sha__ = "90400f1be5e7a4df843b83a02dd1672cfbaccfb6"
20
+ __version__ = "6.28.0"
21
+ __git_tag_sha__ = "a6458162963b57814a69421fed1f969cbbe1d2b6"
@@ -26,6 +26,7 @@ import sys
26
26
  import tempfile
27
27
  import time
28
28
  from collections import Counter
29
+ from concurrent.futures import ThreadPoolExecutor
29
30
  from pathlib import Path
30
31
  from urllib.request import Request, urlopen
31
32
 
@@ -39,14 +40,17 @@ from click_extra import (
39
40
  EnumChoice,
40
41
  FloatRange,
41
42
  IntRange,
43
+ ParameterSource,
42
44
  ParamType,
43
45
  Section,
44
46
  UsageError,
45
47
  argument,
48
+ context,
46
49
  dir_path,
47
50
  echo,
48
51
  file_path,
49
52
  group,
53
+ jobs_option,
50
54
  option,
51
55
  option_group,
52
56
  pass_context,
@@ -167,7 +171,12 @@ from .sponsor import (
167
171
  is_pull_request,
168
172
  is_sponsor,
169
173
  )
170
- from .test_plan import DEFAULT_TEST_PLAN, SkippedTest, parse_test_plan
174
+ from .test_plan import (
175
+ DEFAULT_TEST_PLAN,
176
+ CLITestCase,
177
+ SkippedTest,
178
+ parse_test_plan,
179
+ )
171
180
  from .tool_runner import (
172
181
  TOOL_REGISTRY,
173
182
  binary_tool_context,
@@ -229,9 +238,21 @@ def prep_path(filepath: Path) -> IO:
229
238
 
230
239
  For non-stdout paths, parent directories are created automatically if they don't
231
240
  exist. This absorbs the `mkdir -p` step that workflows previously had to do.
241
+
242
+ ```{note}
243
+ When stdout is a captured in-memory stream with no backing file descriptor
244
+ (Click's test runner, the Sphinx `{click:run}` directive that live-renders CLI
245
+ output in the docs), `fileno()` raises and we write to the stream directly. Such
246
+ streams are already Python text objects, so the Windows `cp1252` concern does not
247
+ apply: that only bites a real terminal, which always has a descriptor.
248
+ ```
232
249
  """
233
250
  if is_stdout(filepath):
234
- return open(sys.stdout.fileno(), "w", encoding="UTF-8", closefd=False)
251
+ try:
252
+ fd = sys.stdout.fileno()
253
+ except (OSError, ValueError):
254
+ return sys.stdout
255
+ return open(fd, "w", encoding="UTF-8", closefd=False)
235
256
  filepath.parent.mkdir(parents=True, exist_ok=True)
236
257
  return filepath.open("w", encoding="UTF-8")
237
258
 
@@ -751,7 +772,12 @@ def metadata(ctx, format, overwrite, output, list_keys, keys):
751
772
  )
752
773
 
753
774
  if is_stdout(output):
754
- if overwrite:
775
+ # The overwrite flag is moot for stdout. Warn only when the user set it
776
+ # explicitly: firing on the default value warns on every bare stdout run.
777
+ if (
778
+ overwrite
779
+ and ctx.get_parameter_source("overwrite") is not ParameterSource.DEFAULT
780
+ ):
755
781
  logging.warning("Ignore the --overwrite/--force/--replace option.")
756
782
  logging.info(f"Print metadata to {sys.stdout.name}")
757
783
  else:
@@ -768,7 +794,9 @@ def metadata(ctx, format, overwrite, output, list_keys, keys):
768
794
  meta = Metadata()
769
795
 
770
796
  # Output a warning in GitHub runners if metadata are not saved to $GITHUB_OUTPUT.
771
- if is_github_ci():
797
+ # Skip the warning for stdout: writing to stdout is a legitimate use case
798
+ # (human inspection, --format json piping, Sphinx docs rendering) even in CI.
799
+ if is_github_ci() and not is_stdout(output):
772
800
  env_file = os.getenv("GITHUB_OUTPUT")
773
801
  if env_file and Path(env_file) != output:
774
802
  logging.warning(
@@ -1451,6 +1479,7 @@ def sync_mailmap(ctx, source, create_if_missing, destination_mailmap):
1451
1479
  default=False,
1452
1480
  help="Exit instantly on first failed test.",
1453
1481
  )
1482
+ @jobs_option
1454
1483
  @option(
1455
1484
  "-T",
1456
1485
  "--timeout",
@@ -1492,7 +1521,15 @@ def test_plan(
1492
1521
  (--plan-envvar), [tool.repomatic] config, or a built-in default.
1493
1522
  Each test invokes the command with the specified arguments and validates
1494
1523
  the output against expected patterns.
1524
+
1525
+ Cases run in parallel by default (see --jobs): each is an independent
1526
+ process invocation, so they overlap well. Pass --jobs 1 for sequential
1527
+ execution, which lets --exit-on-error stop on the first failure.
1495
1528
  """
1529
+ # click-extra's --jobs option stores its clamped worker count on the
1530
+ # context; it does not drive concurrency itself, so we read and act on it.
1531
+ worker_count = context.get(ctx, context.JOBS, 1)
1532
+
1496
1533
  # Load [tool.repomatic] config for fallback values.
1497
1534
  config = get_tool_config(ctx)
1498
1535
 
@@ -1542,16 +1579,21 @@ def test_plan(
1542
1579
 
1543
1580
  counter = Counter(total=len(test_list), skipped=0, failed=0)
1544
1581
 
1582
+ # Select the cases to run (respecting --select-test), keeping their 1-based
1583
+ # numbers for stable reporting.
1584
+ pending: list[tuple[int, CLITestCase]] = []
1545
1585
  for index, test_case in enumerate(test_list):
1546
1586
  test_number = index + 1
1547
- test_name = f"#{test_number}"
1548
- logging.info(f"Run test {test_name}...")
1549
-
1550
1587
  if select_test and test_number not in select_test:
1551
- logging.warning(f"Test {test_name} skipped by user request.")
1588
+ logging.warning(f"Test #{test_number} skipped by user request.")
1552
1589
  counter["skipped"] += 1
1553
1590
  continue
1591
+ pending.append((test_number, test_case))
1554
1592
 
1593
+ def run_case(item: tuple[int, CLITestCase]) -> tuple[int, str, CLITestCase]:
1594
+ """Run one case, returning its number, outcome, and the case itself."""
1595
+ test_number, test_case = item
1596
+ logging.info(f"Run test #{test_number}...")
1555
1597
  try:
1556
1598
  logging.debug(f"Test case parameters: {test_case}")
1557
1599
  test_case.run_cli_test(
@@ -1560,16 +1602,44 @@ def test_plan(
1560
1602
  default_timeout=timeout,
1561
1603
  )
1562
1604
  except SkippedTest as ex:
1563
- counter["skipped"] += 1
1564
- logging.warning(f"Test {test_name} skipped: {ex}")
1605
+ logging.warning(f"Test #{test_number} skipped: {ex}")
1606
+ return test_number, "skipped", test_case
1565
1607
  except Exception as ex: # noqa: BLE001
1608
+ logging.error(f"Test #{test_number} failed: {ex}")
1609
+ return test_number, "failed", test_case
1610
+ return test_number, "passed", test_case
1611
+
1612
+ def tally(outcome: tuple[int, str, CLITestCase]) -> bool:
1613
+ """Record an outcome in the counters and echo a failure's trace.
1614
+
1615
+ :return: `True` if the case failed.
1616
+ """
1617
+ _, status, test_case = outcome
1618
+ if status == "skipped":
1619
+ counter["skipped"] += 1
1620
+ elif status == "failed":
1566
1621
  counter["failed"] += 1
1567
- logging.error(f"Test {test_name} failed: {ex}")
1568
1622
  if show_trace_on_error and test_case.execution_trace:
1569
1623
  echo(test_case.execution_trace)
1570
- if exit_on_error:
1624
+ return status == "failed"
1625
+
1626
+ if worker_count == 1 or len(pending) <= 1:
1627
+ # Sequential: --exit-on-error can short-circuit on the first failure.
1628
+ for item in pending:
1629
+ if tally(run_case(item)) and exit_on_error:
1571
1630
  logging.debug("Don't continue testing, a failed test was found.")
1572
1631
  ctx.exit(1)
1632
+ else:
1633
+ # Parallel: subprocess.run releases the GIL while the child runs, so
1634
+ # worker threads overlap each case's process spawn and execution. All
1635
+ # selected cases run (--exit-on-error has no effect); executor.map
1636
+ # yields in submission order, keeping traces and counters ordered.
1637
+ logging.info(
1638
+ f"Run {len(pending)} test cases across {worker_count} parallel workers."
1639
+ )
1640
+ with ThreadPoolExecutor(max_workers=worker_count) as executor:
1641
+ for outcome in executor.map(run_case, pending):
1642
+ tally(outcome)
1573
1643
 
1574
1644
  if stats:
1575
1645
  echo(
@@ -284,6 +284,30 @@ class TestMatrixConfig:
284
284
  Additive to the upstream default excludes.
285
285
  """
286
286
 
287
+ full_include: list[dict[str, str]] = field(
288
+ default_factory=list,
289
+ metadata={"click_extra.config_path": "full-include"},
290
+ )
291
+ """Full-matrix-only job rows, added as standalone matrix combinations.
292
+
293
+ Each entry is a dict of GitHub Actions matrix keys fully describing one job
294
+ (like `{"os": "ubuntu-24.04-arm", "python-version": "3.10",
295
+ "click-version": "8.3.1"}`). Unlike `include`, these are appended as
296
+ independent rows of the full matrix, never merged into the base
297
+ cross-product, so a cell can't overwrite a shipped-config job that shares
298
+ its `os` and `python-version`. Keys left out inherit the matrix defaults
299
+ (the single-key `include` entries, plus `state: stable`), so a cell lists
300
+ only what differs from the shipped configuration.
301
+
302
+ Use this for heterogeneous coverage, like pinning each release of a
303
+ dependency to its own runner and Python, where carving the same shape from
304
+ the base cross-product with `exclude` would take many rules. Like
305
+ `variations` and `unstable`, it touches the full matrix only; the PR matrix
306
+ stays a curated reduced set. Adding any entry makes the full matrix emit as
307
+ a flat job list (`{"include": [...]}`), which GitHub runs verbatim with no
308
+ cross-product expansion.
309
+ """
310
+
287
311
  include: list[dict[str, str]] = field(default_factory=list)
288
312
  """Extra include directives applied to both full and PR test matrices.
289
313
 
@@ -61,7 +61,7 @@ jobs:
61
61
  - name: Run repomatic metadata
62
62
  id: metadata
63
63
  run: >
64
- uvx --no-progress 'repomatic==6.27.0' metadata
64
+ uvx --no-progress 'repomatic==6.28.0' metadata
65
65
  --format github-json --output "$GITHUB_OUTPUT"
66
66
  new_commits_matrix release_commits_matrix build_targets nuitka_matrix
67
67
  nuitka_extras is_python_project package_name current_version
@@ -142,7 +142,7 @@ jobs:
142
142
  # NUITKA_PYTHON_FLAGS holds the entry point's --python-flag (if any),
143
143
  # meant to word-split.
144
144
  # shellcheck disable=SC2086
145
- uvx --no-progress 'repomatic==6.27.0' run nuitka -- \
145
+ uvx --no-progress 'repomatic==6.28.0' run nuitka -- \
146
146
  ${NUITKA_PYTHON_FLAGS} \
147
147
  --output-filename="${BIN_NAME}" "${MODULE_PATH}"
148
148
  - name: Upload Nuitka crash report
@@ -176,7 +176,7 @@ jobs:
176
176
  BIN_NAME: ${{ matrix.bin_name }}
177
177
  shell: bash
178
178
  run: >
179
- uvx --no-progress 'repomatic==6.27.0'
179
+ uvx --no-progress 'repomatic==6.28.0'
180
180
  verify-binary --target "${TARGET}" --binary "${BIN_NAME}"
181
181
  - name: Upload binaries
182
182
  uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -258,7 +258,7 @@ jobs:
258
258
  BIN_NAME: ${{ matrix.bin_name }}
259
259
  shell: bash
260
260
  run: >
261
- uvx --no-progress 'repomatic==6.27.0' test-plan
261
+ uvx --no-progress 'repomatic==6.28.0' test-plan
262
262
  --binary "${DOWNLOAD_PATH}/${BIN_NAME}"
263
263
 
264
264
  create-tag:
@@ -287,7 +287,7 @@ jobs:
287
287
  CURRENT_VERSION: ${{ matrix.current_version }}
288
288
  COMMIT: ${{ matrix.commit }}
289
289
  run: >
290
- uvx --no-progress 'repomatic==6.27.0' git-tag
290
+ uvx --no-progress 'repomatic==6.28.0' git-tag
291
291
  --tag "v${CURRENT_VERSION}"
292
292
  --commit "${COMMIT}"
293
293
  --skip-existing
@@ -328,7 +328,7 @@ jobs:
328
328
  continue-on-error: true
329
329
  env:
330
330
  GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
331
- run: uvx --no-progress 'repomatic==6.27.0' sync-dev-release --live --delete
331
+ run: uvx --no-progress 'repomatic==6.28.0' sync-dev-release --live --delete
332
332
  - name: Create GitHub release draft
333
333
  # Idempotent: skips if release already exists (e.g. workflow re-run).
334
334
  env:
@@ -502,7 +502,7 @@ jobs:
502
502
  VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }}
503
503
  CURRENT_VERSION: ${{ matrix.current_version }}
504
504
  run: >
505
- uvx --no-progress 'repomatic==6.27.0' scan-virustotal
505
+ uvx --no-progress 'repomatic==6.28.0' scan-virustotal
506
506
  --tag "v${CURRENT_VERSION}"
507
507
  --repo "${{ github.repository }}"
508
508
  --binaries-dir ./binaries
@@ -512,7 +512,7 @@ jobs:
512
512
  VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }}
513
513
  CURRENT_VERSION: ${{ matrix.current_version }}
514
514
  run: >
515
- uvx --no-progress 'repomatic==6.27.0' scan-virustotal
515
+ uvx --no-progress 'repomatic==6.28.0' scan-virustotal
516
516
  --tag "v${CURRENT_VERSION}"
517
517
  --repo "${{ github.repository }}"
518
518
  --poll
@@ -547,5 +547,5 @@ jobs:
547
547
  env:
548
548
  GH_TOKEN: ${{ github.token }}
549
549
  run: >
550
- uvx --no-progress 'repomatic==6.27.0' sync-dev-release --live
550
+ uvx --no-progress 'repomatic==6.28.0' sync-dev-release --live
551
551
  --upload-assets release_assets
@@ -39,7 +39,7 @@ jobs:
39
39
  GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
40
40
  REPOMATIC_PAT: ${{ secrets.REPOMATIC_PAT }}
41
41
  HAS_VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY && 'true' || '' }}
42
- run: uvx --no-progress 'repomatic==6.27.0' setup-guide
42
+ run: uvx --no-progress 'repomatic==6.28.0' setup-guide
43
43
 
44
44
  metadata:
45
45
  name: 🧬 Project metadata
@@ -52,7 +52,7 @@ jobs:
52
52
  - name: Run repomatic metadata
53
53
  id: metadata
54
54
  run: >
55
- uvx --no-progress 'repomatic==6.27.0' metadata
55
+ uvx --no-progress 'repomatic==6.28.0' metadata
56
56
  --format github-json --output "$GITHUB_OUTPUT"
57
57
  gitignore_exists python_files pyproject_files json_files doc_files
58
58
  markdown_files is_python_project mailmap_exists
@@ -81,16 +81,16 @@ jobs:
81
81
  # Explicit list of files is provided, as autopep8 is not able to handle find files in ".github" subdirectory.
82
82
  env:
83
83
  PYTHON_FILES: ${{ fromJSON(needs.metadata.outputs.metadata).python_files }}
84
- run: echo "${PYTHON_FILES}" | xargs uvx --no-progress 'repomatic==6.27.0' run autopep8 --
84
+ run: echo "${PYTHON_FILES}" | xargs uvx --no-progress 'repomatic==6.28.0' run autopep8 --
85
85
  # XXX Ruff is planning to support linting and formatting in one unified command at one point.
86
86
  # See: https://github.com/astral-sh/ruff/issues/8232
87
87
  - name: Run Ruff
88
88
  run: |
89
- uvx --no-progress 'repomatic==6.27.0' run ruff -- check --output-format github
90
- uvx --no-progress 'repomatic==6.27.0' run ruff -- format --output-format github
89
+ uvx --no-progress 'repomatic==6.28.0' run ruff -- check --output-format github
90
+ uvx --no-progress 'repomatic==6.28.0' run ruff -- format --output-format github
91
91
  - id: pr-metadata
92
92
  run: >
93
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
93
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
94
94
  --template format-python
95
95
  --output "$GITHUB_OUTPUT"
96
96
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -124,11 +124,11 @@ jobs:
124
124
  PYPROJECT_FILES: ${{ fromJSON(needs.metadata.outputs.metadata).pyproject_files }}
125
125
  run: |
126
126
  rc=0
127
- echo "${PYPROJECT_FILES}" | xargs uvx --no-progress 'repomatic==6.27.0' run pyproject-fmt -- || rc=$?
127
+ echo "${PYPROJECT_FILES}" | xargs uvx --no-progress 'repomatic==6.28.0' run pyproject-fmt -- || rc=$?
128
128
  [ "$rc" -eq 0 ] || [ "$rc" -eq 123 ] || exit "$rc"
129
129
  - id: pr-metadata
130
130
  run: >
131
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
131
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
132
132
  --template format-pyproject
133
133
  --output "$GITHUB_OUTPUT"
134
134
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -147,7 +147,11 @@ jobs:
147
147
  needs:
148
148
  - metadata
149
149
  if: fromJSON(needs.metadata.outputs.metadata).markdown_files
150
- # Cannot use "ubuntu-slim" because shfmt is not available there.
150
+ # "ubuntu-slim" lacks shfmt (needed by mdformat-shfmt), so this job needs a
151
+ # full image. ARM would run the per-file mdformat pass ~1.26x faster, but
152
+ # mdformat-config pulls taplo, which ships no linux-aarch64 wheel and has a
153
+ # broken 0.9.3 sdist; stay on full x86 until taplo publishes an aarch64 wheel.
154
+ # See docs/test-matrix.md.
151
155
  runs-on: ubuntu-24.04
152
156
  permissions:
153
157
  contents: write
@@ -161,7 +165,7 @@ jobs:
161
165
  - name: Auto-format Markdown
162
166
  env:
163
167
  MARKDOWN_FILES: ${{ fromJSON(needs.metadata.outputs.metadata).markdown_files }}
164
- run: echo "${MARKDOWN_FILES}" | xargs -n1 uvx --no-progress 'repomatic==6.27.0' run mdformat --
168
+ run: echo "${MARKDOWN_FILES}" | xargs -n1 uvx --no-progress 'repomatic==6.28.0' run mdformat --
165
169
  - name: Markdown fixes for Awesome Lists
166
170
  if: startsWith(github.event.repository.name, 'awesome-')
167
171
  # Remove forbidden TOC entries: https://github.com/sindresorhus/awesome-lint/blob/v2.2.2/rules/toc.js#L14-L18
@@ -176,7 +180,7 @@ jobs:
176
180
  -exec gawk -i inplace '!/^- \[(Contents|Contributing|Footnotes|Related Lists)\]\(#.+\)$/{print}' "{}" \;
177
181
  - id: pr-metadata
178
182
  run: >
179
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
183
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
180
184
  --template format-markdown
181
185
  --output "$GITHUB_OUTPUT"
182
186
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -211,10 +215,10 @@ jobs:
211
215
  - name: Format shell scripts
212
216
  env:
213
217
  SHELL_FILES: ${{ fromJSON(needs.metadata.outputs.metadata).shfmt_files }}
214
- run: echo "${SHELL_FILES}" | xargs uvx --no-progress 'repomatic==6.27.0' run shfmt --
218
+ run: echo "${SHELL_FILES}" | xargs uvx --no-progress 'repomatic==6.28.0' run shfmt --
215
219
  - id: pr-metadata
216
220
  run: >
217
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
221
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
218
222
  --template format-shell
219
223
  --output "$GITHUB_OUTPUT"
220
224
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -253,12 +257,12 @@ jobs:
253
257
  JSON_FILES: ${{ fromJSON(needs.metadata.outputs.metadata).json_files }}
254
258
  run: |
255
259
  echo "${JSON_FILES}" | xargs \
256
- uvx --no-progress 'repomatic==6.27.0' run biome -- \
260
+ uvx --no-progress 'repomatic==6.28.0' run biome -- \
257
261
  format --write --no-errors-on-unmatched \
258
262
  --json-parse-allow-comments=true --json-parse-allow-trailing-commas=true
259
263
  - id: pr-metadata
260
264
  run: >
261
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
265
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
262
266
  --template format-json
263
267
  --output "$GITHUB_OUTPUT"
264
268
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -290,10 +294,10 @@ jobs:
290
294
  restore-keys: |
291
295
  repomatic-bin-${{ runner.os }}-${{ runner.arch }}-typos-
292
296
  - name: Fix typos
293
- run: uvx --no-progress 'repomatic==6.27.0' run typos
297
+ run: uvx --no-progress 'repomatic==6.28.0' run typos
294
298
  - id: pr-metadata
295
299
  run: >
296
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
300
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
297
301
  --template fix-typos
298
302
  --output "$GITHUB_OUTPUT"
299
303
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -330,14 +334,14 @@ jobs:
330
334
  env:
331
335
  GH_TOKEN: ${{ secrets.REPOMATIC_PAT || github.token }}
332
336
  run: >
333
- uvx --no-progress 'repomatic==6.27.0' audit --fix
337
+ uvx --no-progress 'repomatic==6.28.0' audit --fix
334
338
  --repo "${{ github.repository }}"
335
339
  --output "$GITHUB_OUTPUT" --output-format github-actions
336
340
  - id: pr-metadata
337
341
  env:
338
342
  REPOMATIC_DIFF_TABLE: ${{ steps.fix.outputs.diff_table }}
339
343
  run: >
340
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
344
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
341
345
  --template fix-vulnerable-deps
342
346
  --output "$GITHUB_OUTPUT"
343
347
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -362,11 +366,11 @@ jobs:
362
366
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
363
367
  - name: Sync repomatic-managed files
364
368
  run: >
365
- uvx --no-progress 'repomatic==6.27.0' init
369
+ uvx --no-progress 'repomatic==6.28.0' init
366
370
  --delete-unmodified --delete-excluded
367
371
  - id: pr-metadata
368
372
  run: >
369
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
373
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
370
374
  --template sync-repomatic
371
375
  --output "$GITHUB_OUTPUT"
372
376
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -408,13 +412,13 @@ jobs:
408
412
  - name: Format images
409
413
  id: format
410
414
  run: >
411
- uvx --no-progress 'repomatic==6.27.0' format-images
415
+ uvx --no-progress 'repomatic==6.28.0' format-images
412
416
  --output "$GITHUB_OUTPUT" --output-format github-actions
413
417
  - id: pr-metadata
414
418
  env:
415
419
  GHA_PR_BODY_PREFIX: ${{ steps.format.outputs.markdown }}
416
420
  run: >
417
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
421
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
418
422
  --template format-images
419
423
  --output "$GITHUB_OUTPUT"
420
424
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -443,10 +447,10 @@ jobs:
443
447
  - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
444
448
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
445
449
  - name: Sync .gitignore
446
- run: uvx --no-progress 'repomatic==6.27.0' sync-gitignore
450
+ run: uvx --no-progress 'repomatic==6.28.0' sync-gitignore
447
451
  - id: pr-metadata
448
452
  run: >
449
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
453
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
450
454
  --template sync-gitignore
451
455
  --output "$GITHUB_OUTPUT"
452
456
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -473,10 +477,10 @@ jobs:
473
477
  - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
474
478
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
475
479
  - name: Sync bumpversion config
476
- run: uvx --no-progress 'repomatic==6.27.0' sync-bumpversion
480
+ run: uvx --no-progress 'repomatic==6.28.0' sync-bumpversion
477
481
  - id: pr-metadata
478
482
  run: >
479
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
483
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
480
484
  --template sync-bumpversion
481
485
  --output "$GITHUB_OUTPUT"
482
486
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -506,10 +510,10 @@ jobs:
506
510
  fetch-depth: 0
507
511
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
508
512
  - name: Sync .mailmap
509
- run: uvx --no-progress 'repomatic==6.27.0' sync-mailmap --skip-if-missing
513
+ run: uvx --no-progress 'repomatic==6.28.0' sync-mailmap --skip-if-missing
510
514
  - id: pr-metadata
511
515
  run: >
512
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
516
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
513
517
  --template sync-mailmap
514
518
  --output "$GITHUB_OUTPUT"
515
519
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -538,14 +542,14 @@ jobs:
538
542
  - id: sync
539
543
  name: Sync uv.lock
540
544
  run: >
541
- uvx --no-progress 'repomatic==6.27.0' sync-uv-lock
545
+ uvx --no-progress 'repomatic==6.28.0' sync-uv-lock
542
546
  --no-table --release-notes
543
547
  --output "$GITHUB_OUTPUT" --output-format github-actions
544
548
  - id: pr-metadata
545
549
  env:
546
550
  REPOMATIC_DIFF_TABLE: ${{ steps.sync.outputs.diff_table }}
547
551
  run: >
548
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
552
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
549
553
  --template sync-uv-lock
550
554
  --output "$GITHUB_OUTPUT"
551
555
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -576,10 +580,10 @@ jobs:
576
580
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
577
581
  - name: Generate graph
578
582
  # Package name and output path are auto-detected from pyproject.toml.
579
- run: uvx --no-progress 'repomatic==6.27.0' update-deps-graph
583
+ run: uvx --no-progress 'repomatic==6.28.0' update-deps-graph
580
584
  - id: pr-metadata
581
585
  run: >
582
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
586
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
583
587
  --template update-deps-graph
584
588
  --output "$GITHUB_OUTPUT"
585
589
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -611,10 +615,10 @@ jobs:
611
615
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
612
616
  - name: Update docs
613
617
  # Runs sphinx-apidoc, converts RST stubs to MyST if applicable, then runs docs/docs_update.py.
614
- run: uvx --no-progress 'repomatic==6.27.0' update-docs
618
+ run: uvx --no-progress 'repomatic==6.28.0' update-docs
615
619
  - id: pr-metadata
616
620
  run: >
617
- uvx --no-progress 'repomatic==6.27.0' pr-body --output-format github-actions
621
+ uvx --no-progress 'repomatic==6.28.0' pr-body --output-format github-actions
618
622
  --template update-docs
619
623
  --output "$GITHUB_OUTPUT"
620
624
  - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1