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
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ in every repository. The first five appear in the changelog; the others are left
unless they are breaking (`!`). A [gitmoji](https://gitmoji.dev) after the type
(`feat: ✨ add X`, or `:sparkles:`) is optional and stripped from the changelog. The
changelog starts at the newest final tag, so a repository tags `v0.0.0` where it adopts
the process.
the process. Each entry ends with an absolute link to its PR (`[#12](https://github.com/…/pull/12)`),
built from `GITHUB_REPOSITORY`: GitHub doesn't autolink `#12` in `CHANGELOG.md`, nor reliably
in release notes. The `just changelog` recipes take the repository from the `origin` remote.

## Adopting release-tools

Expand Down Expand Up @@ -349,7 +351,9 @@ changelog:
set -euo pipefail
ref=$(sed -nE 's|.*Algorithmiq/release-tools/.github/workflows/release.yml@([^[:space:]]+).*|\1|p' \
.github/workflows/release.yml)
uvx --from {{ git_cliff }} git-cliff --unreleased \
# Link the PR numbers like the release PR does: GitHub Actions sets GITHUB_REPOSITORY.
repo=$(git remote get-url origin | sed -E 's#^.*github\.com[:/]##; s#\.git$##')
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$repo}" uvx --from {{ git_cliff }} git-cliff --unreleased \
--config-url "https://raw.githubusercontent.com/Algorithmiq/release-tools/$ref/cliff.toml"
```

Expand All @@ -369,7 +373,10 @@ changelog:
config="$(mktemp -d)/cliff.toml"
gh api -H "Accept: application/vnd.github.raw" \
"repos/Algorithmiq/release-tools/contents/cliff.toml?ref=$ref" > "$config"
uvx --from {{ git_cliff }} git-cliff --unreleased --config "$config"
# Link the PR numbers like the release PR does: GitHub Actions sets GITHUB_REPOSITORY.
repo=$(git remote get-url origin | sed -E 's#^.*github\.com[:/]##; s#\.git$##')
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$repo}" uvx --from {{ git_cliff }} git-cliff --unreleased \
--config "$config"
```

### PR template
Expand Down
11 changes: 10 additions & 1 deletion cliff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ All notable changes to this project are listed here.
# Lets `--prepend` replace the header instead of repeating it.
header_marker = "<!-- git-cliff: end of header -->"
# Literal string ('''), so regex backslashes don't need escaping.
#
# A squash-merged PR's number, `(#N)` at the end of its title, becomes an absolute link to
# the PR on GitHub, for the repository named in GITHUB_REPOSITORY (set by GitHub Actions to
# the calling repository). GitHub doesn't autolink `#N` in files such as CHANGELOG.md, and
# not reliably in release notes either. Without GITHUB_REPOSITORY it stays `(#N)`.
body = '''
{%- set repo = get_env(name="GITHUB_REPOSITORY", default="") %}
{%- if version %}
## {{ version | trim_start_matches(pat="v") }} ({{ timestamp | date(format="%Y-%m-%d") }})
{%- else %}
Expand All @@ -21,7 +27,10 @@ body = '''
{% for entry in commits | commit_groups(groups=commit_parsers_groups) %}
### {{ entry.group }}
{% for commit in entry.commits %}
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}{{ commit.message | upper_first }}
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}
{%- if repo %}{{ commit.message | upper_first | replace_regex(from="\(#(\d+)\)$", to="([#$1](https://github.com/" ~ repo ~ "/pull/$1))") }}
{%- else %}{{ commit.message | upper_first }}
{%- endif %}
{%- if commit.breaking or entry.group == "Deprecations" %}
{%- set parts = commit.body | default(value="") | split_regex(pat="(?m)^##\s*Migration\s*$") %}
{%- if parts | length > 1 %}
Expand Down
4 changes: 3 additions & 1 deletion examples/stubs/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ changelog:
set -euo pipefail
ref=$(sed -nE 's|.*Algorithmiq/release-tools/.github/workflows/release.yml@([^[:space:]]+).*|\1|p' \
.github/workflows/release.yml)
uvx --from {{ git_cliff }} git-cliff --unreleased \
# Link the PR numbers like the release PR does: GitHub Actions sets GITHUB_REPOSITORY.
repo=$(git remote get-url origin | sed -E 's#^.*github\.com[:/]##; s#\.git$##')
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$repo}" uvx --from {{ git_cliff }} git-cliff --unreleased \
--config-url "https://raw.githubusercontent.com/Algorithmiq/release-tools/$ref/cliff.toml"
5 changes: 4 additions & 1 deletion examples/stubs/justfile-internal
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ changelog:
config="$(mktemp -d)/cliff.toml"
gh api -H "Accept: application/vnd.github.raw" \
"repos/Algorithmiq/release-tools/contents/cliff.toml?ref=$ref" > "$config"
uvx --from {{ git_cliff }} git-cliff --unreleased --config "$config"
# Link the PR numbers like the release PR does: GitHub Actions sets GITHUB_REPOSITORY.
repo=$(git remote get-url origin | sed -E 's#^.*github\.com[:/]##; s#\.git$##')
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$repo}" uvx --from {{ git_cliff }} git-cliff --unreleased \
--config "$config"
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ test *ARGS:

# Preview the changelog entry of the next release of this repository.
changelog:
uv run --no-sync git-cliff --unreleased
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-Algorithmiq/release-tools}" uv run --no-sync git-cliff --unreleased
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ def remote_tags(self) -> list[str]:
return sorted(line.split("refs/tags/")[1] for line in lines)


@pytest.fixture(autouse=True)
def no_github_repository(monkeypatch: pytest.MonkeyPatch) -> None:
"""Unset GITHUB_REPOSITORY, which GitHub Actions also sets when it runs the tests.

cliff.toml links PR numbers to that repository; tests that want links set it.
"""
monkeypatch.delenv("GITHUB_REPOSITORY", raising=False)


@pytest.fixture
def repo(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Repo:
"""Return an empty clone with a local bare origin, as the current directory.
Expand Down
26 changes: 26 additions & 0 deletions tests/test_cliff.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,29 @@ def test_trailing_key_value_lines_are_dropped_as_trailers(repo: Repo) -> None:
assert " Rename the call." in notes
assert "Before:" not in notes
assert "After:" not in notes


def test_pr_numbers_link_to_the_repository_of_github_repository(
repo: Repo, monkeypatch: pytest.MonkeyPatch
) -> None:
repo.commit("chore: start")
repo.git("tag", "v0.0.0")
repo.commit("feat: ✨ add X (#12)")
repo.commit("fix(io): handle #3 and (#4) in names (#13)")
repo.commit("fix: pushed without a PR")
monkeypatch.setenv("GITHUB_REPOSITORY", "Algorithmiq/example")
notes = cliff("--unreleased").splitlines()
url = "https://github.com/Algorithmiq/example/pull"
# Only the PR number squash-merging appends becomes a link; the rest stays as it is.
assert [line for line in notes if line.startswith("- ")] == [
f"- Add X ([#12]({url}/12))",
f"- **io:** Handle #3 and (#4) in names ([#13]({url}/13))",
"- Pushed without a PR",
]


def test_pr_numbers_stay_plain_without_github_repository(repo: Repo) -> None:
repo.commit("chore: start")
repo.git("tag", "v0.0.0")
repo.commit("feat: ✨ add X (#12)")
assert "- Add X (#12)" in cliff("--unreleased").splitlines()
Loading