codeplay-common 4.8.7 → 4.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/files/finalrelease +117 -49
- package/package.json +1 -1
package/files/finalrelease
CHANGED
|
@@ -7,7 +7,7 @@ node finalrelease "1,2,7"
|
|
|
7
7
|
|
|
8
8
|
import { existsSync, readFileSync, readdirSync, promises, constants, writeFileSync, unlinkSync, mkdirSync, renameSync } from 'fs';
|
|
9
9
|
import { join, resolve } from 'path';
|
|
10
|
-
import { execSync, execFileSync } from 'child_process';
|
|
10
|
+
import { execSync, execFileSync } from 'child_process';
|
|
11
11
|
import { createInterface } from 'readline';
|
|
12
12
|
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
@@ -179,49 +179,49 @@ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
|
179
179
|
|
|
180
180
|
const _appUniqueId = config.android?.APP_UNIQUE_ID;
|
|
181
181
|
const _appName=config.appName;
|
|
182
|
-
const _appPackageId=config.appId;
|
|
183
|
-
|
|
184
|
-
const releaseSyncConfigPath = join(__dirname, 'buildCodeplay', 'release-sync.config.json');
|
|
185
|
-
let releaseSyncConfig = {};
|
|
186
|
-
if (existsSync(releaseSyncConfigPath)) {
|
|
187
|
-
try {
|
|
188
|
-
releaseSyncConfig = JSON.parse(readFileSync(releaseSyncConfigPath, 'utf8'));
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.warn(`⚠️ Could not read ${releaseSyncConfigPath}: ${error.message}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
const RELEASE_SYNC_URL = process.env.CODEPLAY_RELEASE_SYNC_URL || releaseSyncConfig.url || 'https://htmlcodeplay.com/codeplay/api/v1/release/sync';
|
|
194
|
-
const RELEASE_SYNC_TOKEN = process.env.CODEPLAY_RELEASE_SYNC_TOKEN || releaseSyncConfig.token || '';
|
|
195
|
-
const RELEASE_PLATFORM_IDS = { PlayStore: 1, SamsungStore: 13, AmazonStore: 17, MiStore: 15, HuaweiStore: 12, OppoStore: 14, VivoStore: 16 };
|
|
196
|
-
|
|
197
|
-
function syncReleaseToCodeplay(storeName, finalVersionName, finalVersionCode, releasedDate) {
|
|
198
|
-
if (!RELEASE_SYNC_TOKEN) {
|
|
199
|
-
console.warn(`⚠️ Codeplay release sync skipped: add a token to ${releaseSyncConfigPath}.`);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const payload = JSON.stringify({
|
|
203
|
-
app_name: _appName,
|
|
204
|
-
package_id: _appPackageId,
|
|
205
|
-
version_name: String(finalVersionName),
|
|
206
|
-
version_code: String(finalVersionCode),
|
|
207
|
-
released_date: releasedDate,
|
|
208
|
-
language_id: 0,
|
|
209
|
-
language_name: 'Capacitor+ Framework 7',
|
|
210
|
-
notes: 'Automated release update',
|
|
211
|
-
status: 1,
|
|
212
|
-
folder_name: path.basename(process.cwd()),
|
|
213
|
-
app_unique_id: String(_appUniqueId || ''),
|
|
214
|
-
platform_id: RELEASE_PLATFORM_IDS[storeName],
|
|
215
|
-
});
|
|
216
|
-
try {
|
|
217
|
-
const response = execFileSync('curl.exe', ['-sS', '--fail-with-body', '-X', 'POST', RELEASE_SYNC_URL,
|
|
218
|
-
'-H', 'Content-Type: application/json', '-H', `X-Release-Token: ${RELEASE_SYNC_TOKEN}`, '--data-binary', payload],
|
|
219
|
-
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
220
|
-
console.log(`✅ Codeplay sync (${storeName}): ${response.trim()}`);
|
|
221
|
-
} catch (error) {
|
|
222
|
-
console.warn(`⚠️ Codeplay sync failed for ${storeName}; continuing release builds: ${error.message}`);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
182
|
+
const _appPackageId=config.appId;
|
|
183
|
+
|
|
184
|
+
const releaseSyncConfigPath = join(__dirname, 'buildCodeplay', 'release-sync.config.json');
|
|
185
|
+
let releaseSyncConfig = {};
|
|
186
|
+
if (existsSync(releaseSyncConfigPath)) {
|
|
187
|
+
try {
|
|
188
|
+
releaseSyncConfig = JSON.parse(readFileSync(releaseSyncConfigPath, 'utf8'));
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.warn(`⚠️ Could not read ${releaseSyncConfigPath}: ${error.message}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const RELEASE_SYNC_URL = process.env.CODEPLAY_RELEASE_SYNC_URL || releaseSyncConfig.url || 'https://htmlcodeplay.com/codeplay/api/v1/release/sync';
|
|
194
|
+
const RELEASE_SYNC_TOKEN = process.env.CODEPLAY_RELEASE_SYNC_TOKEN || releaseSyncConfig.token || '';
|
|
195
|
+
const RELEASE_PLATFORM_IDS = { PlayStore: 1, SamsungStore: 13, AmazonStore: 17, MiStore: 15, HuaweiStore: 12, OppoStore: 14, VivoStore: 16 };
|
|
196
|
+
|
|
197
|
+
function syncReleaseToCodeplay(storeName, finalVersionName, finalVersionCode, releasedDate) {
|
|
198
|
+
if (!RELEASE_SYNC_TOKEN) {
|
|
199
|
+
console.warn(`⚠️ Codeplay release sync skipped: add a token to ${releaseSyncConfigPath}.`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const payload = JSON.stringify({
|
|
203
|
+
app_name: _appName,
|
|
204
|
+
package_id: _appPackageId,
|
|
205
|
+
version_name: String(finalVersionName),
|
|
206
|
+
version_code: String(finalVersionCode),
|
|
207
|
+
released_date: releasedDate,
|
|
208
|
+
language_id: 0,
|
|
209
|
+
language_name: 'Capacitor+ Framework 7',
|
|
210
|
+
notes: 'Automated release update',
|
|
211
|
+
status: 1,
|
|
212
|
+
folder_name: path.basename(process.cwd()),
|
|
213
|
+
app_unique_id: String(_appUniqueId || ''),
|
|
214
|
+
platform_id: RELEASE_PLATFORM_IDS[storeName],
|
|
215
|
+
});
|
|
216
|
+
try {
|
|
217
|
+
const response = execFileSync('curl.exe', ['-sS', '--fail-with-body', '-X', 'POST', RELEASE_SYNC_URL,
|
|
218
|
+
'-H', 'Content-Type: application/json', '-H', `X-Release-Token: ${RELEASE_SYNC_TOKEN}`, '--data-binary', payload],
|
|
219
|
+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
220
|
+
console.log(`✅ Codeplay sync (${storeName}): ${response.trim()}`);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.warn(`⚠️ Codeplay sync failed for ${storeName}; continuing release builds: ${error.message}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
225
|
|
|
226
226
|
const FLOWCHART_API_APP_ID = 228;
|
|
227
227
|
const FLOWCHART_SHARED_PATH = join('public', 'src', 'shared.js');
|
|
@@ -742,6 +742,71 @@ function findGradleBlock(content, headerPattern) {
|
|
|
742
742
|
return null;
|
|
743
743
|
}
|
|
744
744
|
|
|
745
|
+
function ensureReleaseCodeOptimization() {
|
|
746
|
+
const currentContent = readFileSync(gradleFilePath, 'utf8');
|
|
747
|
+
const releaseBlock = findGradleBlock(currentContent, /buildTypes\s*\{[\s\S]*?\brelease\s*/);
|
|
748
|
+
if (!releaseBlock) throw new Error('Release build configuration was not found.');
|
|
749
|
+
|
|
750
|
+
const releaseContent = currentContent.slice(releaseBlock.start, releaseBlock.end);
|
|
751
|
+
const optimizedContent = releaseContent.replace(
|
|
752
|
+
/getDefaultProguardFile\(\s*(['"])proguard-android\.txt\1\s*\)/g,
|
|
753
|
+
"getDefaultProguardFile('proguard-android-optimize.txt')"
|
|
754
|
+
);
|
|
755
|
+
if (!/getDefaultProguardFile\(\s*(['"])proguard-android-optimize\.txt\1\s*\)/.test(optimizedContent)) {
|
|
756
|
+
throw new Error('Release build must use the optimisation-enabled default ProGuard rules.');
|
|
757
|
+
}
|
|
758
|
+
if (optimizedContent !== releaseContent) {
|
|
759
|
+
writeFileSync(gradleFilePath, currentContent.slice(0, releaseBlock.start)
|
|
760
|
+
+ optimizedContent + currentContent.slice(releaseBlock.end), 'utf8');
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function signReleaseBundleWithSha256() {
|
|
765
|
+
const buildOptions = readCapacitorConfig().android?.buildOptions;
|
|
766
|
+
if (!buildOptions?.keystorePath || !buildOptions.keystorePassword
|
|
767
|
+
|| !buildOptions.keystoreAlias || !buildOptions.keystoreAliasPassword) {
|
|
768
|
+
throw new Error('Android AAB signing requires the existing keystore path, alias and passwords.');
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
const keystorePath = resolve(__dirname, 'android', buildOptions.keystorePath);
|
|
772
|
+
const bundleDirectory = join(__dirname, 'android', 'app', 'build', 'outputs', 'bundle', 'release');
|
|
773
|
+
const unsignedBundle = join(bundleDirectory, 'app-release.aab');
|
|
774
|
+
const signedBundle = join(bundleDirectory, 'app-release-signed.aab');
|
|
775
|
+
if (!existsSync(keystorePath) || !existsSync(unsignedBundle)) {
|
|
776
|
+
throw new Error('The configured upload keystore or release AAB was not found.');
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const jarsigner = process.env.JAVA_HOME
|
|
780
|
+
? join(process.env.JAVA_HOME, 'bin', process.platform === 'win32' ? 'jarsigner.exe' : 'jarsigner')
|
|
781
|
+
: 'jarsigner';
|
|
782
|
+
try {
|
|
783
|
+
// Keep passwords out of command arguments and error output.
|
|
784
|
+
execFileSync(jarsigner, [
|
|
785
|
+
'-sigalg', 'SHA256withRSA', '-digestalg', 'SHA-256',
|
|
786
|
+
'-keystore', keystorePath,
|
|
787
|
+
'-storepass:env', 'CODEPLAY_AAB_STORE_PASSWORD',
|
|
788
|
+
'-keypass:env', 'CODEPLAY_AAB_KEY_PASSWORD',
|
|
789
|
+
'-signedjar', signedBundle, unsignedBundle, buildOptions.keystoreAlias,
|
|
790
|
+
], {
|
|
791
|
+
stdio: 'pipe',
|
|
792
|
+
env: {
|
|
793
|
+
...process.env,
|
|
794
|
+
CODEPLAY_AAB_STORE_PASSWORD: buildOptions.keystorePassword,
|
|
795
|
+
CODEPLAY_AAB_KEY_PASSWORD: buildOptions.keystoreAliasPassword,
|
|
796
|
+
},
|
|
797
|
+
});
|
|
798
|
+
const verification = execFileSync(jarsigner, [
|
|
799
|
+
'-J-Duser.language=en', '-J-Duser.country=US', '-verify', signedBundle,
|
|
800
|
+
], { encoding: 'utf8', stdio: 'pipe' });
|
|
801
|
+
if (!verification.includes('jar verified.') || verification.includes('treated as unsigned')) {
|
|
802
|
+
throw new Error('Signature verification failed.');
|
|
803
|
+
}
|
|
804
|
+
} catch {
|
|
805
|
+
throw new Error('SHA-256 AAB signing or verification failed. Check the configured upload key and JDK; release stopped.');
|
|
806
|
+
}
|
|
807
|
+
console.log('✅ Release AAB signed with SHA-256 using the existing upload key and signature verified.');
|
|
808
|
+
}
|
|
809
|
+
|
|
745
810
|
const amazonWindowExtensionsDependency = 'implementation "androidx.window.extensions.core:core:1.0.0"';
|
|
746
811
|
const amazonWindowExtensionsDependencyPattern = /^[ \t]*implementation\s+["']androidx\.window\.extensions\.core:core:[^"']+["'][ \t]*(?:\r?\n)?/gm;
|
|
747
812
|
|
|
@@ -1013,11 +1078,14 @@ rl.question('Enter new versionCode (press enter to keep current): ', (newVersion
|
|
|
1013
1078
|
|
|
1014
1079
|
execSync('npx cap sync android', { stdio: 'inherit' });
|
|
1015
1080
|
|
|
1081
|
+
ensureReleaseCodeOptimization();
|
|
1082
|
+
|
|
1016
1083
|
if (buildType === "APK") {
|
|
1017
1084
|
console.log("📦 Using custom Node signing script for APK build...");
|
|
1018
1085
|
execSync('node buildCodeplay/apk-store-builder.js', { stdio: 'inherit' });
|
|
1019
1086
|
} else {
|
|
1020
1087
|
execSync(`npx cap build android --androidreleasetype=${buildType}`, { stdio: 'inherit' });
|
|
1088
|
+
signReleaseBundleWithSha256();
|
|
1021
1089
|
}
|
|
1022
1090
|
|
|
1023
1091
|
|
|
@@ -1036,11 +1104,11 @@ rl.question('Enter new versionCode (press enter to keep current): ', (newVersion
|
|
|
1036
1104
|
const checkFullPath = join("AAB", newFileName.replace(/\.aab$/, `.${newExt}`));
|
|
1037
1105
|
|
|
1038
1106
|
// Rename the output file
|
|
1039
|
-
if (existsSync(oldFilePath)) {
|
|
1040
|
-
renameSync(oldFilePath, checkFullPath);
|
|
1041
|
-
console.log(`✅ Renamed output ${newExt.toUpperCase()} file to: ${path.basename(checkFullPath)}`);
|
|
1042
|
-
syncReleaseToCodeplay(storeName, finalVersionName, finalVersionCode, new Date().toISOString().slice(0, 10));
|
|
1043
|
-
} else {
|
|
1107
|
+
if (existsSync(oldFilePath)) {
|
|
1108
|
+
renameSync(oldFilePath, checkFullPath);
|
|
1109
|
+
console.log(`✅ Renamed output ${newExt.toUpperCase()} file to: ${path.basename(checkFullPath)}`);
|
|
1110
|
+
syncReleaseToCodeplay(storeName, finalVersionName, finalVersionCode, new Date().toISOString().slice(0, 10));
|
|
1111
|
+
} else {
|
|
1044
1112
|
console.error(`❌ ${newExt.toUpperCase()} file not found after build.`);
|
|
1045
1113
|
}
|
|
1046
1114
|
|