How do I automatically submit and release production apps to the App Store and Google Play from my Codemagic pipeline?

Last updated: August 3, 2026

Context

When publishing apps to the App Store and Google Play, you may want your Codemagic pipeline to automatically submit builds for production review and release them after approval — without any manual steps in the store consoles. This article covers how to configure this, including scenarios where the submission decision needs to be made dynamically at runtime (e.g., based on whether a live version already exists in the store).

Answer

There are two approaches depending on whether your submission logic is static or determined at runtime during the build.

Option 1: Static configuration via the publishing block

If your submission settings are fixed and do not need to change based on runtime conditions, you can configure the publishing section of your codemagic.yaml directly:

publishing:
  app_store_connect:
    auth: integration
    submit_to_testflight: true
    submit_to_app_store: true      # sends the build to App Store review, not just TestFlight
    release_type: AFTER_APPROVAL   # MANUAL (default), AFTER_APPROVAL, or SCHEDULED

  google_play:
    credentials: $GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS
    track: production
    submit_as_draft: false         # set to false so the build is submitted, not left as a draft

Key points:

  • iOS: Setting submit_to_app_store: true pushes the build to full App Store review rather than stopping at TestFlight. Setting release_type: AFTER_APPROVAL makes the version go live automatically once Apple approves it. Other options are MANUAL (you release it yourself) and SCHEDULED (release on a date set via earliest_release_date). See the App Store Connect publishing docs for more details.

  • Android: Ensure $GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS is set as a secure environment variable containing the JSON key for your Google Play service account. See the Google Play publishing docs for setup instructions. Note that whether an approved release goes live automatically is also controlled by the Managed publishing setting in the Play Console — if Managed publishing is off, changes are published as soon as Google approves them; if it's on, you must manually publish from the Publishing overview page.

Important: Environment variables used in the publishing block must be defined statically under the environment.vars section of your workflow. They cannot be set or overridden by scripts running during the build, as the publishing block is evaluated as a pre-build configuration. For example:

environment:
  vars:
    SUBMIT_TO_APP_STORE: true
publishing:
  app_store_connect:
    auth: integration
    submit_to_app_store: $SUBMIT_TO_APP_STORE

If you need to toggle these values without editing the YAML, you can pass them in the API trigger payload when starting a build — variables provided at trigger time are available at build start and will resolve correctly in the publishing block.

Option 2: Runtime submission using Codemagic CLI tools

If your submission decision depends on runtime conditions (e.g., checking whether a live version already exists in the store), you should remove the publishing block and handle submission directly in a build script using the Codemagic CLI tools, which are pre-installed on the build VM.

For iOS, add a script step after your build:

PUBLISH_FLAGS="--testflight"
LIVE_BUILD=$(app-store-connect get-latest-app-store-build-number "$APP_APPLE_ID" || true)
if [ -n "$LIVE_BUILD" ]; then
  PUBLISH_FLAGS="$PUBLISH_FLAGS --app-store --release-type AFTER_APPROVAL"
fi
app-store-connect publish --path "build/ios/ipa/*.ipa" $PUBLISH_FLAGS

The --app-store flag pushes the build to full App Store review instead of stopping at TestFlight. The --release-type AFTER_APPROVAL flag makes it go live automatically once Apple approves.

For Android, add a script step after your build:

DRAFT_FLAG="--draft"
PRODUCTION_BUILD=$(google-play get-latest-build-number --package-name "$BUNDLE_IDENTIFIER" --tracks production)
if [ -n "$PRODUCTION_BUILD" ]; then
  DRAFT_FLAG=""   # omit --draft so it's a real submission, not a draft
fi

google-play bundles publish \
  --bundle "android/app/build/outputs/**/*.aab" \
  --track production \
  $DRAFT_FLAG

Important: If you switch to the CLI approach, make sure to remove the corresponding publishing: block from your YAML — otherwise the build will submit to the store twice.

For further reference, see the CLI tool documentation for app-store-connect publish and google-play bundles publish.