From 1fa9222013e88130e02b0a782556638180cdde96 Mon Sep 17 00:00:00 2001 From: Wojciech Kozyra Date: Tue, 8 Sep 2020 15:36:05 +0200 Subject: [PATCH] [expo-cli] EAS Build support `experimental.npmToken` in credentials.json --- .../eas-build/build/__tests__/build-test.ts | 44 +++++++++++-------- .../build/builders/AndroidBuilder.ts | 19 +++++--- .../builders/__tests__/AndroidBuilder-test.ts | 24 +++++----- .../builders/__tests__/iOSBuilder-test.ts | 20 +++++---- .../eas-build/build/builders/iOSBuilder.ts | 25 +++++++---- .../credentialsJson/__tests__/read-test.ts | 25 +++++++++++ .../src/credentials/credentialsJson/read.ts | 14 ++++++ 7 files changed, 122 insertions(+), 49 deletions(-) diff --git a/packages/expo-cli/src/commands/eas-build/build/__tests__/build-test.ts b/packages/expo-cli/src/commands/eas-build/build/__tests__/build-test.ts index c63b40c39b..166cea7653 100644 --- a/packages/expo-cli/src/commands/eas-build/build/__tests__/build-test.ts +++ b/packages/expo-cli/src/commands/eas-build/build/__tests__/build-test.ts @@ -214,11 +214,13 @@ describe('build command', () => { artifactPath: 'android/app/build/outputs/**/*.{apk,aab}', gradleCommand: ':app:bundleRelease', secrets: { - keystore: { - dataBase64: keystore.base64, - keystorePassword: 'keystorePassword', - keyAlias: 'keyAlias', - keyPassword: 'keyPassword', + buildCredentials: { + keystore: { + dataBase64: keystore.base64, + keystorePassword: 'keystorePassword', + keyAlias: 'keyAlias', + keyPassword: 'keyPassword', + }, }, }, }); @@ -251,11 +253,13 @@ describe('build command', () => { artifactPath: 'ios/build/App.ipa', scheme: 'testapp', secrets: { - distributionCertificate: { - dataBase64: cert.base64, - password: 'certPass', + buildCredentials: { + distributionCertificate: { + dataBase64: cert.base64, + password: 'certPass', + }, + provisioningProfileBase64: pprofile.base64, }, - provisioningProfileBase64: pprofile.base64, }, }); }); @@ -293,11 +297,13 @@ describe('build command', () => { artifactPath: 'android/app/build/outputs/**/*.{apk,aab}', gradleCommand: ':app:bundleRelease', secrets: { - keystore: { - dataBase64: keystore.base64, - keystorePassword: 'keystorePassword', - keyAlias: 'keyAlias', - keyPassword: 'keyPassword', + buildCredentials: { + keystore: { + dataBase64: keystore.base64, + keystorePassword: 'keystorePassword', + keyAlias: 'keyAlias', + keyPassword: 'keyPassword', + }, }, }, }); @@ -314,11 +320,13 @@ describe('build command', () => { artifactPath: 'ios/build/App.ipa', scheme: 'testapp', secrets: { - distributionCertificate: { - dataBase64: cert.base64, - password: 'certPass', + buildCredentials: { + distributionCertificate: { + dataBase64: cert.base64, + password: 'certPass', + }, + provisioningProfileBase64: pprofile.base64, }, - provisioningProfileBase64: pprofile.base64, }, }); }); diff --git a/packages/expo-cli/src/commands/eas-build/build/builders/AndroidBuilder.ts b/packages/expo-cli/src/commands/eas-build/build/builders/AndroidBuilder.ts index a47caf9b3e..d4a537ebaa 100644 --- a/packages/expo-cli/src/commands/eas-build/build/builders/AndroidBuilder.ts +++ b/packages/expo-cli/src/commands/eas-build/build/builders/AndroidBuilder.ts @@ -6,6 +6,7 @@ import ora from 'ora'; import path from 'path'; import CommandError from '../../../../CommandError'; +import { readSecretEnvsAsync } from '../../../../credentials/credentialsJson/read'; import AndroidCredentialsProvider, { AndroidCredentials, } from '../../../../credentials/provider/AndroidCredentialsProvider'; @@ -25,13 +26,17 @@ import gradleContent from '../templates/gradleContent'; interface CommonJobProperties { platform: Platform.Android; projectUrl: string; - secrets?: { - keystore: Android.Keystore; + secrets: { + buildCredentials?: { + keystore: Android.Keystore; + }; + secretEnvs?: Record; }; } class AndroidBuilder implements Builder { private credentials?: AndroidCredentials; + private secretEnvs?: Record; private credentialsPrepared: boolean = false; constructor(public readonly ctx: BuilderContext) {} @@ -42,6 +47,7 @@ class AndroidBuilder implements Builder { CredentialsSource.LOCAL | CredentialsSource.REMOTE | undefined > { this.credentialsPrepared = true; + this.secretEnvs = await readSecretEnvsAsync(this.ctx.commandCtx.projectDir); if (!this.shouldLoadCredentials()) { return; } @@ -152,9 +158,9 @@ class AndroidBuilder implements Builder { } private async prepareJobCommonAsync(archiveUrl: string): Promise> { - const secrets = this.credentials + const buildCredentials = this.credentials ? { - secrets: { + buildCredentials: { keystore: { dataBase64: this.credentials.keystore.keystore, keystorePassword: this.credentials.keystore.keystorePassword, @@ -168,7 +174,10 @@ class AndroidBuilder implements Builder { return { platform: Platform.Android, projectUrl: archiveUrl, - ...secrets, + secrets: { + ...(this.secretEnvs ? { secretEnvs: this.secretEnvs } : {}), + ...buildCredentials, + }, }; } diff --git a/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/AndroidBuilder-test.ts b/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/AndroidBuilder-test.ts index cef0fa6f88..07b30d88f3 100644 --- a/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/AndroidBuilder-test.ts +++ b/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/AndroidBuilder-test.ts @@ -74,11 +74,13 @@ describe('AndroidBuilder', () => { artifactPath: 'android/app/build/outputs/**/*.{apk,aab}', gradleCommand: ':app:bundleRelease', secrets: { - keystore: { - dataBase64: keystore.base64, - keystorePassword: 'keystorePassword', - keyAlias: 'keyAlias', - keyPassword: 'keyPassword', + buildCredentials: { + keystore: { + dataBase64: keystore.base64, + keystorePassword: 'keystorePassword', + keyAlias: 'keyAlias', + keyPassword: 'keyPassword', + }, }, }, }); @@ -109,11 +111,13 @@ describe('AndroidBuilder', () => { packageJson: { example: 'packageJson' }, manifest: { example: 'manifest' }, secrets: { - keystore: { - dataBase64: keystore.base64, - keystorePassword: 'keystorePassword', - keyAlias: 'keyAlias', - keyPassword: 'keyPassword', + buildCredentials: { + keystore: { + dataBase64: keystore.base64, + keystorePassword: 'keystorePassword', + keyAlias: 'keyAlias', + keyPassword: 'keyPassword', + }, }, }, }); diff --git a/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/iOSBuilder-test.ts b/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/iOSBuilder-test.ts index 4cb0bb3e6e..0b4b246f55 100644 --- a/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/iOSBuilder-test.ts +++ b/packages/expo-cli/src/commands/eas-build/build/builders/__tests__/iOSBuilder-test.ts @@ -88,11 +88,13 @@ describe('iOSBuilder', () => { scheme: 'testapp', artifactPath: 'ios/build/App.ipa', secrets: { - distributionCertificate: { - dataBase64: cert.base64, - password: 'certPass', + buildCredentials: { + distributionCertificate: { + dataBase64: cert.base64, + password: 'certPass', + }, + provisioningProfileBase64: pprofile.base64, }, - provisioningProfileBase64: pprofile.base64, }, }); }, 10000); @@ -123,11 +125,13 @@ describe('iOSBuilder', () => { packageJson: { example: 'packageJson' }, manifest: { example: 'manifest' }, secrets: { - distributionCertificate: { - dataBase64: cert.base64, - password: 'certPass', + buildCredentials: { + distributionCertificate: { + dataBase64: cert.base64, + password: 'certPass', + }, + provisioningProfileBase64: pprofile.base64, }, - provisioningProfileBase64: pprofile.base64, }, }); }); diff --git a/packages/expo-cli/src/commands/eas-build/build/builders/iOSBuilder.ts b/packages/expo-cli/src/commands/eas-build/build/builders/iOSBuilder.ts index afdda6bb9b..188a7b680a 100644 --- a/packages/expo-cli/src/commands/eas-build/build/builders/iOSBuilder.ts +++ b/packages/expo-cli/src/commands/eas-build/build/builders/iOSBuilder.ts @@ -5,6 +5,7 @@ import figures from 'figures'; import sortBy from 'lodash/sortBy'; import ora from 'ora'; +import { readSecretEnvsAsync } from '../../../../credentials/credentialsJson/read'; import iOSCredentialsProvider, { iOSCredentials, } from '../../../../credentials/provider/iOSCredentialsProvider'; @@ -25,17 +26,21 @@ import { getBundleIdentifier } from '../utils/ios'; interface CommonJobProperties { platform: Platform.iOS; projectUrl: string; - secrets?: { - provisioningProfileBase64: string; - distributionCertificate: { - dataBase64: string; - password: string; + secrets: { + buildCredentials?: { + provisioningProfileBase64: string; + distributionCertificate: { + dataBase64: string; + password: string; + }; }; + secretEnvs?: Record; }; } class iOSBuilder implements Builder { private credentials?: iOSCredentials; + private secretEnvs?: Record; private scheme?: string; constructor(public readonly ctx: BuilderContext) {} @@ -53,6 +58,7 @@ class iOSBuilder implements Builder { public async ensureCredentialsAsync(): Promise< CredentialsSource.LOCAL | CredentialsSource.REMOTE | undefined > { + this.secretEnvs = await readSecretEnvsAsync(this.ctx.commandCtx.projectDir); if (!this.shouldLoadCredentials()) { return; } @@ -150,9 +156,9 @@ class iOSBuilder implements Builder { } private async prepareJobCommonAsync(archiveUrl: string): Promise> { - const secrets = this.credentials + const buildCredentials = this.credentials ? { - secrets: { + buildCredentials: { provisioningProfileBase64: this.credentials.provisioningProfile, distributionCertificate: { dataBase64: this.credentials.distributionCertificate.certP12, @@ -165,7 +171,10 @@ class iOSBuilder implements Builder { return { platform: Platform.iOS, projectUrl: archiveUrl, - ...secrets, + secrets: { + ...(this.secretEnvs ? { secretEnvs: this.secretEnvs } : {}), + ...buildCredentials, + }, }; } diff --git a/packages/expo-cli/src/credentials/credentialsJson/__tests__/read-test.ts b/packages/expo-cli/src/credentials/credentialsJson/__tests__/read-test.ts index 3b76f7bccb..5c3c47e3f2 100644 --- a/packages/expo-cli/src/credentials/credentialsJson/__tests__/read-test.ts +++ b/packages/expo-cli/src/credentials/credentialsJson/__tests__/read-test.ts @@ -179,4 +179,29 @@ describe('credentialsJson', () => { await expect(promise).rejects.toThrow("ENOENT: no such file or directory, open 'pprofile'"); }); }); + + describe('readSecretEnvsAsync', () => { + it('should read secretEnvs field correctly', async () => { + vol.fromJSON({ + './credentials.json': JSON.stringify({ + ios: { + provisioningProfilePath: 'pprofile', + distributionCertificate: { + path: 'cert.p12', + password: 'certPass', + }, + }, + experimental: { + npmToken: 'VALUE', + }, + }), + './pprofile': 'somebinarycontent', + './cert.p12': 'somebinarycontent2', + }); + const result = await credentialsJsonReader.readSecretEnvsAsync('.'); + expect(result).toEqual({ + NPM_TOKEN: 'VALUE', + }); + }); + }); }); diff --git a/packages/expo-cli/src/credentials/credentialsJson/read.ts b/packages/expo-cli/src/credentials/credentialsJson/read.ts index 0f8b155903..672278168e 100644 --- a/packages/expo-cli/src/credentials/credentialsJson/read.ts +++ b/packages/expo-cli/src/credentials/credentialsJson/read.ts @@ -20,6 +20,9 @@ interface CredentialsJson { password: string; }; }; + experimental?: { + npmToken?: string; + }; } const CredentialsJsonSchema = Joi.object({ @@ -38,6 +41,9 @@ const CredentialsJsonSchema = Joi.object({ password: Joi.string().required(), }).required(), }), + experimental: Joi.object({ + npmToken: Joi.string(), + }), }); interface AndroidCredentials { @@ -92,6 +98,14 @@ export async function readIosCredentialsAsync(projectDir: string): Promise | undefined> { + const credentialsJson = await readAsync(projectDir); + const npmToken = credentialsJson?.experimental?.npmToken; + return npmToken ? { NPM_TOKEN: npmToken } : undefined; +} + async function readAsync(projectDir: string): Promise { const credentialsJSONRaw = await readRawAsync(projectDir);