diff --git a/.github/workflows/changelog-preview.yml b/.github/workflows/changelog-preview.yml
index ae66852a..e6d81cc8 100644
--- a/.github/workflows/changelog-preview.yml
+++ b/.github/workflows/changelog-preview.yml
@@ -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:
@@ -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:
@@ -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
@@ -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:
@@ -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="🟢"
+ ;;
+ *)
+ 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}
+
+
+ 📋 Changelog Preview
+
+ This is how your changes will appear in the changelog.
+ Entries from this PR are highlighted with a left border (blockquote style).
+
+ ---
+
+ ${CHANGELOG}
+
+ ---
+
+
+ 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
## Semver Impact of This PR
@@ -162,22 +255,24 @@ jobs:
🤖 This preview updates automatically when you update the PR.
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("")) | .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("")) | .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
diff --git a/docs/src/content/docs/github-actions.md b/docs/src/content/docs/github-actions.md
index 6abee55d..a2772199 100644
--- a/docs/src/content/docs/github-actions.md
+++ b/docs/src/content/docs/github-actions.md
@@ -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
@@ -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
@@ -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**:
@@ -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