[GH-ISSUE #560] TestFlight beta testers: add CSV export/import commands #153

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

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

Summary

Add first-class, non-interactive CSV workflows for TestFlight beta testers:

  • asc testflight beta-testers export (write testers to a CSV file)
  • asc testflight beta-testers import (read testers from a CSV file and apply changes)

These commands should be designed for automation (JSON-first, deterministic, no prompts) while still producing a human-editable CSV artifact.

Why this matters

Managing testers is one of the most common operational workflows for TestFlight:

  • backing up/auditing current tester lists
  • moving testers between apps/accounts
  • bulk onboarding external testers
  • CI-driven “invite + assign to group” workflows

Today, users can script this via asc testflight beta-testers list JSON output, but there is no stable, file-based interchange format.

Current state (verified)

  • asc testflight beta-testers list/get/add/remove/invite/... exists.
  • No import/export subcommands exist in internal/cli/testflight/beta_testers.go.
  • Output formats (json/table/markdown) are good for stdout, but not for a file artifact that can be reviewed/edited and re-applied.

Proposed UX

Export

asc testflight beta-testers export \
  --app "APP_ID" \
  --output "./testflight-testers.csv"

# Optional: export a filtered subset
asc testflight beta-testers export --app "APP_ID" --group "Beta" --output ./testers.csv

Flags (proposal):

  • --app (required; respects ASC_APP_ID like other commands)
  • --output (required; path to write CSV)
  • --group, --build, --email (reuse the same filter semantics as list)
  • --format json|table|markdown (summary output only; default json)
  • --pretty (when --format json)
  • --include-groups (optional; adds a groups column, requires additional API calls)

Behavior:

  • Export should be stable/deterministic (consistent column ordering, consistent row ordering).
  • Export should fetch all pages by default (it is an export command, not a single-page list).

Import

# Dry-run plan first
asc testflight beta-testers import \
  --app "APP_ID" \
  --input "./testflight-testers.csv" \
  --dry-run

# Apply (create missing testers + assign to groups)
asc testflight beta-testers import \
  --app "APP_ID" \
  --input "./testflight-testers.csv"

# Apply + invite testers (explicit opt-in)
asc testflight beta-testers import \
  --app "APP_ID" \
  --input "./testflight-testers.csv" \
  --invite

Flags (proposal):

  • --app (required)
  • --input (required; CSV file path)
  • --dry-run (no network mutations; prints plan + validation results)
  • --invite (send invites for newly added testers; default false)
  • --group "..." (optional; apply a group to all imported testers)
  • --skip-existing (optional; if tester email already exists, don’t modify group membership)
  • --continue-on-error (optional; default true; aggregate row errors and return non-zero at end)
  • --format json|table|markdown and --pretty (summary output)

Behavior:

  • Import should be idempotent and safe to re-run.
  • Import should produce row-level results (created/existed/updated/invited/failed) and return non-zero if any row fails.
  • No interactive prompts.

CSV schema

Minimal schema (phase 1)

Header required:

  • email

Optional columns:

  • first_name
  • last_name
  • groups (comma-separated group names/IDs)

Notes:

  • email is the stable identity key.
  • If groups values are names, resolve them deterministically (same semantics as existing --group flags).
  • Unknown columns should be rejected with a usage error (exit code 2), not silently ignored.

Output model

JSON (default)

Return a structured summary object that includes:

  • output_file / input_file
  • counts: total, created, existed, updated, invited, failed
  • failures[]: row index, email, error message

This allows an agent/CI pipeline to reliably drive remediation.

Detailed implementation plan (TDD-first)

  • Add new subcommands to internal/cli/testflight/beta_testers.go:
    • export
    • import
  • Add CSV helpers (parse + write) under internal/cli/shared/ (or a small internal/csvutil/ package if preferred).
  • Export implementation:
    • fetch testers (all pages)
    • normalize/sort rows
    • write CSV atomically (reject symlink output paths)
  • Import implementation:
    • parse + validate CSV
    • prefetch existing testers (email -> id) for the app (single paginated fetch)
    • create missing testers via existing client methods
    • add to groups (from per-row groups or --group)
    • optional invite step
    • aggregate errors, return non-zero if any failures
  • Add cmdtests:
    • export writes correct CSV header + rows
    • import dry-run performs no mutations and reports plan
    • import create + group assignment
    • import handles existing tester by email
    • invalid CSV schema returns exit usage (2)

Acceptance criteria

  • asc testflight beta-testers export --help and import --help exist and are self-documenting.
  • Export writes a deterministic CSV file.
  • Import supports --dry-run and produces structured results.
  • Import is idempotent and safe to re-run.
  • Row-level failures are reported clearly and cause a non-zero exit.
  • make test passes with new cmdtest coverage.
Originally created by @rudrankriyam on GitHub (Feb 16, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/560 ## Summary Add first-class, non-interactive CSV workflows for TestFlight beta testers: - `asc testflight beta-testers export` (write testers to a CSV file) - `asc testflight beta-testers import` (read testers from a CSV file and apply changes) These commands should be designed for automation (JSON-first, deterministic, no prompts) while still producing a human-editable CSV artifact. ## Why this matters Managing testers is one of the most common operational workflows for TestFlight: - backing up/auditing current tester lists - moving testers between apps/accounts - bulk onboarding external testers - CI-driven “invite + assign to group” workflows Today, users can *script* this via `asc testflight beta-testers list` JSON output, but there is no stable, file-based interchange format. ## Current state (verified) - `asc testflight beta-testers list/get/add/remove/invite/...` exists. - No import/export subcommands exist in `internal/cli/testflight/beta_testers.go`. - Output formats (`json/table/markdown`) are good for stdout, but not for a file artifact that can be reviewed/edited and re-applied. ## Proposed UX ### Export ```bash asc testflight beta-testers export \ --app "APP_ID" \ --output "./testflight-testers.csv" # Optional: export a filtered subset asc testflight beta-testers export --app "APP_ID" --group "Beta" --output ./testers.csv ``` Flags (proposal): - `--app` (required; respects `ASC_APP_ID` like other commands) - `--output` (required; path to write CSV) - `--group`, `--build`, `--email` (reuse the same filter semantics as `list`) - `--format json|table|markdown` (summary output only; default json) - `--pretty` (when `--format json`) - `--include-groups` (optional; adds a `groups` column, requires additional API calls) Behavior: - Export should be stable/deterministic (consistent column ordering, consistent row ordering). - Export should fetch all pages by default (it is an export command, not a single-page list). ### Import ```bash # Dry-run plan first asc testflight beta-testers import \ --app "APP_ID" \ --input "./testflight-testers.csv" \ --dry-run # Apply (create missing testers + assign to groups) asc testflight beta-testers import \ --app "APP_ID" \ --input "./testflight-testers.csv" # Apply + invite testers (explicit opt-in) asc testflight beta-testers import \ --app "APP_ID" \ --input "./testflight-testers.csv" \ --invite ``` Flags (proposal): - `--app` (required) - `--input` (required; CSV file path) - `--dry-run` (no network mutations; prints plan + validation results) - `--invite` (send invites for newly added testers; default false) - `--group "..."` (optional; apply a group to all imported testers) - `--skip-existing` (optional; if tester email already exists, don’t modify group membership) - `--continue-on-error` (optional; default true; aggregate row errors and return non-zero at end) - `--format json|table|markdown` and `--pretty` (summary output) Behavior: - Import should be idempotent and safe to re-run. - Import should produce row-level results (created/existed/updated/invited/failed) and return non-zero if any row fails. - No interactive prompts. ## CSV schema ### Minimal schema (phase 1) Header required: - `email` Optional columns: - `first_name` - `last_name` - `groups` (comma-separated group names/IDs) Notes: - `email` is the stable identity key. - If `groups` values are names, resolve them deterministically (same semantics as existing `--group` flags). - Unknown columns should be rejected with a usage error (exit code 2), not silently ignored. ## Output model ### JSON (default) Return a structured summary object that includes: - `output_file` / `input_file` - counts: total, created, existed, updated, invited, failed - `failures[]`: row index, email, error message This allows an agent/CI pipeline to reliably drive remediation. ## Detailed implementation plan (TDD-first) - [ ] Add new subcommands to `internal/cli/testflight/beta_testers.go`: - [ ] `export` - [ ] `import` - [ ] Add CSV helpers (parse + write) under `internal/cli/shared/` (or a small `internal/csvutil/` package if preferred). - [ ] Export implementation: - [ ] fetch testers (all pages) - [ ] normalize/sort rows - [ ] write CSV atomically (reject symlink output paths) - [ ] Import implementation: - [ ] parse + validate CSV - [ ] prefetch existing testers (email -> id) for the app (single paginated fetch) - [ ] create missing testers via existing client methods - [ ] add to groups (from per-row groups or `--group`) - [ ] optional invite step - [ ] aggregate errors, return non-zero if any failures - [ ] Add cmdtests: - [ ] export writes correct CSV header + rows - [ ] import dry-run performs no mutations and reports plan - [ ] import create + group assignment - [ ] import handles existing tester by email - [ ] invalid CSV schema returns exit usage (2) ## Acceptance criteria - [ ] `asc testflight beta-testers export --help` and `import --help` exist and are self-documenting. - [ ] Export writes a deterministic CSV file. - [ ] Import supports `--dry-run` and produces structured results. - [ ] Import is idempotent and safe to re-run. - [ ] Row-level failures are reported clearly and cause a non-zero exit. - [ ] `make test` passes with new cmdtest coverage.
kerem 2026-02-26 21:33:48 +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#153
No description provided.