auto-semver-control 1.8.8.dev0__tar.gz → 1.8.9.dev0__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 (92) hide show
  1. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/PKG-INFO +1 -1
  2. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/pyproject.toml +1 -1
  3. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/release_pr.py +25 -0
  4. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/bump.py +75 -1
  5. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver_control.egg-info/PKG-INFO +1 -1
  6. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/LICENSE +0 -0
  7. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/README.md +0 -0
  8. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/setup.cfg +0 -0
  9. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/__init__.py +0 -0
  10. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/__init__.py +0 -0
  11. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/__init__.py +0 -0
  12. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/base.py +0 -0
  13. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/constants.py +0 -0
  14. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/local.py +0 -0
  15. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/ops.py +0 -0
  16. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/promote.py +0 -0
  17. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/git/verified.py +0 -0
  18. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/github/__init__.py +0 -0
  19. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/adapters/github/event.py +0 -0
  20. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/__init__.py +0 -0
  21. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/__main__.py +0 -0
  22. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/finalize.py +0 -0
  23. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/main.py +0 -0
  24. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/promote.py +0 -0
  25. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/setup.py +0 -0
  26. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/cli/utils.py +0 -0
  27. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/__init__.py +0 -0
  28. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/__init__.py +0 -0
  29. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/bump.py +0 -0
  30. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/changelog.py +0 -0
  31. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/commit_group.py +0 -0
  32. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/commit_groups.py +0 -0
  33. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/config.py +0 -0
  34. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/lock_sync.py +0 -0
  35. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/promotion.py +0 -0
  36. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/pull_request.py +0 -0
  37. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/_models/release.py +0 -0
  38. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/config.py +0 -0
  39. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/config/constants.py +0 -0
  40. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/__init__.py +0 -0
  41. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/changelog/__init__.py +0 -0
  42. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/changelog/manager.py +0 -0
  43. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/commits/__init__.py +0 -0
  44. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/commits/grouper.py +0 -0
  45. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/commits/parser.py +0 -0
  46. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/pr/__init__.py +0 -0
  47. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/pr/builder.py +0 -0
  48. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/pr/github_builder.py +0 -0
  49. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/semver/__init__.py +0 -0
  50. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/semver/lock.py +0 -0
  51. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/semver/updater.py +0 -0
  52. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/core/semver/version.py +0 -0
  53. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/__init__.py +0 -0
  54. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/patch.py +0 -0
  55. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/pep440.py +0 -0
  56. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/registry.py +0 -0
  57. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/runner.py +0 -0
  58. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/strategies/__init__.py +0 -0
  59. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/strategies/npm.py +0 -0
  60. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/strategies/uv.py +0 -0
  61. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/strategy.py +0 -0
  62. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/lock_sync/sync.py +0 -0
  63. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/py.typed +0 -0
  64. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/__init__.py +0 -0
  65. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/check.py +0 -0
  66. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/links.py +0 -0
  67. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/scaffold.py +0 -0
  68. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/scaffolds/__init__.py +0 -0
  69. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/scaffolds/auto-semver.caller.yml +0 -0
  70. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/scaffolds/auto_semver_config.yml +0 -0
  71. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/setup/scaffolds/promote.caller.yml +0 -0
  72. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/templates/__init__.py +0 -0
  73. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/templates/engine.py +0 -0
  74. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/templates/types.py +0 -0
  75. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver/templates/utils.py +0 -0
  76. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver_control.egg-info/SOURCES.txt +0 -0
  77. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver_control.egg-info/dependency_links.txt +0 -0
  78. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver_control.egg-info/entry_points.txt +0 -0
  79. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver_control.egg-info/requires.txt +0 -0
  80. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/auto_semver_control.egg-info/top_level.txt +0 -0
  81. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/__init__.py +0 -0
  82. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/bridge.py +0 -0
  83. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/config.py +0 -0
  84. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/file_sink.py +0 -0
  85. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/record.py +0 -0
  86. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/renderers/__init__.py +0 -0
  87. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/renderers/base.py +0 -0
  88. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/renderers/github.py +0 -0
  89. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/renderers/plain.py +0 -0
  90. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/renderers/rich_live.py +0 -0
  91. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/reporter.py +0 -0
  92. {auto_semver_control-1.8.8.dev0 → auto_semver_control-1.8.9.dev0}/src/runview/summary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: auto-semver-control
3
- Version: 1.8.8.dev0
3
+ Version: 1.8.9.dev0
4
4
  Summary: Automatically bump semver, update changelogs, and open release PRs on merge.
5
5
  Author-email: Guy Erreich <gerreich.dev@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "auto-semver-control"
3
- version = "1.8.8.dev0"
3
+ version = "1.8.9.dev0"
4
4
  description = "Automatically bump semver, update changelogs, and open release PRs on merge."
5
5
  authors = [{ name = "Guy Erreich", email = "gerreich.dev@gmail.com" }]
6
6
  readme = "README.md"
@@ -33,10 +33,35 @@ if TYPE_CHECKING:
33
33
 
34
34
  logger = logging.getLogger(__package__)
35
35
 
36
+ _HTTP_NOT_FOUND = 404
37
+
36
38
 
