Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

[expo-cli] detect git changes on credentials.json update #2482

Merged
merged 2 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jest.mock('../../../../projects', () => {
};
});
jest.mock('../utils/git');
jest.mock('../../../../git');
jest.mock('../../../../uploads', () => ({
UploadType: {},
uploadAsync: () => mockProjectUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AndroidManagedBuildProfile,
Workflow,
} from '../../../../easJson';
import { gitAddAsync } from '../../../../git';
import log from '../../../../log';
import { ensureCredentialsAsync } from '../credentials';
import gradleContent from '../templates/gradleContent';
Expand Down Expand Up @@ -69,7 +70,7 @@ class AndroidBuilder implements Builder {
const easGradlePath = path.join(androidAppDir, 'eas-build.gradle');

await fs.writeFile(easGradlePath, gradleContent);
await gitUtils.addFileAsync(easGradlePath, { intentToAdd: true });
await gitAddAsync(easGradlePath, { intentToAdd: true });

const buildGradleContent = await fs.readFile(path.join(buildGradlePath), 'utf-8');
const applyEasGradle = 'apply from: "./eas-build.gradle"';
Expand Down
19 changes: 3 additions & 16 deletions packages/expo-cli/src/commands/eas-build/build/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import fs from 'fs-extra';
import ora from 'ora';

import CommandError from '../../../../CommandError';
import { gitDiffAsync, gitStatusAsync } from '../../../../git';
import log from '../../../../log';
import prompts from '../../../../prompts';

async function ensureGitStatusIsCleanAsync(): Promise<void> {
const changes = (await spawnAsync('git', ['status', '-s', '-uno'])).stdout;
const changes = await gitStatusAsync();
if (changes.length > 0) {
throw new DirtyGitTreeError(
'Please commit all changes before building your project. Aborting...'
Expand All @@ -34,18 +35,6 @@ async function makeProjectTarballAsync(tarPath: string): Promise<number> {
return size;
}

async function showDiffAsync(): Promise<void> {
await spawnAsync('git', ['--no-pager', 'diff'], { stdio: ['ignore', 'inherit', 'inherit'] });
}

async function addFileAsync(file: string, options?: { intentToAdd?: boolean }): Promise<void> {
if (options?.intentToAdd) {
await spawnAsync('git', ['add', '--intent-to-add', file]);
} else {
await spawnAsync('git', ['add', file]);
}
}

async function reviewAndCommitChangesAsync(
commitMessage: string,
{ nonInteractive }: { nonInteractive: boolean }
Expand All @@ -58,7 +47,7 @@ async function reviewAndCommitChangesAsync(

log('Please review the following changes and pass the message to make the commit.');
log.newLine();
await showDiffAsync();
await gitDiffAsync();
log.newLine();

const { confirm } = await prompts({
Expand Down Expand Up @@ -89,6 +78,4 @@ export {
ensureGitStatusIsCleanAsync,
makeProjectTarballAsync,
reviewAndCommitChangesAsync,
showDiffAsync,
addFileAsync,
};
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('update credentials.json', () => {
expect(credJson).toEqual({
android: {
keystore: {
keystorePath: './android/keystores/keystore.jks',
keystorePath: 'android/keystores/keystore.jks',
keystorePassword: testKeystore.keystorePassword,
keyAlias: testKeystore.keyAlias,
keyPassword: testKeystore.keyPassword,
Expand Down Expand Up @@ -120,7 +120,7 @@ describe('update credentials.json', () => {
expect(credJson).toEqual({
android: {
keystore: {
keystorePath: './android/keystores/keystore.jks',
keystorePath: 'android/keystores/keystore.jks',
keystorePassword: testKeystore.keystorePassword,
keyAlias: testKeystore.keyAlias,
keyPassword: testKeystore.keyPassword,
Expand Down Expand Up @@ -208,9 +208,9 @@ describe('update credentials.json', () => {
expect(pprofile).toEqual(testAllCredentialsForApp.credentials.provisioningProfile);
expect(credJson).toEqual({
ios: {
provisioningProfilePath: './ios/certs/profile.mobileprovision',
provisioningProfilePath: 'ios/certs/profile.mobileprovision',
distributionCertificate: {
path: './ios/certs/dist-cert.p12',
path: 'ios/certs/dist-cert.p12',
password: testAllCredentialsForApp.distCredentials.certPassword,
},
},
Expand Down
49 changes: 46 additions & 3 deletions packages/expo-cli/src/credentials/credentialsJson/update.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs-extra';
import path from 'path';

import { gitStatusAsync } from '../../git';
import log from '../../log';
import prompts from '../../prompts';
import { Context } from '../context';
Expand Down Expand Up @@ -42,9 +43,10 @@ export async function updateAndroidCredentialsAsync(ctx: Context) {
}

const keystorePath =
rawCredentialsJsonObject?.android?.keystore?.keystorePath ?? './android/keystores/keystore.jks';
rawCredentialsJsonObject?.android?.keystore?.keystorePath ?? 'android/keystores/keystore.jks';
log(`Writing Keystore to ${keystorePath}`);
await updateFileAsync(ctx.projectDir, keystorePath, keystore.keystore);
const shouldWarnKeystore = await isFileUntrackedAsync(keystorePath);

rawCredentialsJsonObject.android = {
keystore: {
Expand All @@ -57,6 +59,12 @@ export async function updateAndroidCredentialsAsync(ctx: Context) {
await fs.writeJson(credentialsJsonFilePath, rawCredentialsJsonObject, {
spaces: 2,
});
const shouldWarnCredentialsJson = await isFileUntrackedAsync('credentials.json');
const newFilePaths = [
shouldWarnKeystore && keystorePath,
shouldWarnCredentialsJson && 'credentials.json',
].filter(i => i);
displayUntrackedFilesWarning(newFilePaths);
}

export async function updateIosCredentialsAsync(ctx: Context, bundleIdentifier: string) {
Expand All @@ -79,9 +87,9 @@ export async function updateIosCredentialsAsync(ctx: Context, bundleIdentifier:
bundleIdentifier,
};
const pprofilePath =
rawCredentialsJsonObject?.ios?.provisioningProfilePath ?? './ios/certs/profile.mobileprovision';
rawCredentialsJsonObject?.ios?.provisioningProfilePath ?? 'ios/certs/profile.mobileprovision';
const distCertPath =
rawCredentialsJsonObject?.ios?.distributionCertificate?.path ?? './ios/certs/dist-cert.p12';
rawCredentialsJsonObject?.ios?.distributionCertificate?.path ?? 'ios/certs/dist-cert.p12';
const appCredentials = await ctx.ios.getAppCredentials(appLookupParams);
const distCredentials = await ctx.ios.getDistCert(appLookupParams);
if (!appCredentials?.credentials?.provisioningProfile && !distCredentials) {
Expand Down Expand Up @@ -113,8 +121,11 @@ export async function updateIosCredentialsAsync(ctx: Context, bundleIdentifier:
pprofilePath,
appCredentials?.credentials?.provisioningProfile
);
const shouldWarnPProfile = await isFileUntrackedAsync(pprofilePath);

log(`Writing Distribution Certificate to ${distCertPath}`);
await updateFileAsync(ctx.projectDir, distCertPath, distCredentials?.certP12);
const shouldWarnDistCert = await isFileUntrackedAsync(distCertPath);

rawCredentialsJsonObject.ios = {
...(appCredentials?.credentials?.provisioningProfile
Expand All @@ -132,6 +143,14 @@ export async function updateIosCredentialsAsync(ctx: Context, bundleIdentifier:
await fs.writeJson(credentialsJsonFilePath, rawCredentialsJsonObject, {
spaces: 2,
});
const shouldWarnCredentialsJson = await isFileUntrackedAsync('credentials.json');

const newFilePaths = [
shouldWarnPProfile && pprofilePath,
shouldWarnDistCert && distCertPath,
shouldWarnCredentialsJson && 'credentials.json',
].filter(i => i);
displayUntrackedFilesWarning(newFilePaths);
}

async function updateFileAsync(projectDir: string, filePath: string, base64Data?: string) {
Expand All @@ -144,3 +163,27 @@ async function updateFileAsync(projectDir: string, filePath: string, base64Data?
await fs.writeFile(filePath, Buffer.from(base64Data, 'base64'));
}
}

async function isFileUntrackedAsync(path: string): Promise<boolean> {
const withUntrackedFiles = await gitStatusAsync({ showUntracked: true });
const trackedFiles = await gitStatusAsync({ showUntracked: false });
const pathWithouLeadingDot = path.replace(/^\.\//, ''); // remove leading './' from path
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const pathWithouLeadingDot = path.replace(/^\.\//, ''); // remove leading './' from path
const pathWithoutLeadingDot = path.replace(/^\.\//, ''); // remove leading './' from path

return (
withUntrackedFiles.includes(pathWithouLeadingDot) &&
!trackedFiles.includes(pathWithouLeadingDot)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
withUntrackedFiles.includes(pathWithouLeadingDot) &&
!trackedFiles.includes(pathWithouLeadingDot)
withUntrackedFiles.includes(pathWithoutLeadingDot) &&
!trackedFiles.includes(pathWithoutLeadingDot)

);
}

function displayUntrackedFilesWarning(newFilePaths: string[]) {
if (newFilePaths.length === 1) {
log.warn(
`File ${newFilePaths[0]} is currently untracked, remember to add it to .gitignore or to encrypt it.`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`File ${newFilePaths[0]} is currently untracked, remember to add it to .gitignore or to encrypt it.`
`File ${newFilePaths[0]} is currently untracked, remember to add it to .gitignore or to encrypt it (e.g. with git-crypt).`

);
} else if (newFilePaths.length > 1) {
log.warn(
`Files ${newFilePaths.join(
', '
)} are currently untracked, remember to add them to .gitignore or to encrypt them.`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
)} are currently untracked, remember to add them to .gitignore or to encrypt them.`
)} are currently untracked, remember to add them to .gitignore or to encrypt them (e.g. with git-crypt).`

);
}
}
24 changes: 24 additions & 0 deletions packages/expo-cli/src/git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import spawnAsync from '@expo/spawn-async';

interface GitStatusOptions {
showUntracked?: boolean;
}

export async function gitStatusAsync({ showUntracked }: GitStatusOptions = {}): Promise<string> {
return (await spawnAsync('git', ['status', '-s', showUntracked ? '-uall' : '-uno'])).stdout;
}

export async function gitDiffAsync(): Promise<void> {
await spawnAsync('git', ['--no-pager', 'diff'], { stdio: ['ignore', 'inherit', 'inherit'] });
}

export async function gitAddAsync(
file: string,
options?: { intentToAdd?: boolean }
): Promise<void> {
if (options?.intentToAdd) {
await spawnAsync('git', ['add', '--intent-to-add', file]);
} else {
await spawnAsync('git', ['add', file]);
}
}