Skip to content
Reference

Configuration Reference

Every key in Shipfile.yml, with defaults and examples.

Shipfile.yml is only the default config filename. ShipIt reads ./Shipfile.yml when --shipfile is omitted, but any YAML file path works with --shipfile <path>.

For config-backed CLI commands, the selected file must exist. A missing ./Shipfile.yml or missing --shipfile <path> target causes the command to exit with code 2.

Priority Order

CLI flags  >  SHIPIT_* env vars  >  .env file  >  config file  >  Built-in defaults

.env file auto-loading

ShipIt automatically loads a .env file from the same directory as Shipfile.yml before resolving configuration. Variables already in the process environment take precedence and are never overwritten.

Supported formats: KEY=VALUE, export KEY=VALUE, quoted values, and # comments. Use shipit generate to create a pre-populated .env file; it is automatically added to .gitignore.

Environment variable naming convention

Shipfile YAML keys map to env vars by upper-casing and joining path segments with _, prefixed with SHIPIT_. Nested keys use __ (double-underscore) as the section separator.

Shipfile keyEnvironment variable
app.schemeSHIPIT_APP__SCHEME
app.bundle_idSHIPIT_APP__BUNDLE_ID
app.team_idSHIPIT_APP__TEAM_ID
app_store_connect.key_idSHIPIT_APP_STORE_CONNECT__KEY_ID
app_store_connect.issuer_idSHIPIT_APP_STORE_CONNECT__ISSUER_ID
build.configurationSHIPIT_BUILD__CONFIGURATION
archive.export_methodSHIPIT_ARCHIVE__EXPORT_METHOD
code_signing.git_urlSHIPIT_CODE_SIGNING__GIT_URL

Secrets bypass: ASC_KEY_ID, ASC_ISSUER_ID, ASC_PRIVATE_KEY, ASC_PRIVATE_KEY_PATH, and VAULT_PASSWORD are also read directly (without the SHIPIT_ prefix) for compatibility with standard CI secret naming.

Top-Level Structure

platform:
app:
app_store_connect:
code_signing:
build:
archive:
export:
testflight:
screenshots:
metadata:
versioning:
project_generation:
notifications:
workflows:
custom_actions:
# Platform-specific overrides (merged on top of shared config)
ios:
android:

app

KeyTypeDescription
workspacestringPath to .xcworkspace
projectstringPath to .xcodeproj (used when workspace is nil)
schemestringXcode scheme for build and test
bundle_idstringApp bundle identifier. Optional if it can be inferred from Xcode build settings
team_idstringApple Developer Team ID. Optional if it can be inferred from Xcode build settings

Where to find these values manually:

  • bundle_id: your target's bundle identifier / application ID in Xcode Signing settings or PRODUCT_BUNDLE_IDENTIFIER in build settings
  • team_id: the 10-character Apple Developer Team ID for the team selected in Xcode Signing, also shown in the Apple Developer account / Certificates, IDs & Profiles

app_store_connect

For App Store Connect API actions, provide key_id, issuer_id, and exactly one private key source: private_key or key_path.

issuer_id is not inside the .p8 file. Copy it from the App Store Connect API Keys page.

You can omit this whole section if you only use local Xcode actions such as build, test, archive, or export.

Find these values in App Store Connect:

  1. Open Users and Access.
  2. Open Integrations.
  3. Open App Store Connect API.
  4. Create or select an API key.
  5. Copy Key ID and Issuer ID.
  6. Download the .p8 file and use it via private_key or key_path.

If ShipIt cannot infer app.team_id, use the team selected in Xcode for the app target. The value you need is the Apple Developer Team ID, not the App Store Connect issuer ID.

KeyTypeEnv VarDescription
key_idstringASC_KEY_IDAPI key ID
issuer_idstringASC_ISSUER_IDIssuer ID
key_pathstringPath to .p8 key file
private_keystringASC_PRIVATE_KEYRaw .p8 contents

code_signing

KeyTypeDefaultDescription
typestringvaultautomatic, vault, or manual
storagestringgitgit, s3, or gcs
git_urlstringURL of the certificate repo
app_identifierstringBundle ID for matching
profile_typestringappstore, adhoc, development
p12_pathstringLocal .p12 certificate path (manual signing)
p12_base64stringBase64-encoded .p12 for CI / manual signing
p12_passwordstring.p12 certificate password
provisioning_profile_pathstringLocal .mobileprovision path (manual signing)
provisioning_profile_base64stringBase64-encoded .mobileprovision for CI / manual signing

Set VAULT_PASSWORD env var for the encrypted repo passphrase.

With type: automatic, ShipIt passes -allowProvisioningUpdates to Xcode build/export operations and writes signingStyle=automatic into export options.

With type: manual, shipit sign sync installs the configured .p12 certificate and provisioning profile. Local paths are preferred when they exist; base64 values are used as a CI fallback.

build

KeyTypeDefaultDescription
configurationstringReleaseBuild configuration
derived_data_pathstringCustom derived data path
xcargsmap{}Extra flags for xcodebuild

archive

Top-level archive keys apply to iOS archives. Android archive options are set per workflow step (see archive action options).

KeyTypeDefaultDescription
export_methodstringapp-storeapp-store, ad-hoc, enterprise, development
include_symbolsbooltrueInclude dSYMs
include_bitcodeboolInclude bitcode (deprecated Xcode 14+)
output_pathstringOutput path for .xcarchive

export

KeyTypeDescription
archive_pathstringPath to .xcarchive
output_directorystringOutput directory for IPA

testflight

KeyTypeDefaultDescription
skip_waiting_for_build_processingboolfalseSkip Apple's processing wait
distribute_externalboolfalseDistribute to external testers
groupslist[]Beta group names
changelogstringRelease notes

screenshots

KeyTypeDefaultDescription
deviceslist[]Simulator device names
localeslist[en-US]Locale identifiers
schemestringScreenshot UI test scheme
output_directorystring./screenshotsOutput directory

metadata

KeyTypeDefaultDescription
directorystring./metadataMetadata directory
submit_for_reviewboolfalseSubmit for review
automatic_releaseboolfalseAuto-release after approval
phased_releaseboolfalsePhased release

versioning

ShipItSwifty follows Apple's two-version model:

Plist keyFormatMeaning
CFBundleShortVersionStringMAJOR.MINOR.PATCHUser-facing marketing version (e.g. 2.4.1). Bumped manually for releases.
CFBundleVersionplain integerInternal build number (e.g. 317). Auto-incremented on every beta run.

The versioning section controls how CFBundleVersion is incremented. CFBundleShortVersionString is only changed when the version action is called with bump: major, bump: minor, or bump: patch.

KeyTypeDefaultDescription
strategystringsequentialsequential — adds 1 each run (guarantees a plain integer). timestamp — uses YYYYMMDDHHmm format.
sourcestringxcodeprojxcodeproj — reads MARKETING_VERSION/CURRENT_PROJECT_VERSION from xcodebuild -showBuildSettings; falls back to agvtool, then plutil on Info.plist. asc — reads current build number from App Store Connect. project_spec — reads/writes version values in a YAML spec file (XcodeGen/Tuist). kmp — reads/writes versionName/versionCode in gradle.properties. gradle — reads/writes directly in build.gradle.kts or build.gradle; default for Android projects.
spec_pathstringPath to the project spec file (used with source: project_spec).
build_keystringYAML key path for the build number in the spec file (e.g. settings.CURRENT_PROJECT_VERSION).
marketing_keystringYAML key path for the marketing version in the spec file (e.g. settings.MARKETING_VERSION).

version action options

The version action accepts a bump option that selects which counter to change:

