Prepare or update a release PR from dev to master with auto-generated release notes
Scanned 9/1/2026
Install to Claude Code
npx -y skills add FgForrest/evitaDB --skill release-pr --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Release Pr?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/fgforrest-release-pr)More formats (shields.io, HTML) on the badges page.
---
name: release-pr
description: Prepare or update a release PR from dev to master with auto-generated release notes
allowed-tools: Read, Edit, Grep, WebFetch, AskUserQuestion, Agent, Bash(git *), Bash(grep *), Bash(mvn *), Bash(./tools/verify-pgp-keys.sh *), Bash(./tools/list-issues.sh *), Bash(./tools/list-commits.sh *), Bash(gh pr list --repo FgForrest/evitaDB *), Bash(gh pr create --repo FgForrest/evitaDB *), Bash(gh pr edit *), Bash(gh api --method POST /repos/FgForrest/evitaDB/pulls/*)
---
# Release PR
## Overview
Creates or updates a GitHub pull request from `dev` (main branch) to `master` (release branch) with auto-generated release notes. The release notes are assembled from GitHub milestone issues and git commit history, following the established evitaDB release notes format.
## When to Use
- You are ready to cut a release and need a PR from `dev` to `master`
- You want to refresh the release notes on an existing release PR
- Invoked as `/release-pr`
## Workflow
Execute the following steps **in order**. Stop and report to the user if any step fails.
### Preliminary Phase: Pre-Release Verification
Verify dependency signatures, dependency freshness, and (optionally) backward compatibility before proceeding with the release.
#### PGP dependency signature verification
Verify that all dependency signatures are valid before proceeding with the release. This catches PGP key rotations that would break the CI/CD `PGP Keys Check` step.
#### P1: Run PGP verification
```shell
./tools/verify-pgp-keys.sh --check
```
If it exits 0 (all signatures valid), skip to Step 1.
If it exits non-zero, the script outputs a structured report for each failing group with:
- New signing fingerprint
- Cross-reference result (same key signs other group artifacts)
- Public keyserver lookup result (which server, UID)
- Old key expiry status
#### P2: Present findings to the user
For each group in the script output, present a summary table:
| Check | Result |
|---|---|
| New key fingerprint | `0x...` (from script output) |
| Cross-ref: same key signs other group artifacts | Yes/No |
| Key found on public keyserver | Yes/No (which server) |
| Key UID | From script output |
| Old key expired | Yes (date) / No |
#### P3: Apply validated keys
**For `[PASS]` entries** (cross-reference succeeded AND/OR key exists on a keyserver):
- Ask the user for confirmation using AskUserQuestion before applying changes.
- If confirmed, run:
```shell
./tools/verify-pgp-keys.sh --fix
```
This updates `pgp-keys-map.list` with the validated fingerprints.
- Commit the change: `git add pgp-keys-map.list && git commit -m "chore: update PGP keys for <groupIds> after key rotation"`
- Proceed to P4 to re-verify.
**For `[FAIL]` entries** (cross-reference failed AND key not on any keyserver):
- **Stop and warn the user.** Do NOT proceed with the release. Report exactly which checks failed and advise manual investigation. This could indicate a supply-chain compromise.
If the report contains a mix of PASS and FAIL entries, apply the PASS fixes first, then stop and report the FAIL entries. Do not proceed to Step 1 until all entries are resolved.
#### P4: Re-run verification
After applying fixes, re-run the check:
```shell
./tools/verify-pgp-keys.sh --check
```
If it passes, proceed to P5. If it still fails, repeat from P2 for the remaining failures.
#### P5: Check for dependency updates (informational)
Run:
```shell
mvn versions:display-dependency-updates
```
This check is purely informational and must **never** block the release. If the command fails, hangs, or exits non-zero, note that it could not complete and move on to P6 regardless — do not stop the workflow or ask the user to fix anything here. If it succeeds, briefly summarize any dependencies with available updates for the user's awareness; upgrading them is out of scope for this skill.
#### P6: Backward-compatibility checks (optional, ask first)
Both checks below are slow (a long-running test / a static-analysis audit) — ask before running either. Skipping is a valid choice; note whatever was skipped in the final report (Step 7).
1. **Data backward compatibility.** **Ask the user via AskUserQuestion before doing anything else here** — whether to run `EvitaBackwardCompatibilityTest` now.
- If yes, run:
```shell
mvn -pl evita_test/evita_long_running_tests test -P longRunning -Dtest=EvitaBackwardCompatibilityTest
```
If it fails, **stop** and report the failure to the user — a backward-compatibility regression should not ship silently in a release PR. Let the user decide how to proceed.
- If no, record it as skipped and continue.
2. **Kryo serialization backward compatibility.** **Ask the user via AskUserQuestion before launching anything** — whether to run the `kryo-bwc-audit` skill now, as a separate sub-agent so it doesn't clutter this session's context. Do not launch the sub-agent speculatively or by default; the question must be asked and answered first.
- If yes, launch it with the Agent tool (e.g. `general-purpose`), instructing the agent to invoke the `kryo-bwc-audit` skill against the current branch and return its findings table and verdict summary.
- Relay the agent's summary to the user. If it reports any blocking (`***`) findings, flag them clearly and let the user decide how to proceed — do not silently continue to PR creation.
- If no, record it as skipped and continue.
Proceed to Step 1.
Note: Any PGP key update commits from the Preliminary Phase will be part of the working tree when Step 2 checks for a clean state. The user must push those commits before proceeding.
---
### Step 1: Validate branch
Run `git branch --show-current` and verify the result is `dev`. If not, stop and tell the user they must be on the `dev` branch.
### Step 2: Validate working tree is clean and pushed
1. Run `git status --porcelain` — if output is non-empty, stop and tell the user to commit or stash changes.
2. Run `git fetch origin dev` then compare `git rev-parse dev` vs `git rev-parse origin/dev` — if they differ, stop and tell the user to push their commits first.
### Step 3: Extract release version
1. Read the root `pom.xml` and extract the version from the first `<version>` tag.
2. Strip the `-SNAPSHOT` suffix if present (e.g. `2026.1-SNAPSHOT` becomes `2026.1`).
3. Format the PR title as `Release {version}` (e.g. `Release 2026.1`).
4. **Ask the user to confirm** the version using AskUserQuestion before proceeding.
### Step 4: Determine base version for dependency comparison
Run the following to find the latest release tag on `master`:
```shell
git fetch origin master
git describe --tags --abbrev=0 origin/master
```
This returns a tag like `v2025.8.15`. Strip the leading `v` to get the base version (e.g. `2025.8.15`). This is passed to `list-issues.sh` as the second argument for dependency comparison.
### Step 5: Generate release notes
Run both scripts and capture their output:
```shell
./tools/list-issues.sh "{version}" "{base_version}"
./tools/list-commits.sh "{base_version}"
```
Where `{version}` is the milestone title from Step 3 (e.g. `2026.1`) and `{base_version}` is from Step 4 (e.g. `2025.8.15`).
Then **aggregate** the two outputs into a single release notes body following these rules:
1. **Issues from `list-issues.sh` are authoritative** — they have proper issue numbers and milestone categorization. Always include all of them.
2. **Commits from `list-commits.sh` supplement** — include commit entries that represent meaningful user-facing features or bug fixes not already covered by an issue entry. Match by description similarity to avoid duplicates.
3. **Filter out non-user-facing items** from the commits list:
- CI/CD fixes (GitHub Actions, Docker workflows)
- Internal code quality refactors (toString fixes, code style)
- Compilation fixes
- Test infrastructure changes
4. **Keep these sections** in order:
- `### ☢️ Breaking changes`
- `### 🚀 Features`
- `### 🐛 Bug Fixes`
- `### ⛓ Dependencies upgrades`
5. **Omit** documentation (`📝`) and test (`🧪`) sections from the final release notes — they are internal-facing.
6. Omit empty sections entirely.
7. The final body must start with `## What's Changed`.
### Step 6: Create or update the PR
1. Check if a PR from `dev` to `master` already exists:
```shell
gh pr list --repo FgForrest/evitaDB --head dev --base master --state open --json number,title --jq '.[0]'
```
2. **If no PR exists**: create one:
```shell
gh pr create --repo FgForrest/evitaDB --head dev --base master \
--title "Release {version}" \
--body "<release notes body>"
```
Then request Copilot review:
```shell
gh api --method POST /repos/FgForrest/evitaDB/pulls/{PR_NUMBER}/requested_reviewers \
-f 'reviewers[]=copilot-pull-request-reviewer[bot]'
```
3. **If PR exists**: update its title and body:
```shell
gh pr edit {PR_NUMBER} --repo FgForrest/evitaDB \
--title "Release {version}" \
--body "<release notes body>"
```
### Step 7: Report result
Print the PR URL and a summary of what was done (created vs updated), plus the status of the P5/P6 checks (dependency updates found, whether `EvitaBackwardCompatibilityTest` and `kryo-bwc-audit` were run or skipped, and their outcomes).
## Important Notes
- Always use a HEREDOC to pass the PR body to `gh pr create` or `gh pr edit` to preserve markdown formatting.
- The `list-issues.sh` script requires the `gh` CLI to be authenticated.
- If `list-issues.sh` reports no milestone found, tell the user to verify the milestone title exists on GitHub.
- If the base version tag doesn't exist, tell the user and ask them to provide the previous release version manually.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!