# CLAUDE.md — rpm-changelog ## Project overview Composite Gitea Action that generates rpm `%changelog` entries from git history and prepends them to a target spec file. Consumed by release CI across `helexa/*` and `grenade/*` projects that ship rpms. See `README.md` for usage. This file covers the release workflow and conventions specific to publishing the action itself. ## Repository layout ``` rpm-changelog/ ├── action.yml # composite action manifest ├── scripts/ │ └── generate-rpm-changelog.sh ├── README.md # user-facing docs └── CLAUDE.md # ← you are here ``` ## Release workflow Consumers pin to a major-version tag (e.g. `@v1`) which tracks the latest release in that major line. Every release gets both a moving major-version tag and an immutable semver tag. ### On a normal change (bug fix, internal refactor, non-breaking feature) 1. Commit changes to `main` with a conventional-commit message. 2. Determine the next version by bumping the patch or minor from the latest semver tag (e.g. `v1.0.3` → `v1.0.4` for a fix, `v1.1.0` for a non-breaking feature). 3. Tag and push. This repo has `tag.gpgsign=true` globally, so tags must be annotated with a message (`-m`) and a GPG key must be available. Both the immutable semver tag and the moving major tag get pushed in the same release: ```sh git tag -m "v1.0.4" v1.0.4 git tag -f -m "v1 - track latest v1.x.y" v1 git push origin main git push origin v1.0.4 git push origin v1 --force ``` The `-f` / `--force` on the major tag is intentional — it's a moving ref by design. Consumers pinned to `@v1` pick up the new release on their next workflow run. ### On a breaking change 1. Commit to `main`. 2. Cut a new major tag (`v2.0.0`) and a new major-line tag (`v2`): ```sh git tag -m "v2.0.0" v2.0.0 git tag -m "v2 - track latest v2.x.y" v2 git push origin main v2.0.0 v2 ``` 3. Do **not** move `v1` — projects still pinned to `@v1` keep working against the last v1.x release. Update `v1` only for bugfix backports. ### Dry run before pushing There's no test harness in this repo (composite actions with shell scripts are hard to unit-test in isolation). Before publishing a release, run the script locally against a sample spec to sanity-check: ```sh cd /tmp && mkdir -p fake && cd fake git init && git commit --allow-empty -m "init" git tag v0.0.1 git commit --allow-empty -m "feat: add thing" git commit --allow-empty -m "chore: bump version to 0.0.2" cp /path/to/some.spec . ~/git/actions/rpm-changelog/scripts/generate-rpm-changelog.sh some.spec 0.0.2 cat some.spec | head -20 ``` Verify the new entry appears above any existing `%changelog` block with a correct weekday, the right commits listed, and bot-authored commits filtered out. ## Conventions - **Shell**: bash only. No zsh-isms, no node, no python — runners must work with nothing beyond a Fedora base install. - **Dependencies**: `git`, `grep -E`, `awk`, `date`, `mktemp`. All present by default on Fedora. - **Style**: `set -euo pipefail` at the top of every script. Quote all variable expansions. Use `printf` over `echo` when content could start with `-`. - **Commit messages**: conventional commits (`feat:`, `fix:`, `docs:`, `chore:`). This action's own `%changelog` isn't generated (it's not an rpm), but commit hygiene still matters for anyone reading git log to diagnose a regression. ## Consuming projects As of this writing: - `helexa/cortex` — uses `@v1` via Gitea's full-URL syntax: `uses: https://git.lair.cafe/actions/rpm-changelog@v1`. When adding a new consumer, update this list so future sessions know what breaks if a release is botched. ## Not this action's job - Generating human-readable `CHANGELOG.md` files — that's `requarks/changelog-action` territory. This action only cares about the rpm spec's `%changelog` section. - Creating GitHub/Gitea releases — that belongs in the consumer's release job. - Running `rpmbuild` or signing — handled by `rpmbuild -bs` in the consumer, signing is done by COPR.