bump valueChangesLeaves untouched
buildCFBundleVersion (integer)CFBundleShortVersionString
patchPatch segment of CFBundleShortVersionString; resets CFBundleVersion to 1Major and minor segments
minorMinor segment; resets patch and CFBundleVersion to 1Major segment
majorMajor segment; resets minor, patch, and CFBundleVersion to 1

Version dry-run preview

Use --dry-run to see the computed before/after version values without writing anything:

shipit version --bump build --dry-run
shipit version --bump patch --dry-run --output json

Safe bump ordering

When a workflow bumps the marketing version (patch/minor/major) and the build number in the same run, place the marketing version bump first. A marketing version bump resets the build number to 1, so running it after a build bump would discard the incremented value. Pair each version step with an immediate git commit so a late-stage failure leaves a clean rollback target.

workflows:
  beta:
    - action: test
    - action: archive
    - action: version # bump only after build succeeds
      options: { bump: build }
    - action: git # commit immediately so git is the rollback mechanism
      options:
        operation: commit # stages all changes (git add -A) then commits
        commit_message: "chore: bump build number [skip ci]"
    - action: export
    - action: testflight

The git action's operation: commit stages every change in the working tree (git add -A) before committing — there is no per-file option. In CI this is usually what you want, since the runner starts from a clean checkout and the only modified files are the version bump. If you have unrelated local changes, commit or stash them first.

Beta workflow pattern (local-only, Apple semantics)

For a local beta that increments the build number, runs tests, then archives and exports:

versioning:
  strategy: sequential # CFBundleVersion stays a plain integer
  source: xcodeproj # reads/writes MARKETING_VERSION + CURRENT_PROJECT_VERSION in .xcodeproj
 
workflows:
  beta:
    - action: version
      options:
        bump: build # increments CFBundleVersion only; marketing version unchanged
    - action: test
      options:
        destinations:
          - "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2"
        retry_on_failure: true # retry each failing test once before surfacing a failure
        # only_testing:           # narrow to specific targets, e.g. [NovalingoTests/CoreTests]
        # skip_testing:           # skip slow targets, e.g. [NovalingoUITests]
    - action: archive
    - action: export # exports IPA locally; no upload to App Store Connect

Use xcodebuild -showdestinations -scheme <Scheme> (or shipit ai-session --goal local) to discover destination strings that are valid on your machine before filling in the destinations array. You can list multiple destinations to run tests on several simulators or devices in one step.

How source: xcodeproj is resolved:

  1. xcodebuild -showBuildSettings — reads MARKETING_VERSION and CURRENT_PROJECT_VERSION directly from Xcode build settings. This is the primary path for modern Xcode projects.
  2. xcrun agvtool — fallback for projects that have VERSIONING_SYSTEM = apple-generic but not the newer MARKETING_VERSION key.
  3. plutil on Info.plist — last resort for legacy projects.

To add a TestFlight upload later, append a testflight step and uncomment the app_store_connect section.

test action options

The test action is configured inline in a workflow step. It does not have a top-level Shipfile section.

retry_on_failure, rerun_failed_tests, and infrastructure_retry solve different problems. Use retry_on_failure for xcodebuild's built-in one-pass iOS retry behavior. Use rerun_failed_tests when you want ShipIt to collect the initial failures, rerun those specific tests once, and emit flaky/persistent failure information in TestRunReport. Use infrastructure_retry for whole-run failures such as simulator launch crashes, Android emulator disconnects, Flutter tool crashes, or JS worker failures.

shipit generate asks whether generated test steps should enable infrastructure_retry. shipit ai-session includes the same guidance in the agent prompt so AI-assisted workflow creation asks the same question.

