iPhone Duo: accept platform IPHONE_APP_STORE from appAssetLibraryRefData; a Duo failure warns, other sets continue

This commit is contained in:
CRTkafa 2026-11-08 15:48:58 +07:00
parent f6f9fc3c41
commit b18d480d65
4 changed files with 9 additions and 5 deletions

View file

@ -3,6 +3,8 @@
## Unreleased
- **iPhone Duo:** the live API names the platform IPHONE_APP_STORE (not IOS); accepted. A Duo problem now warns and the other screenshot sets still upload.
## 0.8.72 · 2026-11-08
- **iPhone Duo screenshots upload.** `apple screenshots` now sends them through the App Asset Library (display class

View file

@ -22,11 +22,11 @@ export const DUO_CATEGORY = 'APP_SCREENSHOTS_AND_PREVIEWS';
export const DUO_MAX = 10;
const sumOf = (a: J | undefined): string | undefined => /^storebound ([0-9a-f]{32})$/.exec(String(a?.attributes?.referenceName ?? ''))?.[1];
/** iOS placement profile group ids of the IPHONE_DUO display class in an appAssetLibraryRefData response. Pure. */
/** iPhone placement profile group ids (platform IOS or IPHONE_APP_STORE, as the live API answers) of the IPHONE_DUO display class in an appAssetLibraryRefData response. Pure. */
export function duoGroups(refData: J[]): string[] {
const ids = new Set<string>();
for (const r of refData) for (const g of (r?.attributes?.placementProfileGroups ?? []) as J[])
if (g?.displayClassId === 'IPHONE_DUO' && (!g.platform || g.platform === 'IOS') && g.placementProfileGroupId) ids.add(String(g.placementProfileGroupId));
if (g?.displayClassId === 'IPHONE_DUO' && (!g.platform || /IOS|IPHONE/.test(String(g.platform))) && g.placementProfileGroupId) ids.add(String(g.placementProfileGroupId));
return [...ids];
}

View file

@ -96,8 +96,9 @@ export async function run(ctx: Ctx): Promise<void> {
const version = await c.editableVersion(platform);
if (!version) throw new Error(`no editable ${platformLabel(platform)} App Store version (run apple listing --version x.y.z first)`);
log('apple', `screenshots for version ${versionLabel(version)}`);
const duo = platform === 'MAC_OS' ? [] : duoDirs(config.apple);
const duoGroupId = duo.length ? await duoGroup(c) : '';
let duo = platform === 'MAC_OS' ? [] : duoDirs(config.apple);
// a Duo problem never stops the other sets
const duoGroupId = duo.length ? await duoGroup(c).catch((e: Error) => { warn('apple', `iPhone Duo skipped: ${e.message}`); duo = []; return ''; }) : '';
const appId = duo.length ? await c.app() : '';
if (platform === 'MAC_OS' && !config.apple?.mac) throw new Error('macOS version: set apple.mac: true and render the mac size (storebound shots render --size mac) first');
if (platform !== 'MAC_OS' && config.apple?.mac) log('apple', 'Mac screenshots (mac/, APP_DESKTOP) go to the macOS version: run apple screenshots --platform macos');
@ -129,7 +130,7 @@ export async function run(ctx: Ctx): Promise<void> {
if (duo.length) {
const files = duo.flatMap(dir => numberedImages(join(src, lang.id, dir)).filter(f => f.endsWith('.png')));
if (!files.length) warn('apple', `${locale}: nothing in ${duo.map(d => join(src, lang.id, d)).join(' or ')}, iPhone Duo skipped`);
else await syncDuo(c, { appId, group: duoGroupId, loc, files, dry: ctx.args.has('dry') });
else await syncDuo(c, { appId, group: duoGroupId, loc, files, dry: ctx.args.has('dry') }).catch((e: Error) => { warn('apple', `${locale} iPhone Duo: ${e.message}`); process.exitCode = 1; });
}
});
}

View file

@ -104,6 +104,7 @@ describe('iPhone Duo (foldable) sizes', () => {
{ placementProfileGroupId: 'g-mac', platform: 'MAC_OS', displayClassId: 'IPHONE_DUO' }] } }];
expect(duoGroups(ref)).toEqual(['g-duo']);
expect(duoGroups([])).toEqual([]);
expect(duoGroups([{ attributes: { placementProfileGroups: [{ placementProfileGroupId: 'IPHONE_DUO_PROFILE', platform: 'IPHONE_APP_STORE', displayClassId: 'IPHONE_DUO' }] } }])).toEqual(['IPHONE_DUO_PROFILE']);
expect(duoUpToDate(['a', 'b'], ['a', 'b'])).toBe(true);
expect(duoUpToDate(['b', 'a'], ['a', 'b'])).toBe(false);
expect(duoUpToDate(['a', undefined], ['a', 'b'])).toBe(false);