Windows builds and moved credentials: play build runs gradlew.bat through cmd /c and takes C:/ keystore paths as absolute (pitfall 98); check names credential paths missing on this machine and a keystore the stored password / alias do not open (keytool) (pitfall 99); play / apple build write <out>/latest.json for CI; CI install from a git clone documented
This commit is contained in:
parent
4fcee60ba6
commit
73d308164d
9 changed files with 95 additions and 9 deletions
|
|
@ -4,7 +4,7 @@ import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, ut
|
|||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { installedProfiles } from '../cli/apple/build';
|
||||
import { androidSigning, ascKeyFile } from '../cli/lib/credentials';
|
||||
import { androidSigning, ascKeyFile, credentialFileIssues } from '../cli/lib/credentials';
|
||||
import { buildCsr, csrContent, newSigningKey, spkiOfKey } from '../cli/lib/csr';
|
||||
import { aabInfo, appBuildFile, findBundles, gradleArgs, pickGradle, signingEnv, validatePlayBuild, versionSourceIssues, versionSourceMessage } from '../cli/lib/gradle';
|
||||
import { parseBinaryPlist, parseMobileprovision, parsePlist, parseXmlPlist, toXmlPlist } from '../cli/lib/plist';
|
||||
|
|
@ -269,8 +269,10 @@ describe('gradle projects', () => {
|
|||
touch(rn, 'android/settings.gradle'); touch(rn, 'android/gradlew', '#!/bin/sh'); touch(rn, 'android/app/build.gradle');
|
||||
const t = pickGradle(rn);
|
||||
expect(t).toMatchObject({ framework: 'react-native', module: 'app', task: ':app:bundleRelease' });
|
||||
expect(gradleArgs(t, { versionCode: 7, versionName: '1.2.0', hasWrapper: true })).toEqual(['./gradlew', ':app:bundleRelease', '--no-daemon', '--console=plain',
|
||||
expect(gradleArgs(t, { versionCode: 7, versionName: '1.2.0', hasWrapper: true }, 'linux')).toEqual(['./gradlew', ':app:bundleRelease', '--no-daemon', '--console=plain',
|
||||
'-Pandroid.injected.version.code=7', '-PversionCode=7', '-Pandroid.injected.version.name=1.2.0', '-PversionName=1.2.0']);
|
||||
// Windows: a bare gradlew.bat is looked up on PATH only; cmd /c runs the one in the project folder
|
||||
expect(gradleArgs(t, { hasWrapper: true }, 'win32').slice(0, 4)).toEqual(['cmd', '/c', 'gradlew.bat', ':app:bundleRelease']);
|
||||
expect(pickGradle(rn, { flavor: 'prod' }).task).toBe(':app:bundleProdRelease');
|
||||
const unity = dir('unity');
|
||||
touch(unity, 'Export/settings.gradle'); touch(unity, 'Export/launcher/build.gradle'); touch(unity, 'Export/unityLibrary/build.gradle');
|
||||
|
|
@ -360,12 +362,26 @@ describe('credentials for builds', () => {
|
|||
delete process.env.ANDROID_KEYSTORE;
|
||||
expect(androidSigning(d)).toEqual({ storeFile: join(d, 'keys/upload.jks'), storePassword: 'pw', keyAlias: 'upload', keyPassword: 'pw' });
|
||||
expect(androidSigning(dir('nocreds'))).toBeNull();
|
||||
// a Windows absolute path is used as it is, not joined onto the project folder
|
||||
if (process.platform === 'win32') {
|
||||
const w = dir('wincreds');
|
||||
touch(w, '.storebound/credentials.json', JSON.stringify({ ANDROID_KEYSTORE: 'C:/keys/upload.jks', ANDROID_KEYSTORE_PASSWORD: 'pw', ANDROID_KEY_ALIAS: 'upload' }));
|
||||
expect(androidSigning(w)?.storeFile).toBe('C:/keys/upload.jks');
|
||||
}
|
||||
// another machine's paths and a keystore the stored password does not open are named by field
|
||||
const m = dir('moved');
|
||||
touch(m, 'keys/upload.jks', 'x');
|
||||
touch(m, '.storebound/credentials.json', JSON.stringify({ ANDROID_KEYSTORE: 'keys/upload.jks', ANDROID_KEYSTORE_PASSWORD: 'wrong', ANDROID_KEY_ALIAS: 'upload', PLAY_SERVICE_ACCOUNT: '/Users/someone/keys/play.json' }));
|
||||
const issues = credentialFileIssues(m, () => ({ ok: false, out: 'keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect' }));
|
||||
expect(issues.some(i => i.startsWith('PLAY_SERVICE_ACCOUNT: /Users/someone/keys/play.json does not exist'))).toBe(true);
|
||||
expect(issues.some(i => i.startsWith('ANDROID_KEYSTORE_PASSWORD does not open'))).toBe(true);
|
||||
expect(credentialFileIssues(m, () => ({ ok: true, out: '' })).some(i => i.startsWith('ANDROID'))).toBe(false);
|
||||
const { pem } = newSigningKey();
|
||||
const p8 = createPrivateKey(pem).export({ type: 'pkcs8', format: 'pem' }).toString();
|
||||
Object.assign(process.env, { ASC_KEY_ID: 'KEYID00001', ASC_ISSUER_ID: '00000000-0000-0000-0000-000000000000', ASC_P8: p8 });
|
||||
const k = ascKeyFile(d);
|
||||
expect(readFileSync(k.keyPath, 'utf8')).toBe(p8);
|
||||
expect(k.keyPath.split('/').pop()).toBe(['AuthKey', 'KEYID00001.p8'].join('_'));
|
||||
expect(k.keyPath.split(/[\\/]/).pop()).toBe(['AuthKey', 'KEYID00001.p8'].join('_'));
|
||||
k.cleanup();
|
||||
expect(() => readFileSync(k.keyPath)).toThrow();
|
||||
} finally { for (const key of ['ASC_KEY_ID', 'ASC_ISSUER_ID', 'ASC_P8']) if (saved[key] === undefined) delete process.env[key]; else process.env[key] = saved[key]; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue