[GH-ISSUE #727] builds latest: add --exclude-expired for deterministic latest/next build numbers #197

Closed
opened 2026-02-26 21:33:58 +03:00 by kerem · 2 comments
Owner

Originally created by @cursor[bot] on GitHub (Feb 22, 2026).
Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/727

Summary

Add a new --exclude-expired flag to asc builds latest so expired builds are ignored when returning the latest build and when computing --next build numbers.

Problem

Teams using Fastlane/TestFlight frequently hit build-number instability when expired builds are included in latest-build queries.

Related upstream pain points:

asc builds latest already supports deterministic filters (--version, --platform) and --next, but does not currently expose a way to exclude expired builds.

Proposal

Add a boolean flag:

  • --exclude-expired (default false)

Behavior:

  1. Without --next:
    • Return the latest build matching existing filters and expired=false when --exclude-expired is set.
  2. With --next:
    • Compute LatestProcessedBuildNumber using the same expired filter semantics.
    • Continue considering in-flight build uploads for collision safety.

API support

OpenAPI for /v1/builds supports filter[expired], so this should be implemented server-side in client query/options plumbing and used by builds latest fetches.

Scope

  • internal/asc: add builds query option for expired filter(s)
  • internal/cli/builds/builds_latest.go: thread new flag through all latest build fetch branches
  • tests: add CLI/cmdtest and unit tests for valid + invalid flag behavior and output expectations

Acceptance criteria

  • asc builds latest --exclude-expired never returns an expired latest build when non-expired builds exist
  • asc builds latest --next --exclude-expired computes next number from non-expired processed builds + uploads
  • Existing behavior unchanged when flag is not set
  • Help text includes new flag and example
  • Targeted tests pass with ASC_BYPASS_KEYCHAIN=1

Suggested tests

  • New flag valid-path tests
  • New flag invalid-value tests (assert stderr and exit code 2)
  • Regression test: expired newest build + older non-expired build => non-expired selected with flag
  • Regression test: --next honors exclude-expired

Notes

This is intentionally a focused, low-risk enhancement that maps directly to recurring ASC/TestFlight workflow pain.

Originally created by @cursor[bot] on GitHub (Feb 22, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/727 ## Summary Add a new `--exclude-expired` flag to `asc builds latest` so expired builds are ignored when returning the latest build and when computing `--next` build numbers. ## Problem Teams using Fastlane/TestFlight frequently hit build-number instability when expired builds are included in latest-build queries. Related upstream pain points: - https://github.com/fastlane/fastlane/issues/29529 (expired builds included) - https://github.com/fastlane/fastlane/issues/29908 (latest build regression) `asc builds latest` already supports deterministic filters (`--version`, `--platform`) and `--next`, but does not currently expose a way to exclude expired builds. ## Proposal Add a boolean flag: - `--exclude-expired` (default `false`) Behavior: 1. Without `--next`: - Return the latest build matching existing filters and `expired=false` when `--exclude-expired` is set. 2. With `--next`: - Compute `LatestProcessedBuildNumber` using the same expired filter semantics. - Continue considering in-flight build uploads for collision safety. ## API support OpenAPI for `/v1/builds` supports `filter[expired]`, so this should be implemented server-side in client query/options plumbing and used by `builds latest` fetches. ## Scope - `internal/asc`: add builds query option for expired filter(s) - `internal/cli/builds/builds_latest.go`: thread new flag through all latest build fetch branches - tests: add CLI/cmdtest and unit tests for valid + invalid flag behavior and output expectations ## Acceptance criteria - `asc builds latest --exclude-expired` never returns an expired latest build when non-expired builds exist - `asc builds latest --next --exclude-expired` computes next number from non-expired processed builds + uploads - Existing behavior unchanged when flag is not set - Help text includes new flag and example - Targeted tests pass with `ASC_BYPASS_KEYCHAIN=1` ## Suggested tests - New flag valid-path tests - New flag invalid-value tests (assert stderr and exit code 2) - Regression test: expired newest build + older non-expired build => non-expired selected with flag - Regression test: `--next` honors exclude-expired ## Notes This is intentionally a focused, low-risk enhancement that maps directly to recurring ASC/TestFlight workflow pain.
kerem closed this issue 2026-02-26 21:33:58 +03:00
Author
Owner

@rudrankriyam commented on GitHub (Feb 22, 2026):

@cursor please implement this

<!-- gh-comment-id:3940413391 --> @rudrankriyam commented on GitHub (Feb 22, 2026): @cursor please implement this
Author
Owner

@cursor[bot] commented on GitHub (Feb 22, 2026):

Implemented end-to-end on cursor/builds-latest-expired-filter-7e49 and pushed in 3 commits (8e9d8b9, b2faf5d, e7eb705):

  • Added new CLI flag --exclude-expired to asc builds latest with help text + example updates (internal/cli/builds/builds_latest.go).
  • Threaded expired filtering through all latest-build fetch paths (no pre-release filter, single pre-release, multi pre-release), so both normal latest and --next processed-build calculations honor expired=false when requested.
  • Added ASC client support for expired filtering:
    • buildsQuery.expired *bool
    • new option WithBuildsExpired(bool)
    • GetBuilds now serializes filter[expired] and correctly uses /v1/builds when this filter is set.
  • Kept default behavior unchanged when --exclude-expired is not passed.

I also added/updated tests for valid and invalid behavior:

  • Client/unit coverage for new option/query wiring (internal/asc/client_test.go, internal/asc/client_http_test.go).
  • Builds latest flag/help coverage (internal/cli/builds/builds_latest_test.go).
  • Cmdtest regressions for:
    • latest with --exclude-expired
    • --next --exclude-expired honoring processed-build filter semantics
      (internal/cli/cmdtest/builds_latest_output_test.go).
  • Invalid-value exit behavior (--exclude-expired=maybe) validated via built-binary subprocess test asserting stderr + exit code 2 (cmd/exit_codes_test.go).

Validation performed:

  • make format
  • make lint
  • ASC_BYPASS_KEYCHAIN=1 make test
  • plus focused targeted tests for new coverage.
    Walkthrough artifacts:

View PR

Open in Web Open in Cursor 

<!-- gh-comment-id:3940413460 --> @cursor[bot] commented on GitHub (Feb 22, 2026): Implemented end-to-end on `cursor/builds-latest-expired-filter-7e49` and pushed in 3 commits (`8e9d8b9`, `b2faf5d`, `e7eb705`): - Added new CLI flag `--exclude-expired` to `asc builds latest` with help text + example updates (`internal/cli/builds/builds_latest.go`). - Threaded expired filtering through all latest-build fetch paths (no pre-release filter, single pre-release, multi pre-release), so both normal latest and `--next` processed-build calculations honor `expired=false` when requested. - Added ASC client support for expired filtering: - `buildsQuery.expired *bool` - new option `WithBuildsExpired(bool)` - `GetBuilds` now serializes `filter[expired]` and correctly uses `/v1/builds` when this filter is set. - Kept default behavior unchanged when `--exclude-expired` is not passed. I also added/updated tests for valid and invalid behavior: - Client/unit coverage for new option/query wiring (`internal/asc/client_test.go`, `internal/asc/client_http_test.go`). - Builds latest flag/help coverage (`internal/cli/builds/builds_latest_test.go`). - Cmdtest regressions for: - latest with `--exclude-expired` - `--next --exclude-expired` honoring processed-build filter semantics (`internal/cli/cmdtest/builds_latest_output_test.go`). - Invalid-value exit behavior (`--exclude-expired=maybe`) validated via built-binary subprocess test asserting stderr + exit code `2` (`cmd/exit_codes_test.go`). Validation performed: - `make format` - `make lint` - `ASC_BYPASS_KEYCHAIN=1 make test` - plus focused targeted tests for new coverage. Walkthrough artifacts: <artifact path="/opt/cursor/artifacts/builds_latest_exclude_expired_walkthrough.txt"></artifact> <artifact path="/opt/cursor/artifacts/builds_latest_exclude_expired_full_checks.txt"></artifact> <p><a href="https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/728"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/view-pr-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/view-pr-light.png"><img alt="View PR" width="86" height="28" src="https://cursor.com/assets/images/view-pr-light.png"></picture></a></p> <p><a href="https://cursor.com/agents?id=bc-76248876-13c2-46d5-943d-4fe33de1b0d7"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-76248876-13c2-46d5-943d-4fe33de1b0d7"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</p>
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#197
No description provided.