cross-store text: other platforms named in App Store text (2.3.10: Android, Google Play, ...) or Play text (Metadata: iOS, App Store, Game Center, ...) are refused by every text write (apple / play listing, play release / upload notes, listing set, whats-new, storebound edit, desktop editor), blockers in check / validate, scan other-platforms / play-other-platforms; listing.allowPlatformMentions for the owner's functional mentions; whats-new splits [apple] / [play] lines per store; storebound api --yes without a TTY is refused (exit 1, stderr) instead of a silent dry run; pitfalls 77, 78
This commit is contained in:
parent
3e4015b686
commit
edabbec874
32 changed files with 613 additions and 53 deletions
|
|
@ -12,6 +12,7 @@
|
|||
// storebound play listing pull [--write] [--json] live listings -> diff -> (with --write) the Play listing file
|
||||
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { parsePlayListing } from '../lib/copy';
|
||||
import { fieldsMentions, refuseMentions } from '../lib/cross-store';
|
||||
import { compactDiff } from '../lib/diff';
|
||||
import { mergePlayListing, overLimits } from '../lib/listing-pull';
|
||||
import { counts, draftReason, draftSections, type ItemPlan, itemLines, planItem, type Skipped } from '../lib/listing-plan';
|
||||
|
|
@ -21,6 +22,12 @@ import { done, log, printJson, step, warn } from '../lib/log';
|
|||
import { playClient } from './client';
|
||||
import { stdinIsTTY } from '../lib/tty';
|
||||
|
||||
/** Play release notes that name iOS, iPhone, App Store, ... are refused before any edit, dry runs included (pitfall 77). */
|
||||
export function refusePlayNotes(ctx: Ctx, notes: { language: string; text: string }[], what: string): void {
|
||||
const allow = ctx.loaded.config.listing?.allowPlatformMentions;
|
||||
refuseMentions(notes.flatMap(n => fieldsMentions('play', n.language, { whatsNew: n.text }, allow)), what);
|
||||
}
|
||||
|
||||
export function readPlayCopy(ctx: Ctx) {
|
||||
const { config, resolve } = ctx.loaded;
|
||||
const file = resolve(config.play?.listing ?? 'store/listing.md');
|
||||
|
|
@ -125,6 +132,8 @@ export async function run(ctx: Ctx): Promise<void> {
|
|||
skipped.push({ key: c.lang, reason: draftReason(st) });
|
||||
return false;
|
||||
});
|
||||
// Play Metadata policy: iOS / App Store / Game Center in Play text stop the run, dry runs included (pitfall 77)
|
||||
refuseMentions(copy.flatMap(c => fieldsMentions('play', c.lang, { title: c.title, short: c.short, full: c.full }, config.listing?.allowPlatformMentions)), `play listing${a.has('dry') ? ' (dry run)' : ''}`);
|
||||
const details = { defaultLanguage: config.play?.defaultLanguage ?? 'en-US', contactEmail: config.app.contactEmail, contactWebsite: config.app.website };
|
||||
if (!all.some(c => c.lang === details.defaultLanguage) && !a.has('only')) throw new Error(`listing has no section for the default language ${details.defaultLanguage}`);
|
||||
if (!a.has('json')) log('play', `${copy.length} listings: ${copy.map(c => c.lang).join(', ')}${config.play?.video ? ` · promo video ${config.play.video}` : ''}`);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { done, log, warn } from '../lib/log';
|
|||
import { aabInfo } from '../lib/gradle';
|
||||
import { playClient } from './client';
|
||||
import { usedVersionCodes } from './next-version-code';
|
||||
import { readPlayCopy } from './listing';
|
||||
import { readPlayCopy, refusePlayNotes } from './listing';
|
||||
|
||||
const TRACKS = ['internal', 'alpha', 'beta', 'production'];
|
||||
|
||||
|
|
@ -45,9 +45,10 @@ export async function run(ctx: Ctx): Promise<void> {
|
|||
for (const t of tracks) if (!STATUSES.includes(t.status)) throw new Error(`--${t.track}: status must be one of ${STATUSES.join(', ')}`);
|
||||
const fraction = a.get('fraction');
|
||||
const live = tracks.find(t => t.track === 'production' && t.status !== 'draft');
|
||||
const notes = readPlayCopy(ctx).filter(c => c.whatsNew).map(c => ({ language: c.lang, text: c.whatsNew }));
|
||||
refusePlayNotes(ctx, notes, `play release notes${a.has('dry') ? ' (dry run)' : ''}`);
|
||||
if (live && !a.has('dry') && !(await confirm(ctx, `Release to PRODUCTION as "${live.status}" (public once Google approves)?`))) return;
|
||||
|
||||
const notes = readPlayCopy(ctx).filter(c => c.whatsNew).map(c => ({ language: c.lang, text: c.whatsNew }));
|
||||
const play = await playClient(root, pkg);
|
||||
try {
|
||||
await play.edit(async (id, ctl) => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { aabInfo } from '../lib/gradle';
|
|||
import { done, log, printJson } from '../lib/log';
|
||||
import { nextVersionCode } from '../lib/release';
|
||||
import { playClient } from './client';
|
||||
import { readPlayCopy } from './listing';
|
||||
import { readPlayCopy, refusePlayNotes } from './listing';
|
||||
import { usedVersionCodes } from './next-version-code';
|
||||
|
||||
const TAG = 'upload';
|
||||
|
|
@ -43,6 +43,7 @@ export async function run(ctx: Ctx): Promise<void> {
|
|||
const dry = a.has('dry');
|
||||
const json = a.has('json');
|
||||
const notes = readPlayCopy(ctx).filter(c => c.whatsNew).map(c => ({ language: c.lang, text: c.whatsNew }));
|
||||
refusePlayNotes(ctx, notes, `play upload release notes${dry ? ' (dry run)' : ''}`);
|
||||
const play = await playClient(root, pkg);
|
||||
const { used, current } = await play.read(async id => ({
|
||||
used: await usedVersionCodes(play, id),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue