- ChatBubble: useActionSheet replaces custom Modal (native iOS popup, Android bottom sheet) - DM mode (isDM prop): hides like-count, shows Insta-style heart badge under bubble when liked - Group chat unchanged - Cleanup: remove unused Modal/Platform imports, sheet styles, actionsOpen state - deploy.sh: auto-detect ANDROID_HOME + auto-create local.properties for local Gradle - NEXT_RELEASE.md: DM reactions release note - Includes other staged work across binder-mac, marketing, ops/mdm, ios/
180 lines
6.1 KiB
JavaScript
180 lines
6.1 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* play-submit.mjs — Google Play Console AAB/APK Upload
|
|
*
|
|
* Nutzt die Google Play Developer API (v3) via googleapis package.
|
|
* Lädt AAB/APK direkt in einen Track (internal/alpha/beta/production).
|
|
*
|
|
* Usage:
|
|
* node scripts/play-submit.mjs \
|
|
* --package org.rebreak.app \
|
|
* --aab android/app/build/outputs/bundle/release/app-release.aab \
|
|
* --track internal \
|
|
* --service-account ~/secrets/rebreak-play-service-account.json
|
|
*
|
|
* Env-Variablen (Fallback):
|
|
* PLAY_SERVICE_ACCOUNT_JSON — Pfad zum Service-Account-JSON
|
|
*
|
|
* Service-Account-Setup:
|
|
* 1. Google Cloud Console → IAM & Admin → Service Accounts
|
|
* 2. Create Service Account → JSON-Key downloaden
|
|
* 3. Play Console → Setup → API-Access → Service-Account verlinken
|
|
* 4. Permissions: "Releases" (Edit + Read)
|
|
*
|
|
* Exit-Codes:
|
|
* 0 — Upload erfolgreich
|
|
* 1 — Fehler (File nicht gefunden, Auth-Fehler, API-Fehler)
|
|
*/
|
|
|
|
import { readFile } from 'fs/promises';
|
|
import { createReadStream } from 'fs';
|
|
import { resolve } from 'path';
|
|
import { google } from 'googleapis';
|
|
|
|
// ─── CLI-Args ────────────────────────────────────────────────────────────────
|
|
|
|
const args = process.argv.slice(2);
|
|
const getArg = (flag) => {
|
|
const idx = args.indexOf(flag);
|
|
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : null;
|
|
};
|
|
|
|
const packageName = getArg('--package');
|
|
const aabPath = getArg('--aab');
|
|
const track = getArg('--track') || 'internal';
|
|
const serviceAccountPath = getArg('--service-account') || process.env.PLAY_SERVICE_ACCOUNT_JSON || `${process.env.HOME}/secrets/rebreak-play-service-account.json`;
|
|
|
|
if (!packageName || !aabPath) {
|
|
console.error(`ERROR: Fehlende Args
|
|
|
|
Usage:
|
|
node scripts/play-submit.mjs \\
|
|
--package <package-name> \\
|
|
--aab <path-to-aab> \\
|
|
[--track <internal|alpha|beta|production>] \\
|
|
[--service-account <path-to-json>]
|
|
|
|
Env-Variablen (Fallback):
|
|
PLAY_SERVICE_ACCOUNT_JSON — Service-Account-JSON-Pfad
|
|
`);
|
|
process.exit(1);
|
|
}
|
|
|
|
// ─── Auth ────────────────────────────────────────────────────────────────────
|
|
|
|
const expandTilde = (p) => p.replace(/^~/, process.env.HOME);
|
|
const serviceAccountFullPath = resolve(expandTilde(serviceAccountPath));
|
|
const aabFullPath = resolve(expandTilde(aabPath));
|
|
|
|
let auth;
|
|
try {
|
|
const keyFile = await readFile(serviceAccountFullPath, 'utf-8');
|
|
const credentials = JSON.parse(keyFile);
|
|
|
|
auth = new google.auth.GoogleAuth({
|
|
credentials,
|
|
scopes: ['https://www.googleapis.com/auth/androidpublisher'],
|
|
});
|
|
|
|
console.log(`[play-submit] Auth: ${serviceAccountFullPath}`);
|
|
} catch (err) {
|
|
console.error(`ERROR: Service-Account-JSON konnte nicht geladen werden
|
|
|
|
Pfad: ${serviceAccountFullPath}
|
|
Fehler: ${err.message}
|
|
|
|
Setup:
|
|
1. Google Cloud Console → Service Accounts → Create → JSON-Key
|
|
2. Play Console → Setup → API-Access → Service-Account linken
|
|
3. Permissions: "Releases" (Edit + Read)
|
|
4. JSON-Key ablegen in ~/secrets/ (NICHT committen)
|
|
`);
|
|
process.exit(1);
|
|
}
|
|
|
|
// ─── Upload ─────────────────────────────────────────────────────────────────
|
|
|
|
const androidpublisher = google.androidpublisher({ version: 'v3', auth });
|
|
|
|
try {
|
|
console.log(`[play-submit] Package : ${packageName}`);
|
|
console.log(`[play-submit] AAB : ${aabFullPath}`);
|
|
console.log(`[play-submit] Track : ${track}`);
|
|
console.log('');
|
|
|
|
// 1. Edit erstellen (neue Transaction)
|
|
console.log('[play-submit] → Creating edit...');
|
|
const editRes = await androidpublisher.edits.insert({
|
|
packageName,
|
|
});
|
|
const editId = editRes.data.id;
|
|
console.log(`[play-submit] Edit-ID: ${editId}`);
|
|
|
|
// 2. AAB/APK hochladen
|
|
console.log('[play-submit] → Uploading AAB...');
|
|
const uploadRes = await androidpublisher.edits.bundles.upload({
|
|
packageName,
|
|
editId,
|
|
media: {
|
|
mimeType: 'application/octet-stream',
|
|
body: createReadStream(aabFullPath),
|
|
},
|
|
});
|
|
|
|
const versionCode = uploadRes.data.versionCode;
|
|
console.log(`[play-submit] Version-Code: ${versionCode}`);
|
|
|
|
// 3. Track-Assignment (Bundle in Track packen)
|
|
console.log(`[play-submit] → Assigning to track '${track}'...`);
|
|
await androidpublisher.edits.tracks.update({
|
|
packageName,
|
|
editId,
|
|
track,
|
|
requestBody: {
|
|
track,
|
|
releases: [
|
|
{
|
|
versionCodes: [String(versionCode)],
|
|
status: 'completed', // Draft = 'draft', Live = 'completed'
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// 4. Edit committen (Transaction abschließen)
|
|
console.log('[play-submit] → Committing edit...');
|
|
await androidpublisher.edits.commit({
|
|
packageName,
|
|
editId,
|
|
});
|
|
|
|
console.log('');
|
|
console.log(`✓ Upload erfolgreich!`);
|
|
console.log(` Version-Code: ${versionCode}`);
|
|
console.log(` Track : ${track}`);
|
|
console.log(` Play-Console: https://play.google.com/console/u/0/developers/${packageName.split('.')[1]}/app/${packageName}/tracks/${track}`);
|
|
console.log('');
|
|
console.log('Status-Check:');
|
|
console.log(` Release erscheint in ~10-30min im Play-Console-Dashboard`);
|
|
|
|
} catch (err) {
|
|
console.error('');
|
|
console.error('ERROR: Upload fehlgeschlagen');
|
|
console.error('');
|
|
console.error(`Fehler: ${err.message}`);
|
|
|
|
if (err.response?.data) {
|
|
console.error('API-Response:', JSON.stringify(err.response.data, null, 2));
|
|
}
|
|
|
|
console.error('');
|
|
console.error('Mögliche Ursachen:');
|
|
console.error(' - Service-Account hat keine "Releases"-Permission im Play-Console');
|
|
console.error(' - Package-Name stimmt nicht mit dem im Play-Console überein');
|
|
console.error(' - Version-Code existiert bereits (muss unique + monoton steigend sein)');
|
|
console.error(' - AAB ist nicht korrekt signiert (Keystore-Hash muss in Play-Console registriert sein)');
|
|
console.error('');
|
|
|
|
process.exit(1);
|
|
}
|