Skip to content
Open
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
61 changes: 55 additions & 6 deletions .claude/skills/create-java-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
---
name: create-java-pr
description: Create a pull request in sentry-java. Use when asked to "create pr", "prepare pr", "prep pr", "open pr", "ready for pr", "prepare for review", "finalize changes". Handles branch creation, code formatting, API dump, committing, pushing, PR creation, and changelog.
description: Create a pull request in sentry-java. Use when asked to "create pr", "prepare pr", "prep pr", "open pr", "ready for pr", "prepare for review", "finalize changes". Handles branch creation, code formatting, API dump, committing, pushing, PR creation, changelog, and stacked PRs.
---

# Create Pull Request (sentry-java)

Prepare local changes and create a pull request for the sentry-java repo.

**Required reading:** Before proceeding, read `.cursor/rules/pr.mdc` for the full PR and stacked PR workflow details. That file is the source of truth for PR conventions, stack comment format, branch naming, and merge strategy.

## Step 0: Determine PR Type

Ask the user (or infer from context) whether this is:

- **Standalone PR** โ€” a regular PR targeting `main`. Follow Steps 1โ€“6 as written.
- **First PR of a new stack** โ€” ask for a topic name (e.g. "Global Attributes"). Create a collection branch from `main`, then branch the first PR off it. The first PR targets the collection branch.
- **Next PR in an existing stack** โ€” identify the previous stack branch and topic. This PR targets the previous stack branch.

If the user mentions "stack", "stacked PR", or provides a topic name with a number (e.g. `[Topic 2]`), treat it as a stacked PR. See `.cursor/rules/pr.mdc` ยง "Stacked PRs" for full details.

## Step 1: Ensure Feature Branch

```bash
Expand All @@ -21,6 +33,8 @@ git checkout -b <type>/<short-description>

Derive the branch name from the changes being made. Use `feat/`, `fix/`, `ref/`, etc. matching the commit type conventions.

**For stacked PRs:** For the first PR in a new stack, first create and push the collection branch (see `.cursor/rules/pr.mdc` ยง "Creating the Collection Branch"), then branch the PR off it. For subsequent PRs, branch off the previous stack branch. Use the naming conventions from `.cursor/rules/pr.mdc` ยง "Branch Naming".

## Step 2: Format Code and Regenerate API Files

```bash
Expand Down Expand Up @@ -92,13 +106,38 @@ Invoke the `sentry-skills:create-pr` skill to create a draft PR. When providing

Fill in each section based on the changes being PR'd. Check any checklist items that apply.

Then continue to Step 6.
**For stacked PRs:**

- Pass `--base <previous-stack-branch>` so the PR targets the previous branch (first PR in a stack targets the collection branch).
- Use the stacked PR title format: `<type>(<scope>): [<Topic> <N>] <Subject>` (see `.cursor/rules/pr.mdc` ยง "PR Title Naming").
- Include the stack list at the top of the PR body, before the `## :scroll: Description` section (see `.cursor/rules/pr.mdc` ยง "Stack List in PR Description" for the format).

Then continue to Step 5.5 (stacked PRs only) or Step 6.

## Step 5.5: Update Stack List on All PRs (stacked PRs only)

Skip this step for standalone PRs.

After creating the PR, update the PR description on **every other PR in the stack** so all PRs have the same up-to-date stack list. Follow the format and commands in `.cursor/rules/pr.mdc` ยง "Stack List in PR Description".

## Step 6: Update Changelog

After the PR is created, add an entry to `CHANGELOG.md` under the `## Unreleased` section.
First, determine whether a changelog entry is needed. **Skip this step** (and go straight to "No changelog needed" below) if the changes are not user-facing, for example:

- Test-only changes (new tests, test refactors, test fixtures)
- CI/CD or build configuration changes
- Documentation-only changes
- Code comments or formatting-only changes
- Internal refactors with no behavior change visible to SDK users
- Sample app changes

If unsure, ask the user.

### If changelog is needed

