Skip to content

About

Python package used to create automated release changelog notes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

AutoChangelog

Internal tool for generating release notes from GitHub repository activity.

Setting up a new consumer repo? See Setting up a receiver repo below for the step-by-step guide, including the tag naming convention required for branch-aware changelogs.

v1 Composite Action usage

- name: Generate release notes
  uses: XPGAMESLLC/AutoChangelog@v1.0.4
  with:
    organization: XPGAMESLLC
    repo_name: Biomes
    auth_token: ${{ secrets.AUTH_TOKEN }}

This creates body.txt in the workflow workspace by default.

Optional Discord webhook notification

- name: Generate release notes and send to Discord
  uses: XPGAMESLLC/AutoChangelog@v1.0.4
  with:
    organization: XPGAMESLLC
    repo_name: Biomes
    auth_token: ${{ secrets.AUTH_TOKEN }}
    discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
    discord_role_tag: "<@&123456789012345678>"
    discord_role_tags: "<@&123456789012345678>,<@&987654321098765432>"

When discord_webhook_url is provided, the action posts changelog text to Discord as:

<repo_name> [<tag>](<release_page>) <changelog> <role_tag(s)> (optional)

For multiple pings, provide discord_role_tags (comma/newline/semicolon separated).

<version> is taken from github.ref_name (usually your release tag).

Long changelogs are automatically split into multiple Discord messages to stay under webhook limits.

Prerelease builds

Pass prerelease: "true" (a plain string) to mark a run as a prerelease build. This does two things:

  • The Discord message header/emoji switches from 🎉 New release for <repo>! to 🧪 Pre-release for <repo>, and discord_role_tag/discord_role_tags pings are skipped — nobody needs an @-mention for a WIP branch build.
  • It's purely presentational for the Discord message; the changelog content (which commits/PRs/ issues are included) is driven entirely by the tag naming convention described in Setting up a receiver repo, not by this flag.
- uses: XPGAMESLLC/AutoChangelog@v1.1.0
  with:
    organization: XPGAMESLLC
    repo_name: Biomes
    auth_token: ${{ secrets.AUTH_TOKEN }}
    discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
    prerelease: "true"

Optional AI summary

- name: Generate release notes with AI summary
  uses: XPGAMESLLC/AutoChangelog@v1.0.4
  with:
    organization: XPGAMESLLC
    repo_name: Biomes
    auth_token: ${{ secrets.AUTH_TOKEN }}
    ai_summary: "true"
    ai_api_key: ${{ secrets.AI_API_KEY }}
    # ai_model is optional, defaults to claude-haiku-4-5-20251001
    # ai_model: "claude-haiku-4-5-20251001"

CLI usage

python -m releasenotes.generator XPGAMESLLC Biomes

CLI with optional AI summary

# --ai-model is optional, defaults to claude-haiku-4-5-20251001
AI_API_KEY=*** python -m releasenotes.generator XPGAMESLLC Biomes --ai-summary

Local testing against a receiver repo

You can dry-run the exact behavior a receiver repo's workflow would trigger — including the branch-aware windowing, AI summary, and Discord notification — without touching CI, by pointing a local .env at that repo's secrets and picking the tag to simulate.

