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
141 changes: 118 additions & 23 deletions .github/workflows/changelog-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ on:
#
# 1. Grant required permissions:
# - contents: read (to checkout repo and read git history)
# - pull-requests: write (to post/update PR comments)
# - pull-requests: write (to post/update PR comments in comment mode)
# - statuses: write (to create commit statuses in status check mode)
#
# 2. Inherit secrets:
# - secrets: inherit (ensures caller's GITHUB_TOKEN is used)
#
# Example caller workflow:
# Example caller workflow (comment mode):
#
# on:
# pull_request:
Expand All @@ -28,6 +29,19 @@ on:
# uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2
# secrets: inherit
#
# Example caller workflow (status check mode):
#
# permissions:
# contents: read
# statuses: write
#
# jobs:
# changelog-preview:
# uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2
# with:
# comment: false
# secrets: inherit
#
workflow_call:
inputs:
working-directory:
Expand All @@ -39,6 +53,11 @@ on:
description: 'Version of Craft to use (tag or "latest")'
required: false
type: string
comment:
description: 'Post changelog as PR comment (true) or as check run with job summary (false)'
required: false
type: boolean
default: true

# Also run on PRs in this repository (for dogfooding)
# Includes 'edited' and 'labeled' to update when PR title/description/labels change
Expand All @@ -47,7 +66,8 @@ on:

permissions:
contents: read
pull-requests: write
pull-requests: write # For comment mode
statuses: write # For status check mode

jobs:
preview:
Expand Down Expand Up @@ -137,9 +157,82 @@ jobs:
*) BUMP_BADGE="⚪ **None** (no version bump detected)" ;;
esac

# Build comment body using a temp file (safer than heredoc)
COMMENT_FILE=$(mktemp)
cat > "$COMMENT_FILE" << CRAFT_CHANGELOG_COMMENT_END
# Create descriptions for status check (no emoji support in Commit Status API)
case "$BUMP_TYPE" in
major)
BUMP_SHORT="Major"
BUMP_EMOJI="🔴"
;;
minor)
BUMP_SHORT="Minor"
BUMP_EMOJI="🟡"
;;
patch)
BUMP_SHORT="Patch"
BUMP_EMOJI="🟢"
Comment on lines +164 to +172
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that color codes are WORLDWIDE known to signal:
green: go ahead, yellow: warning, and red: don't.

what about using arbitrary colors instead ☮️

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was kind of the intention though?

Patch -> Always safe
Minor -> Might be safe
Major -> Danger, be careful!

;;
*)
BUMP_SHORT="None"
BUMP_EMOJI="⚪"
;;
esac

# Determine mode: use status check mode when comment is false OR when running internally (no input)
USE_COMMENT_MODE="${{ inputs.comment }}"
if [[ "$USE_COMMENT_MODE" == "false" ]] || [[ -z "$USE_COMMENT_MODE" ]]; then
# Status check mode (new feature or internal dogfooding)
echo "Using status check mode..."

HEAD_SHA="${{ github.event.pull_request.head.sha || github.sha }}"
TARGET_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
PR_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/${PR_NUMBER}"

# Create commit status via GitHub API
echo "Creating commit status..."
gh api --method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"repos/$GITHUB_REPOSITORY/statuses/$HEAD_SHA" \
-f state="success" \
-f context="Changelog Preview / Semver Impact" \
-f description="$BUMP_SHORT" \
-f target_url="$TARGET_URL"

echo "✓ Commit status created"

# 2. Write to job summary
cat >> $GITHUB_STEP_SUMMARY << CRAFT_CHANGELOG_SUMMARY_END
# Changelog Preview for PR #${PR_NUMBER}

[→ View PR #${PR_NUMBER}](${PR_URL})

## Semver Impact of This PR

${BUMP_BADGE}

<details>
<summary>📋 Changelog Preview</summary>

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).

---

${CHANGELOG}

---

</details>
CRAFT_CHANGELOG_SUMMARY_END

echo "✓ Job summary written"
else
# Comment mode (original behavior)
echo "Using comment mode..."

# Build comment body using a temp file (safer than heredoc)
COMMENT_FILE=$(mktemp)
cat > "$COMMENT_FILE" << CRAFT_CHANGELOG_COMMENT_END
<!-- craft-changelog-preview -->
## Semver Impact of This PR

Expand All @@ -162,22 +255,24 @@ jobs:
<sub>🤖 This preview updates automatically when you update the PR.</sub>
CRAFT_CHANGELOG_COMMENT_END