Add an entry to `CHANGELOG.md` under the `## Unreleased` section.

### Determine the subsection
#### Determine the subsection

| Change Type | Subsection |
|---|---|
Expand All @@ -109,15 +148,15 @@ After the PR is created, add an entry to `CHANGELOG.md` under the `## Unreleased

Create the subsection under `## Unreleased` if it does not already exist.

### Entry format
#### Entry format

```markdown
- <Short description of the change> ([#<PR_NUMBER>](https://github.com/getsentry/sentry-java/pull/<PR_NUMBER>))
```

Use the PR number returned by `sentry-skills:create-pr`. Match the style of existing entries โ€” sentence case, ending with the PR link, no trailing period.

### Commit and push
#### Commit and push

Stage `CHANGELOG.md`, commit with message `changelog`, and push:

Expand All @@ -126,3 +165,13 @@ git add CHANGELOG.md
git commit -m "changelog"
git push
```

### No changelog needed

If no changelog entry is needed, add `#skip-changelog` to the PR description to disable the changelog CI check:

```bash
gh pr view <PR_NUMBER> --json body --jq '.body' > /tmp/pr-body.md
printf '\n#skip-changelog\n' >> /tmp/pr-body.md
gh pr edit <PR_NUMBER> --body-file /tmp/pr-body.md
```
71 changes: 47 additions & 24 deletions .cursor/rules/pr.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,25 @@ Stacked PRs split a large feature into small, easy-to-review PRs where each buil
### Structure

```
main โ†’ stack-pr-1 โ†’ stack-pr-2 โ†’ stack-pr-3 โ†’ ...
main โ† collection-branch โ† stack-pr-1 โ† stack-pr-2 โ† stack-pr-3 โ† ...
```

- The first PR in the stack targets `main` as its base branch.
- A **collection branch** is created from `main` and targets `main`. It serves as the base for the entire stack.
- The first PR in the stack targets the collection branch (not `main`).
- Each subsequent PR targets the previous stack PR's branch as its base.
- Each PR contains only incremental changes on top of the previous one.

The collection branch exists so that individual stack PRs can be **merge-committed** (not squashed). PRs targeting `main` use squash merging, but that causes repeated merge conflicts when syncing the stack. Merge commits on non-`main` branches avoid this. The collection branch itself is squash-merged into `main` at the end.

### Branch Naming

Prefer a shared prefix for the feature, with descriptive suffixes per PR. The type prefix (`feat/`, `fix/`, etc.) may vary depending on the nature of each PR's changes:
Prefer a shared prefix for the feature, with descriptive suffixes per PR. The collection branch uses the shared prefix. The type prefix (`feat/`, `fix/`, etc.) may vary depending on the nature of each PR's changes:

```
feat/scope-attributes # PR 1
feat/scope-attributes-logger # PR 2
fix/attribute-type-detection # PR 3 (fix, different name โ€” that's fine)
feat/scope-attributes # collection branch โ†’ targets main
feat/scope-attributes-api # PR 1 โ†’ targets collection branch
feat/scope-attributes-logger # PR 2 โ†’ targets PR 1
fix/attribute-type-detection # PR 3 (fix, different name โ€” that's fine) โ†’ targets PR 2
```

### PR Title Naming
Expand All @@ -158,30 +162,42 @@ Do **not** rely on branch name patterns โ€” later PRs in a stack may use differe
```bash
gh pr list --head "$(git branch --show-current)" --json number,title,baseRefName --jq '.[0]'
```
2. Read the stack comment on that PR โ€” it lists every PR in the stack.
3. If there is no stack comment yet, walk the chain in both directions:
2. Read the PR description โ€” the stack list is at the top of the body.
3. If there is no stack list yet, walk the chain in both directions:
```bash
# Find the PR whose head branch is the current PR's base (go up)
gh pr list --head <baseRefName> --json number,title,baseRefName

# Find PRs whose base branch is the current PR's head (go down)
gh pr list --base <currentBranch> --json number,title,headRefName
```
Repeat until you reach `main` going up and find no more PRs going down.
Repeat until you reach the collection branch going up and find no more PRs going down.

