---
title: "Setting Up Release Infrastructure"
url: https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure/
---

# Setting Up Release Infrastructure

This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement levels.

Statusstable[](https://develop.sentry.dev/sdk/getting-started/standards/spec-lifecycle.md "Learn about spec statuses")

Version`1.0.0`[(changelog)](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#changelog)

## [Overview](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#overview)

This playbook guides SDK maintainers through setting up automated release infrastructure for a new SDK repository using [Craft](https://craft.sentry.dev). It covers initial tagging, CI configuration, version management, and branch protection rules. By following these steps, the repository will support automated changelog generation, artifact publishing, and controlled releases via GitHub Actions.

Related resources:

* [Release Versioning Standard](https://develop.sentry.dev/sdk/getting-started/standards/release-versioning.md) — version format and tooling requirements
* [Craft Documentation](https://craft.sentry.dev) — release automation tool
* [Craft GitHub Actions](https://craft.sentry.dev/github-actions/) — workflow configuration options

***

## [Steps](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#steps)

#### [1. Set Up CI for Release Branches](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#1-set-up-ci-for-release-branches)

The repository's CI **MUST** respond to `release/**` branches and produce a named artifact.

#### [2. Configure Craft (`.craft.yml`)](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#2-configure-craft-craftyml)

You **MUST** create a `.craft.yml` with targets for your package registry and GitHub releases:

```yaml
minVersion: 2.27.1
targets:
  - name: pypi
  - name: github
```

It is highly recommended for you to enable [automatic versioning](https://craft.sentry.dev/configuration/#versioning) and [automated changelog generation](https://craft.sentry.dev/configuration/#auto-mode).

See the [Craft configuration docs](https://craft.sentry.dev/configuration/) for all available targets and options.

#### [3. Add Version Bump Script - *OPTIONAL* (`scripts/bump-version.sh`)](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#3-add-version-bump-script---optional-scriptsbump-versionsh)

See [Automated Version Bumping](https://craft.sentry.dev/configuration/#automatic-version-bumping) and *only* add a custom script if you really need to.

Craft invokes this script when bumping the version. The script **MUST** accept the old version as `$1` and the new version as `$2`:

```bash
#!/usr/bin/env bash
set -euxo pipefail

sed -i "s/^version =.*/version = $2/" setup.cfg
```

For a real-world example with multiple version locations, see [sentry-python's bump-version.sh](https://github.com/getsentry/sentry-python/blob/master/scripts/bump-version.sh).

#### [4. Add Release Workflow (`.github/workflows/release.yml`)](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#4-add-release-workflow-githubworkflowsreleaseyml)

You **MUST** add a release workflow that triggers releases from the GitHub UI. The workflow **SHOULD** use `vars.SENTRY_RELEASE_BOT_CLIENT_ID` and `secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY` which are available to repositories in the `getsentry` org automatically. These are needed because [GitHub prevents `GITHUB_TOKEN` from triggering downstream workflows](https://docs.github.com/en/actions/reference/events-that-trigger-workflows).

```yaml
name: Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: Version to release
        required: false
      force:
        description: Force a release even when there are release-blockers (optional)
        required: false

jobs:
  release:
    runs-on: ubuntu-latest
    name: "Release a new version"
    steps:
      - name: Get auth token
        id: token
        uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
        with:
          app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }}
          private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }}
      - uses: actions/checkout@v6
        with:
          token: ${{ steps.token.outputs.token }}
          fetch-depth: 0
      - name: Prepare release
        uses: getsentry/craft@v2
        env:
          GITHUB_TOKEN: ${{ steps.token.outputs.token }}
        with:
          version: ${{ github.event.inputs.version }}
          force: ${{ github.event.inputs.force }}
```

For full details on all available options including auto-versioning, changelog preview, merge targets, and multiple Craft configs, see [Craft's GitHub Actions documentation](https://craft.sentry.dev/github-actions/). Repositories outside the `getsentry` org can use the simpler [reusable workflow](https://craft.sentry.dev/github-actions/#option-1-reusable-workflow-recommended) which handles token management automatically via `secrets: inherit`.

#### [5. Set Repository Permissions](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#5-set-repository-permissions)

You **MUST** give the `engineering` team write access via [security-as-code](https://github.com/getsentry/security-as-code/) [like this](https://github.com/getsentry/security-as-code/blob/2da8c01ad34b12539cc345c08896b420eb86049f/rbac/env/prod-github/repo/craft.yml#L5)

#### [6. Create Branch Ruleset](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#6-create-branch-ruleset)

Download the [default ruleset template](https://develop.sentry.dev/json/Default_ruleset.json). You **MUST** import it at `https://github.com/getsentry/REPONAME_HERE/settings/rules` via **New ruleset** > **Import a ruleset**. You **MAY** adjust settings but **MUST NOT** remove the App in the Bypass List.

#### [7. Cut Your First Release](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#7-cut-your-first-release)

Navigate to the Actions tab, locate the Release workflow, and trigger it. This creates an [issue in `getsentry/publish`](https://github.com/getsentry/publish/issues) which requires a reviewer to add the `accepted` label before artifacts are published.

For the ongoing release process after setup, see "Cutting a release" (wip).

## [Referenced Standards](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#referenced-standards)

* [Version format](https://develop.sentry.dev/sdk/getting-started/standards/release-versioning.md#versioning) — SemVer requirements
* [Release tooling](https://develop.sentry.dev/sdk/getting-started/standards/release-versioning.md#release-tooling) — Craft and publish setup
* [Release gating criteria](https://develop.sentry.dev/sdk/getting-started/standards/review-ci.md#release-gating) — Pre-release validation requirements
* [Rollback procedures](https://develop.sentry.dev/sdk/getting-started/standards/coordination-maintenance.md#releases) — Emergency release rollback process

***

## [Changelog](https://develop.sentry.dev/sdk/getting-started/playbooks/setup/setting-up-release-infrastructure.md#changelog)

| Version | Date       | Summary                                                                                               |
| ------- | ---------- | ----------------------------------------------------------------------------------------------------- |
| `1.0.0` | 2026-02-20 | Initial playbook — standardized release infrastructure setup with Craft, CI/CD, and branch protection |
