[GH-ISSUE #484] Migrate Import: ingest Deliverfile + metadata/screenshots with automatic localization mapping #137

Closed
opened 2026-02-26 21:33:42 +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/484

Summary

Expand asc migrate import so it can ingest a full Deliver-style project layout, not just a subset of localization text files.

Why this matters

Migration friction is highest at import time:

  • teams already have Deliverfile + metadata/ + screenshots/
  • current import handles text metadata only
  • screenshots and review metadata still require manual follow-up commands

Reducing this to a single import command is a high-leverage onboarding win.

Current state (verified)

  • internal/cli/migrate/migrate.go currently:
    • reads localized version metadata from metadata/<locale>
    • reads app-info name/subtitle
    • uploads version + app-info localizations
  • It does not currently:
    • parse Deliverfile
    • ingest screenshot directories
    • process review information files
    • handle privacy_url.txt

Proposed UX

Input discovery

asc migrate import should auto-discover inputs in this order:

  1. explicit flags
  2. Deliverfile values (metadata_path, screenshots_path, app_identifier, app_version, platform, skip flags)
  3. conventional project directories (metadata/, screenshots/)

Import scope

In one run, import:

  1. Localized metadata files:
    • name.txt, subtitle.txt, description.txt, keywords.txt, release_notes.txt, promotional_text.txt, support_url.txt, marketing_url.txt, privacy_url.txt
  2. Review information files from metadata/review_information/
  3. Screenshots from screenshots/<locale>/...:
    • locale inferred from directory
    • display type inferred from filename hints + dimensions
    • uploaded via existing screenshot asset flow

Dry-run behavior

--dry-run should show a complete import plan:

  • detected locales
  • metadata files to apply
  • screenshot files grouped by locale/display type
  • fields/files skipped with reasons

Detailed implementation plan

  • Add Deliverfile parser in internal/cli/migrate/deliverfile_parser.go.
  • Add path resolution helper in internal/cli/migrate/path_resolution.go.
  • Extend import models in internal/cli/migrate/migrate.go to include:
    • review information payload
    • screenshot import plan + results
    • privacy URL support
  • Extract reusable screenshot upload helpers (or factor shared code) to avoid duplication with internal/cli/assets/assets_screenshots.go.
  • Add filename + dimension-based display type inference utility for import mode.
  • Add idempotency guardrails (re-running import should update/skip cleanly, not duplicate unpredictably).
  • Add tests:
    • Deliverfile parsing and precedence rules
    • metadata/review import coverage
    • screenshot discovery + locale mapping
    • dry-run output includes all planned changes
    • malformed input produces actionable errors
  • Update README.md migrate section with new import behavior and examples.

Acceptance criteria

  • asc migrate import can run from a project containing only Deliverfile + metadata/screenshots directories.
  • Localizations, screenshots, and review metadata import in one invocation.
  • privacy_url.txt is imported where supported.
  • --dry-run accurately reports what would change.
  • Re-running import is safe and predictable.
  • make test passes with new migrate coverage.
Originally created by @rudrankriyam on GitHub (Feb 10, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/484 ## Summary Expand `asc migrate import` so it can ingest a full Deliver-style project layout, not just a subset of localization text files. ## Why this matters Migration friction is highest at import time: - teams already have `Deliverfile` + `metadata/` + `screenshots/` - current import handles text metadata only - screenshots and review metadata still require manual follow-up commands Reducing this to a single import command is a high-leverage onboarding win. ## Current state (verified) - `internal/cli/migrate/migrate.go` currently: - reads localized version metadata from `metadata/<locale>` - reads app-info `name`/`subtitle` - uploads version + app-info localizations - It does **not** currently: - parse `Deliverfile` - ingest screenshot directories - process review information files - handle `privacy_url.txt` ## Proposed UX ### Input discovery `asc migrate import` should auto-discover inputs in this order: 1. explicit flags 2. `Deliverfile` values (`metadata_path`, `screenshots_path`, `app_identifier`, `app_version`, `platform`, skip flags) 3. conventional project directories (`metadata/`, `screenshots/`) ### Import scope In one run, import: 1. Localized metadata files: - `name.txt`, `subtitle.txt`, `description.txt`, `keywords.txt`, `release_notes.txt`, `promotional_text.txt`, `support_url.txt`, `marketing_url.txt`, `privacy_url.txt` 2. Review information files from `metadata/review_information/` 3. Screenshots from `screenshots/<locale>/...`: - locale inferred from directory - display type inferred from filename hints + dimensions - uploaded via existing screenshot asset flow ### Dry-run behavior `--dry-run` should show a complete import plan: - detected locales - metadata files to apply - screenshot files grouped by locale/display type - fields/files skipped with reasons ## Detailed implementation plan - [ ] Add `Deliverfile` parser in `internal/cli/migrate/deliverfile_parser.go`. - [ ] Add path resolution helper in `internal/cli/migrate/path_resolution.go`. - [ ] Extend import models in `internal/cli/migrate/migrate.go` to include: - [ ] review information payload - [ ] screenshot import plan + results - [ ] privacy URL support - [ ] Extract reusable screenshot upload helpers (or factor shared code) to avoid duplication with `internal/cli/assets/assets_screenshots.go`. - [ ] Add filename + dimension-based display type inference utility for import mode. - [ ] Add idempotency guardrails (re-running import should update/skip cleanly, not duplicate unpredictably). - [ ] Add tests: - [ ] `Deliverfile` parsing and precedence rules - [ ] metadata/review import coverage - [ ] screenshot discovery + locale mapping - [ ] dry-run output includes all planned changes - [ ] malformed input produces actionable errors - [ ] Update `README.md` migrate section with new import behavior and examples. ## Acceptance criteria - [ ] `asc migrate import` can run from a project containing only `Deliverfile` + metadata/screenshots directories. - [ ] Localizations, screenshots, and review metadata import in one invocation. - [ ] `privacy_url.txt` is imported where supported. - [ ] `--dry-run` accurately reports what would change. - [ ] Re-running import is safe and predictable. - [ ] `make test` passes with new migrate coverage.
kerem 2026-02-26 21:33:42 +03:00
Author
Owner

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

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

What to build

Enhance asc migrate import to ingest Deliver-style project layouts (metadata + screenshots + review info) with automatic localization mapping and dry-run planning.

Implementation plan

  1. Deliverfile + path discovery
  • Add parser for key config values (e.g. metadata path, screenshots path, app identifier, version/platform hints).
  • Resolve input precedence:
    • explicit flags > Deliverfile > conventional directories.
  1. Metadata expansion
  • Extend import support for additional localized files:
    • privacy_url.txt (where API supports it)
    • existing metadata fields remain supported
  • Ingest review info files from metadata/review_information/.
  1. Screenshot ingestion
  • Discover screenshots under localized directories.
  • Infer display type via filename hints + dimension mapping.
  • Reuse/refactor existing screenshot upload flow from assets commands (avoid duplicate upload logic).
  1. Dry-run and result model
  • Expand dry-run output with:
    • detected locales
    • metadata changes
    • review info changes
    • screenshot upload plan
    • skipped files + reasons
  1. Idempotency / safety
  • Re-runs should be predictable (update/skip behavior clearly reported).
  • Validation errors should point to exact file and remediation.

New tests to write

A) Parser + discovery tests (internal/cli/migrate)

  • Deliverfile path resolution and precedence rules
  • missing/invalid Deliverfile values
  • metadata/review folder discovery behavior

B) Import behavior tests (internal/cli/cmdtest)

  • successful metadata + screenshot + review import
  • dry-run includes full change plan
  • invalid screenshots and malformed metadata produce actionable errors
  • idempotent re-run behavior

C) Field coverage tests

  • include privacy_url.txt handling in supported paths
  • verify locale mapping for both metadata and screenshots

How to test locally

Run exactly:

  • make format
  • make lint
  • make test

Targeted tests:

  • go test ./internal/cli/migrate -run 'Deliverfile|Import|DryRun'
  • go test ./internal/cli/cmdtest -run 'migrate import'

Done criteria

  • One asc migrate import run can ingest metadata, screenshots, and review info from local project layout.
  • Dry-run accurately previews changes.
  • Re-running import is safe/predictable.
  • Tests cover parser, mapping, and upload plan behavior.
  • All checks pass (format, lint, test).
<!-- gh-comment-id:3881458922 --> @rudrankriyam commented on GitHub (Feb 11, 2026): @cursor Please implement this issue end-to-end. ## What to build Enhance `asc migrate import` to ingest Deliver-style project layouts (metadata + screenshots + review info) with automatic localization mapping and dry-run planning. ## Implementation plan 1. **Deliverfile + path discovery** - Add parser for key config values (e.g. metadata path, screenshots path, app identifier, version/platform hints). - Resolve input precedence: - explicit flags > Deliverfile > conventional directories. 2. **Metadata expansion** - Extend import support for additional localized files: - `privacy_url.txt` (where API supports it) - existing metadata fields remain supported - Ingest review info files from `metadata/review_information/`. 3. **Screenshot ingestion** - Discover screenshots under localized directories. - Infer display type via filename hints + dimension mapping. - Reuse/refactor existing screenshot upload flow from assets commands (avoid duplicate upload logic). 4. **Dry-run and result model** - Expand dry-run output with: - detected locales - metadata changes - review info changes - screenshot upload plan - skipped files + reasons 5. **Idempotency / safety** - Re-runs should be predictable (update/skip behavior clearly reported). - Validation errors should point to exact file and remediation. ## New tests to write ### A) Parser + discovery tests (`internal/cli/migrate`) - Deliverfile path resolution and precedence rules - missing/invalid Deliverfile values - metadata/review folder discovery behavior ### B) Import behavior tests (`internal/cli/cmdtest`) - successful metadata + screenshot + review import - dry-run includes full change plan - invalid screenshots and malformed metadata produce actionable errors - idempotent re-run behavior ### C) Field coverage tests - include `privacy_url.txt` handling in supported paths - verify locale mapping for both metadata and screenshots ## How to test locally Run exactly: - `make format` - `make lint` - `make test` Targeted tests: - `go test ./internal/cli/migrate -run 'Deliverfile|Import|DryRun'` - `go test ./internal/cli/cmdtest -run 'migrate import'` ## Done criteria - One `asc migrate import` run can ingest metadata, screenshots, and review info from local project layout. - Dry-run accurately previews changes. - Re-running import is safe/predictable. - Tests cover parser, mapping, and upload plan behavior. - All checks pass (`format`, `lint`, `test`).
Author
Owner

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

