Ship-step contract for pipelines: uniform exit codes (0/1/2/3/4/7) in cli/lib/ship-step.ts, one final --json line, --result-file (atomic, also on failure), --progress json, --env-file with secret redaction, --version-from; idempotent play upload / apple upload / play release / apple submit re-runs end with exit 7; play upload takes --track production and --version-code
This commit is contained in:
parent
4eac8e8cd8
commit
06a0b424f5
14 changed files with 928 additions and 24 deletions
|
|
@ -28,11 +28,15 @@ import { readSubmitState, submitPlanned } from './iap-submit';
|
|||
import { explain409, isScreenshotProcessing409, pendingScreenshots, updateLedger, versionScreenshotRows } from './screenshot-health';
|
||||
import { openSubmissions } from './submission';
|
||||
import { ensureGcSwitch, gameCenterInUse, gcSwitchPlan, readGcSwitch } from './game-center';
|
||||
import { shipNoop, shipPhase, shipReport, shipRun } from '../lib/ship-step';
|
||||
import { consoleUrl } from '../lib/console-links';
|
||||
import { allVersions, parsePlatform, pickPlatform, platformLabel, platformOf, versionsPath } from './platform';
|
||||
|
||||
/** App Store version states a first submission may send: the editable version (Prepare for Submission, a rejected
|
||||
* one, or one already Ready for Review in a draft). */
|
||||
export const SUBMITTABLE_APP = new Set(['PREPARE_FOR_SUBMISSION', 'READY_FOR_REVIEW', ...REJECTED_APP]);
|
||||
/** App Store version states after a submission went through: a re-run of `apple submit` with the same build has nothing to do. */
|
||||
export const SUBMITTED_APP = new Set(['WAITING_FOR_REVIEW', 'IN_REVIEW', 'PENDING_DEVELOPER_RELEASE', 'PENDING_APPLE_RELEASE', 'PROCESSING_FOR_DISTRIBUTION', 'READY_FOR_DISTRIBUTION', 'READY_FOR_SALE']);
|
||||
|
||||
export async function run(ctx: Ctx): Promise<void> { await submitVersion(ctx, 'resubmit'); }
|
||||
|
||||
|
|
@ -45,6 +49,24 @@ export async function submitVersion(ctx: Ctx, mode: 'submit' | 'resubmit'): Prom
|
|||
if (!/^\d+(\.\d+)*$/.test(number)) throw new Error(`--build ${number}: a build number like 42 or 1.0.3 (the one you just uploaded, never "the latest")`);
|
||||
const c = await ascClient(root, need(config.apple?.bundleId, 'apple.bundleId'), config.apple?.appId);
|
||||
const appId = await c.app();
|
||||
shipReport({ build: number, version: a.get('version'), url: consoleUrl('asc.app-review') });
|
||||
shipPhase('verify', `reading the App Store versions and build ${number}`);
|
||||
// the ship-step contract: the version already went to App Review with this build: nothing to do (exit 7)
|
||||
if (mode === 'submit' && shipRun()) {
|
||||
const want0 = a.get('version');
|
||||
const flag0 = parsePlatform(a.get('platform'));
|
||||
const sent = (await allVersions(c, appId)).filter((x: J) => (!want0 || x.attributes.versionString === want0) && (!flag0 || platformOf(x) === flag0)
|
||||
&& SUBMITTED_APP.has(String(x.attributes.appVersionState ?? x.attributes.appStoreState)));
|
||||
for (const x of sent) {
|
||||
const att = (await c.maybe(`/v1/appStoreVersions/${x.id}/build`))?.data;
|
||||
if (att && String(att.attributes?.version ?? '') === number) {
|
||||
const st = String(x.attributes.appVersionState ?? x.attributes.appStoreState);
|
||||
shipNoop({ version: String(x.attributes.versionString), build: number, state: st });
|
||||
done(TAG, `version ${String(x.attributes.versionString)} with build ${number} is ${st} already: nothing sent`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
const ids = [...(config.products ?? []).filter(p => sellsOn(config, p, 'apple')).map(p => p.id), ...allSubscriptions(config.subscriptions).filter(x => sellsOn(config, x.sub, 'apple')).map(x => x.sub.id)];
|
||||
|
||||
// the platform: --platform, else the one whose version (or UNRESOLVED_ISSUES submission) this needs; both -> ask
|
||||
|
|
@ -100,6 +122,7 @@ export async function submitVersion(ctx: Ctx, mode: 'submit' | 'resubmit'): Prom
|
|||
// the desktop's owner dialog shows the output text: the plan table goes with the result there
|
||||
if (process.env.STOREBOUND_MACHINE === '1') { console.log(formatRows(rows)); for (const x of blockers) warn(TAG, x); }
|
||||
if (blockers.length) process.exitCode = 1;
|
||||
else if (state.choice?.action === 'busy') shipNoop({ version: versionString, state: stateOf(v) });
|
||||
if (dry || blockers.length || state.choice?.action === 'busy') return;
|
||||
} else {
|
||||
console.log(formatRows(rows));
|
||||
|
|
@ -108,12 +131,13 @@ export async function submitVersion(ctx: Ctx, mode: 'submit' | 'resubmit'): Prom
|
|||
for (const x of blockers) warn(TAG, x);
|
||||
}
|
||||
if (blockers.length) { process.exitCode = 1; done(TAG, 'nothing sent: fix the blockers above'); return; }
|
||||
if (state.choice?.action === 'busy') { done(TAG, `nothing to ${mode}: ${state.choice.why}`); return; }
|
||||
if (state.choice?.action === 'busy') { shipNoop({ version: versionString, state: stateOf(v) }); done(TAG, `nothing to ${mode}: ${state.choice.why}`); return; }
|
||||
if (dry) {
|
||||
done(TAG, a.has('dry') ? 'dry run: nothing sent' : `dry run (no --yes): nothing sent. ${mode === 'submit' ? 'Submitting' : 'Resubmitting'} is the owner's step: after the owner's yes, run it again with --yes`);
|
||||
return;
|
||||
}
|
||||
|
||||
shipPhase('submit', `${mode === 'submit' ? 'submitting' : 'resubmitting'} ${versionString} with build ${number}`);
|
||||
if (build.action === 'attach') {
|
||||
await c.asc('PATCH', `/v1/appStoreVersions/${v.id}/relationships/build`, { data: { type: 'builds', id: build.id } });
|
||||
log(TAG, `build ${number} attached to ${versionString}`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue