[GH-ISSUE #765] publish testflight: add --build flag to distribute an already-uploaded build #209

Closed
opened 2026-02-26 21:34:01 +03:00 by kerem · 0 comments
Owner

Originally created by @mithileshchellappan on GitHub (Feb 24, 2026).
Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/765

Summary

Add a `--build` flag to `publish testflight` that skips the upload step and distributes an existing build, enabling the full publish workflow for builds uploaded externally.

Problem

`publish testflight` currently requires `--ipa` and always performs an upload (line 153 in `publish.go` calls `uploadBuildAndWaitForID()`). There is no way to use the command with a build that was already uploaded via:

  • `xcodebuild -exportArchive` with `destination: upload` (preferred for automatic signing/provisioning)
  • Xcode Cloud
  • `asc builds upload` (separate step)
  • Another CI system

This means the excellent post-upload workflow in `publish testflight` (wait for processing → add test notes → add to groups → notify testers) cannot be reused. Agents must manually replicate each step:

# Current workaround after external upload
# 1. Find the build
asc pre-release-versions builds list --id VERSION_ID  # find build ID
# 2. Wait for processing (no standalone command)
while ...; do sleep 30; done
# 3. Add test notes
asc beta-build-localizations update --id LOC_ID --whats-new "notes"
# 4. Distribute
asc builds add-groups --build BUILD_ID --group GROUP_ID

Proposal

# Distribute an already-uploaded build (by build ID)
asc publish testflight \
  --app APP_ID \
  --build BUILD_ID \
  --group "Friends & Family" \
  --test-notes "What to test..." \
  --wait \
  --notify

# Distribute by build number (resolved automatically)
asc publish testflight \
  --app APP_ID \
  --build-number 28 \
  --group "Friends & Family" \
  --test-notes "What to test..." \
  --wait \
  --notify

Behavior

When `--build` or `--build-number` is provided instead of `--ipa`:

  1. Skip upload — resolve the build by ID or number
  2. Wait for processing (if `--wait`) — reuse existing wait logic
  3. Add test notes (if `--test-notes`) — reuse existing `UpsertBetaBuildLocalization`
  4. Add to groups — reuse existing group assignment
  5. Notify testers (if `--notify`)

The `--ipa` flag becomes optional when `--build` or `--build-number` is provided. The two modes are mutually exclusive.

Flag Changes

Flag Change
`--ipa` Optional (required only if `--build`/`--build-number` not set)
`--build` New — Build UUID to distribute
`--build-number` New — CFBundleVersion to resolve and distribute

Implementation

In `internal/cli/publish/publish.go`, the `testflight` handler should:

  1. Check if `--build` or `--build-number` is set
  2. If so, skip `uploadBuildAndWaitForID()` and resolve the build directly
  3. For `--build-number`, use the existing `findBuildByNumber()` from `internal/cli/shared/build_wait.go`
  4. Continue with the rest of the existing flow (wait, test notes, groups, notify)

Acceptance Criteria

  • `asc publish testflight --build BUILD_ID --app APP_ID --group GROUP_ID` distributes without uploading
  • `asc publish testflight --build-number 28 --app APP_ID --group GROUP_ID` resolves and distributes
  • `--wait` still works (waits for PROCESSING → VALID transition)
  • `--test-notes` still works via upsert
  • Error if both `--ipa` and `--build`/`--build-number` are provided
  • Error if neither `--ipa` nor `--build`/`--build-number` is provided
  • Existing `--ipa` behavior unchanged
  • Tests pass with `ASC_BYPASS_KEYCHAIN=1`

Use Case

Many teams use `xcodebuild -exportArchive -allowProvisioningUpdates` for uploads because it handles automatic signing and provisioning profile resolution better than standalone upload tools. These teams want to use `asc` for the distribution step without re-uploading. This flag bridges that gap and makes `publish testflight` the single command for TestFlight distribution regardless of how the build was uploaded.

Originally created by @mithileshchellappan on GitHub (Feb 24, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/765 ## Summary Add a \`--build\` flag to \`publish testflight\` that skips the upload step and distributes an existing build, enabling the full publish workflow for builds uploaded externally. ## Problem \`publish testflight\` currently **requires \`--ipa\`** and always performs an upload (line 153 in \`publish.go\` calls \`uploadBuildAndWaitForID()\`). There is no way to use the command with a build that was already uploaded via: - \`xcodebuild -exportArchive\` with \`destination: upload\` (preferred for automatic signing/provisioning) - Xcode Cloud - \`asc builds upload\` (separate step) - Another CI system This means the excellent post-upload workflow in \`publish testflight\` (wait for processing → add test notes → add to groups → notify testers) cannot be reused. Agents must manually replicate each step: ```bash # Current workaround after external upload # 1. Find the build asc pre-release-versions builds list --id VERSION_ID # find build ID # 2. Wait for processing (no standalone command) while ...; do sleep 30; done # 3. Add test notes asc beta-build-localizations update --id LOC_ID --whats-new "notes" # 4. Distribute asc builds add-groups --build BUILD_ID --group GROUP_ID ``` ## Proposal ```bash # Distribute an already-uploaded build (by build ID) asc publish testflight \ --app APP_ID \ --build BUILD_ID \ --group "Friends & Family" \ --test-notes "What to test..." \ --wait \ --notify # Distribute by build number (resolved automatically) asc publish testflight \ --app APP_ID \ --build-number 28 \ --group "Friends & Family" \ --test-notes "What to test..." \ --wait \ --notify ``` ### Behavior When \`--build\` or \`--build-number\` is provided instead of \`--ipa\`: 1. **Skip upload** — resolve the build by ID or number 2. **Wait for processing** (if \`--wait\`) — reuse existing wait logic 3. **Add test notes** (if \`--test-notes\`) — reuse existing \`UpsertBetaBuildLocalization\` 4. **Add to groups** — reuse existing group assignment 5. **Notify testers** (if \`--notify\`) The \`--ipa\` flag becomes optional when \`--build\` or \`--build-number\` is provided. The two modes are mutually exclusive. ### Flag Changes | Flag | Change | |------|--------| | \`--ipa\` | Optional (required only if \`--build\`/\`--build-number\` not set) | | \`--build\` | New — Build UUID to distribute | | \`--build-number\` | New — CFBundleVersion to resolve and distribute | ### Implementation In \`internal/cli/publish/publish.go\`, the \`testflight\` handler should: 1. Check if \`--build\` or \`--build-number\` is set 2. If so, skip \`uploadBuildAndWaitForID()\` and resolve the build directly 3. For \`--build-number\`, use the existing \`findBuildByNumber()\` from \`internal/cli/shared/build_wait.go\` 4. Continue with the rest of the existing flow (wait, test notes, groups, notify) ## Acceptance Criteria - \`asc publish testflight --build BUILD_ID --app APP_ID --group GROUP_ID\` distributes without uploading - \`asc publish testflight --build-number 28 --app APP_ID --group GROUP_ID\` resolves and distributes - \`--wait\` still works (waits for PROCESSING → VALID transition) - \`--test-notes\` still works via upsert - Error if both \`--ipa\` and \`--build\`/\`--build-number\` are provided - Error if neither \`--ipa\` nor \`--build\`/\`--build-number\` is provided - Existing \`--ipa\` behavior unchanged - Tests pass with \`ASC_BYPASS_KEYCHAIN=1\` ## Use Case Many teams use \`xcodebuild -exportArchive -allowProvisioningUpdates\` for uploads because it handles automatic signing and provisioning profile resolution better than standalone upload tools. These teams want to use \`asc\` for the distribution step without re-uploading. This flag bridges that gap and makes \`publish testflight\` the single command for TestFlight distribution regardless of how the build was uploaded.
kerem closed this issue 2026-02-26 21:34:01 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/App-Store-Connect-CLI#209
No description provided.