python-semantic-release 8.0.0a6__tar.gz → 8.0.0a7__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 (109) hide show
  1. {python-semantic-release-8.0.0a6/python_semantic_release.egg-info → python-semantic-release-8.0.0a7}/PKG-INFO +1 -1
  2. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/pyproject.toml +3 -1
  3. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7/python_semantic_release.egg-info}/PKG-INFO +1 -1
  4. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/python_semantic_release.egg-info/SOURCES.txt +1 -0
  5. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/python_semantic_release.egg-info/entry_points.txt +1 -0
  6. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/python_semantic_release.egg-info/requires.txt +1 -0
  7. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/__init__.py +1 -1
  8. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/commands/main.py +19 -3
  9. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/commands/publish.py +10 -3
  10. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/commands/version.py +27 -7
  11. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/config.py +1 -0
  12. python-semantic-release-8.0.0a7/tests/command_line/test_main.py +32 -0
  13. python-semantic-release-8.0.0a7/tests/command_line/test_publish.py +37 -0
  14. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/command_line/test_version.py +31 -165
  15. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/cli/test_config.py +0 -1
  16. python-semantic-release-8.0.0a6/tests/command_line/test_main.py +0 -18
  17. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/AUTHORS.rst +0 -0
  18. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/LICENSE +0 -0
  19. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/MANIFEST.in +0 -0
  20. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/README.rst +0 -0
  21. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/python_semantic_release.egg-info/dependency_links.txt +0 -0
  22. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/python_semantic_release.egg-info/top_level.txt +0 -0
  23. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/__main__.py +0 -0
  24. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/changelog/__init__.py +0 -0
  25. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/changelog/context.py +0 -0
  26. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/changelog/release_history.py +0 -0
  27. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/changelog/template.py +0 -0
  28. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/__init__.py +0 -0
  29. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/commands/__init__.py +0 -0
  30. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/commands/changelog.py +0 -0
  31. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/commands/generate_config.py +0 -0
  32. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/common.py +0 -0
  33. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/const.py +0 -0
  34. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/github_actions_output.py +0 -0
  35. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/masking_filter.py +0 -0
  36. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/cli/util.py +0 -0
  37. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/__init__.py +0 -0
  38. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/_base.py +0 -0
  39. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/angular.py +0 -0
  40. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/emoji.py +0 -0
  41. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/scipy.py +0 -0
  42. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/tag.py +0 -0
  43. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/token.py +0 -0
  44. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/commit_parser/util.py +0 -0
  45. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/const.py +0 -0
  46. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/data/templates/CHANGELOG.md.j2 +0 -0
  47. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/data/templates/release_notes.md.j2 +0 -0
  48. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/enums.py +0 -0
  49. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/errors.py +0 -0
  50. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/helpers.py +0 -0
  51. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/__init__.py +0 -0
  52. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/_base.py +0 -0
  53. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/gitea.py +0 -0
  54. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/github.py +0 -0
  55. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/gitlab.py +0 -0
  56. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/token_auth.py +0 -0
  57. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/hvcs/util.py +0 -0
  58. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/version/__init__.py +0 -0
  59. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/version/algorithm.py +0 -0
  60. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/version/declaration.py +0 -0
  61. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/version/translator.py +0 -0
  62. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/semantic_release/version/version.py +0 -0
  63. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/setup.cfg +0 -0
  64. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/setup.py +0 -0
  65. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/command_line/__init__.py +0 -0
  66. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/command_line/conftest.py +0 -0
  67. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/command_line/test_changelog.py +0 -0
  68. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/command_line/test_generate_config.py +0 -0
  69. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/command_line/test_help.py +0 -0
  70. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/fixtures/__init__.py +0 -0
  71. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/fixtures/commit_parsers.py +0 -0
  72. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/fixtures/example_project.py +0 -0
  73. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/fixtures/git_repo.py +0 -0
  74. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/fixtures/scipy.py +0 -0
  75. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/scenario/__init__.py +0 -0
  76. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/scenario/test_next_version.py +0 -0
  77. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/scenario/test_release_history.py +0 -0
  78. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/scenario/test_template_render.py +0 -0
  79. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/__init__.py +0 -0
  80. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/__init__.py +0 -0
  81. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/changelog/__init__.py +0 -0
  82. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/changelog/test_changelog_context.py +0 -0
  83. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/changelog/test_default_changelog.py +0 -0
  84. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/changelog/test_release_notes.py +0 -0
  85. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/changelog/test_template.py +0 -0
  86. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/cli/__init__.py +0 -0
  87. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/cli/test_github_actions_output.py +0 -0
  88. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/cli/test_masking_filter.py +0 -0
  89. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/cli/test_version.py +0 -0
  90. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/__init__.py +0 -0
  91. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/helper.py +0 -0
  92. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/test_angular.py +0 -0
  93. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/test_emoji.py +0 -0
  94. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/test_scipy.py +0 -0
  95. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/test_tag.py +0 -0
  96. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/test_token.py +0 -0
  97. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/commit_parser/test_util.py +0 -0
  98. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/__init__.py +0 -0
  99. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/test__base.py +0 -0
  100. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/test_gitea.py +0 -0
  101. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/test_github.py +0 -0
  102. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/test_gitlab.py +0 -0
  103. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/test_token_auth.py +0 -0
  104. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/hvcs/test_util.py +0 -0
  105. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/version/__init__.py +0 -0
  106. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/version/test_algorithm.py +0 -0
  107. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/version/test_declaration.py +0 -0
  108. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/version/test_translator.py +0 -0
  109. {python-semantic-release-8.0.0a6 → python-semantic-release-8.0.0a7}/tests/unit/semantic_release/version/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-semantic-release
3
- Version: 8.0.0a6
3
+ Version: 8.0.0a7
4
4
  Summary: Automatic Semantic Versioning for Python projects
5
5
  Author-email: Rolf Erik Lekang <me@rolflekang.com>
6
6
  License: MIT
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "python-semantic-release"
9
- version = "8.0.0-alpha.6"
9
+ version = "8.0.0-alpha.7"
10
10
  description = "Automatic Semantic Versioning for Python projects"
11
11
  requires-python = ">=3.7"
12
12
  license = { text = "MIT" }
@@ -37,6 +37,7 @@ dependencies = [
37
37
 
38
38
  [project.scripts]
39
39
  semantic-release = "semantic_release.cli:main"
40
+ psr = "semantic_release.cli:main"
40
41
 
41
42
  [project.urls]
42
43
  "Project Url" = "http://github.com/python-semantic-release/python-semantic-release"
@@ -47,6 +48,7 @@ docs = [
47
48
  "Sphinx==5.2.3",
48
49
  "sphinxcontrib-apidoc==0.3.0",
49
50
  "sphinx-autobuild==2021.03.14",
51
+ "furo>=2023.5.20",
50
52
  ]
51
53
  test = [
52
54
  "coverage[toml]>=6,<7",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-semantic-release
3
- Version: 8.0.0a6
3
+ Version: 8.0.0a7
4
4
  Summary: Automatic Semantic Versioning for Python projects
5
5
  Author-email: Rolf Erik Lekang <me@rolflekang.com>
6
6
  License: MIT
@@ -61,6 +61,7 @@ tests/command_line/test_changelog.py
61
61
  tests/command_line/test_generate_config.py
62
62
  tests/command_line/test_help.py
63
63
  tests/command_line/test_main.py
64
+ tests/command_line/test_publish.py
64
65
  tests/command_line/test_version.py
65
66
  tests/fixtures/__init__.py
66
67
  tests/fixtures/commit_parsers.py
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
+ psr = semantic_release.cli:main
2
3
  semantic-release = semantic_release.cli:main
@@ -22,6 +22,7 @@ black
22
22
  Sphinx==5.2.3
23
23
  sphinxcontrib-apidoc==0.3.0
24
24
  sphinx-autobuild==2021.03.14
25
+ furo>=2023.5.20
25
26
 
26
27
  [mypy]
27
28
  mypy
@@ -23,7 +23,7 @@ from semantic_release.version import (
23
23
  tags_and_versions as tags_and_versions,
24
24
  )
25
25
 
26
- __version__ = "8.0.0-alpha.6"
26
+ __version__ = "8.0.0-alpha.7"
27
27
 
28
28
 
29
29
  def setup_hook(argv: list[str]) -> None:
@@ -54,12 +54,20 @@ FORMAT = "[%(name)s] %(levelname)s %(module)s.%(funcName)s: %(message)s"
54
54
  show_default=True,
55
55
  type=click.IntRange(0, 2, clamp=True),
56
56
  )
57
+ @click.option(
58
+ "--strict",
59
+ "strict",
60
+ is_flag=True,
61
+ default=False,
62
+ help="Enable strict mode",
63
+ )
57
64
  @click.pass_context
58
65
  def main(
59
66
  ctx: click.Context,
60
67
  config_file: str = DEFAULT_CONFIG_FILE,
61
68
  verbosity: int = 0,
62
69
  noop: bool = False,
70
+ strict: bool = False,
63
71
  ) -> None:
64
72
  """
65
73
  Python Semantic Release
@@ -106,9 +114,14 @@ def main(
106
114
  ":shield: [bold cyan]You are running in no-operation mode, because the "
107
115
  "'--noop' flag was supplied"
108
116
  )
117
+
109
118
  cli_options = GlobalCommandLineOptions(
110
- noop=noop, verbosity=verbosity, config_file=config_file
119
+ noop=noop,
120
+ verbosity=verbosity,
121
+ config_file=config_file,
122
+ strict=strict,
111
123
  )
124
+ log.debug("global cli options: %s", cli_options)
112
125
 
113
126
  try:
114
127
  if config_file.endswith(".toml"):
@@ -130,8 +143,11 @@ def main(
130
143
  raw_config, repo=repo, global_cli_options=cli_options
131
144
  )
132
145
  except NotAReleaseBranch as exc:
133
- rprint(f"[bold red]{str(exc)}")
134
- ctx.exit(2)
146
+ rprint(f"[bold {'red' if strict else 'orange1'}]{str(exc)}")
147
+ # If not strict, exit 0 so other processes can continue. For example, in
148
+ # multibranch CI it might be desirable to run a non-release branch's pipeline
149
+ # without specifying conditional execution of PSR based on branch name
150
+ ctx.exit(2 if strict else 0)
135
151
  except InvalidConfiguration as exc:
136
152
  ctx.fail(str(exc))
137
153
  ctx.obj = runtime
@@ -14,8 +14,14 @@ log = logging.getLogger(__name__)
14
14
  "help_option_names": ["-h", "--help"],
15
15
  },
16
16
  )
17
+ @click.option(
18
+ "--tag",
19
+ "tag",
20
+ help="The tag associated with the release to publish to",
21
+ default="latest",
22
+ )
17
23
  @click.pass_context
18
- def publish(ctx: click.Context) -> None:
24
+ def publish(ctx: click.Context, tag: str = "latest") -> None:
19
25
  """
20
26
  Build and publish a distribution to a VCS release.
21
27
  """
@@ -25,7 +31,8 @@ def publish(ctx: click.Context) -> None:
25
31
  translator = runtime.version_translator
26
32
  dist_glob_patterns = runtime.dist_glob_patterns
27
33
 
28
- latest_tag = tags_and_versions(repo.tags, translator)[0][0]
34
+ if tag == "latest":
35
+ tag = str(tags_and_versions(repo.tags, translator)[0][0])
29
36
  if runtime.global_cli_options.noop:
30
37
  noop_report(
31
38
  "would have uploaded files matching any of the globs "
@@ -36,4 +43,4 @@ def publish(ctx: click.Context) -> None:
36
43
 
37
44
  log.info("Uploading distributions to release")
38
45
  for pattern in dist_glob_patterns:
39
- hvcs_client.upload_dists(tag=latest_tag, dist_glob=pattern)
46
+ hvcs_client.upload_dists(tag=tag, dist_glob=pattern)
@@ -172,6 +172,13 @@ def shell(cmd: str, *, check: bool = True) -> subprocess.CompletedProcess:
172
172
  default=os.getenv("PSR_BUILD_METADATA"),
173
173
  help="Build metadata to append to the new version",
174
174
  )
175
+ @click.option(
176
+ "--skip-build",
177
+ "skip_build",
178
+ default=False,
179
+ is_flag=True,
180
+ help="Skip building the current project",
181
+ )
175
182
  @click.pass_context
176
183
  def version(
177
184
  ctx: click.Context,
@@ -184,6 +191,7 @@ def version(
184
191
  push_changes: bool = True,
185
192
  make_vcs_release: bool = True,
186
193
  build_metadata: str | None = None,
194
+ skip_build: bool = False,
187
195
  ) -> str:
188
196
  """
189
197
  Detect the semantically correct next version that should be applied to your
@@ -278,14 +286,24 @@ def version(
278
286
 
279
287
  gha_output.released = False
280
288
  gha_output.version = new_version
281
- # If the new version has already been released, we fail and abort
289
+
290
+ # Print the new version so that command-line output capture will work
291
+ click.echo(str(new_version))
292
+
293
+ # If the new version has already been released, we fail and abort if strict;
294
+ # otherwise we exit with 0.
282
295
  if new_version in {v for _, v in tags_and_versions(repo.tags, translator)}:
283
- ctx.fail(
284
- f"No release will be made, {str(new_version)} has already been released!"
285
- )
296
+ if opts.strict:
297
+ ctx.fail(
298
+ f"No release will be made, {str(new_version)} has already been released!"
299
+ )
300
+ else:
301
+ rprint(
302
+ f"[bold orange1]No release will be made, {str(new_version)} has already been released!"
303
+ )
304
+ ctx.exit(0)
286
305
 
287
306
  if print_only:
288
- click.echo(str(new_version))
289
307
  ctx.exit(0)
290
308
 
291
309
  rprint(
@@ -302,9 +320,11 @@ def version(
302
320
 
303
321
  # Build distributions before committing any changes - this way if the
304
322
  # build fails, modifications to the source code won't be committed
305
- if not build_command:
323
+ if skip_build:
324
+ rprint("[bold orange1]Skipping build due to --skip-build flag")
325
+ elif not build_command:
306
326
  rprint("[green]No build command specified, skipping")
307
- if runtime.global_cli_options.noop:
327
+ elif runtime.global_cli_options.noop:
308
328
  noop_report(f"would have run the build_command {build_command}")
309
329
  else:
310
330
  try:
@@ -171,6 +171,7 @@ class GlobalCommandLineOptions:
171
171
  noop: bool = False
172
172
  verbosity: int = 0
173
173
  config_file: str = DEFAULT_CONFIG_FILE
174
+ strict: bool = False
174
175
 
175
176
 
176
177
  ######
@@ -0,0 +1,32 @@
1
+ import pytest
2
+
3
+ from semantic_release import __version__
4
+ from semantic_release.cli import main
5
+
6
+
7
+ def test_main_prints_version_and_exits(cli_runner):
8
+ result = cli_runner.invoke(main, ["--version"])
9
+ assert result.exit_code == 0
10
+ assert result.output == f"semantic-release, version {__version__}\n"
11
+
12
+
13
+ @pytest.mark.parametrize("args", [[], ["--help"]])
14
+ def test_main_prints_help_text(cli_runner, args):
15
+ result = cli_runner.invoke(main, args)
16
+ assert result.exit_code == 0
17
+
18
+
19
+ def test_not_a_release_branch_exit_code(repo_with_git_flow_angular_commits, cli_runner):
20
+ # Run anything that doesn't trigger the help text
21
+ repo_with_git_flow_angular_commits.git.checkout("-b", "branch-does-not-exist")
22
+ result = cli_runner.invoke(main, ["version", "--no-commit"])
23
+ assert result.exit_code == 0
24
+
25
+
26
+ def test_not_a_release_branch_exit_code_with_strict(
27
+ repo_with_git_flow_angular_commits, cli_runner
28
+ ):
29
+ # Run anything that doesn't trigger the help text
30
+ repo_with_git_flow_angular_commits.git.checkout("-b", "branch-does-not-exist")
31
+ result = cli_runner.invoke(main, ["--strict", "version", "--no-commit"])
32
+ assert result.exit_code != 0
@@ -0,0 +1,37 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+
5
+ from semantic_release.cli import main, publish
6
+ from semantic_release.hvcs import Github
7
+ from semantic_release.version import tags_and_versions
8
+
9
+
10
+ @pytest.mark.parametrize("cmd_args", [(), ("--tag", "latest")])
11
+ def test_publish_latest_uses_latest_tag(
12
+ repo_with_single_branch_angular_commits,
13
+ cli_runner,
14
+ cmd_args,
15
+ ):
16
+ with mock.patch.object(Github, "upload_dists") as mocked_upload_dists, mock.patch(
17
+ "semantic_release.cli.commands.publish.tags_and_versions",
18
+ return_value=([("v1.0.0", "1.0.0")]),
19
+ ) as mock_tags_and_versions:
20
+ result = cli_runner.invoke(main, [publish.name, *cmd_args])
21
+ assert result.exit_code == 0
22
+
23
+ mock_tags_and_versions.assert_called_once()
24
+ mocked_upload_dists.assert_called_once_with(tag="v1.0.0", dist_glob="dist/*")
25
+
26
+
27
+ def test_publish_to_tag_uses_tag(repo_with_single_branch_angular_commits, cli_runner):
28
+ tag = "v99.999.9999+build.1234"
29
+ with mock.patch.object(Github, "upload_dists") as mocked_upload_dists, mock.patch(
30
+ "semantic_release.cli.commands.publish.tags_and_versions",
31
+ return_value=([("v1.0.0", "1.0.0")]),
32
+ ) as mock_tags_and_versions:
33
+ result = cli_runner.invoke(main, [publish.name, "--tag", tag])
34
+ assert result.exit_code == 0
35
+
36
+ mock_tags_and_versions.assert_not_called()
37
+ assert mocked_upload_dists.called_once_with(tag=tag, dist_glob="dist/*")
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import difflib
4
4
  import filecmp
5
5
  import re
6
- import shlex
7
6
  import shutil
8
7
  from subprocess import CompletedProcess
9
8
  from unittest import mock
@@ -240,7 +239,7 @@ def test_version_already_released_no_push(repo, cli_runner):
240
239
  # In these tests, unless arguments are supplied then the latest version
241
240
  # has already been released, so we expect an exit code of 2 with the message
242
241
  # to indicate that no release will be made
243
- result = cli_runner.invoke(main, [version.name, "--no-push"])
242
+ result = cli_runner.invoke(main, ["--strict", version.name, "--no-push"])
244
243
  assert result.exit_code == 2
245
244
  assert "no release will be made" in result.output.lower()
246
245
 
@@ -440,168 +439,6 @@ def test_version_no_push_force_level(
440
439
  assert added == [f'__version__ = "{expected_new_version}"\n']
441
440
 
442
441
 
443
- @pytest.mark.parametrize(
444
- "repo, cli_args, expected_stdout",
445
- [
446
- *[
447
- (
448
- lazy_fixture("repo_with_no_tags_angular_commits"),
449
- cli_args,
450
- expected_stdout,
451
- )
452
- for cli_args, expected_stdout in (
453
- ([], "0.1.0"),
454
- (["--build-metadata", "build.12345"], "0.1.0+build.12345"),
455
- (["--patch"], "0.0.1"),
456
- (["--minor"], "0.1.0"),
457
- (["--major"], "1.0.0"),
458
- (["--patch", "--prerelease"], "0.0.1-rc.1"),
459
- (["--minor", "--prerelease"], "0.1.0-rc.1"),
460
- (["--major", "--prerelease"], "1.0.0-rc.1"),
461
- (
462
- ["--patch", "--prerelease", "--prerelease-token", "beta"],
463
- "0.0.1-beta.1",
464
- ),
465
- )
466
- ],
467
- *[
468
- (
469
- lazy_fixture("repo_with_single_branch_angular_commits"),
470
- cli_args,
471
- expected_stdout,
472
- )
473
- for cli_args, expected_stdout in (
474
- ([], "0.1.2"),
475
- (["--build-metadata", "build.12345"], "0.1.2+build.12345"),
476
- (["--patch"], "0.1.2"),
477
- (["--minor"], "0.2.0"),
478
- (["--major"], "1.0.0"),
479
- (["--patch", "--prerelease"], "0.1.2-rc.1"),
480
- (["--minor", "--prerelease"], "0.2.0-rc.1"),
481
- (["--major", "--prerelease"], "1.0.0-rc.1"),
482
- (
483
- ["--patch", "--prerelease", "--prerelease-token", "beta"],
484
- "0.1.2-beta.1",
485
- ),
486
- )
487
- ],
488
- *[
489
- (
490
- lazy_fixture("repo_with_single_branch_and_prereleases_angular_commits"),
491
- cli_args,
492
- expected_stdout,
493
- )
494
- for cli_args, expected_stdout in (
495
- ([], "0.2.1"),
496
- (["--build-metadata", "build.12345"], "0.2.1+build.12345"),
497
- (["--patch"], "0.2.1"),
498
- (["--minor"], "0.3.0"),
499
- (["--major"], "1.0.0"),
500
- (["--patch", "--prerelease"], "0.2.1-rc.1"),
501
- (["--minor", "--prerelease"], "0.3.0-rc.1"),
502
- (["--major", "--prerelease"], "1.0.0-rc.1"),
503
- (
504
- ["--patch", "--prerelease", "--prerelease-token", "beta"],
505
- "0.2.1-beta.1",
506
- ),
507
- )
508
- ],
509
- *[
510
- (
511
- lazy_fixture("repo_with_main_and_feature_branches_angular_commits"),
512
- cli_args,
513
- expected_stdout,
514
- )
515
- for cli_args, expected_stdout in (
516
- ([], "0.3.0-beta.2"),
517
- (["--build-metadata", "build.12345"], "0.3.0-beta.2+build.12345"),
518
- (["--patch"], "0.3.1"),
519
- (["--minor"], "0.4.0"),
520
- (["--major"], "1.0.0"),
521
- (["--patch", "--prerelease"], "0.3.1-beta.1"),
522
- (["--minor", "--prerelease"], "0.4.0-beta.1"),
523
- (["--major", "--prerelease"], "1.0.0-beta.1"),
524
- (
525
- ["--patch", "--prerelease", "--prerelease-token", "beta"],
526
- "0.3.1-beta.1",
527
- ),
528
- )
529
- ],
530
- *[
531
- (
532
- lazy_fixture("repo_with_git_flow_angular_commits"),
533
- cli_args,
534
- expected_stdout,
535
- )
536
- for cli_args, expected_stdout in (
537
- ([], "1.2.0-alpha.3"),
538
- (["--build-metadata", "build.12345"], "1.2.0-alpha.3+build.12345"),
539
- (["--patch"], "1.2.1"),
540
- (["--minor"], "1.3.0"),
541
- (["--major"], "2.0.0"),
542
- (["--patch", "--prerelease"], "1.2.1-alpha.1"),
543
- (["--minor", "--prerelease"], "1.3.0-alpha.1"),
544
- (["--major", "--prerelease"], "2.0.0-alpha.1"),
545
- (
546
- ["--patch", "--prerelease", "--prerelease-token", "beta"],
547
- "1.2.1-beta.1",
548
- ),
549
- )
550
- ],
551
- *[
552
- (
553
- lazy_fixture("repo_with_git_flow_and_release_channels_angular_commits"),
554
- cli_args,
555
- expected_stdout,
556
- )
557
- for cli_args, expected_stdout in (
558
- ([], "1.1.0-alpha.4"),
559
- (["--build-metadata", "build.12345"], "1.1.0-alpha.4+build.12345"),
560
- (["--patch"], "1.1.1"),
561
- (["--minor"], "1.2.0"),
562
- (["--major"], "2.0.0"),
563
- (["--patch", "--prerelease"], "1.1.1-alpha.1"),
564
- (["--minor", "--prerelease"], "1.2.0-alpha.1"),
565
- (["--major", "--prerelease"], "2.0.0-alpha.1"),
566
- (
567
- ["--patch", "--prerelease", "--prerelease-token", "beta"],
568
- "1.1.1-beta.1",
569
- ),
570
- )
571
- ],
572
- ],
573
- )
574
- def test_version_print(
575
- repo, cli_args, expected_stdout, example_project, tmp_path_factory, cli_runner
576
- ):
577
- # Make a commit to ensure we have something to release
578
- # otherwise the "no release will be made" logic will kick in first
579
- new_file = example_project / "temp.txt"
580
- new_file.write_text("noop version test")
581
-
582
- repo.git.add(str(new_file.resolve()))
583
- repo.git.commit(m="fix: temp new file")
584
-
585
- tempdir = tmp_path_factory.mktemp("test_version_print")
586
- shutil.rmtree(str(tempdir.resolve()))
587
- shutil.copytree(src=str(example_project.resolve()), dst=tempdir)
588
- head_before = repo.head.commit
589
- tags_before = sorted(list(repo.tags), key=lambda tag: tag.name)
590
-
591
- result = cli_runner.invoke(main, [version.name, *cli_args, "--print"])
592
-
593
- tags_after = sorted(list(repo.tags), key=lambda tag: tag.name)
594
- head_after = repo.head.commit
595
-
596
- assert result.exit_code == 0
597
- assert tags_before == tags_after
598
- assert head_before == head_after
599
- assert result.output.rstrip("\n") == expected_stdout
600
- dcmp = filecmp.dircmp(str(example_project.resolve()), tempdir)
601
- differing_files = flatten_dircmp(dcmp)
602
- assert not differing_files
603
-
604
-
605
442
  @pytest.mark.parametrize(
606
443
  "repo",
607
444
  [
@@ -614,7 +451,9 @@ def test_version_print(
614
451
  )
615
452
  def test_version_build_metadata_triggers_new_version(repo, cli_runner):
616
453
  # Verify we get "no version to release" without build metadata
617
- no_metadata_result = cli_runner.invoke(main, [version.name, "--no-push"])
454
+ no_metadata_result = cli_runner.invoke(
455
+ main, ["--strict", version.name, "--no-push"]
456
+ )
618
457
  assert no_metadata_result.exit_code == 2
619
458
  assert "no release will be made" in no_metadata_result.output.lower()
620
459
 
@@ -648,6 +487,20 @@ def test_version_runs_build_command(
648
487
  )
649
488
 
650
489
 
490
+ def test_version_skips_build_command_with_skip_build(
491
+ repo_with_git_flow_angular_commits, cli_runner
492
+ ):
493
+ with mock.patch(
494
+ "subprocess.run", return_value=CompletedProcess(args=(), returncode=0)
495
+ ) as patched_subprocess_run:
496
+ result = cli_runner.invoke(
497
+ main, [version.name, "--patch", "--no-push", "--skip-build"]
498
+ ) # force a new version
499
+ assert result.exit_code == 0
500
+
501
+ patched_subprocess_run.assert_not_called()
502
+
503
+
651
504
  def test_version_writes_github_actions_output(
652
505
  repo_with_git_flow_angular_commits, cli_runner, monkeypatch, tmp_path
653
506
  ):
@@ -665,3 +518,16 @@ def test_version_writes_github_actions_output(
665
518
  assert action_outputs["version"] == "1.2.1"
666
519
  assert "tag" in action_outputs
667
520
  assert action_outputs["tag"] == "v1.2.1"
521
+
522
+
523
+ def test_version_exit_code_when_strict(repo_with_git_flow_angular_commits, cli_runner):
524
+ result = cli_runner.invoke(main, ["--strict", version.name, "--no-push"])
525
+ assert result.exit_code != 0
526
+
527
+
528
+ def test_version_exit_code_when_not_strict(
529
+ repo_with_git_flow_angular_commits, cli_runner
530
+ ):
531
+ # Testing "no release will be made"
532
+ result = cli_runner.invoke(main, [version.name, "--no-push"])
533
+ assert result.exit_code == 0
@@ -2,7 +2,6 @@ from unittest import mock
2
2
 
3
3
  import pytest
4
4
  import tomlkit
5
- from git import Repo
6
5
 
7
6
  from semantic_release.cli.config import (
8
7
  GlobalCommandLineOptions,
@@ -1,18 +0,0 @@
1
- import logging
2
-
3
- import pytest
4
-
5
- from semantic_release import __version__
6
- from semantic_release.cli import main
7
-
8
-
9
- def test_main_prints_version_and_exits(cli_runner):
10
- result = cli_runner.invoke(main, ["--version"])
11
- assert result.exit_code == 0
12
- assert result.output == f"semantic-release, version {__version__}\n"
13
-
14
-
15
- @pytest.mark.parametrize("args", [[], ["--help"]])
16
- def test_main_prints_help_text(cli_runner, args):
17
- result = cli_runner.invoke(main, args)
18
- assert result.exit_code == 0