Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,30 +45,33 @@ jobs:
- run: just test --cov-report xml

action-smoke:
# PR-only: on push-to-main the latest commit IS a `feat/`/`bugfix/` merge,
# so branch-prefix returns `created`/`patch`/`minor` — the no-bump
# assertions would fail. End-to-end coverage on main is provided by the
# dogfood workflow (`.github/workflows/semvertag.yml`), which runs the
# same `uses: ./` and pushes a real tag.
# PR-only: action-smoke has no value on push-to-main, where the dogfood
# workflow (`.github/workflows/semvertag.yml`) exercises the real
# composite action against the merge commit. Under `dry-run: true`,
# this job is side-effect-free regardless of main's tag state.
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: write
# No `permissions:` block: `contents: read` is sufficient because
# dry-run guarantees no tag-push attempt. Even a future regression
# that bypassed dry-run would be denied by the API.
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- id: semvertag
uses: ./
with:
dry-run: 'true'
env:
SEMVERTAG_BRANCH_PREFIX__MINOR: '["feat/"]'
- name: Verify outputs match the no-bump contract
# The CLI queries the GitHub API for the latest commit on the default
# branch (not the local PR checkout), so on every PR it lands in one
# of branch-prefix's no-bump statuses (`already_tagged`,
# `no_merge_commit`, `no_conforming_commit`) — all normalized to
# `no-bump` by action.yml. `tag` is intentionally NOT asserted:
# `already_tagged` populates it with the existing tag.
- name: Verify the composite normalized dry-run to no-bump
# Under `dry-run: true`, the CLI's status is one of `dry_run`,
# `no_tags`, `already_tagged`, `no_merge_commit`, `no_conforming_commit` —
# all normalized to `no-bump` by action.yml. If action.yml's
# dry-run wiring regresses, the CLI would push a tag, status would
# be `created`, and this assertion would fail loudly. `bump` is
# intentionally NOT asserted: under dry-run it reflects the would-be
# value (`patch`/`minor`/`major` for an untagged merge, `none`
# otherwise) — not a stable smoke value.
run: |
test "${{ steps.semvertag.outputs.status }}" = "no-bump"
test "${{ steps.semvertag.outputs.bump }}" = "none"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ GitHub Enterprise setup, outputs, and troubleshooting.
header (`feat:` minor, `fix:`/`perf:` patch, `!` or `BREAKING
CHANGE:` major).

Both are configurable via env vars. See [docs](https://semvertag.readthedocs.io)
Both are configurable via env vars. See [docs](https://semvertag.modern-python.org)
for the full configuration surface.

## License
Expand Down
12 changes: 10 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ inputs:
description: 'GitHub token with contents: write. Defaults to the workflow-issued github.token.'
required: false
default: ${{ github.token }}
dry-run:
description: 'If true, compute the bump and emit the planned tag/bump but do not push a tag.'
required: false
default: 'false'

outputs:
tag:
Expand All @@ -40,10 +44,14 @@ runs:
SEMVERTAG_STRATEGY: ${{ inputs.strategy }}
run: |
set -euo pipefail
result=$(uvx 'semvertag>=0.3.1,<1' tag --json)
dry_run_flag=''
if [ "${{ inputs.dry-run }}" = "true" ]; then dry_run_flag='--dry-run'; fi
# `$dry_run_flag` is intentionally unquoted: empty value collapses
# to no argument; non-empty expands to the literal `--dry-run`.
result=$(uvx 'semvertag>=0.5.0,<1' tag --json $dry_run_flag)
printf '%s\n' "$result"
# Normalize the CLI's internal status (`no_tags`, `already_tagged`,
# `no_merge_commit`, `no_conforming_commit`, ...) to a stable
# `no_merge_commit`, `no_conforming_commit`, `dry_run`, ...) to a stable
# consumer-facing enum. `set -euo pipefail` ensures we never reach
# here on CLI errors, so there is no `error` value to surface.
case "$(jq -r '.status' <<<"$result")" in
Expand Down
29 changes: 29 additions & 0 deletions docs/providers/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,35 @@ jobs:
echo "bump=${{ steps.semvertag.outputs.bump }}"
```

## Preview the next bump

Pass `dry-run: true` to compute the bump without pushing a tag — useful in
CI smoke tests, in PR previews, or to see what the next release would be:

```yaml
- id: semvertag
uses: modern-python/semvertag@v0
with:
dry-run: true
```

When `dry-run: true`, the action's `status` output is `no-bump` (no real tag
was pushed) and `bump` / `tag` reflect what *would* have happened. The raw
CLI's `status` field is `dry_run`; the action surface normalizes it to
`no-bump` so callers see a stable two-value enum.

You can also run this locally without the action:

```bash
uvx 'semvertag>=0.5.0' tag --dry-run --json
```

Output (example):

```json
{"schema_version":"1.0","strategy":"branch-prefix","bump":"minor","status":"dry_run","tag":"0.6.0","commit":"abc1234..."}
```

## Token scope: `GITHUB_TOKEN` vs Personal Access Tokens

Three cases govern which token the job should use:
Expand Down
Loading
Loading