# Find existing comment with our marker
COMMENT_ID=$(gh api \
"repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \
--jq '.[] | select(.body | contains("<!-- craft-changelog-preview -->")) | .id' \
| head -1)

if [[ -n "$COMMENT_ID" ]]; then
echo "Updating existing comment $COMMENT_ID..."
gh api -X PATCH \
"repos/$GITHUB_REPOSITORY/issues/comments/$COMMENT_ID" \
-F body=@"$COMMENT_FILE"
else
echo "Creating new comment..."
gh api -X POST \
# Find existing comment with our marker
COMMENT_ID=$(gh api \
"repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \
-F body=@"$COMMENT_FILE"
fi
--jq '.[] | select(.body | contains("<!-- craft-changelog-preview -->")) | .id' \
| head -1)

rm -f "$COMMENT_FILE"
if [[ -n "$COMMENT_ID" ]]; then
echo "Updating existing comment $COMMENT_ID..."
gh api -X PATCH \
"repos/$GITHUB_REPOSITORY/issues/comments/$COMMENT_ID" \
-F body=@"$COMMENT_FILE"
else
echo "Creating new comment..."
gh api -X POST \
"repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \
-F body=@"$COMMENT_FILE"
fi

rm -f "$COMMENT_FILE"
echo "✓ Comment posted"
fi
93 changes: 86 additions & 7 deletions docs/src/content/docs/github-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,85 @@ jobs:

### Inputs

| Input | Description | Default |
| --------------- | ----------------------------------------- | -------- |
| `craft-version` | Version of Craft to use (tag or "latest") | `latest` |
| Input | Description | Default |
| ------------------- | -------------------------------------------------------------------------------- | -------- |
| `working-directory` | Directory to run Craft in (relative to repo root) | `.` |
| `craft-version` | Version of Craft to use (tag or "latest") | `latest` |
| `comment` | Post changelog as PR comment (true) or as commit status with job summary (false) | `true` |

### Output Modes

The workflow supports two output modes for displaying changelog previews:

#### Comment Mode (Default)

Posts the changelog preview as a PR comment that updates automatically:

```yaml
jobs:
changelog-preview:
uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2
with:
comment: true # or omit for default
secrets: inherit
```

**Pros:**

- Changelog visible directly on PR page
- All team members see updates immediately
- Familiar commenting interface

**Cons:**

- Creates notification noise on every update
- Multiple updates trigger multiple notifications
- Can clutter PR conversation on active branches

**Required permissions:**

```yaml
permissions:
contents: read
pull-requests: write
```

#### Status Check Mode

Creates a commit status with the semver impact and writes the full changelog to the Actions job summary:

```yaml
jobs:
changelog-preview:
uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2
with:
comment: false
secrets: inherit
```

**Pros:**

- Minimal notification noise
- Cleaner PR interface
- Semver impact visible in status checks section
- Full changelog available in Actions job summary

**Cons:**

- Requires clicking through to Actions run to see full changelog
- Less immediate visibility than comment

**Required permissions:**

```yaml
permissions:
contents: read
statuses: write
```

:::tip
Craft itself uses status check mode to avoid notification noise. You can see it in action on any PR in the [getsentry/craft repository](https://github.com/getsentry/craft/pulls).
:::

### Pinning a Specific Version

Expand All @@ -168,8 +244,8 @@ jobs:
3. **Categorizes the PR** - Matches the PR to changelog categories based on labels and commit patterns
4. **Suggests version bump** - Based on matched categories with semver fields (major/minor/patch)
5. **Highlights PR entries** - The current PR is rendered with blockquote style (displayed with a left border in GitHub)
6. **Posts a comment** - Creates or updates a comment on the PR with the changelog preview
7. **Auto-updates** - The comment is automatically updated when you update the PR (push commits, edit title/description, or change labels)
6. **Displays the preview** - Posts as a PR comment (default) or creates a neutral check run with job summary (when `comment: false`)
7. **Auto-updates** - The preview is automatically updated when you update the PR (push commits, edit title/description, or change labels)

:::note
The version bump suggestion requires categories in your `.github/release.yml` to have
Expand Down Expand Up @@ -225,7 +301,8 @@ The workflow requires specific permissions and secrets to function correctly:
**Permissions** (required):

- `contents: read` - Allows the workflow to checkout your repository and read git history for changelog generation
- `pull-requests: write` - Allows the workflow to post and update comments on pull requests
- `pull-requests: write` - Required for comment mode (default) to post and update comments on pull requests
- `statuses: write` - Required for status check mode (when `comment: false`) to create commit statuses

**Secrets**:

Expand All @@ -236,7 +313,9 @@ The workflow requires specific permissions and secrets to function correctly:
- The repository should have a git history with tags for the changelog to be meaningful

:::note[Why are these permissions needed?]
GitHub Actions reusable workflows use permission intersection - the final permissions are the intersection of what the caller grants and what the workflow declares. By explicitly declaring these permissions in your workflow file, you ensure the workflow can access your repository and post comments, even for private repositories.
GitHub Actions reusable workflows use permission intersection - the final permissions are the intersection of what the caller grants and what the workflow declares. By explicitly declaring these permissions in your workflow file, you ensure the workflow can access your repository and perform the necessary actions, even for private repositories.

Note: You only need `pull-requests: write` for comment mode OR `statuses: write` for status check mode, not both. However, it's safe to grant both permissions if you're unsure which mode you'll use.
:::

## Skipping Changelog Entries
Expand Down
Loading