# Gradle previews

Build and share Android apps and native command-line tools directly from Gradle. Start with the <.localized_link href="/guides/get-started/gradle-project">Gradle project guide</.localized_link> to connect the project and authenticate.

## Android apps

```bash
./gradlew :app:tuistShareDebug
```

The `dev.tuist` settings plugin registers a `tuistShare<Variant>` task for each application variant from the Android Gradle Plugin (8.8.2 or later). Replace `app` and `Debug` with your application module and variant, for example `:app:tuistShareDemoDebug` for a product flavor. The task builds the APK through Gradle's declared artifact dependencies before publishing it. It also works when build outputs are up to date or restored from the build cache.

Only a single, signed, universal application APK is supported. Android's debug variant normally uses a debug signing key; release variants need your own signing configuration. The task verifies the APK signature before authentication or upload. Unsigned, invalid, instrumentation, and split APKs are rejected. Library modules, test APKs, and Android App Bundles (`.aab`) are not publication targets.

## Native command-line tools

Projects using Gradle's `cpp-application` or `swift-application` plugin get a share task for each native binary:

```bash
./gradlew :app:tuistShareMainDebug
```

The task builds and packages the installed distribution, including its launcher and runtime libraries. Use `tuistShareMainRelease` for the release binary. Projects targeting multiple machines have a task for each binary; run `./gradlew :app:tasks --all` to find their names.

Native macOS and Linux executables for arm64 or x86_64 are supported. Build on the target platform with the toolchain required by your Gradle plugin. JVM applications and their generated launcher scripts are not supported by this integration.

## Publication behavior

Share tasks publish using the plugin's existing Tuist credentials, without invoking the Tuist CLI. Ordinary `assemble`, `build`, and test tasks never publish previews.

After sharing, open **Previews** in your project to copy the link. Repeating a share of the same build and track reuses its publication, including after a build-cache hit. Failed or unconfirmed uploads fail the share task; they are not reported as successful previews.

## CI and tracks

Configure <.localized_link href="/guides/integrations/continuous-integration">CI authentication</.localized_link> with the same credentials you use for the plugin's other authenticated features, then request publication explicitly:

```bash
./gradlew :app:tuistShareDebug --track nightly
```

Add `--track nightly` to a native share task in the same way. Tasks use the configured Tuist project, server URL, and proxy settings. Preview publication always requires authentication. Git revision metadata, release notes, and automatic pull-request comments are not attached by these tasks.

Artifact publications expire after 30 days on hosted Tuist. Self-hosted instances use `TUIST_APP_PREVIEW_RETENTION_DAYS`; leaving it unset disables expiry for this family. Expired publications cannot be revived by repeating the same intent.

## Share an existing APK

For an APK built outside this workflow, or to include release notes with the legacy upload flow, the CLI remains available:

```bash
tuist share app/build/outputs/apk/debug/app-debug.apk \
  --track nightly --release-notes "Improve checkout"
```

See <.localized_link href="/guides/features/previews#run-a-preview">Run a preview</.localized_link> for running published builds, access, tracks, and README badges.

## Tracks with tuist share {#share-tracks}

For workflows that publish with `tuist share`, use `--track` to select a track:

```bash
tuist share App --track beta
tuist share App --track nightly
```

## Release notes {#release-notes}

Use tracks for environment groups and release notes for the purpose of an individual build:

```bash
tuist share App --track QA --release-notes "Fix sign-in and improve the checkout flow"
```

Replace `App` with your app name, application file path, or executable distribution and its `--executable` option. Release notes are optional plain text, up to 10,000 characters. The first nonblank line appears as a single-line snippet in preview lists, so build numbers and other identifying information are visible at a glance. Long lines are truncated; full notes appear on the detail pages. Search matches display names and full release notes, including lines not shown in the snippet. Multiline notes are supported, for example `--release-notes "$(< release-notes.txt)"`. They do not change the app's display name or its track.

### Compatibility {#preview-metadata-compatibility}

Release notes are additive metadata, not part of a preview's identity. Uploads from old and new clients still group into the same preview across platforms. The first nonblank notes are retained: a later upload can fill notes that were previously absent, but cannot overwrite existing notes. Omitting `release_notes`, sending `null`, or sending an empty or whitespace-only string never clears notes. Existing previews are not backfilled and remain valid without notes.

The list API's optional `track` query parameter matches a whole track name, case-insensitively, consistent with existing track storage. Omit it or send an empty value (`?track=`) to list all tracks. Track names remain open strings, not a fixed list of values. `GET /api/projects/:account_handle/:project_handle/previews/tracks` returns `{total_count, tracks: [{name, count}]}` with sorted, case-insensitively grouped named tracks, under the same preview-read authorization as listing builds. Counts cover the whole project independently of pagination, search, and the selected track; the total includes untracked previews. Only listable previews with a bundle identifier are counted. The list API also accepts optional `search` for a literal, case-insensitive substring of the display name or full release notes, combined with the track before pagination. Existing `display_name` filtering remains exact.

Old clients can continue uploading and listing previews without sending either field. New clients accept older responses that omit track or notes, and ignore unknown response properties added by future servers. API integrations should likewise ignore unknown response properties so additive metadata remains compatible.

Self-hosted deployments need a server version that supports release notes and track filtering, together with an updated client, to use these features. Older servers may ignore notes or unknown query parameters.

## Pull/merge request comments {#pullmerge-request-comments}

> [!WARNING]
> **Integration With Git Platform Required**
>
> To get automatic pull/merge request comments, integrate your <.localized_link href="/guides/server/accounts-and-projects">remote project</.localized_link> with a <.localized_link href="/guides/server/authentication">Git platform</.localized_link>.

Once your Tuist project is connected with your Git platform, add <.localized_link href="/cli/share">`tuist share`</.localized_link> after a successful application build in CI. Tuist will post a preview link directly in your pull/merge requests, so reviewers can test without building locally:

![GitHub app comment with a Tuist Preview link](/images/guides/features/github-app-with-preview.png)

## Automations {#automations}

Use `--json` to get JSON output from `tuist share`:

```bash
tuist share --json
```

Use the result for custom automations, such as posting a Slack message from CI. The `url` key contains the full preview link; `qrCodeURL` points to a QR code image for opening the preview on a device:

```json
{
  "id": 1234567890,
  "url": "https://cloud.tuist.io/preview/1234567890",
  "qrCodeURL": "https://cloud.tuist.io/preview/1234567890/qr-code.svg"
}
```