.env (gitignored; mirror whatever the receiver repo's workflow passes as with: secrets):

AUTH_TOKEN='<github token with access to the receiver repo>'
ORGANIZATION='XPGAMESLLC'
AI_API_KEY='<optional, enables --ai-summary>'
DISCORD_WEBHOOK_URL='<optional, enables the Discord notification>'
DISCORD_ROLE_TAGS='<optional>'

With ORGANIZATION set, only repo_name is required on the command line — pass --tag for the tag you're testing:

python -m releasenotes.generator Biomes --tag v1.1.0-poolrooms.1 --ai-summary
# Stable tag, with Discord notification
python -m releasenotes.generator Biomes --tag v1.2.3 --ai-summary

# Prerelease tag: also pass --prerelease to preview the alternate Discord header (no role pings)
python -m releasenotes.generator Biomes --tag v1.1.0-poolrooms.2 --ai-summary --prerelease

--tag overrides GITHUB_REF_NAME for the run (setting GITHUB_REF_NAME yourself works identically, --tag just saves a step).

Testing a tag before you've pushed it

You don't need to actually push v1.1.0-poolrooms.1 to preview it — pass it to --tag as-is. Windowing and commit collection go through repo.compare(...), which needs real refs on both ends, so if the exact tag doesn't exist yet the tool automatically falls back to comparing against the branch the tag would be cut from instead (the <branch-slug> for a prerelease tag, or the repo's default branch for a stable one) — that branch's current tip is what the tag would point to once you actually push it. You'll see a note on stdout when this fallback kicks in:

Tag 'v1.1.0-poolrooms.1' not found on XPGAMESLLC/Backrooms; comparing against branch
'poolrooms' instead (pre-push preview).

The only requirement is that the fallback branch itself exists (which it will, since you're presumably about to tag it). If neither the tag nor that branch exists — e.g. a typo in the slug — you get a clear error telling you so instead of a raw 404 from the GitHub API.

This means the full local-testing loop for a prerelease is just:

python -m releasenotes.generator Biomes --tag v1.1.0-poolrooms.1 --ai-summary --prerelease

run from your local checkout of the poolrooms branch (or any checkout — the branch is read from GitHub, not your working tree), no push required. Once you push the real tag, running the same command (or the CI workflow) picks up the actual tagged commit instead of the fallback.

Other notes:

  • AUTH_TOKEN is required to read repo activity.
  • organization can still be passed positionally instead of via ORGANIZATION (e.g. if you're testing against more than one org and don't want to keep editing .env).
  • DISCORD_WEBHOOK_URL/DISCORD_ROLE_TAG/DISCORD_ROLE_TAGS can come from .env or their matching --discord-* flags — a local test run with a webhook set will actually post to Discord, so use a scratch webhook/channel if you don't want real notifications going out.
  • If no tag is resolved at all, version falls back to latest in the Discord title.

Setting up a receiver repo

This is the step-by-step guide for wiring AutoChangelog into another repository (a "receiver"), for example Backrooms.

1. Prerequisites

Secrets the receiver repo needs, set in its GitHub repo/environment settings:

  • Required: AUTH_TOKEN — a GitHub token with access to read the repo's tags, PRs, issues, and releases (and create releases, if using softprops/action-gh-release).
  • Required if the repo builds via Regolith: a filter-dependency token (e.g. a FLICKER_TOKEN-style secret) that Bedrock-OSS/regolith-action needs to pull private filter dependencies. Name and value depend on what the repo's config.json filters require.
  • Optional: AI_API_KEY (enables the ai_summary section), DISCORD_WEBHOOK_URL and DISCORD_ROLE_TAGS (enables the Discord notification).

2. Copy an example

Start from a complete, runnable workflow rather than assembling one from scratch:

  • examples/full-build.yaml — for Regolith-based Bedrock add-on repos: classifies the tag, builds dev + release artifacts, generates the changelog, and publishes a GitHub release.
  • examples/minimal-changelog.yaml — for repos that already build/release another way and just want the tag-triggered changelog + Discord notification bolted on.

Copy the chosen file into the receiver repo as .github/workflows/build.yaml (or similar).

3. Fill in placeholders

Replace every <angle-bracket> value in the copied file: organization/repo name, Regolith profile names (build-dev/build-release), the filter-dependency secret name, the AutoChangelog version pin, and Discord role-mention IDs.

4. Adopt the tag naming convention

AutoChangelog's branch-aware changelog windowing depends on tags following this shape:

v<MAJOR>.<MINOR>.<PATCH>                      (stable release)
v<MAJOR>.<MINOR>.<PATCH>-<branch-slug>.<N>    (prerelease build on a feature branch)
  • Stable tags (v1.2.3) are only ever compared against the nearest earlier stable tag — prerelease tags from feature branches are ignored, even if they sit chronologically in between.
  • Prerelease tags (v1.1.0-poolrooms.1, v1.1.0-poolrooms.2, ...) are grouped by their <branch-slug> into a family. The first tag in a family is compared against the repo's default branch (so the changelog only shows commits unique to that branch); later tags in the same family are compared against the previous tag in that family.

This shape is also what drives the classify job in the example workflows (it decides is_prerelease, which feeds both AutoChangelog's prerelease input and softprops/action-gh-release's prerelease/make_latest inputs). Get the shape wrong and a prerelease tag either won't be recognized as one, or won't be grouped with its branch's earlier builds.

5. Test it

  1. Push a throwaway prerelease tag on a scratch branch, e.g. v0.0.1-test.1. Confirm a non-"latest" GitHub prerelease is created with a changelog scoped to that branch (commits unique to the branch since it diverged from the default branch).
  2. Push a second prerelease tag on the same branch, e.g. v0.0.1-test.2. Confirm the changelog only covers what changed since v0.0.1-test.1.
  3. Push a stable tag, e.g. v0.0.1. Confirm it ignores any prerelease tags sitting chronologically in between and diffs against the previous stable tag instead.

6. Keep this in sync

The example workflows in examples/ are the source of truth for what a working pipeline looks like — this section explains the concepts, but for the actual steps/inputs, follow the example files rather than a copy pasted here.

Legacy CLI

python -m releasenotes.legacy_generator XPGAMESLLC Biomes

About

Python package used to create automated release changelog notes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages