[GH-ISSUE #487] Builds Latest: add --next to return collision-safe next build number #139

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

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

Summary

Add --next to asc builds latest so CI can request a safe next build number (latest + 1) that accounts for both processed builds and in-flight uploads.

Why this matters

Parallel pipelines can race when only processed builds are considered.
If an upload is in progress but not yet reflected in processed builds, the next job can reuse the same build number and fail.

Current state (verified)

  • internal/cli/builds/builds_latest.go computes latest from builds endpoints only.
  • In-flight upload data is available via GetBuildUploads in internal/asc/client_builds.go but is not included in latest-number logic.

Proposed UX

asc builds latest --app "APP_ID" --version "1.2.3" --platform IOS --next

Behavior:

  • without --next: existing output remains unchanged
  • with --next: return a structured payload including:
    • latestProcessedBuildNumber
    • latestUploadBuildNumber
    • latestObservedBuildNumber
    • nextBuildNumber
    • sourcesConsidered

Optional support:

  • --initial-build-number (default 1) when no prior builds/uploads exist

Selection algorithm

  1. Resolve latest processed build number using existing filters (app, version, platform)
  2. Query matching build uploads and include relevant states (e.g. AWAITING_UPLOAD, PROCESSING, COMPLETE)
  3. Parse numeric build numbers from both sources
  4. Compute max observed build number and return max + 1

If non-numeric build numbers are encountered, return an explicit, actionable error.

Detailed implementation plan

  • Add --next (and optional --initial-build-number) flags to internal/cli/builds/builds_latest.go.
  • Add helper(s) for numeric build number parsing/comparison with clear error messages.
  • Add build-upload query branch with version/platform filters using existing ASC options.
  • Add new output type for next-build response in internal/asc/output_builds.go (or equivalent output file).
  • Keep existing builds latest response contract unchanged when --next is absent.
  • Add tests in:
    • internal/cli/builds/builds_latest_test.go for flag validation
    • internal/cli/cmdtest/builds_latest_output_test.go for race-condition scenarios
    • ASC client-level tests if additional query/filter behavior is added

Acceptance criteria

  • asc builds latest --next returns next build number based on processed + in-flight uploads.
  • Parallel-upload race is prevented in covered test scenarios.
  • Non-numeric build numbers produce clear errors.
  • Default behavior of asc builds latest remains backward-compatible.
  • make test passes with expanded build-number coverage.
Originally created by @rudrankriyam on GitHub (Feb 10, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/487 ## Summary Add `--next` to `asc builds latest` so CI can request a safe next build number (`latest + 1`) that accounts for both processed builds and in-flight uploads. ## Why this matters Parallel pipelines can race when only processed builds are considered. If an upload is in progress but not yet reflected in processed builds, the next job can reuse the same build number and fail. ## Current state (verified) - `internal/cli/builds/builds_latest.go` computes latest from builds endpoints only. - In-flight upload data is available via `GetBuildUploads` in `internal/asc/client_builds.go` but is not included in latest-number logic. ## Proposed UX ```bash asc builds latest --app "APP_ID" --version "1.2.3" --platform IOS --next ``` Behavior: - without `--next`: existing output remains unchanged - with `--next`: return a structured payload including: - `latestProcessedBuildNumber` - `latestUploadBuildNumber` - `latestObservedBuildNumber` - `nextBuildNumber` - `sourcesConsidered` Optional support: - `--initial-build-number` (default `1`) when no prior builds/uploads exist ### Selection algorithm 1. Resolve latest processed build number using existing filters (`app`, `version`, `platform`) 2. Query matching build uploads and include relevant states (e.g. `AWAITING_UPLOAD`, `PROCESSING`, `COMPLETE`) 3. Parse numeric build numbers from both sources 4. Compute max observed build number and return max + 1 If non-numeric build numbers are encountered, return an explicit, actionable error. ## Detailed implementation plan - [ ] Add `--next` (and optional `--initial-build-number`) flags to `internal/cli/builds/builds_latest.go`. - [ ] Add helper(s) for numeric build number parsing/comparison with clear error messages. - [ ] Add build-upload query branch with version/platform filters using existing ASC options. - [ ] Add new output type for next-build response in `internal/asc/output_builds.go` (or equivalent output file). - [ ] Keep existing `builds latest` response contract unchanged when `--next` is absent. - [ ] Add tests in: - [ ] `internal/cli/builds/builds_latest_test.go` for flag validation - [ ] `internal/cli/cmdtest/builds_latest_output_test.go` for race-condition scenarios - [ ] ASC client-level tests if additional query/filter behavior is added ## Acceptance criteria - [ ] `asc builds latest --next` returns next build number based on processed + in-flight uploads. - [ ] Parallel-upload race is prevented in covered test scenarios. - [ ] Non-numeric build numbers produce clear errors. - [ ] Default behavior of `asc builds latest` remains backward-compatible. - [ ] `make test` passes with expanded build-number coverage.
kerem 2026-02-26 21:33:44 +03:00
Author
Owner

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

@cursor Please implement this issue end-to-end.

What to build

Add --next to asc builds latest so CI can get a collision-safe next build number derived from both processed builds and in-flight uploads.

Implementation plan

  1. CLI flag + behavior
  • internal/cli/builds/builds_latest.go
    • Add --next.
    • Optional --initial-build-number fallback when no prior numbers exist.
  • Preserve existing output contract when --next is not set.
  1. Observed-number computation
  • Source A: processed builds (existing latest logic)
  • Source B: build uploads via GetBuildUploads with relevant filters/states
  • Parse numeric build numbers and compute max observed + 1.
  1. Filtering and compatibility
  • Respect existing --app, --version, --platform semantics.
  • Ensure consistent behavior when one source has data and the other does not.
  1. Output shape for next mode
  • include:
    • latestProcessedBuildNumber
    • latestUploadBuildNumber
    • latestObservedBuildNumber
    • nextBuildNumber
    • sourcesConsidered
  1. Error handling
  • non-numeric build numbers return clear actionable errors
  • malformed/missing values are handled deterministically

New tests to write

A) CLI unit tests (internal/cli/builds/builds_latest_test.go)

  • flag validation for --next and fallback behavior
  • non-numeric build number error path

B) Cmdtests (internal/cli/cmdtest/builds_latest_output_test.go)

  • race scenario where upload number > processed number
  • processed-only and uploads-only scenarios
  • no-history scenario uses --initial-build-number

C) ASC query tests (if needed)

  • verify build uploads query filters/states used for next-number logic

How to test locally

Run exactly:

  • make format
  • make lint
  • make test

Targeted tests:

  • go test ./internal/cli/builds -run 'Latest.*Next|BuildNumber'
  • go test ./internal/cli/cmdtest -run 'BuildsLatest'

Done criteria

  • asc builds latest --next returns collision-safe next number.
  • Existing asc builds latest behavior remains unchanged by default.
  • In-flight upload scenarios are covered by tests.
  • All checks pass (format, lint, test).
<!-- gh-comment-id:3881459354 --> @rudrankriyam commented on GitHub (Feb 11, 2026): @cursor Please implement this issue end-to-end. ## What to build Add `--next` to `asc builds latest` so CI can get a collision-safe next build number derived from both processed builds and in-flight uploads. ## Implementation plan 1. **CLI flag + behavior** - `internal/cli/builds/builds_latest.go` - Add `--next`. - Optional `--initial-build-number` fallback when no prior numbers exist. - Preserve existing output contract when `--next` is not set. 2. **Observed-number computation** - Source A: processed builds (existing latest logic) - Source B: build uploads via `GetBuildUploads` with relevant filters/states - Parse numeric build numbers and compute max observed + 1. 3. **Filtering and compatibility** - Respect existing `--app`, `--version`, `--platform` semantics. - Ensure consistent behavior when one source has data and the other does not. 4. **Output shape for next mode** - include: - `latestProcessedBuildNumber` - `latestUploadBuildNumber` - `latestObservedBuildNumber` - `nextBuildNumber` - `sourcesConsidered` 5. **Error handling** - non-numeric build numbers return clear actionable errors - malformed/missing values are handled deterministically ## New tests to write ### A) CLI unit tests (`internal/cli/builds/builds_latest_test.go`) - flag validation for `--next` and fallback behavior - non-numeric build number error path ### B) Cmdtests (`internal/cli/cmdtest/builds_latest_output_test.go`) - race scenario where upload number > processed number - processed-only and uploads-only scenarios - no-history scenario uses `--initial-build-number` ### C) ASC query tests (if needed) - verify build uploads query filters/states used for next-number logic ## How to test locally Run exactly: - `make format` - `make lint` - `make test` Targeted tests: - `go test ./internal/cli/builds -run 'Latest.*Next|BuildNumber'` - `go test ./internal/cli/cmdtest -run 'BuildsLatest'` ## Done criteria - `asc builds latest --next` returns collision-safe next number. - Existing `asc builds latest` behavior remains unchanged by default. - In-flight upload scenarios are covered by tests. - All checks pass (`format`, `lint`, `test`).
Author
Owner

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

Summary:

  • I added --next/--initial-build-number handling in asc builds latest, including build upload checks, numeric validation, and a new structured next-build payload + table/markdown rows, plus tests that cover processed-only, uploads-only, and no-history scenarios.
type BuildsLatestNextResult struct {
	LatestProcessedBuildNumber *string  `json:"latestProcessedBuildNumber"`
	LatestUploadBuildNumber    *string  `json:"latestUploadBuildNumber"`
	LatestObservedBuildNumber  *string  `json:"latestObservedBuildNumber"`
	NextBuildNumber            string   `json:"nextBuildNumber"`
	SourcesConsidered          []string `json:"sourcesConsidered"`
}

Tests & verification:

  • go test ./internal/cli/builds -run 'Latest.*Next|BuildNumber'
  • go test ./internal/cli/cmdtest -run 'BuildsLatest'
  • go build -o /tmp/asc . and /tmp/asc builds latest --app "app-1" --next --initial-build-number 0 (exit code 2, expected validation error)
  • PATH="$PATH:/home/ubuntu/go/bin" make format
  • PATH="$PATH:/home/ubuntu/go/bin" make lint (after reinstalling golangci-lint with Go 1.26)
  • PATH="$PATH:/home/ubuntu/go/bin" make test
  • Note: make format initially failed due to missing gofumpt, fixed via make tools, and lint required reinstalling golangci-lint using GOTOOLCHAIN=go1.26.0.

Artifact:

  • Video walkthrough (cmdtest run): builds_latest_next_cmdtest/recording_demo.mp4

View PR

Open in Cursor Open in Web

<!-- gh-comment-id:3881459625 --> @cursor[bot] commented on GitHub (Feb 11, 2026): Summary: - I added `--next`/`--initial-build-number` handling in `asc builds latest`, including build upload checks, numeric validation, and a new structured next-build payload + table/markdown rows, plus tests that cover processed-only, uploads-only, and no-history scenarios. ```40:46:internal/asc/output_builds.go type BuildsLatestNextResult struct { LatestProcessedBuildNumber *string `json:"latestProcessedBuildNumber"` LatestUploadBuildNumber *string `json:"latestUploadBuildNumber"` LatestObservedBuildNumber *string `json:"latestObservedBuildNumber"` NextBuildNumber string `json:"nextBuildNumber"` SourcesConsidered []string `json:"sourcesConsidered"` } ``` Tests & verification: - `go test ./internal/cli/builds -run 'Latest.*Next|BuildNumber'` - `go test ./internal/cli/cmdtest -run 'BuildsLatest'` - `go build -o /tmp/asc .` and `/tmp/asc builds latest --app "app-1" --next --initial-build-number 0` (exit code 2, expected validation error) - `PATH="$PATH:/home/ubuntu/go/bin" make format` - `PATH="$PATH:/home/ubuntu/go/bin" make lint` (after reinstalling golangci-lint with Go 1.26) - `PATH="$PATH:/home/ubuntu/go/bin" make test` - Note: `make format` initially failed due to missing gofumpt, fixed via `make tools`, and lint required reinstalling golangci-lint using `GOTOOLCHAIN=go1.26.0`. Artifact: - Video walkthrough (cmdtest run): `builds_latest_next_cmdtest/recording_demo.mp4` <p><a href="https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/489"><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/background-agent?bcId=bc-d82958f4-c6ba-4ddc-8a2a-68b1a46851b0"><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;<a href="https://cursor.com/agents?id=bc-d82958f4-c6ba-4ddc-8a2a-68b1a46851b0"><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></p>
Author
Owner

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

Resolved by PR #489 (https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/489), which is merged into main.

<!-- gh-comment-id:3887482001 --> @rudrankriyam commented on GitHub (Feb 11, 2026): Resolved by PR #489 (https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/489), which is merged into main.
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#139
No description provided.