> ## Documentation Index
> Fetch the complete documentation index at: https://v2.spacedrive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Releases

Spacedrive uses GitHub Actions workflows, git tags, and a custom xtask command to manage releases. This page covers the full release pipeline from version bump to published artifacts.

## Versioning

Spacedrive follows semver with pre-release suffixes for alpha/beta releases.

```
2.0.0-alpha.1   # Pre-release
2.0.0-beta.1    # Pre-release
2.0.0           # Stable release
```

The version string lives in 7 files across the repo:

* `core/Cargo.toml`
* `apps/server/Cargo.toml`
* `apps/cli/Cargo.toml`
* `apps/tauri/src-tauri/Cargo.toml`
* `apps/tauri/sd-tauri-core/Cargo.toml`
* `apps/tauri/src-tauri/tauri.conf.json`
* `apps/tauri/package.json`

These must stay in sync. The bump command handles this automatically.

## Bump Command

`cargo xtask bump` updates all version files, commits the changes, and creates a git tag.

```bash theme={null}
cargo xtask bump 2.0.0-alpha.2
```

This does three things:

1. Updates the version string in all 7 files
2. Commits with message `v2.0.0-alpha.2`
3. Creates git tag `v2.0.0-alpha.2`

It does not push. You push manually when ready:

```bash theme={null}
git push --tags
```

Pushing the tag triggers the release workflows.

## Workflows

Five GitHub Actions workflows handle CI and releases.

### CI (`ci.yml`)

Runs on every pull request and push to `main`. Handles formatting checks, linting, and build verification. This is the standard PR gate.

### Core Tests (`core_tests.yml`)

Runs `sd-core` integration tests on push to `main` across macOS, Linux, and Windows. Tests run on real hardware including self-hosted macOS ARM64 and Windows runners.

### Release (`release.yml`)

Triggered by pushing a `v*` tag or manual dispatch. Builds all release artifacts and creates a draft GitHub release.

**Server binary builds:**

| Platform | Architecture |
| -------- | ------------ |
| Linux    | x86\_64      |
| Linux    | aarch64      |

Server binaries are compiled with `sd-core/heif`, `sd-core/ffmpeg`, and `sd-core/ai` features enabled. Each produces a tarball with the binary and a SHA256 checksum.

**Desktop builds (Tauri):**

| Platform | Architecture | Bundle   |
| -------- | ------------ | -------- |
| macOS    | aarch64      | DMG, App |
| macOS    | x86\_64      | DMG, App |
| Windows  | x86\_64      | NSIS     |
| Linux    | x86\_64      | DEB      |
| Linux    | aarch64      | DEB      |

Desktop builds go through `tauri-action` which handles code signing (macOS), Tauri signing keys (for the updater), and bundle creation. macOS builds run on self-hosted runners with Apple signing certificates.

The final `release` job waits for all builds to complete, downloads all artifacts, and creates a draft release on GitHub. The release is always created as a draft so you can review before publishing.

<Note>The release is created as a **draft**. You must manually publish it on GitHub after verifying the artifacts.</Note>

### Server Docker (`server.yml`)

Triggered by the same `v*` tag or manual dispatch. Builds a multi-arch Docker image (amd64 + arm64) and pushes it to GitHub Container Registry at `ghcr.io/spacedriveapp/spacedrive/server`.

The Docker build uses `buildah` with QEMU emulation for cross-platform images. The Dockerfile is at `apps/server/Dockerfile`.

**Tagging behavior:**

| Tag pushed       | Docker tags applied      | `latest` updated? |
| ---------------- | ------------------------ | ----------------- |
| `v2.0.0-alpha.1` | `v2.0.0-alpha.1`         | No                |
| `v2.0.0-beta.1`  | `v2.0.0-beta.1`          | No                |
| `v2.0.0`         | `v2.0.0`, `latest`       | Yes               |
| Manual dispatch  | `{short-sha}`, `staging` | No                |

The `latest` tag only moves for stable releases (tags matching `vX.Y.Z` with no suffix). Pre-release tags like `alpha` or `beta` are published under their specific version only. This protects users pulling `latest` from getting unstable builds.

### Mobile Release (`mobile.yml`)

Manual dispatch only. Builds the React Native app for iOS and/or Android. A platform picker lets you build `ios`, `android`, or `all`.

The mobile app bundles `sd-mobile-core`, a native Expo module that wraps the Spacedrive Rust core. This means mobile builds require the full Cargo workspace and Rust cross-compilation toolchain, not just JavaScript bundling.

**iOS (TestFlight):**

1. Compiles `sd-mobile-core` for `aarch64-apple-ios` via `cargo xtask build-mobile`
2. Runs `expo prebuild` to generate the Xcode project
3. Archives with `xcodebuild` using manual code signing
4. Exports IPA with `app-store-connect` distribution method
5. Uploads directly to TestFlight via `xcrun altool`

Runs on a self-hosted macOS ARM64 runner (same as desktop macOS builds). TestFlight handles distribution to testers automatically after upload.

**Android (Play Store Internal):**

1. Compiles `sd-mobile-core` for `aarch64-linux-android` via `cargo xtask build-mobile`
2. Runs `expo prebuild` to generate the Android project
3. Builds a signed AAB with `./gradlew bundleRelease`
4. Uploads to Play Store internal testing track

Runs on a Linux runner with Java 17 and the Android SDK/NDK.

<Note>The mobile workflow is manual dispatch only. It is not triggered by tags. Run it from the Actions tab when you want to push a mobile build to testers.</Note>

**Required secrets (in addition to existing Apple secrets):**

| Secret                        | Purpose                                                              |
| ----------------------------- | -------------------------------------------------------------------- |
| `MOBILE_PROVISIONING_PROFILE` | iOS App Store distribution profile for `com.spacedrive.app` (base64) |
| `ANDROID_KEYSTORE`            | Android release keystore file (base64)                               |
| `ANDROID_KEYSTORE_PASSWORD`   | Keystore password                                                    |
| `ANDROID_KEY_ALIAS`           | Signing key alias                                                    |
| `ANDROID_KEY_PASSWORD`        | Signing key password                                                 |
| `GOOGLE_PLAY_SERVICE_ACCOUNT` | Google Play API service account JSON (for automated upload)          |

## Release Flow

A full release looks like this:

```bash theme={null}
# 1. Bump version, commit, and tag
cargo xtask bump 2.0.0-alpha.2

# 2. Push the tag (triggers release + server docker workflows)
git push --tags

# 3. Wait for workflows to complete on GitHub Actions

# 4. Review the draft release on GitHub, then publish
```

Both `release.yml` and `server.yml` trigger in parallel from the same tag push. The GitHub release is created as a draft. The Docker image is pushed to ghcr.io immediately.

Mobile releases are decoupled from this flow. Trigger the mobile workflow manually from the Actions tab when you want to push a build to TestFlight or Play Store internal testing.

## Tauri Updater

Desktop builds include `includeUpdaterJson: true` in the Tauri action config. This generates a JSON manifest that the Tauri updater checks against to notify users of new versions. The updater JSON files are included as release artifacts alongside the binaries.

## Secrets

The release workflow depends on several repository secrets:

| Secret                       | Purpose                                 |
| ---------------------------- | --------------------------------------- |
| `APPLE_CERTIFICATE`          | macOS code signing certificate (base64) |
| `APPLE_CERTIFICATE_PASSWORD` | Certificate password                    |
| `APPLE_SIGNING_IDENTITY`     | Signing identity string                 |
| `APPLE_API_KEY`              | App Store Connect API key ID            |
| `APPLE_API_KEY_BASE64`       | API key file (base64)                   |
| `APPLE_API_ISSUER`           | API key issuer ID                       |
| `APPLE_PROVIDER_SHORT_NAME`  | Team provider short name                |
| `TAURI_PRIVATE_KEY`          | Tauri update signing key                |
| `TAURI_KEY_PASSWORD`         | Tauri signing key password              |
| `SENTRY_AUTH_TOKEN`          | Sentry error tracking                   |

The Docker workflow uses only `GITHUB_TOKEN` which is provided automatically.
