跳到正文
cccskills
免费在 GitHub 公开

app-store-deploy

Use when a mobile app needs a release pipeline - fastlane GitHub Actions to TestFlight (iOS) and Play internal track (Android), with code signing and the release naming that maps to TaskTrooper's prod deploy

中文简介正在准备中。当前显示原文说明。

集成工具GitHub
查看安装方法

包含的文件(1)

  • SKILL.md7.6 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

App Store Deploy (mobile)

Overview

Mobile does not deploy to a cloud you run — it deploys to Apple's and Google's stores, so there is no GCP/AWS split. The CD pipeline builds a signed artifact and uploads it to a test track (TestFlight / Play internal), which is the mobile equivalent of a staged deploy. Read [[ci-cd-pipeline-authoring]] for the workflow naming/dispatch contract; this skill fills in the store steps.

Core principle: Signing is the hard part, not the upload. Get reproducible, secret-driven signing right and the release is a one-command fastlane lane.

Set up the pipeline

If the repo has no fastlane/ yet, create it directly: Fastfile lanes beta (stage) and release (prod, store-executor driven), per the iOS/Android sections below, plus deploy-stage/preprod/prod.yml workflow files. There is no search_boilerplate_catalog tool in this agent's tool list — don't call it.

Environment mapping

  • stage → internal test track: TestFlight (iOS) / Play internal track (Android).
  • preprod → TestFlight external group / Play closed (beta) track.
  • prod → App Store / Play production — the workflow file must still contain prod/production/release so the pipeline's prod_deploy check detects it, but nothing dispatches it directly: mobile ships through a batch delivery profile. A merged mobile task joins the component's draft release and waits in done; a human cuts the release on the Deploy tab, and the release engineer then starts the build (store executor) or lets a tag push trigger it (github_actions executor — see [[ci-cd-pipeline-authoring]]'s batch section).

iOS — TestFlight

  • Build on a macOS runner (runs-on: macos-26; macos-14 is deprecated since 2026-07-06 and unsupported from 2026-11-02, and cannot run Xcode 26, which every App Store Connect upload has needed since 2026-04-28). Select the Xcode version the app needs (≥26) with xcode-select/xcodes; Xcode 27 needs macOS Tahoe 26.6+ on the runner image.
  • Signing via fastlane match (certs/profiles in a private git repo, decrypted with MATCH_PASSWORD) — never check certificates into the app repo.
  • Auth to App Store Connect with an API key (.p8 + key id + issuer id), not an Apple ID password.
  • Lane: fastlane build_app → upload_to_testflight. For prod, submit for review (fastlane deliver).

Android — Play

  • Build the AAB (bundleRelease); sign with the upload keystore from a base64 secret decoded at runtime.
  • Auth with a Play service-account JSON (SUPPLY_JSON_KEY_DATA secret); upload with fastlane supply(track: 'internal') (or production for prod).
  • targetSdk 36 — required for new apps and updates on Play since 2026-08-31 (existing apps may stay on 35 under the extension window).

Build numbers

TaskTrooper chooses the build number; the generated scripts/mobile-release.sh reads it from BUILD_NUMBER and passes it to xcodebuild (CURRENT_PROJECT_VERSION) and Gradle (-PversionCode, -Pandroid.injected.version.code). Do not add increment_build_number, a latest_testflight_build_number + 1 lane or a github.run_number versionCode — two counters fight, and the store rejects the lower one.

  • One counter per app, the higher of TaskTrooper's own record and the store's current highest build.
  • iOS: <sequence>.<task number>.<attempt> (e.g. 412.54.2) — CFBundleVersion takes up to three integers and TestFlight compares the first one first, so every upload is higher than the last whatever task it belongs to. The project's Info.plist must take CFBundleVersion from $(CURRENT_PROJECT_VERSION).
  • Android: versionCode = <sequence>. A project that hardcodes versionCode still gets the number through AGP's injected override.

Per-task test builds: a task entering Human UAT is built from its checkout and uploaded to TestFlight (opened to the internal groups) and to Play internal app sharing (a per-build link, no versionCode ordering). A rejected task that comes back to UAT gets the next attempt number. The "What to Test" note carries the task key, attempt and commit. Test builds share the release's marketing version, so the iOS prod channel submits only the build named by the workflow's build_number input, and Android test builds never go to the internal track the release promotes from.

Secrets (these ARE real secrets)

Unlike cloud deploys, mobile signing needs genuine secrets in GitHub secrets: — App Store Connect API key, MATCH_PASSWORD, keystore + passwords, Play service-account JSON. Store them as encrypted secrets, decode at runtime, never commit or log them. There is no OIDC path for the stores.

Gate & smoke

The "health check" is the store's own processing/validation. Fail the job if fastlane upload fails or the build is rejected. A successful upload is the store gate passing at ready_for_qa time — it still does not move the task anywhere: mobile is a batch delivery profile, so a merged mobile task waits in done, joined into the component's draft release, until a human cuts it.

When the store executor ships a cut release

For a store-executor batch component, deploy_release (called by the release engineer once a human has cut the release) is storeops.Service.StartBuild for every platform with a linked app — the same build this skill's stage lane produces, just started directly instead of by this workflow's own trigger. It records the internal-channel build number before starting (baseline_build) and the release is verified once the internal channel shows a build other than that baseline (build). A platform whose start fails keeps its error on the release; the others still proceed.

Store rules in force (2026-10)

Code-level, this agent can act on these directly:

  • iOS: build with Xcode 26+; PrivacyInfo.xcprivacy listing required-reason APIs, including ones pulled in by third-party SDKs; an NS*UsageDescription string for every permission the app requests (a missing one terminates the app at the request, not a graceful denial); in-app account deletion if the app creates accounts (guideline 5.1.1(v)); a monotonic build number (see above).
  • Android: targetSdk 36; 16 KB-aligned native libraries (keep Flutter/NDK deps current — only matters if the app ships native code); Photo Picker instead of READ_MEDIA_IMAGES unless media access is the app's core use; declared foreground-service types; an account-deletion path (in-app + web link) if the app creates accounts; a monotonic versionCode (see above).
  • Human/metadata, not code: age-rating questionnaire, EU trader status, Data safety form — list these in the release task for a human, don't attempt them from here.

Common Mistakes

  • Certificates or keystores committed to the app repo instead of match/secrets.
  • Using an Apple ID + password instead of an App Store Connect API key → 2FA breaks CI.
  • Uploading a debug/unsigned build.
  • Bumping to the prod track on a plain branch push — prod is never triggered that way: mobile ships through a batch delivery profile, a merged task waits in done, and a human cuts the release that then starts the build (see "When the store executor ships a cut release" above).
  • Reusing a build/version number across uploads.

Red Flags

  • Signing material in the repo tree or printed in logs.
  • A build job on ubuntu trying to build iOS (needs macOS).
  • Same version/build number reused → store rejects the upload.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月21日 更新

Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月21日 更新

Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月21日 更新

Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月21日 更新

How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月21日 更新

Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月21日 更新

查看 makifbaysal 的全部技能

报告此技能的问题