chore(android): move release signing secrets to gitignored keystore.properties
This commit is contained in:
parent
0ac57d4250
commit
fc0231bea5
3 changed files with 102 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -35,6 +35,7 @@ yarn.lock
|
||||||
# Local secrets & signing material (never commit)
|
# Local secrets & signing material (never commit)
|
||||||
*.jks
|
*.jks
|
||||||
*.keystore
|
*.keystore
|
||||||
|
keystore.properties
|
||||||
local.properties
|
local.properties
|
||||||
|
|
||||||
# Local build artifacts
|
# Local build artifacts
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@
|
||||||
"build": "npm i --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'Project built successfully!'",
|
"build": "npm i --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'Project built successfully!'",
|
||||||
"test": "npm i --silent && tsc --noEmit && eslint && vitest run --reporter=dot --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'All tests passed!'",
|
"test": "npm i --silent && tsc --noEmit && eslint && vitest run --reporter=dot --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'All tests passed!'",
|
||||||
"deploy": "npm i --silent && npm run build && npx -y nostr-deploy-cli deploy --skip-setup",
|
"deploy": "npm i --silent && npm run build && npx -y nostr-deploy-cli deploy --skip-setup",
|
||||||
"android:init": "npm run android:build:apk && npx cap add android && npx cap sync android && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs",
|
"android:init": "npm run android:build:apk && npx cap add android && npx cap sync android && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs && node scripts/inject-signing-config.mjs",
|
||||||
"android:sync": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs",
|
"android:sync": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs && node scripts/inject-signing-config.mjs",
|
||||||
"android:open": "npx cap open android",
|
"android:open": "npx cap open android",
|
||||||
"android:version": "node scripts/sync-android-version.mjs",
|
"android:version": "node scripts/sync-android-version.mjs",
|
||||||
"android:build": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs && cd android && ./gradlew assembleRelease",
|
"android:build": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs && node scripts/inject-signing-config.mjs && cd android && ./gradlew assembleRelease",
|
||||||
"android:build:apk": "CAPACITOR_BUILD=1 vite build && sed -i 's|<script type=\"module\" src=\"/shakespeare_tailwind[^\"]*\\.js\"></script>||g' dist/index.html && sed -i 's|<style type=\"text/tailwindcss\">|<style>|g' dist/index.html && cp dist/index.html dist/404.html"
|
"android:build:apk": "CAPACITOR_BUILD=1 vite build && sed -i 's|<script type=\"module\" src=\"/shakespeare_tailwind[^\"]*\\.js\"></script>||g' dist/index.html && sed -i 's|<style type=\"text/tailwindcss\">|<style>|g' dist/index.html && cp dist/index.html dist/404.html"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
98
scripts/inject-signing-config.mjs
Normal file
98
scripts/inject-signing-config.mjs
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#!/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.');
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue