apple.macos listing / review notes per platform + iOS-only claim warnings; apple upload of a .pkg: bounded pkgutil, macOS processing wait, heartbeats; release 409 pattern

This commit is contained in:
CRTkafa 2026-11-03 23:30:59 +07:00
parent 53d57544bf
commit 1e47c2ee60
18 changed files with 417 additions and 63 deletions

View file

@ -3,14 +3,15 @@
// field takes up to 4000 bytes; a demo account must keep working during the whole review (Guideline 2.1).
// https://developer.apple.com/help/app-store-connect/reference/app-information/platform-version-information
// https://developer.apple.com/documentation/appstoreconnectapi/appstorereviewdetail/attributes-data.dictionary
import type { ShipConfig } from './config';
import { reviewNotesFor, type ShipConfig } from './config';
import { type DemoAccount, maskSecret, maskUser } from './credentials';
export const NOTES_MAX_BYTES = 4000;
/** Notes for the reviewer: apple.info.reviewNotes, then reviewAccess.instructions, then where account deletion is. */
export function reviewNotes(config: Pick<ShipConfig, 'apple' | 'reviewAccess' | 'accounts'>): string {
const parts = [config.apple?.info?.reviewNotes?.trim() ?? ''];
/** Notes for the reviewer: apple.info.reviewNotes (macOS: apple.macos.reviewNotes when set), then reviewAccess.instructions,
* then where account deletion is. */
export function reviewNotes(config: Pick<ShipConfig, 'apple' | 'reviewAccess' | 'accounts'>, platform?: string): string {
const parts = [reviewNotesFor(config, platform)?.trim() ?? ''];
const ins = config.reviewAccess?.instructions?.trim();
if (ins && !parts[0]!.includes(ins)) parts.push(`Sign-in: ${ins}`);
const del = config.accounts?.enabled ? config.accounts.inApp?.trim() : '';
@ -29,8 +30,8 @@ export interface ReviewDetailPlan {
* (throws when it is missing, so a submission never goes out with "sign-in required" and no account); without it the
* demo fields are cleared.
*/
export function reviewDetailPlan(config: Pick<ShipConfig, 'apple' | 'reviewAccess' | 'accounts'>, contact: Record<string, string>, demo: DemoAccount | null): ReviewDetailPlan {
const notes = reviewNotes(config);
export function reviewDetailPlan(config: Pick<ShipConfig, 'apple' | 'reviewAccess' | 'accounts'>, contact: Record<string, string>, demo: DemoAccount | null, platform?: string): ReviewDetailPlan {
const notes = reviewNotes(config, platform);
const bytes = new TextEncoder().encode(notes).length;
if (bytes > NOTES_MAX_BYTES) throw new Error(`review notes are ${bytes} bytes; App Store Connect takes ${NOTES_MAX_BYTES}`);
const required = !!config.reviewAccess?.signInRequired;