Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save jonasvanderhaegen/e392a4d7f8601e7f0d45056c9dd3e12e to your computer and use it in GitHub Desktop.

Select an option

Save jonasvanderhaegen/e392a4d7f8601e7f0d45056c9dd3e12e to your computer and use it in GitHub Desktop.
Prompt: design advanced release flows (App Store Connect / Play Console patterns)

Designing Advanced Release-Management Flows

A Reusable Prompt for LLM-Assisted System Design


1. How to use this prompt

Paste Section 9 ("The prompt") into any capable LLM and replace the bracketed parameters with your application's domain, platform constraints, and team conventions. The remaining sections are reference material: read them before customising the prompt so you understand the concepts being referenced. The models below are derived from Google Play Console and App Store Connect; they generalise to any system where an artifact must pass through composition, validation, review, and staged deployment.


2. Core domain model

Entities

Entity Key properties Notes
Artifact artifactId, versionCode (monotonic integer), versionName (human string), uploadedAt, fileType, file metadata Immutable once uploaded. Lives in a library independent of any release. Persists forever; releasing or deleting a release never removes its artifacts.
Release releaseId, trackId, name (internal only), status, attached artifactId(s), releaseNotes[locale] Composition object. One or more artifacts from the library plus human-readable notes. Belongs to exactly one track.
Track trackId, name (production / open testing / closed testing / internal testing), managedPublishingEnabled Governs who receives the release. Internal tracks skip review; production requires it.
Submission / Changeset submissionId, status, list of pending changes (releases + declarations + listing edits) A batch of all current pending changes sent to review as one atomic unit. There is at most one active submission per app at a time.
Declaration declarationId, category, answers, publishedAt Policy questionnaire (e.g. data safety, advertising ID, export compliance). First-class entity: gating, not a footnote. Validated against the binary at submission time.
Review reviewId, submissionId, status, messages[] Async process initiated by submission. Each message has a structured body: guideline reference, description, next steps. Supports threaded replies.
Rollout rolloutId, releaseId, percentage, mode (staged / full), status Controls what fraction of the eligible audience receives the release. Can be halted and resumed.

Relationships

Developer account
  └── App
        ├── Artifact Library  (1 app → many artifacts)
        ├── Track[]           (1 app → fixed set of tracks)
        │     └── Release[]   (1 track → many releases, one active at a time)
        ├── Declaration[]     (1 app → one declaration per category)
        ├── Submission        (0..1 active per app at any time)
        │     ├── includes Release changes
        │     ├── includes Declaration changes
        │     └── triggers Review
        └── Rollout           (1 published release → 1 rollout plan)

A Release references artifacts by ID (pointer, not copy). Swapping the artifact on a release is allowed before submission; it updates the pointer and re-triggers validation. A Declaration saved but not yet submitted floats in a "what you've told us" bucket: it is factored into validation but is not yet public.


3. Page & route inventory

Google Play Console

Base: https://play.google.com/console/u/0/developers/{developerId}

Page Route pattern Purpose
App list /app-list Account home. Table of apps with name, package, install count, app status, update status, last updated date.
App dashboard /app/{appId}/app-dashboard Per-app landing. Banner surfaces publishing overview when changes or problems are pending.
Releases hub /app/{appId}/test-and-release Overview of all tracks. Latest production release card; testing-track cards; "For your next release" policy items.
Track page /app/{appId}/tracks/production?tab=releasedashboard|releases|countryAvailability Track-scoped view. Header: active status, latest release, country count, install count. Releases tab: chronological rows with status labels and row-level actions.
Release editor (compose) /app/{appId}/tracks/{trackId}/releases/{releaseId}/prepare Step 1 of 2. Artifact attachment (upload or "Add from library" modal), release name, per-locale release notes with tag markup, Play App Signing status. Footer: Discard / Save as draft / Next.
Release editor (review) /app/{appId}/tracks/{trackId}/releases/{releaseId}/review Step 2 of 2. Read-only summary: errors/warnings panel, device-support diff table, delivery metrics (install size, download size, update size). Footer: Back / Save (to publishing overview).
Release details /app/{appId}/tracks/{trackId}/releases/{releaseId}/details Read-only post-submission view. Delivery and performance metrics, bundle list, delete action, recovery tools.
Publishing overview /app/{appId}/publishing Central submission hub. Managed publishing toggle, "Changes ready to publish" bucket, "Changes not yet sent for review" bucket, async quick-checks panel, hard-block banner, "What you've told us" declarations bucket.
App content hub /app/{appId}/app-content Declarations index. Lists all policy questionnaire categories with completion status.
Advertising ID declaration /app/{appId}/app-content/ad-id-declaration Declares whether the app uses the advertising ID and for which purposes. Validated against the binary's manifest permissions.
Data safety wizard /app/{appId}/app-content/data-privacy-security Five-step declaration wizard: Overview → Data collection & security → Data types → Data usage & handling → Preview. CSV import/export supported.
Monitor / policy status /app/{appId}/monitor Policy status banner, Android vitals, crash and ANR rates.

App Store Connect

Base: https://appstoreconnect.apple.com/apps/{appId}

Page Route pattern Purpose
Version list / sidebar /distribution Left sidebar listing all platform versions with status labels. Entry point to any version's detail page.
Version detail /distribution/ios/version/inflight Version-centric page. Metadata (screenshots, description, keywords, URLs, copyright), exactly one attached build, App Review information, export-compliance gate at build-attach time.
App Review hub /distribution/reviewsubmissions Submissions history table (last 180 days). Columns: date, version(s), submitter, items, status.
Submission detail /distribution/reviewsubmissions/details/{submissionId} Items submitted, per-item review status, "Resubmit to App Review" button, structured rejection message thread.
App Privacy /distribution/privacy Published state header. Privacy policy URL. Product page preview cards. Data Types summary with Edit entry into the data-collection wizard.

4. Flow state machines

4a. Release lifecycle (Google Play model)

                 ┌─────────┐
                 │  Draft  │◄──────────────────────────────┐
                 └────┬────┘                               │
                      │ Save (sends to publishing overview) │
                      ▼                                     │
           ┌──────────────────────┐                        │
           │ Saved / Not yet sent │ ──► [Delete release] ──┘
           │  (in publishing ovw) │     (artifacts stay in library;
           └──────────┬───────────┘      previously superseded release
                      │ Send for review                     reverts to pending)
                      ▼
             ┌──────────────────┐
             │   In review      │◄── [Withdraw → back to Not yet sent]
             └────────┬─────────┘
              ┌───────┴────────┐
              ▼                ▼
    ┌──────────────────┐  ┌─────────┐
    │ Ready to publish │  │Rejected │──► fix → resubmit
    └────────┬─────────┘  └─────────┘
             │ Publish (manual if managed publishing ON;
             │          automatic if OFF)
             ▼
     ┌──────────────────┐
     │  Live / Published│
     └──────────────────┘
             │
             │ [Newer release published on same track]
             ▼
     ┌────────────────────────┐
     │  Superseded            │
     │  ("Replaced by another │
     │   release")            │
     └────────────────────────┘

Withdrawn is a transient state: a release pulled back from review returns to "Not yet sent." There is no terminal "Withdrawn" status; the release re-enters the pending bucket.

Superseded is set automatically when a newer release on the same track moves to Live. Only one release can be Live per track at a time.

Deleting a Draft or Not-yet-sent release removes it from the publishing overview and, if it had superseded an older pending release, resurrects that older release to pending status.

4b. Submission batching (changeset model)

All pending changes (releases across tracks, modified declarations, listing edits) aggregate in the publishing overview. They form a single changeset sent to review together.

Individual changes (releases, declarations, listing edits)
  │
  ▼  accumulate in publishing overview
┌────────────────────────────────────┐
│  Changeset (pending)               │
│  [Changes not yet sent for review] │
└─────────────────┬──────────────────┘
                  │ "Send N changes for review"
                  ▼
┌────────────────────────────────────┐
│  Changeset (in review)             │
│  [Changes are being reviewed]      │
└──────┬─────────────────────────────┘
       │                │
       │ Approved        │ Issues found
       ▼                ▼
┌──────────────┐  ┌───────────────────────────┐
│ Ready to     │  │ Problems panel; fix and    │
│ publish      │  │ resubmit changeset         │
└──────┬───────┘  └───────────────────────────┘
       │ Publish (manual or auto per managed-publishing toggle)
       ▼
┌──────────────┐
│  Published   │
└──────────────┘

The "What you've told us" bucket holds saved-but-unpublished declarations that ride along with the next submission. They are not yet public but are validated as if they were.

4c. Apple variant (version-centric, single-item submission)

Version states:
  Prepare for Submission
    │ attach build → export-compliance questionnaire
    │ save metadata
    │ "Submit for Review" button
    ▼
  Waiting for Review
    │ (queue position opaque)
    ▼
  In Review  ←────────────────────────────────────────────┐
    │                                                      │
    ├─► Rejected (Unresolved Issues)                       │
    │     └── message thread: guideline ref, description,  │
    │         next steps, review device, build reviewed     │
    │     resolve → swap build if needed → Resubmit ───────┘
    │
    └─► Ready for Distribution
          │ release mode: manual / scheduled date / phased (7-day staged)
          ▼
        Live

One build is attached per version at a time. Removing and reattaching a build re-triggers the export-compliance gate. Submitting an artifact that is not the newest build triggers a warning dialog; the submitter may proceed or cancel and resubmit the newer build.


5. Validation & gating patterns

Async pre-submit checks

Before the submit button becomes active, the system runs background checks against the current changeset. This is surfaced as a progress panel ("Quick checks for common problems") with a time estimate (typically ~14 minutes) and a progress bar. The submit button is disabled until checks complete.

On completion, the panel shows either "No problems found" or a count linking to a problems list. Each problem entry includes:

  • Title and description
  • Policy tag (e.g. "Advertising policy", "Data safety")
  • Deep-link action ("Update declaration", "More information")
  • Severity (hard block vs. soft warning)

Hard blocks vs. soft warnings

Hard block: The submit button is disabled. A red banner at the top of the publishing overview states the count and nature of problems. The user must resolve all hard blocks before submission is possible. Example: a declaration marked incomplete, or a declared permission that contradicts the binary manifest.

Soft warning: Submission is permitted. The problem panel shows the warning with a skip affordance. Example: "Your advertising ID will be zeroed because you declared usage but the manifest permission is absent. You can skip this error and proceed with the release." The consequence is stated; the choice is the developer's.

Declaration–binary validation

The backend compares the answers in each Declaration against what the binary's manifest (or privacy manifest, for Apple) actually declares. Mismatches produce either hard blocks (undeclared sensitive permission present in manifest) or soft warnings (declared permission absent from manifest, usually benign but potentially deceptive).

For App Store Connect, the privacy manifest embedded in the binary must list all privacy nutrition labels declared in the app's privacy page. Automated checks flag gaps.

Attach-time gates (Apple)

When a build is attached to a version, an export-compliance questionnaire fires immediately (before save). The developer answers whether the binary uses encryption algorithms above a regulatory threshold. The answer is stored with the build attachment and is required before submission can proceed.


6. Publishing controls

Managed publishing toggle (Google Play model)

The track-level toggle has two states:

  • ON ("you decide when approved changes are published"): Approved changes enter the "Changes ready to publish" bucket. They wait indefinitely for a manual "Publish N changes" action. This is the default for production tracks in regulated or coordinated release scenarios.
  • OFF ("updates publish automatically once approved"): As soon as review passes, the release goes live without further manual action.

Changing the toggle state opens a confirmation dialog with radio buttons explaining the consequences of each mode.

"Changes ready to publish" bucket actions:

  • "Publish N changes": immediately moves all ready changes to live.
  • "Remove changes": discards the ready changeset; it does not delete the release or artifacts.
  • Per-row "View change": navigates to the specific release or declaration detail.

Withdraw from review: While a changeset is in review, a "Remove changes" (withdraw) action is available. The changeset returns to "Not yet sent" status. The releases and declarations revert to the pending bucket, ready to be amended and resubmitted.

Apple equivalents

Three release modes per version, set before submission:

  • Manual release: After approval the version sits at "Ready for Distribution" until the developer clicks "Release This Version."
  • Scheduled release: The version publishes automatically at a specified date/time after approval.
  • Phased release: A 7-day staged rollout; the percentage increases automatically each day (1% → 2% → 5% → 10% → 20% → 50% → 100%). Can be paused or advanced to 100% at any time.

Staged rollout (Google Play model)

A production release can target a percentage of the eligible audience (e.g. 10%, 20%, 50%, 100%). The developer sets the initial percentage when publishing. The rollout can be:

  • Increased to a higher percentage at any time.
  • Halted if monitoring surfaces crashes or policy violations.
  • Resumed after a halt (same or higher percentage).
  • Expanded to full (100%) immediately.

Halting does not remove the release from users who already received it.


7. UX patterns worth copying

Artifact library modal. "Add from library" opens a modal table listing all previously uploaded artifacts for the app: columns for file type, version code, version name, API levels supported, and upload date. Multi-select allowed (within monotonic constraints). Confirms with "Add to release." The library is the source of truth; the release holds references.

Per-artifact inclusion on existing releases. When creating a release, previously deployed artifacts from the preceding release are listed with an Include/Exclude toggle. This enables rollback-by-inclusion without re-upload.

Release notes per locale with tag markup. The notes field uses XML-style locale tags (<en-GB>…</en-GB>, <nl-NL>…</nl-NL>). A "Copy from a previous release" action pre-fills the field from the most recent published release on that track. The editor should validate that at least one locale is present before allowing submission.

Auto release naming. The release name defaults to {versionCode} ({versionName}) (e.g. 26 (1.4.0)). It is editable, never shown to end users, and is internal scaffolding for the operator's own bookkeeping.

Device-support diff table. The review step shows, per form factor (phone, tablet, TV, wearable, auto, Chromebook, XR), four columns: Previously supported / No longer supported / Newly supported / Total. Numbers are absolute device counts. This makes regressions immediately visible before confirmation.

Delivery metrics. Alongside the diff: install size for new users, estimated download time on a reference connection, update size for existing users. Lets the operator spot size regressions before going live.

Release confirmation dialog. Submitting a changeset shows a dialog stating consequences: estimated review time ("reviews are usually completed within 7 days but can take longer"), what will change, and requires an explicit confirm action.

Status lines per release row. The track releases tab shows each release as a row with a colour-coded status label. Actionable states (Not yet sent, Ready to publish) include direct links to the relevant page. Informational states (Live, Superseded) show contextual metadata (release date, what superseded it).

Rejection as threaded message. A rejection is not a flat status flag. It is a structured message: submission ID, review date, review device, version reviewed, guideline reference with section number, issue description in plain language, and numbered next steps covering multiple resolution paths. The developer can reply in-thread to communicate with the review team.

"Newer build available" warning at submission. If the artifact attached to the release is not the most recently uploaded artifact for that app, the system warns before final submission: "A newer build exists. Consider deleting this earlier build and resubmitting the newer one." The operator can override and submit the older artifact.


8. Gotchas & failure modes

Declaration catch-22. A declaration saved to the "What you've told us" bucket is not yet published. If it contains a hard-block problem (e.g. an incomplete data-safety response), it keeps the submit button locked. But the only way to publish (and thus "clear") the declaration is to submit. Resolution: the system must allow editing a saved-but-unpublished declaration directly from the problems panel deep link, so the user can fix it and unblock submission without navigating away.

Stale per-release validation snapshots. Validation runs against the release at a point in time. If a declaration is amended after validation runs but before submission, the displayed check result may be stale. The system should re-trigger validation (or at minimum invalidate the cached result) whenever any change in the changeset is modified.

Disabled buttons with no feedback. If the submit button is disabled and the user does not notice the red hard-block banner, they have no indication why the button does not respond. Provide a tooltip or inline message on the disabled button itself: "N problems must be fixed before you can submit."

Deep links that reset wizard state. A problem entry's "Update declaration" deep link navigates to the declaration wizard. If the wizard uses URL-based routing for its steps, returning to the publishing overview may clear in-progress wizard state. Wizard state must be persisted (server-side or local draft) across navigation, not held only in component memory.

Deleting a release resurrects superseded releases. When the newest pending release (which has implicitly superseded an older pending release on the same track) is deleted, the older one re-enters the pending bucket. This can surprise operators who thought they had cancelled a release. The deletion confirmation dialog must explicitly state: "If this release replaced an earlier pending release, that earlier release will become pending again."

Withdraw concurrency. If a changeset is in review and the developer simultaneously edits a declaration (permitted because metadata stays editable during review on Apple's model), the submitted version and the in-progress edit diverge. The system must clearly distinguish what was submitted from what is being edited, and block publishing of the diverged edit until a new submission is made.

Monotonic version code enforcement. Attempting to attach an artifact with a lower version code than the currently live or pending artifact must fail with an explicit error, not silently ignore the attachment. The error message should state the current minimum accepted version code.


9. The prompt

You are designing a release-management system for {MY_APP_DOMAIN}.

Context:
- Artifact type: {ARTIFACT_TYPE} (e.g. compiled binary, configuration bundle, plugin package, content pack)
- Deployment targets: {TRACK_NAMES} (e.g. internal / beta / production; or staging / canary / stable)
- Review requirement: {REVIEW_TYPE} (e.g. automated only / human gated / none for internal tracks)
- Staged rollout: {ROLLOUT_SUPPORTED} (yes/no; if yes, describe audience segmentation)
- Declarations required: {DECLARATION_TYPES} (e.g. data-privacy questionnaire, export compliance, content rating)
- Team size / access model: {ACCESS_MODEL} (e.g. single developer / multi-team with role-based access)

Design a complete release-management flow with all of the following components.
Produce: route table, per-page spec, state machines, API surface (resource + verbs), and a section on edge cases.

--- REQUIRED COMPONENTS ---

1. ARTIFACT LIBRARY
   - Immutable artifacts identified by monotonic version code
   - Upload is out of scope (one sentence only); focus on library query, selection, and reference
   - "Add from library" UX: filterable table, multi-select, attach to release by reference (not copy)
   - Deletion semantics: releases referencing an artifact do not delete it; artifact persists

2. TRACKS
   - Define at minimum: internal, staging, production equivalents for {MY_APP_DOMAIN}
   - Each track: name, audience, review requirement, rollout capability
   - Managed-publishing toggle per track (manual publish vs. auto-on-approval)

3. RELEASE EDITOR (two-step)
   - Step 1 "Compose": artifact selection from library, release name (internal, auto-generated default),
     per-locale release notes with markup, include/exclude prior artifacts
   - Step 2 "Review": read-only summary, device/environment support diff, delivery metrics,
     warnings/errors panel; footer actions Save-to-overview / Back
   - Draft auto-save; "Delete draft" preserves artifacts in library;
     deleting the newest pending release reverts any superseded pending release

4. PUBLISHING OVERVIEW (changeset batching)
   - All pending changes (releases + declarations + metadata edits) aggregate here
   - Buckets: "Not yet sent" / "In review" / "Ready to publish"
   - Managed-publishing toggle with consequence dialog
   - Withdraw-from-review action returning changeset to "Not yet sent"
   - "What you've told us" bucket: saved-but-unpublished declarations

5. ASYNC PRE-SUBMIT VALIDATION
   - Background checks with time estimate and progress bar; gate submit button until complete
   - Problems panel: per-problem title, description, policy tag, deep-link action
   - Hard blocks (button disabled, red banner with count) vs. soft warnings (skippable with stated consequence)
   - Declaration–artifact cross-validation: check declared answers against artifact metadata
   - Re-trigger validation whenever any change in the changeset is modified

6. DECLARATIONS AS FIRST-CLASS ENTITIES
   - One declaration per category (e.g. {DECLARATION_TYPES})
   - Editable independently; save stores to "What you've told us" without publishing
   - Hard-block when declaration is incomplete; deep link from problems panel must allow in-place editing
   - At artifact-attach time: fire synchronous questionnaire for any attach-time gates (e.g. export compliance)

7. REVIEW FLOW
   - Structured rejection: issue ID, review date/device/version, policy reference, description, numbered next steps
   - Threaded reply to reviewer
   - "Newer artifact available" warning when submitting a non-latest artifact
   - Resubmit loop: resolve issue → optionally swap artifact → resubmit same submission or create new

8. STAGED ROLLOUT & ROLLOUT CONTROLS
   - Initial percentage set at publish time
   - Increase / halt / resume / expand to full actions
   - Halt does not remove artifact from users who already received it
   - Rollout status visible on track page header and release row

9. STATE MACHINES (provide explicit states and valid transitions for each)
   - Release: Draft → Saved/Pending → In review → Ready to publish → Live → Superseded
     plus Withdrawn (transient, returns to Pending) and terminal Deleted (draft only)
   - Submission/Changeset: Accumulating → Sent for review → Approved (ready) → Published
     plus Withdrawn → Accumulating
   - Rollout: Not started → In progress → Halted → Completed (100%)
   - Declaration: Draft → Saved (unpublished) → Submitted → Published → Outdated (binary changed)

10. EDGE CASES (address all of these explicitly)
    - Declaration catch-22: incomplete saved declaration blocks submit; fix path must not require navigation away
    - Stale validation snapshots: invalidate on any changeset change
    - Disabled submit button: provide inline explanation, not silent non-response
    - Deep link preserving wizard state across navigation
    - Deleting newest pending release: resurrection dialog for superseded release
    - Monotonic version code: reject downgrade with explicit error stating minimum accepted code
    - Concurrent edit during review: clearly distinguish submitted version from in-progress edit

--- OUTPUT FORMAT ---

Produce the following sections in order:
A. Domain model (entities, relationships, key invariants)
B. Route table (method, path pattern, purpose, auth required)
C. Per-page spec (for each page: purpose, entry conditions, components, actions, exit paths)
D. State machine diagrams (ASCII or mermaid)
E. API surface (REST or GraphQL resource shapes + verbs; include version-code validation rule)
F. Edge case handling (one paragraph per edge case from item 10 above)
G. Open questions (anything requiring {MY_APP_DOMAIN}-specific decisions before implementation)

Document version: 1.0, June 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment