storebound/cli/play/next-version-code.ts
CRT 41319562d8 Signing, builds, uploads and an originality check
apple signing status|ensure: bundle id capabilities, a distribution certificate from a key made locally (kept in .storebound/signing, never printed), App Store profiles installed for Xcode; Developer ID 403 explained.
apple build / apple upload: xcodebuild archive + export with a generated ExportOptions.plist, next build number, App Store Connect API build upload (or altool), processing wait. Native, Capacitor, React Native, Flutter, Unity projects.
play build / play upload: Gradle bundleRelease with the upload key passed through the environment, next versionCode read back from the AAB, testing tracks only.
originality: offline Guideline 4.3 check (name, listing text, icon and screenshot perceptual hashes, project structure).
New skill build-and-sign; zero new dependencies.
2026-10-11 23:42:48 +08:00

32 lines
2 KiB
TypeScript

// Next Play versionCode: one above every code in uploaded bundles and on any track. Read-only (the edit is deleted).
// Prints only the number on stdout:
// storebound play next-version-code -> 43
// ./gradlew bundleRelease -PversionCode=$(storebound play next-version-code)
import type { Ctx } from '../lib/ctx';
import { need } from '../lib/ctx';
import { printJson } from '../lib/log';
import { nextVersionCode } from '../lib/release';
import { type PlayClient, playClient } from './client';
/** Every versionCode Play knows for the app: uploaded bundles and APKs, and the codes on every track (read-only edit). */
export async function usedVersionCodes(play: PlayClient, id: string): Promise<number[]> {
const bundles = (await play.call<{ bundles?: { versionCode: number }[] }>('GET', `${play.API}/edits/${id}/bundles`)).bundles ?? [];
const apks = (await play.call<{ apks?: { versionCode: number }[] }>('GET', `${play.API}/edits/${id}/apks`).catch(() => ({ apks: [] }))).apks ?? [];
const tracks = (await play.call<{ tracks?: { releases?: { versionCodes?: string[] }[] }[] }>('GET', `${play.API}/edits/${id}/tracks`)).tracks ?? [];
return [...bundles.map(b => b.versionCode), ...apks.map(a => a.versionCode), ...tracks.flatMap(t => (t.releases ?? []).flatMap(r => (r.versionCodes ?? []).map(Number)))];
}
export async function run(ctx: Ctx): Promise<void> {
const { config, root } = ctx.loaded;
const play = await playClient(root, need(config.play?.packageName, 'play.packageName'));
await play.read(async id => {
const codes = await usedVersionCodes(play, id);
// the same code is in the bundle list and on every track it was released to: count distinct codes
const distinct = new Set(codes.map(String)).size;
if (ctx.args.has('json')) printJson({ next: nextVersionCode(codes), seen: distinct });
else {
console.error(`[play] ${distinct} distinct version code(s) in bundles, APKs and tracks; next versionCode:`);
console.log(nextVersionCode(codes));
}
});
}