98 lines
3.9 KiB
JavaScript
98 lines
3.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Inject the Android release signing configuration.
|
|
*
|
|
* WHY THIS EXISTS
|
|
* ───────────────
|
|
* The Android project (android/) is generated and NOT tracked in git —
|
|
* `npm run android:init` recreates it with `cap add android`. Release signing
|
|
* therefore has to be re-applied after every regeneration, and its secrets must
|
|
* never be committed. Previously the keystore path, alias and passwords were
|
|
* hardcoded inline in android/app/build.gradle.
|
|
*
|
|
* This script (idempotent, part of the android build, same pattern as the other
|
|
* scripts/inject-*.mjs helpers):
|
|
* 1. Removes any previously managed signing block.
|
|
* 2. Removes a legacy hardcoded signingConfigs block (inline passwords).
|
|
* 3. Writes a managed signingConfigs block into android/app/build.gradle that
|
|
* reads secrets from the gitignored keystore.properties at the repo root.
|
|
*
|
|
* It exits quietly (0) when android/ isn't generated yet, or when
|
|
* keystore.properties is absent — so debug-only builds without a keystore still
|
|
* work.
|
|
*/
|
|
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, join } from 'node:path';
|
|
|
|
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
const buildGradle = join(root, 'android', 'app', 'build.gradle');
|
|
const keystoreProps = join(root, 'keystore.properties');
|
|
|
|
const BEGIN = '// >>> managed by scripts/inject-signing-config.mjs';
|
|
const END = '// <<< managed by scripts/inject-signing-config.mjs <<<';
|
|
|
|
if (!existsSync(buildGradle)) {
|
|
console.log('[inject-signing-config] android/ not generated yet — skipping.');
|
|
process.exit(0);
|
|
}
|
|
if (!existsSync(keystoreProps)) {
|
|
console.log('[inject-signing-config] keystore.properties not found — skipping release signing.');
|
|
process.exit(0);
|
|
}
|
|
|
|
const managedLines = [
|
|
`${BEGIN} >>>`,
|
|
'// Release signing is read from keystore.properties at the repo root',
|
|
'// (gitignored). Edit that file, not this block.',
|
|
'def _keystoreProps = new Properties()',
|
|
"def _keystorePropsFile = rootProject.file('../keystore.properties')",
|
|
'if (_keystorePropsFile.exists()) {',
|
|
' _keystorePropsFile.withInputStream { _keystoreProps.load(it) }',
|
|
'}',
|
|
'signingConfigs {',
|
|
' release {',
|
|
' if (_keystorePropsFile.exists()) {',
|
|
" storeFile rootProject.file(_keystoreProps['storeFile'])",
|
|
" storePassword _keystoreProps['storePassword']",
|
|
" keyAlias _keystoreProps['keyAlias']",
|
|
" keyPassword _keystoreProps['keyPassword']",
|
|
' }',
|
|
' }',
|
|
'}',
|
|
END,
|
|
];
|
|
const managed = managedLines.map((l) => ' ' + l).join('\n');
|
|
|
|
let src = readFileSync(buildGradle, 'utf8');
|
|
const before = src;
|
|
|
|
// 1. Drop any previously managed block so the script is idempotent.
|
|
const bIdx = src.indexOf(BEGIN);
|
|
if (bIdx !== -1) {
|
|
const eIdx = src.indexOf(END, bIdx);
|
|
if (eIdx !== -1) {
|
|
const lineStart = src.lastIndexOf('\n', bIdx);
|
|
const lineEnd = src.indexOf('\n', eIdx);
|
|
src = src.slice(0, lineStart) + (lineEnd === -1 ? '' : src.slice(lineEnd));
|
|
}
|
|
}
|
|
|
|
// 2. Drop a legacy hardcoded signingConfigs block (has an inline keyPassword).
|
|
src = src.replace(/\n[ \t]*signingConfigs\s*\{[\s\S]*?keyPassword\s+"[^"]*"\s*\}\s*\}/g, '');
|
|
|
|
// 3. Insert the managed block immediately after the `android {` opening.
|
|
const androidIdx = src.indexOf('android {');
|
|
if (androidIdx === -1) {
|
|
console.error('[inject-signing-config] could not find `android {` in build.gradle — aborting.');
|
|
process.exit(1);
|
|
}
|
|
const lineEnd = src.indexOf('\n', androidIdx);
|
|
src = src.slice(0, lineEnd + 1) + managed + '\n' + src.slice(lineEnd + 1);
|
|
|
|
if (src === before) {
|
|
console.log('[inject-signing-config] already up to date.');
|
|
} else {
|
|
writeFileSync(buildGradle, src);
|
|
console.log('[inject-signing-config] ✓ Wrote managed release signing config into android/app/build.gradle.');
|
|
}
|