### Creating the Collection Branch

Before the first stacked PR, create the collection branch with an empty commit (so GitHub allows opening a PR) and create the collection PR:

```bash
git checkout main
git checkout -b feat/<topic>
git commit --allow-empty -m "collection: <topic>"
git push -u origin HEAD
gh pr create --base main --draft --title "<type>(<scope>): <Topic>" --body "Collection PR for the <Topic> stack. Squash-merge this once all stack PRs are merged."
```

### Creating a New Stacked PR

1. Start from the tip of the previous stack branch (or `main` for the first PR).
1. Start from the tip of the previous stack branch (or the collection branch for the first PR).
2. Create a new branch, make changes, format, commit, and push.
3. Create the PR with `--base <previous-branch>`:
3. Create the PR with `--base <previous-branch>` (the collection branch for the first PR):
```bash
gh pr create --base feat/previous-branch --draft --title "<type>(<scope>): [<Topic> <N>] <Subject>" --body "..."
```
4. Add the stack comment to the new PR and update it on all existing PRs in the stack (see below).
4. Add the stack list to the top of the new PR's description and update it on all existing PRs in the stack (see below).

### Stack Comment
### Stack List in PR Description

Every PR in the stack must have a comment listing all PRs in the stack. When a new PR is added, update the comment on **all** PRs in the stack.
Every PR in the stack must have a stack list **at the top of its description** (before the `## :scroll: Description` section). When a new PR is added, update the description on **all** PRs in the stack.

Format:

Expand All @@ -191,26 +207,33 @@ Format:
- [#5118](https://github.com/getsentry/sentry-java/pull/5118) โ€” Add scope-level attributes API
- [#5120](https://github.com/getsentry/sentry-java/pull/5120) โ€” Wire scope attributes into LoggerApi and MetricsApi
- [#5121](https://github.com/getsentry/sentry-java/pull/5121) โ€” Showcase scope attributes in Spring Boot 4 samples

---
```

No status column โ€” GitHub already shows that.
No status column โ€” GitHub already shows that. The `---` separates the stack list from the rest of the PR description.

To add or update the stack comment on a PR:
To update the PR description, use `--body-file` to avoid shell quoting issues with special characters in the body:

```bash
# Find existing stack comment (if any)
gh api repos/getsentry/sentry-java/issues/<PR_NUMBER>/comments --jq '.[] | select(.body | startswith("## PR Stack")) | .id'
# Get current PR description into a temp file
gh pr view <PR_NUMBER> --json body --jq '.body' > /tmp/pr-body.md

# Create new comment
gh pr comment <PR_NUMBER> --body "<stack comment body>"
# Edit /tmp/pr-body.md to prepend or replace the stack list section
# (replace everything from "## PR Stack" up to and including the "---" separator,
# or prepend before the existing description if no stack list exists yet)

# Or update existing comment
gh api repos/getsentry/sentry-java/issues/comments/<COMMENT_ID> -X PATCH -f body="<stack comment body>"
# Update the description
gh pr edit <PR_NUMBER> --body-file /tmp/pr-body.md
```

### Merging Stacked PRs
### Merging Stacked PRs (done by the user, not the agent)

Individual stack PRs are merged in order from bottom to top (PR 1 first, then PR 2, etc.) using **merge commits** (not squash). After each merge, the next PR's base automatically becomes the merged branch's target. GitHub handles rebasing onto the new base.

Once all stack PRs are merged into the collection branch, the collection PR is **squash-merged** into `main`. This gives `main` a clean single commit for the entire feature.

Merge in order from bottom to top (PR 1 first, then PR 2, etc.). After each merge, the next PR's base automatically becomes the merged branch's target. GitHub handles rebasing onto the new base. Verify each PR's diff still looks correct after the previous one merges.
**Do not merge PRs.** Only the user merges PRs.

### Syncing the Stack

Expand Down
Loading