Summary:

  • I expanded migrate import to resolve Deliverfile/paths, ingest metadata + app info + review info, build screenshot plans, and carry skip handling into the dry-run/output flow.
			inputs, skipped, err := resolveImportInputs(importInputOptions{
				WorkDir:     workDir,
				FastlaneDir: strings.TrimSpace(*fastlaneDir),
			})
			if err != nil {
				return fmt.Errorf("migrate import: %w", err)
			}

			metadataDir := inputs.MetadataDir
			screenshotsDir := inputs.ScreenshotsDir
			if inputs.DeliverfileConfig.SkipMetadata && metadataDir != "" {
				skipped = append(skipped, SkippedItem{
					Path:   metadataDir,
					Reason: "skip_metadata in Deliverfile",
				})
				metadataDir = ""
			}
  • I added screenshot discovery + display-type inference with locale normalization/validation to support locale/display grouping and safe file handling.
func discoverScreenshotPlan(screenshotsDir string) ([]ScreenshotPlan, []SkippedItem, error) {
	entries, err := os.ReadDir(screenshotsDir)
	if err != nil {
		return nil, nil, err
	}

	type planKey struct {
		locale      string
		displayType string
	}
	plans := make(map[planKey][]string)
	var skipped []SkippedItem

Tests:

  • make format
  • go test ./internal/cli/migrate -run 'Deliverfile|Import|DryRun'
  • go test ./internal/cli/cmdtest -run TestMigrateImport
  • go test ./internal/cli/cmdtest -run 'migrate import' (no tests matched)
  • make lint
  • make test
  • go build -o /tmp/asc . && /tmp/asc migrate import (exit code 2 with usage output)

View PR

Open in Cursor Open in Web

<!-- gh-comment-id:3881459247 --> @cursor[bot] commented on GitHub (Feb 11, 2026): Summary: - I expanded `migrate import` to resolve Deliverfile/paths, ingest metadata + app info + review info, build screenshot plans, and carry skip handling into the dry-run/output flow. ```102:125:internal/cli/migrate/migrate.go inputs, skipped, err := resolveImportInputs(importInputOptions{ WorkDir: workDir, FastlaneDir: strings.TrimSpace(*fastlaneDir), }) if err != nil { return fmt.Errorf("migrate import: %w", err) } metadataDir := inputs.MetadataDir screenshotsDir := inputs.ScreenshotsDir if inputs.DeliverfileConfig.SkipMetadata && metadataDir != "" { skipped = append(skipped, SkippedItem{ Path: metadataDir, Reason: "skip_metadata in Deliverfile", }) metadataDir = "" } ``` - I added screenshot discovery + display-type inference with locale normalization/validation to support locale/display grouping and safe file handling. ```29:66:internal/cli/migrate/screenshots.go func discoverScreenshotPlan(screenshotsDir string) ([]ScreenshotPlan, []SkippedItem, error) { entries, err := os.ReadDir(screenshotsDir) if err != nil { return nil, nil, err } type planKey struct { locale string displayType string } plans := make(map[planKey][]string) var skipped []SkippedItem ``` Tests: - `make format` - `go test ./internal/cli/migrate -run 'Deliverfile|Import|DryRun'` - `go test ./internal/cli/cmdtest -run TestMigrateImport` - `go test ./internal/cli/cmdtest -run 'migrate import'` (no tests matched) - `make lint` - `make test` - `go build -o /tmp/asc . && /tmp/asc migrate import` (exit code 2 with usage output) <p><a href="https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/493"><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-e37ade75-cbcc-4a8c-82fa-f81d15306d00"><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-e37ade75-cbcc-4a8c-82fa-f81d15306d00"><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 #493 (https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/493), which is merged into main.

<!-- gh-comment-id:3887482522 --> @rudrankriyam commented on GitHub (Feb 11, 2026): Resolved by PR #493 (https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/493), 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#137
No description provided.