fix(release): recover uploaded iOS store builds

This commit is contained in:
tianma-if committed 2026-09-06 21:42:44 +08:00
1 parent 1b50b864f1
commit 96039cd060
3 files changed
+48 -4

No files matched your search

+11 -4
View File
@@ -31,6 +31,11 @@ on:
required: true
default: false
type: boolean
ios_build_number:
description: "Existing App Store Connect build number to submit without rebuilding"
required: false
default: ""
type: string
permissions:
contents: write
@@ -301,6 +306,7 @@ jobs:
--cache-dir "$RUNNER_TEMP/edgeever-bun-cache-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
- name: Build the iOS archive on EAS
if: ${{ inputs.ios_build_number == '' }}
id: build
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
@@ -328,6 +334,7 @@ jobs:
working-directory: apps/mobile
- name: Upload archive to App Store Connect and TestFlight
if: ${{ inputs.ios_build_number == '' }}
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: |
@@ -341,10 +348,10 @@ jobs:
- name: Submit the uploaded build to App Review
env:
APP_STORE_BUILD_NUMBER: ${{ steps.build.outputs.build_number }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
APP_STORE_CONNECT_API_KEY_P8_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_P8_BASE64 }}
APP_STORE_BUILD_NUMBER: ${{ inputs.ios_build_number || steps.build.outputs.build_number }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.EDGEEVER_APPLE_API_ISSUER }}
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.EDGEEVER_APPLE_API_KEY_ID }}
APP_STORE_CONNECT_API_KEY_P8_BASE64: ${{ secrets.EDGEEVER_APPLE_API_KEY_BASE64 }}
APP_STORE_VERSION: ${{ needs.plan.outputs.version }}
run: |
test -n "$APP_STORE_CONNECT_API_ISSUER_ID"
+11
View File
@@ -14,6 +14,7 @@ Options:
--platform <target> android, ios, or both (default: both)
--android-track <track> production, alpha, beta, or internal (default: production)
--recover-play-apk Skip Play upload and recover its already signed APK
--ios-build-number <number> Submit an existing App Store Connect build without rebuilding
--repository <owner/name> GitHub repository (default: ${DEFAULT_REPOSITORY})
--dry-run Print the workflow dispatch plan
--help Show this help
@@ -27,12 +28,14 @@ export const parseStoreDeliveryArgs = (argv) => {
repository: DEFAULT_REPOSITORY,
dryRun: false,
recoverPlayApk: false,
iosBuildNumber: "",
help: false,
};
const valueOptions = new Map([
["--release", "releaseTag"],
["--platform", "platform"],
["--android-track", "androidTrack"],
["--ios-build-number", "iosBuildNumber"],
["--repository", "repository"],
]);
@@ -79,6 +82,12 @@ export const parseStoreDeliveryArgs = (argv) => {
if (!/^[^/\s]+\/[^/\s]+$/.test(options.repository)) {
throw new Error("--repository must use owner/name format.");
}
if (options.iosBuildNumber && !/^[1-9]\d*$/.test(options.iosBuildNumber)) {
throw new Error("--ios-build-number must be a positive integer.");
}
if (options.iosBuildNumber && options.platform === "android") {
throw new Error("--ios-build-number requires --platform ios or both.");
}
return options;
};
@@ -99,6 +108,8 @@ const run = (options) => {
`android_track=${options.androidTrack}`,
"-f",
`recover_play_apk=${options.recoverPlayApk}`,
"-f",
`ios_build_number=${options.iosBuildNumber}`,
];
if (options.dryRun) {
console.log(`gh ${args.join(" ")}`);
+26
View File
@@ -30,6 +30,19 @@ describe("store delivery command", () => {
).toBe(true);
});
test("supports submitting an existing iOS build without rebuilding", () => {
expect(
parseStoreDeliveryArgs([
"--release",
"v1.7.0",
"--platform",
"ios",
"--ios-build-number",
"30",
]).iosBuildNumber,
).toBe("30");
});
test("rejects malformed release tags", () => {
expect(() => parseStoreDeliveryArgs(["--release", "latest"])).toThrow(
"stable vX.Y.Z",
@@ -55,6 +68,19 @@ describe("store delivery command", () => {
/edgeever-bun-cache-\$\{GITHUB_RUN_ID\}-\$\{GITHUB_RUN_ATTEMPT\}/g,
),
).toHaveLength(3);
expect(workflow).toContain("inputs.ios_build_number == ''");
expect(workflow).toContain(
"APP_STORE_BUILD_NUMBER: ${{ inputs.ios_build_number || steps.build.outputs.build_number }}",
);
expect(workflow).toContain(
"APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.EDGEEVER_APPLE_API_ISSUER }}",
);
expect(workflow).toContain(
"APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.EDGEEVER_APPLE_API_KEY_ID }}",
);
expect(workflow).toContain(
"APP_STORE_CONNECT_API_KEY_P8_BASE64: ${{ secrets.EDGEEVER_APPLE_API_KEY_BASE64 }}",
);
});
test("replaces the GitHub APK with the Play-signed universal APK", () => {