OptionTypeDefaultDescription
destinationslistRequired. One or more xcodebuild destination strings. Each entry triggers a separate xcodebuild test pass; pass/fail/skip counts are aggregated. Discover valid values with xcodebuild -showdestinations -scheme <Scheme>.
destinationstringLegacy single-destination string. Promoted to a one-element destinations list internally. Prefer destinations for new configuration.
schemestringapp.schemeXcode scheme containing the test targets. Falls back to app.scheme when omitted.
configurationstringDebugBuild configuration used for test compilation.
enable_code_coverageboolEnable -enableCodeCoverage YES. When true and result_bundle_path is unset, a path of ./build/<scheme>-tests.xcresult is auto-derived.
result_bundle_pathstringOutput path for the .xcresult bundle. Auto-derived when enable_code_coverage is true.
test_planstringNamed .xctestplan to run.
only_testinglistRestrict to specific targets or test cases. Each entry maps to -only-testing.
skip_testinglistSkip specific targets or test cases. Each entry maps to -skip-testing.
retry_on_failureboolfalsePass -retry-tests-on-failure to retry each failing test once.
rerun_failed_testsobjectSelectively rerun only the failed tests when the runner supports it. Supports enabled and max_attempts (default 2).
report_pathstringOptional path to write the structured JSON TestRunReport for CI artifact upload.
infrastructure_retryobjectRetry the entire test invocation for transient infrastructure failures (iOS simulator crashes, Android emulator disconnects, Flutter tool crashes, JS worker failures). Presence of this block enables retries; omit to disable. Recommended default: { max_attempts: 3, initial_delay_seconds: 2, max_delay_seconds: 30 }.
modulestringandroid.moduleAndroid/KMP. Gradle module whose tests should run.
kindstringunitAndroid only. unit for JVM tests (no device), instrumented for on-device tests, e2e for end-to-end.
scopestringautoAndroid only. Gradle task scope: module qualifies the task with the module path; root runs the root-level task (cascades across all modules). When kind: instrumented and scope is unset, defaults to root. Set scope: module explicitly for single-module behaviour.
build_variantstringdebugAndroid only. Overrides android.build_variant for this test step.
taskstringAndroid only. Explicit Gradle task name (e.g. testDebugUnitTest). Overrides variant-based task selection.
devicesobjectAndroid only. Device config for instrumented runs. Fields: strategy (none/connected/named_emulators/managed), emulators (AVD names), group (managed device group), prompt_locally (interactive selection outside CI).

Destination string format

platform=iOS Simulator,name=<SimulatorName>,OS=<Version>
platform=iOS,name=<DeviceName>
platform=macOS

Run xcodebuild -showdestinations -scheme <Scheme> (with -workspace or -project as appropriate) to list all valid destination strings for your scheme on the current machine. Alternatively, run shipit ai-session --goal local which calls destination discovery automatically and includes the results in nextQuestion so an AI agent can ask which destinations to use.

Android examples:

workflows:
  beta:
    steps:
      # JVM unit tests for a single module
      - action: test
        options:
          kind: unit
          build_variant: debug
 
      # Instrumented tests — defaults to scope:root for multi-module projects
      - action: test
        options:
          kind: instrumented
          devices:
            strategy: named_emulators
            emulators: [Pixel_9_API_35]
 
      # Explicit root-level aggregate task
      - action: test
        options:
          task: testDebugUnitTest
          scope: root

For Android aggregate tasks, ShipItSwifty falls back to JUnit XML reports under build/test-results/<taskName>/ when Gradle stdout does not include a test summary.

test-results action options

Use test-results to parse an existing .xcresult bundle or Gradle JUnit XML directory into a normalized JSON report.

OptionTypeDefaultDescription
formatstringtextOutput format hint: text, json, or markdown.
platformstringresolved platformExplicit platform override when parsing outside a Shipfile-backed context.
xcresult_pathstringauto-discoverExplicit path to a .xcresult bundle (iOS). Falls back to ./build/<scheme>-tests.xcresult or the first .xcresult under ./build/.
report_pathstringauto-discoverExplicit path to a JUnit XML report directory (Android). Falls back to common Gradle build/test-results/... locations.
failed_onlyboolfalseOnly include failed and errored tests in the parsed output.
include_passedbooltrueInclude passed tests in the parsed output.
report_output_pathstringOptional path to write the structured JSON report to disk.

Archive action options

The archive action accepts inline step options for both iOS and Android:

OptionTypeDefaultDescription
schemestringapp.schemeXcode scheme to archive (iOS).
configurationstringReleaseBuild configuration.
export_methodstringapp-storeDistribution method (iOS only): app-store, ad-hoc, development, enterprise.
output_pathstringOutput .xcarchive path (iOS) or .aab path (Android).
include_symbolsbooltrueInclude dSYMs (iOS only).
modulestringandroid.moduleGradle module to bundle (Android).
build_variantstringreleaseGradle bundle variant (Android).
flavorstringProduct flavor name. Combined with build_variant for Gradle task names. Also used by Flutter and React Native archives.
scopestringmoduleAndroid Gradle task scope: module or root.
gradle_propertiesobject{}Additional -P key=value properties passed to the Gradle bundle task (Android).
infrastructure_retryobjectRetry the iOS archive for transient Apple provisioning-server failures that occur when -allowProvisioningUpdates contacts Apple's servers. Presence enables retries; omit to disable. Permanent failures (missing certificate, invalid team ID) are never retried. Recommended: { max_attempts: 3, initial_delay_seconds: 5, max_delay_seconds: 30 }.

project_generation

Configuration for automatic project file generation (XcodeGen, Tuist) before Xcode-dependent steps.

KeyTypeDefaultDescription
toolstringGeneration tool: xcodegen or tuist
commandstringCustom shell command (overrides tool)
spec_pathstringPath to the project spec file (e.g. project.yml for XcodeGen)
output_projectstringExpected output .xcodeproj path (used to verify generation succeeded)
auto_generatebooltrueAutomatically run generation before Xcode-dependent actions. Set to false to skip.

When project_generation.tool is configured, Workflow.run() automatically generates the Xcode project before the first Xcode-dependent step (build, test, archive, etc.), including steps reached through nested custom_actions. Generation is skipped when the output project already exists.

notifications.slack

KeyTypeDescription
webhook_urlstringIncoming webhook URL (use ${SLACK_WEBHOOK_URL})
channelstringDefault Slack channel
on_successboolNotify on success
on_failureboolNotify on failure

workflows

Workflows can be defined as a plain array of steps (legacy) or as an object with optional workflow-level overrides:

# Legacy format: plain array of steps
workflows:
  beta:
    - action: archive
    - action: testflight
 
# New format: object with workflow-level overrides
workflows:
  release:
    build_variant: prodRelease
    steps:
      - action: archive
      - action: play-store
        options:
          track: production

Workflow-level overrides

KeyTypeDescription
build_variantstringOverrides android.build_variant for all steps in this workflow. Used by actions that auto-discover paths.
flavorstringOverrides android.gradle_properties.flavor for all steps in this workflow.
stepsarrayRequired when using the object format. The ordered sequence of action steps.

Each step:

KeyDescription
actionRegistered action name
optionsOptional key-value map passed to the action
whenOptional condition. Reserved tokens are substituted, then the result must be truthy (true/1/yes) for the step to run; otherwise the step is skipped (status skipped) and the workflow continues.

Use these AI-oriented commands to inspect the supported workflow surface:

swift run shipit ai-session --goal beta
swift run shipit schema --output json
swift run shipit inspect project --output json
swift run shipit generate --goal beta
swift run shipit validate yml --shipfile ./Shipfile.yml --output json

ai-session always emits JSON and is intended for AI/tooling integrations rather than direct human consumption.

Workflow notes:

  • export can write an IPA into export.output_directory.
  • testflight and upload can reuse that exported IPA automatically when they run after export in the same workflow and no explicit ipa / ipa_path is set.
  • validate reports an error when testflight or upload has no explicit IPA and no prior export context.
  • Human output from shipit run <workflow> now prints per-step summaries when available, including test pass/fail/skip counts, version strings, and archive artifact filenames.