37
39
  class GitReleasePr(GitOpsBase):
38
40
  """Release PR ownership and discovery."""
39
41
 
42
+ def github_release_exists(self, *, tag: str, github_token: str) -> bool:
43
+ """Return whether a GitHub Release exists for ``tag``.
44
+
45
+ Args:
46
+ tag: Tag name. GitHub uses that name as the release id.
47
+ github_token: Token used to query the GitHub API.
48
+
49
+ Returns:
50
+ True when the release exists. False when GitHub returns 404.
51
+
52
+ Raises:
53
+ GithubException: For API errors other than a missing release.
54
+ """
55
+ gh = self._github_client_for(github_token)
56
+ repo: Repository = gh.get_repo(full_name_or_id=self._repo_full_name)
57
+ try:
58
+ repo.get_release(tag)
59
+ except GithubException as err:
60
+ if err.status == _HTTP_NOT_FOUND:
61
+ return False
62
+ raise
63
+ return True
64
+
40
65
  def get_lock_at_ref(self, ref: str) -> SemverLock | None:
41
66
  """Load `.semver.lock` from a branch or tag ref."""
42
67
  try:
@@ -162,6 +162,73 @@ def _apply_version_bump(
162
162
  return None
163
163
 
164
164
 
165
+ def _unpublished_notes_base(
166
+ *,
167
+ gitops: GitOps,
168
+ lockfile: SemverLock,
169
+ github_token: str,
170
+ ) -> str | None:
171
+ """Return an earlier baseline when the current version never shipped.
172
+
173
+ A finalized version with no GitHub Release did not publish. The next release
174
+ notes should include that version's changes, so the commit range starts at
175
+ the previous finalized baseline instead of the failed release merge.
176
+
177
+ Args:
178
+ gitops: Git operations handler.
179
+ lockfile: Lock loaded from the integration branch, before it is rewritten.
180
+ github_token: Token used to check for a GitHub Release.
181
+
182
+ Returns:
183
+ The earlier baseline SHA, or None when the current baseline should be used.
184
+ """
185
+ current_base = lockfile.target_base_sha
186
+ if lockfile.finalized is not True or not isinstance(current_base, str) or not current_base:
187
+ return None
188
+
189
+ version = str(lockfile.version)
190
+ try:
191
+ shipped = gitops.github_release_exists(tag=version, github_token=github_token)
192
+ except Exception as err:
193
+ logger.warning("Could not check GitHub release for %s: %s", version, err)
194
+ return None
195
+ if shipped:
196
+ return None
197
+
198
+ earlier = _previous_finalized_baseline(gitops=gitops, version=version)
199
+ if earlier is None or earlier == current_base:
200
+ return None
201
+
202
+ logger.info(
203
+ "Version %s has no GitHub release; including its changes in the next release notes",
204
+ version,
205
+ )
206
+ return earlier
207
+
208
+
209
+ def _previous_finalized_baseline(*, gitops: GitOps, version: str) -> str | None:
210
+ """Return the baseline SHA of the finalized lock before ``version``.
211
+
212
+ Args:
213
+ gitops: Git operations handler.
214
+ version: Version whose own lock entries should be skipped.
215
+
216
+ Returns:
217
+ The previous finalized lock's ``target_base_sha``, or None when absent.
218
+ """
219
+ seen: set[str] = set()
220
+ for commit in gitops.repo.iter_commits(paths=SemverLock.path):
221
+ lock = gitops.get_lock_at_ref(commit.hexsha)
222
+ if lock is None or lock.finalized is not True or not lock.target_base_sha:
223
+ continue
224
+ lock_version = str(lock.version)
225
+ if lock_version == version or lock_version in seen:
226
+ continue
227
+ seen.add(lock_version)
228
+ return lock.target_base_sha
229
+ return None
230
+
231
+
165
232
  def _push_release_branch(
166
233
  *,
167
234
  gitops: GitOps,
@@ -271,6 +338,11 @@ def run(
271
338
  target_branch=target_branch,
272
339
  )
273
340
  baseline_sha = lockfile.target_base_sha
341
+ notes_base_sha = _unpublished_notes_base(
342
+ gitops=gitops,
343
+ lockfile=lockfile,
344
+ github_token=github_token,
345
+ )
274
346
 
275
347
  if not is_tag_promotion:
276
348
  with status("Applying version bump..."):
@@ -321,7 +393,9 @@ def run(
321
393
  f"Skipping baseline check. Details: {e}"
322
394
  )
323
395
 
324
- latest_commit_sha = lockfile.target_base_sha or event.get_merged_commit_sha()
396
+ latest_commit_sha = (
397
+ notes_base_sha or lockfile.target_base_sha or event.get_merged_commit_sha()
398
+ )
325
399
 
326
400
  commit_messages = gitops.get_recent_commits(latest_commit_sha, config=config)
327
401
  changelog.update(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: auto-semver-control
3
- Version: 1.8.8.dev0
3
+ Version: 1.8.9.dev0
4
4
  Summary: Automatically bump semver, update changelogs, and open release PRs on merge.
5
5
  Author-email: Guy Erreich <gerreich.dev@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later