play release --dry: no bundle upload into a discarded edit (a long upload outlived it: edit expired); shows the planned tracks

This commit is contained in:
CRTkafa 2026-10-29 19:54:05 +07:00
parent ab69ce020c
commit f5296cc9e9
3 changed files with 17 additions and 0 deletions

View file

@ -3,6 +3,7 @@
## Unreleased
- `play release <aab> --dry` uploads nothing: it names the versionCode it would upload and the track changes it would make (the bundle went into a discarded edit, and a long upload could outlive the edit: "This edit has expired").
- `play build`: an absolute `--dir` / `play.build.dir` stays absolute (it was taken as a folder under the project and lost its leading slash); a `gradlew` without the exec bit (committed from Windows) is made executable with a note to commit the mode. The desktop release signs by key path only.
## 0.8.59 · 2026-10-29

View file

@ -82,12 +82,20 @@ export async function run(ctx: Ctx): Promise<void> {
}
let code = fixed ?? '';
let uploaded = false;
// a dry run never uploads: the bundle would go into an edit that is thrown away (14 MB for nothing, and a long
// upload can outlive the edit: "This edit has expired"); its tracks are shown, not PUT (Play refuses a track
// with a versionCode the edit does not have)
let planOnly = false;
if (aab) {
// a versionCode Play already has (an earlier run uploaded it) is reused, never uploaded twice
const info = aabInfo(aab);
if ((await usedVersionCodes(play, id)).includes(info.versionCode)) {
code = String(info.versionCode);
log('play', `versionCode ${code} is on Play already: not uploaded again`);
} else if (a.has('dry')) {
code = String(info.versionCode);
planOnly = true;
log('play', `dry run: would upload ${aab} (${(statSync(aab).size / 1048576).toFixed(1)} MB, versionCode ${code}); not uploaded`);
} else {
shipPhase('upload', `uploading ${aab}`, 0);
log('play', `uploading ${aab} (${(statSync(aab).size / 1048576).toFixed(1)} MB), this can take minutes`);
@ -108,6 +116,7 @@ export async function run(ctx: Ctx): Promise<void> {
if (t.status === 'inProgress') release.userFraction = Number(fraction ?? 0.1);
const cur = (await play.call<{ releases?: PlayTrackRelease[] }>('GET', `${play.API}/edits/${id}/tracks/${t.track}`).catch(() => ({ releases: [] }))).releases ?? [];
if (sameRelease(cur, release)) { log('play', `${t.track}: already ${t.status} ${code}, unchanged`); continue; }
if (planOnly) { log('play', `dry run: ${t.track} <- ${code} (${t.status}, notes in ${notes.length} languages)`); changed++; continue; }
await play.call('PUT', `${play.API}/edits/${id}/tracks/${t.track}`, { track: t.track, releases: [release] });
changed++;
log('play', `${t.track} <- ${code} (${t.status}, notes in ${notes.length} languages)`);

View file

@ -573,6 +573,13 @@ describe('listing, appinfo, data safety and the owner commands: a second run wri
expect(s.play.committed).toHaveLength(1);
});
test('play release <aab> --dry: no upload, no track PUT (the bundle went into a discarded edit; a long upload outlived it: "This edit has expired")', async () => {
const p = project(CONFIG, { 'store/listing.md': LISTING, 'build/android/app.aab': makeAab('com.example.notes', 43) });
const r = await twice(() => playRelease(p.ctx([join(p.root, 'build/android/app.aab'), '--internal', 'completed', '--dry'])));
expect(r.first.filter(x => x.includes('/bundles') || x.startsWith('PUT '))).toEqual([]);
expect(s.play.committed).toHaveLength(0);
});
test('prices import (Play): changed regions written once, then the diff is empty', async () => {
const p = project({ ...CONFIG, products: [CONFIG.products![0]!] }, { 'store/prices.csv': 'product,store,region,currency,price\ncom.example.notes.pro,play,DE,EUR,3.49\n' });
await capture(() => playProducts(p.ctx([])));