custom_actions

User-defined composite actions — reusable, parameterized sequences of built-in actions (or other custom actions). Use these to avoid duplicating step blocks across workflows (for example sharing test → archive → export between beta and adhoc).

custom_actions:
  <composite-name>:
    description: "Human-readable summary (optional)."
    parameters:
      <param-name>:
        type: string # string | bool | int | number | array | object | any
        required: true # defaults to true when no default is set
        default: <value> # optional fallback when call site omits the value
        description: "..."
    steps:
      - action: <registered-action-or-other-composite>
        options:
          <option>: "{{param.<param-name>}}"

Invocation is identical to a built-in action — a workflow step uses action: <composite-name> and forwards call-site values via its options: block:

custom_actions:
  build_and_sign:
    description: "Test, archive, and export the app with a chosen export method."
    parameters:
      method:
        type: string
        required: true
    steps:
      - action: test
      - action: archive
      - action: export
        options:
          method: "{{param.method}}"
 
workflows:
  beta:
    - action: build_and_sign
      options:
        method: app-store
    - action: testflight
  adhoc:
    - action: build_and_sign
      options:
        method: ad-hoc
    - action: notify

Parameter reference syntax: {{param.NAME}}

Inside a step's options: block, string values may reference declared parameters using {{param.NAME}}. This delimiter is chosen to stay out of the way of every common template system that surrounds a Shipfile:

SystemTemplate syntaxSafe alongside {{param.X}}?
Shipfile ${ENV_VAR} expansion${FOO}✅ Different delimiter. Env expansion runs before composite substitution, so you can freely mix: key: "{{param.track}}-${DEPLOY_ENV}".
GitHub Actions${{ env.X }}, ${{ secrets.X }}✅ Different delimiter (leading $ + double braces).
CircleCI parameters<< parameters.X >>✅ Different delimiter.
Xcode Cloud / shell$VAR, ${VAR}✅ Different delimiter.

Rules:

  • Only string leaves in a step's options: are scanned. Keys and non-string scalars are untouched.
  • When a string is exactly {{param.NAME}}, the underlying typed JSON value is substituted (bool, int, array, object). When it appears inline with other text, the value is stringified.
  • Unknown parameter references cause shipit validate yml to report an error rather than silently expanding to an empty string.

Validation rules

shipit validate yml enforces:

  • Custom action names must not collide with built-in action names.
  • steps: must contain at least one step.
  • Each step's action: must resolve to a built-in or another declared custom action.
  • Each {{param.NAME}} reference inside a step's options must match a declared parameter.
  • Required parameters must be supplied at the call site (or have a default:).
  • The graph of composite-to-composite references must be acyclic.

AI-session integration

shipit ai-session includes the user's custom actions in the generated agent prompt (name, description, and declared parameters). Agents are instructed to prefer invoking an existing composite over duplicating its step sequence in a new workflow.

Workflow tokens & step conditions

Top-level workflow steps support reserved interpolation tokens and an optional when: condition. Together they let a single shipit run bump the version, distribute, then commit and tag the release — no shell or jq glue required.

Reserved tokens

TokenResolves to
{{version}}The marketing version (e.g. 1.2.3), from a prior version step or the current versioning source.
{{build_number}}The build number (e.g. 42).
{{version_changed}}true/false — whether the marketing version changed (false for a build-only bump, or when no version step ran).

Rules:

  • Tokens are substituted into string leaves of a step's options: and into its when: value, at run time.
  • Values come from the most recent version step's result. Before any version step runs they are seeded best-effort from the current versioning source (and {{version_changed}} is false).
  • An unknown or not-yet-resolved token is left literal (and logged) rather than expanding to empty.
  • These are distinct from composite {{param.NAME}} references and from Shipfile ${ENV_VAR} expansion. Resolution is scoped to top-level workflow steps; tokens inside custom_actions substeps are not resolved in this release.

when: conditions

A step may carry when: "<expr>". Reserved tokens are substituted first, then the result is evaluated for truthiness: true, 1, or yes (case-insensitive) run the step; anything else — including an unresolved literal token — skips it (recorded with status skipped; the workflow continues). v1 supports a single truthy token, not operators or comparisons.

Skips are the only exception to fail-fast workflow semantics. A failing step still aborts the workflow as before.

Example: tag the released version in one shipit run

workflows:
  release:
    - action: version
      options: { bump: patch } # or { bump: ${RELEASE_BUMP} } to drive from CI
    - action: archive
    - action: play-store
      options: { track: production }
    - action: git
      options:
        operation: commit
        commit_message: "chore: release v{{version}} (build {{build_number}})"
    - action: git
      when: "{{version_changed}}" # skipped on build-only bumps
      options:
        operation: tag
        tag_name: "v{{version}}"
    - action: git
      options:
        operation: push
        push_tags: true

shipit generate --goal release scaffolds this commit/tag/push tail for you — for both iOS and Android — and offers to drive the bump from CI via ${RELEASE_BUMP}. CI prerequisites the generator prints: a full-history checkout, write permission on the repo, and a configured git identity (user.name / user.email).

Environment Variables Summary

VariableMaps To
ASC_KEY_IDapp_store_connect.key_id
ASC_ISSUER_IDapp_store_connect.issuer_id
ASC_PRIVATE_KEYapp_store_connect.private_key
ASC_PRIVATE_KEY_PATHapp_store_connect.key_path
VAULT_PASSWORDCode signing passphrase
SLACK_WEBHOOK_URLnotifications.slack.webhook_url
SHIPIT_SCHEMEapp.scheme
SHIPIT_BUNDLE_IDapp.bundle_id
SHIPIT_TEAM_IDapp.team_id

android

Platform-specific Android configuration. These values are merged on top of shared config when --platform android is active or the platform is auto-detected as Android.

KeyTypeDefaultEnv VarDescription
build_systemstringnativeSHIPIT_ANDROID__BUILD_SYSTEMBuild system: native, flutter, react_native, or kmp. See Build systems.
modulestringappGradle module to build/bundle
build_variantstringreleaseGradle build variant (e.g. release, debug)
build_typestringaabaab (Android App Bundle) or apk
scopestringmoduleDefault Gradle task scope: module qualifies tasks with the module; root runs from the Gradle root.
test_kindstringunitDefault test kind: unit (JVM tests), instrumented (on-device), e2e (end-to-end).
package_namestringSHIPIT_ANDROID__PACKAGE_NAMEAndroid application ID (e.g. com.example.app)
keystore_pathstringPath to the release keystore
keystore_passwordstringANDROID_KEYSTORE_PASSWORDKeystore password
keystore_aliasstringANDROID_KEY_ALIASKey alias in the keystore
key_passwordstringANDROID_KEY_PASSWORDKey password
rollout_fractionfloatStaged rollout fraction (0.0–1.0), for production track
gradle_propertiesmap{}Extra -P key=value properties passed to Gradle
gradlew_pathstringSHIPIT_ANDROID__GRADLEW_PATHExplicit path to the gradlew script (auto-detected when omitted)
gradle_project_dirstringShipfile directorySHIPIT_ANDROID__GRADLE_PROJECT_DIRDirectory containing the Gradle root project
gradle_flagsarray[]Extra Gradle flags such as --stacktrace

Google Play credentials

Set these environment variables for Google Play upload actions:

VariableDescription
GOOGLE_PLAY_SERVICE_ACCOUNT_JSONFull JSON content of the service account key file
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_PATHPath to the service account key JSON file

Lookup notes:

  • package_name is your Android applicationId, usually from app/build.gradle or app/build.gradle.kts
  • play-store steps require a track option (or --track on the CLI) to target a Play Console track such as internal, alpha, beta, or production
  • Create the service account in Google Cloud, enable the Google Play Developer API, then invite that service account in Play Console Users and permissions
  • Give the service account Play Console permissions that match the rollout you want to perform

Env var naming: Android keystore variables support both the short form (ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_PASSWORD, ANDROID_KEY_ALIAS) and the standard SHIPIT_ form (SHIPIT_ANDROID__KEYSTORE_PASSWORD, SHIPIT_ANDROID__KEY_PASSWORD, SHIPIT_ANDROID__KEY_ALIAS). The short forms are checked as a compatibility fallback when the SHIPIT_ names are not set.

ios

Platform-specific iOS overrides. Merged on top of shared config when --platform ios is active. All top-level app, code_signing, archive, export, testflight, and screenshots keys can appear here to override the shared defaults for iOS only.

KeyTypeDefaultEnv VarDescription
build_systemstringnativeSHIPIT_IOS__BUILD_SYSTEMnative, flutter, react_native, or kmp. See Build systems.
kmp_shared_modulestringsharedSHIPIT_IOS__KMP_SHARED_MODULEGradle module containing KMP framework/test tasks
kmp_build_targetstringIosSimulatorArm64SHIPIT_IOS__KMP_BUILD_TARGETKMP target linked before local xcodebuild build
kmp_archive_targetstringIosArm64SHIPIT_IOS__KMP_ARCHIVE_TARGETKMP target linked before xcodebuild archive
kmp_test_taskstringiosSimulatorArm64TestSHIPIT_IOS__KMP_TEST_TASKKMP Gradle task used by shipit test --platform ios
schemestringSHIPIT_IOS__SCHEMEiOS-specific Xcode scheme override
workspacestringSHIPIT_IOS__WORKSPACEiOS-specific Xcode workspace override
projectstringSHIPIT_IOS__PROJECTiOS-specific Xcode project override
ios:
  build_system: native # native (default) | flutter | react_native | kmp
  scheme: MyApp
archive:
  export_method: app-store

Build systems

build_system is orthogonal to platform: a single Kotlin Multiplatform or Flutter source tree can produce both an iOS .ipa and an Android .aab.

ValueiOS compilationAndroid compilation
nativexcodebuildgradlew assemble / bundle
kmplink KMP shared framework via Gradle → xcodebuildgradlew :androidApp:assembleRelease / bundleRelease
flutterflutter build ipa (IPA at build/ios/ipa/)flutter build apk / flutter build appbundle
react_nativeMetro bundle → xcodebuild archive + exportnpx react-native build-android --tasks bundleRelease

Auto-detection

When build_system is unset, ShipItSwifty resolves it automatically:

Project markerDetected value
pubspec.yaml with a flutter: keyflutter
package.json declaring react-native in dependenciesreact_native
build.gradle.kts applying kotlin("multiplatform")kmp
None of the abovenative

KMP example

ios:
  build_system: kmp
  scheme: iosApp
  workspace: iosApp/iosApp.xcworkspace
  kmp_shared_module: shared
  kmp_build_target: IosSimulatorArm64
  kmp_archive_target: IosArm64
android:
  build_system: kmp
  module: androidApp
  gradle_project_dir: .
versioning:
  source: kmp
  spec_path: gradle.properties

coverage action options

The coverage action reads native coverage artifacts — it does not generate them.

OptionTypeDefaultDescription
platformstringauto-detectedios or android
xcresultstringauto-discoveredExplicit .xcresult bundle path (iOS)
reportstringauto-discoveredExplicit JaCoCo XML report path (Android)
first_party_onlybooltrueSuppress test bundles, SPM deps, and known vendor prefixes
targetsboolfalseShow per-target (iOS) or per-module (Android) breakdown
filesboolfalseShow per-file breakdown
include_targetlist[]Include only these targets (overrides first-party filter)
exclude_targetlist[]Exclude specific targets
sortstringcoveragecoverage (lowest first — most actionable) or name
limitintCap number of entries shown
formatstringtexttext, json, or markdown