Compare commits

...
Author SHA1 Message Date
evanbacon c8d4262aa7 Delete remote previews when removed from config
Update PreviewsTask to only sync/upload preview sets when previews are configured and to delete remote previews that are no longer present in the config. The task now retrieves existing preview sets, syncs configured preview types, and iterates existing sets to remove previews whose types were removed from the config (using preview.deleteAsync with logging). Add a unit test to cover deletion of remote previews and a small typing fix in the nock mock (cast adapter to any) to satisfy TypeScript.
2026-04-17 10:36:40 -07:00
3 changed files with 83 additions and 15 deletions

No files matched your search

@@ -5,4 +5,4 @@ import { getAdapter } from 'axios';
// see: https://github.com/nock/nock#axios
export { default } from 'nock';
getRequestClient().defaults.adapter = getAdapter('http');
getRequestClient().defaults.adapter = getAdapter('http') as any;
@@ -443,5 +443,54 @@ describe(PreviewsTask, () => {
})
);
});
it('deletes remote previews when preview type is removed from config', async () => {
const config = new AppleConfigReader({
info: {
'en-US': {
title: 'My App',
// No previews configured — the IPHONE_67 preview should be deleted
},
},
});
const locale = new AppStoreVersionLocalization(requestContext, 'LOC_1', {
locale: 'en-US',
} as any);
const existingPreview = new AppPreview(requestContext, 'PV_1', {
fileName: 'demo.mp4',
fileSize: 10240,
previewFrameTimeCode: null,
assetDeliveryState: { state: 'COMPLETE', errors: [], warnings: [] },
} as any);
const deleteScope = nock('https://api.appstoreconnect.apple.com')
.delete(`/v1/${AppPreview.type}/PV_1`)
.reply(204);
const previewTypeMap = new Map<PreviewType, AppPreviewSet>();
previewTypeMap.set(
PreviewType.IPHONE_67,
new AppPreviewSet(requestContext, 'PSET_1', {
previewType: PreviewType.IPHONE_67,
appPreviews: [existingPreview],
} as any)
);
const previewSets = new Map();
previewSets.set('en-US', previewTypeMap);
await new PreviewsTask().uploadAsync({
config,
context: {
previewSets,
versionLocales: [locale],
projectDir: '/test/project',
} as any,
});
expect(deleteScope.isDone()).toBeTruthy();
});
});
});
@@ -136,9 +136,7 @@ export class PreviewsTask extends AppleTask {
for (const localeCode of locales) {
const previews = config.getPreviews(localeCode);
if (!previews || Object.keys(previews).length === 0) {
continue;
}
const existingSets = context.previewSets.get(localeCode);
const localization = context.versionLocales.find(l => l.attributes.locale === localeCode);
if (!localization) {
@@ -146,18 +144,39 @@ export class PreviewsTask extends AppleTask {
continue;
}
for (const [previewType, previewConfig] of Object.entries(previews)) {
if (!previewConfig) {
continue;
}
// Upload/sync configured previews
if (previews) {
for (const [previewType, previewConfig] of Object.entries(previews)) {
if (!previewConfig) {
continue;
}
await syncPreviewSetAsync(
context.projectDir,
localization,
previewType as PreviewType,
normalizePreviewConfig(previewConfig),
context.previewSets.get(localeCode)
);
await syncPreviewSetAsync(
context.projectDir,
localization,
previewType as PreviewType,
normalizePreviewConfig(previewConfig),
existingSets
);
}
}
// Delete remote previews that are no longer in config
if (existingSets) {
for (const [previewType, previewSet] of existingSets) {
if (previews?.[previewType]) {
continue;
}
const existingPreviews = previewSet.attributes.appPreviews || [];
for (const preview of existingPreviews) {
await logAsync(() => preview.deleteAsync(), {
pending: `Deleting video preview ${chalk.bold(preview.attributes.fileName)} (${localeCode})...`,
success: `Deleted video preview ${chalk.bold(preview.attributes.fileName)} (${localeCode})`,
failure: `Failed deleting video preview ${chalk.bold(preview.attributes.fileName)} (${localeCode})`,
});
}
}
}
}
}