GitHub Actions
Craft provides GitHub Actions for automating releases and previewing changelog entries in pull requests.
For a real-world example of using Craft’s GitHub Actions, see the getsentry/publish repository.
Prepare Release
Section titled “Prepare Release”Craft offers two ways to automate releases in GitHub Actions:
| Option | Best For | Flexibility |
|---|---|---|
| Reusable Workflow | Quick setup, standard release flow | Low - runs as a complete job |
| Composite Action | Custom workflows, pre/post steps | High - composable with other steps |
Option 1: Reusable Workflow (Recommended)
Section titled “Option 1: Reusable Workflow (Recommended)”The simplest way to set up Craft releases. Call the workflow and let it handle everything:
name: Releaseon: workflow_dispatch: inputs: version: description: 'Version to release (or "auto")' required: false
jobs: release: permissions: contents: write uses: getsentry/craft/.github/workflows/release.yml@v2 with: version: ${{ inputs.version }} secrets: inheritWorkflow Inputs
Section titled “Workflow Inputs”| Input | Description | Default |
|---|---|---|
version |
Version to release. Can be a semver string (e.g., “1.2.3”), a bump type (“major”, “minor”, “patch”), or “auto” for automatic detection. | Uses versioning.policy from config |
merge_target |
Target branch to merge into. | Default branch |
force |
Force a release even when there are release-blockers. | false |
blocker_label |
Label that blocks releases. | release-blocker |
publish_repo |
Repository for publish issues (owner/repo format). Use "self" to create issues in the source repository itself. |
{owner}/publish |
git_user_name |
Git committer name. | GitHub actor |
git_user_email |
Git committer email. | Actor’s noreply email |
path |
The path that Craft will run inside. | . |
craft_config_from_merge_target |
Use the craft config from the merge target branch. | false |
Workflow Outputs
Section titled “Workflow Outputs”| Output | Description |
|---|---|
version |
The resolved version being released |
branch |
The release branch name |
sha |
The commit SHA on the release branch |
previous_tag |
The tag before this release (for diff links) |
changelog |
The changelog for this release |
Option 2: Composite Action
Section titled “Option 2: Composite Action”Use the action directly when you need to add custom steps before or after the release, or integrate Craft into a more complex workflow:
name: Releaseon: workflow_dispatch: inputs: version: description: 'Version to release (or "auto")' required: false
jobs: release: runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@v4 with: fetch-depth: 0
# Custom pre-release steps - run: echo "Running pre-release checks..."
- uses: getsentry/craft@v2 with: version: ${{ github.event.inputs.version }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Custom post-release steps - run: echo "Release prepared!"The action accepts the same inputs and produces the same outputs as the reusable workflow.
Native executable selection
Section titled “Native executable selection”The Action uses the matching standalone executable when the selected Craft release
includes one. Craft’s own release workflow prefers the native build artifact from
the same run. Versions before standalone binaries and GHCR nightlies retain the
JavaScript compatibility path, so Node remains required by the composite Action.
The Action invokes the same install script served on the website. That script
selects the source, detects GITHUB_ACTIONS or CI, and skips shell completions
and agent skill setup automatically. Missing native release assets use the
JavaScript compatibility path; other download or verification failures stop
installation. Native candidates must report the selected version before placement.
AI summary authentication
Section titled “AI summary authentication”Enable summaries with changelog.aiSummary: {}. The default connection is
Copilot Responses, gpt-5.4-nano and the GITHUB_TOKEN environment variable.
The model must be available to the supplied credential. Use aiSummary: false
to disable generation.
For a custom provider, pass llm JSON and map a secret to llm_api_key:
- uses: getsentry/craft@v2 env: GITHUB_TOKEN: ${{ github.token }} # release operations with: llm: '{"endpoint":"https://gateway.example.com/v1/chat/completions","model":"your-model"}' llm_api_key: ${{ secrets.TEAM_MODEL_TOKEN }}llm_api_key selects a dedicated environment variable over llm.apiKeyEnv;
it never replaces the release token. Alternatively, map a secret to your
configured apiKeyEnv. Craft reads environment variables, not GitHub’s secret
store. Secrets must be available to the workflow’s repository; an organization
secret can grant selected-repository access.
Pass repository/organization configuration as llm: ${{ vars.CRAFT_AI_LLM }}.
The reusable release workflow supplies this fallback and forwards its llm
input and optional llm_api_key secret to both Action paths.
For built-in-token Copilot access, callers (including reusable workflow callers)
must grant copilot-requests: write alongside their release permissions. The
organization must enable “Allow use of Copilot CLI billed to the organization.”
Usage is billed to the organization; permissions alone do not enable access.
Craft’s own release workflow keeps its release-bot token for Git operations and
passes the workflow token separately for AI requests. An explicit llm_api_key
secret takes precedence.
Map ${{ github.token }} to GITHUB_TOKEN, or pass it as llm_api_key when
release operations use a different token. See GitHub’s workflow-token guide.
Personal Copilot credentials require Copilot access; fine-grained PATs need
Copilot Requests: write. Custom provider credentials need no Copilot permission.
Copilot’s direct HTTP backend is outside GitHub’s public REST API contract. Missing credentials or failed requests preserve the original changelog without switching providers. See AI summary configuration for precedence, limits and output examples.
The AI summary integration workflow makes one live request using public fixture facts when the AI connection/release wiring changes in an internal pull request. Fork pull requests skip that credentialed check. Regular AI unit, HTTP-fixture, and CLI/Action integration tests still run in the Node 22/24 CI suites. A green release with fallback warnings alone does not prove live AI summaries worked.
Test a Craft nightly
Section titled “Test a Craft nightly”Every successful push build on Craft’s master branch publishes its binary to
ghcr.io/getsentry/craft as an OCI artifact. The nightly tag advances when the
current master build finishes publishing; nightly-<full commit SHA> keeps each
build available after master advances. These artifact tags are separate from the
package’s Docker image tags.
Pin the action to a master commit to test that exact build. When the action’s
package.json declares a development version, the action automatically downloads
nightly-<action commit SHA>:
- uses: getsentry/craft@<full-master-commit-sha> env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}To use the newest successful master build with another action ref, set
craft_version: nightly. You can also set craft_version: nightly-<full commit SHA>
to select a specific build. The reusable Release workflow forwards its
craft_version input to the action too. Nightlies are available only after the
Publish Craft nightly to GHCR job succeeds. Missing or invalid artifacts stop
the action; it never substitutes a different build or the latest stable release.
Published action releases continue to select their matching stable Craft release
by default.
Auto-versioning Example
Section titled “Auto-versioning Example”When using auto-versioning, Craft analyzes conventional commits to determine the version bump. This works with both the workflow and the action:
# Using the reusable workflowname: Auto Releaseon: schedule: - cron: '0 10 * * 1' # Every Monday at 10 AM
jobs: release: permissions: contents: write uses: getsentry/craft/.github/workflows/release.yml@v2 with: version: auto secrets: inheritChangelog Preview (Reusable Workflow)
Section titled “Changelog Preview (Reusable Workflow)”The changelog preview workflow posts a comment on pull requests showing how they will appear in the changelog. This helps contributors understand the impact of their changes.
Basic Usage
Section titled “Basic Usage”Call the reusable workflow from your repository:
name: Changelog Previewon: pull_request_target: types: [opened, synchronize, reopened, edited, labeled, unlabeled]
permissions: contents: read pull-requests: write statuses: write
jobs: changelog-preview: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 secrets: inheritInputs
Section titled “Inputs”| 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
Section titled “Output Modes”The workflow supports two output modes for displaying changelog previews:
Comment Mode (Default)
Section titled “Comment Mode (Default)”Posts the changelog preview as a PR comment that updates automatically:
jobs: changelog-preview: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 with: comment: true # or omit for default secrets: inheritPros:
- 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
Status Check Mode
Section titled “Status Check Mode”Creates a commit status with the semver impact and writes the full changelog to the Actions job summary:
jobs: changelog-preview: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 with: comment: false secrets: inheritPros:
- 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
Multiple Previews per PR
Section titled “Multiple Previews per PR”If one repository releases several packages from separate Craft configs, call the workflow once per package with its working-directory. Each directory gets its own PR comment and its own status context, and the heading names the directory, e.g. Semver Impact of This PR (packages/python). A PR that touches several packages shows one preview per package:
jobs: changelog-preview-python: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 with: working-directory: packages/python changelog-preview-rust: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 with: working-directory: packages/rustPreviews run from the repository root keep the plain Changelog Preview / Semver Impact status context. In directory names, characters other than letters, digits, ., _, / and - are replaced with -, and a short hash is appended so that, for example, foo bar and foo-bar still get separate previews. Directory names with uppercase letters also get the hash, because GitHub compares status contexts case-insensitively.
Pinning a Specific Version
Section titled “Pinning a Specific Version”on: pull_request_target: types: [opened, synchronize, reopened, edited, labeled, unlabeled]
permissions: contents: read pull-requests: write statuses: write
jobs: changelog-preview: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 with: craft-version: '2.15.0' secrets: inheritHow It Works
Section titled “How It Works”- Generates the changelog - Runs
craft changelog --pr <number> --format jsonto generate the upcoming changelog with metadata - Fetches PR info - Gets PR title, body, labels, and base branch from GitHub API
- Categorizes the PR - Matches the PR to changelog categories based on labels and commit patterns
- Suggests version bump - Based on matched categories with semver fields (major/minor/patch)
- Highlights PR entries - The current PR is rendered with blockquote style (displayed with a left border in GitHub)
- Displays the preview - Posts as a PR comment (default) or creates a neutral check run with job summary (when
comment: false) - Auto-updates - The preview is automatically updated when you update the PR (push commits, edit title/description, or change labels)
Example Comment
Section titled “Example Comment”The workflow posts a comment like this:
## Suggested Version Bump
🟡 **Minor** (new features)
## 📋 Changelog Preview
This is how your changes will appear in the changelog.Entries from this PR are highlighted with a left border (blockquote style).
---
### New Features ✨
> - feat(api): Add new endpoint by @you in #123
- feat(core): Existing feature by @other in #100
### Bug Fixes 🐛
- fix(ui): Resolve crash by @other in #99
---
🤖 This preview updates automatically when you update the PR.PR Trigger Types
Section titled “PR Trigger Types”The workflow supports these PR event types:
opened- When a PR is createdsynchronize- When new commits are pushedreopened- When a closed PR is reopenededited- When the PR title or description is changedlabeled- When labels are added or removed
Requirements
Section titled “Requirements”The workflow requires specific permissions and secrets to function correctly:
Permissions (all three required):
permissions: contents: read pull-requests: write statuses: writecontents: read- Allows the workflow to checkout your repository and read git history for changelog generationpull-requests: write- Required for comment mode to post and update comments on pull requestsstatuses: write- Required for status check mode to create commit statuses
Secrets:
secrets: inherit- Passes your repository’sGITHUB_TOKENto the workflow, ensuring it has access to your repository (especially important for private repositories)
Repository Setup:
- The repository should have a git history with tags for the changelog to be meaningful
Skipping Changelog Entries
Section titled “Skipping Changelog Entries”Using Magic Words
Section titled “Using Magic Words”Use #skip-changelog in your commit message or PR body to exclude a commit from the changelog:
chore: Update dependencies
#skip-changelogUsing Labels
Section titled “Using Labels”You can configure labels to exclude PRs from the changelog. In your .craft.yml:
changelog: categories: - title: 'New Features ✨' labels: ['feature', 'enhancement'] - title: 'Bug Fixes 🐛' labels: ['bug', 'fix'] exclude: labels: ['skip-changelog', 'dependencies'] authors: ['dependabot[bot]', 'renovate[bot]']PRs with the skip-changelog label or from excluded authors will not appear in the changelog.
Combining Both Workflows
Section titled “Combining Both Workflows”You can use both the changelog preview and release workflows together for a complete release flow:
name: Changelog Previewon: pull_request_target: types: [opened, synchronize, reopened, edited, labeled, unlabeled]
permissions: contents: read pull-requests: write statuses: write
jobs: changelog-preview: uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 secrets: inheritname: Releaseon: workflow_dispatch: inputs: version: description: 'Version (leave empty for auto)' required: false
jobs: release: permissions: contents: write uses: getsentry/craft/.github/workflows/release.yml@v2 with: version: ${{ inputs.version || 'auto' }} secrets: inherit