fix(release): enforce Android version parity (#141)

Adds a deterministic metadata guard before CI and F-Droid builds so generated release artifacts cannot silently inherit stale Gradle versions.\n\nPlan: https://github.com/dzianisv/opencode-mobile/issues/95#issuecomment-5047827673

Co-authored-by: engineer <engineer@gray-knight-m1.local>
This commit is contained in:
Den
2026-07-22 08:50:35 -07:00
committed by GitHub
parent 47363280f6
commit 5f9dd2a80c
5 changed files with 40 additions and 2 deletions

View File

@@ -23,6 +23,9 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm install --legacy-peer-deps run: npm install --legacy-peer-deps
- name: Check release version metadata
run: npm run check:versions
- name: Typecheck - name: Typecheck
run: npm run typecheck run: npm run typecheck

View File

@@ -46,6 +46,9 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm install --legacy-peer-deps run: npm install --legacy-peer-deps
- name: Check release version metadata
run: npm run check:versions
- name: Set Sentry release identifiers - name: Set Sentry release identifiers
# sentry.gradle (applied from android/app/build.gradle) defaults the # sentry.gradle (applied from android/app/build.gradle) defaults the
# upload's --release/--dist to `${applicationId}@${versionName}+${versionCode}`, # upload's --release/--dist to `${applicationId}@${versionName}+${versionCode}`,

View File

@@ -94,8 +94,8 @@ android {
applicationId 'cc.agentlabs.opencode' applicationId 'cc.agentlabs.opencode'
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 34 versionCode 37
versionName "0.4.7" versionName "0.4.10"
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\"" buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
} }

View File

@@ -9,6 +9,7 @@
"ios": "expo run:ios", "ios": "expo run:ios",
"android": "expo run:android", "android": "expo run:android",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"check:versions": "node scripts/check-version-parity.mjs",
"test": "node --test 'src/**/*.test.ts'" "test": "node --test 'src/**/*.test.ts'"
}, },
"dependencies": { "dependencies": {

View File

@@ -0,0 +1,31 @@
import { readFile } from "node:fs/promises";
const app = JSON.parse(await readFile("app.json", "utf8"));
const pkg = JSON.parse(await readFile("package.json", "utf8"));
const gradle = await readFile("android/app/build.gradle", "utf8");
const name = gradle.match(/^\s*versionName\s+"([^"]+)"/m)?.[1];
const code = Number(gradle.match(/^\s*versionCode\s+(\d+)/m)?.[1]);
const expectedName = app.expo.version;
const expectedCode = app.expo.android.versionCode;
const errors = [];
if (pkg.version !== expectedName) {
errors.push(`package.json version ${pkg.version} != app.json version ${expectedName}`);
}
if (name !== expectedName) {
errors.push(`Gradle versionName ${name ?? "missing"} != app.json version ${expectedName}`);
}
if (code !== expectedCode) {
errors.push(`Gradle versionCode ${Number.isNaN(code) ? "missing" : code} != app.json versionCode ${expectedCode}`);
}
if (errors.length) {
console.error(errors.join("\n"));
process.exitCode = 1;
} else {
console.log(`Version metadata aligned: ${expectedName} (${expectedCode})`);
}