apple creative-assets: a placement App Store Connect refuses on the live version is reported with the live version page's deep link, the live page stays unchanged (new placement first, old one removed after) and the other live slots are not retried; pitfall 76
This commit is contained in:
parent
98d3bf4410
commit
1736300784
4 changed files with 42 additions and 5 deletions
|
|
@ -34,6 +34,7 @@ import { ffprobe } from '../shots/report';
|
|||
import { imageInfo } from '../shots/spec';
|
||||
import { checkCreativeImage, checkCreativeVideo, type CreativeFile, creativeFiles, PLACEMENT_TYPE, type Placement } from '../shots/creative';
|
||||
import { ascClient, md5, type J } from './asc';
|
||||
import { AmbiguousWriteError } from '../lib/upsert';
|
||||
import { addItem, ensureDraft, OtherSubmissionError } from './submission';
|
||||
|
||||
const TAG = 'apple';
|
||||
|
|
@ -158,6 +159,7 @@ export async function run(ctx: Ctx): Promise<void> {
|
|||
if (verify) return verifySlots();
|
||||
|
||||
const rows: Row[] = [];
|
||||
let liveRefused = ''; // the first 4xx on a live-version placement: later live slots are not tried
|
||||
const planned = new Set<string>(); // dry run: MD5s already planned for upload
|
||||
async function upload(f: CreativeFile, sum: string): Promise<J> {
|
||||
const buf = readFileSync(f.file);
|
||||
|
|
@ -231,10 +233,26 @@ export async function run(ctx: Ctx): Promise<void> {
|
|||
}
|
||||
const action = placed.length ? 'replace' : 'select';
|
||||
if (dry) { log(TAG, `${tag}: would ${action === 'replace' ? `replace ${placed.length} selected asset(s) with` : 'select'} ${basename(f.file)} (${asset.attributes?.state})`); row(action, asset); continue; }
|
||||
for (const p of placed) await c.asc('DELETE', `/v1/appAssetLibraryPlacements/${p.id}`);
|
||||
if (onLive && liveRefused) { warn(TAG, `${tag}: not tried (App Store Connect refused a placement on the live version above; no blind retries)`); row('refuse', asset); continue; }
|
||||
const media = f.kind === 'image' ? 'image' : 'video';
|
||||
await c.asc('POST', '/v1/appAssetLibraryPlacements', { data: { type: 'appAssetLibraryPlacements', attributes: { placementType: ptype },
|
||||
const place = () => c.asc('POST', '/v1/appAssetLibraryPlacements', { data: { type: 'appAssetLibraryPlacements', attributes: { placementType: ptype },
|
||||
relationships: { [media]: { data: { type: asset.type, id: asset.id } }, appStoreVersionLocalization: { data: { type: 'appStoreVersionLocalizations', id: loc.id } } } } });
|
||||
if (onLive) {
|
||||
// Live version: place the new asset first, remove the old one only after Apple accepted it, so a refusal
|
||||
// leaves the live page as it was. Whether the API takes placements on a live version is not documented.
|
||||
try { await place(); }
|
||||
catch (e) {
|
||||
const status = /-> (4\d\d)/.exec(String((e as Error).message))?.[1];
|
||||
if (!status || e instanceof AmbiguousWriteError) throw e;
|
||||
liveRefused = String(e instanceof Error ? e.message : e).split('\n')[0]!;
|
||||
warn(TAG, `${tag}: App Store Connect refused to select ${basename(f.file)} on the live version ${version.attributes.versionString} (${status}): ${liveRefused}. The live page is unchanged. Select it in the console instead (Header and Search Results on the live version page): ${consoleLink('asc.version', '', { appleAppId: appId }).replace('/version/inflight', '/version/deliverable')}, or create a new version and re-run; the remaining live slots are not tried`);
|
||||
row('refuse', asset); continue;
|
||||
}
|
||||
for (const p of placed) await c.asc('DELETE', `/v1/appAssetLibraryPlacements/${p.id}`);
|
||||
} else {
|
||||
for (const p of placed) await c.asc('DELETE', `/v1/appAssetLibraryPlacements/${p.id}`);
|
||||
await place();
|
||||
}
|
||||
log(TAG, `${tag}: selected ${basename(f.file)} (${asset.attributes?.state})`);
|
||||
row(action, asset);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue