Skip to content

Commit

Permalink
[ENG-10412] Upload projectMetadata file
Browse files Browse the repository at this point in the history
  • Loading branch information
khamilowicz committed Dec 19, 2023
1 parent 43180c0 commit 7995c38
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This is the log of notable changes to EAS CLI and related packages.

### 🎉 New features

- Generate metadata file for project archive ([#2149](https://github.com/expo/eas-cli/pull/2149) by [@khamilowicz](https://github.com/khamilowicz))

### 🐛 Bug fixes

### 🧹 Chores
Expand Down
12 changes: 12 additions & 0 deletions packages/eas-cli/graphql.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 46 additions & 8 deletions packages/eas-cli/src/build/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ import { transformMetadata } from './graphql';
import { LocalBuildMode, runLocalBuildAsync } from './local';
import { collectMetadataAsync } from './metadata';
import { printDeprecationWarnings } from './utils/printBuildInfo';
import { makeProjectTarballAsync, reviewAndCommitChangesAsync } from './utils/repository';
import {
makeProjectMetadataFileAsync,
makeProjectTarballAsync,
reviewAndCommitChangesAsync,
} from './utils/repository';

export interface CredentialsResult<Credentials> {
source: CredentialsSource.LOCAL | CredentialsSource.REMOTE;
Expand Down Expand Up @@ -133,9 +137,10 @@ export async function prepareBuildRequestForPlatformAsync<

let projectArchive: ArchiveSource | undefined;
if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
const projectPath = (await makeProjectTarballAsync(ctx.vcsClient)).path;
projectArchive = {
type: ArchiveSourceType.PATH,
path: (await makeProjectTarballAsync(ctx.vcsClient)).path,
path: projectPath,
};
} else if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL) {
projectArchive = {
Expand All @@ -145,7 +150,7 @@ export async function prepareBuildRequestForPlatformAsync<
} else if (!ctx.localBuildOptions.localBuildMode) {
projectArchive = {
type: ArchiveSourceType.GCS,
bucketKey: await uploadProjectAsync(ctx),
...(await uploadProjectAsync(ctx)),
};
}
assert(projectArchive);
Expand Down Expand Up @@ -231,8 +236,14 @@ export function handleBuildRequestError(error: any, platform: Platform): never {

async function uploadProjectAsync<TPlatform extends Platform>(
ctx: BuildContext<TPlatform>
): Promise<string> {
): Promise<{
bucketKey: string;
metadataLocation?: string;
}> {
let projectTarballPath;
let projectMetadataFile: any;
let bucketKey: string | null = null;

try {
return await withAnalyticsAsync(
ctx.analytics,
Expand Down Expand Up @@ -260,8 +271,7 @@ async function uploadProjectAsync<TPlatform extends Platform>(
}

projectTarballPath = projectTarball.path;

const bucketKey = await uploadFileAtPathToGCSAsync(
bucketKey = await uploadFileAtPathToGCSAsync(
ctx.graphqlClient,
UploadSessionType.EasBuildGcsProjectSources,
projectTarball.path,
Expand All @@ -274,7 +284,24 @@ async function uploadProjectAsync<TPlatform extends Platform>(
completedMessage: (duration: string) => `Uploaded to EAS ${chalk.dim(duration)}`,
})
);
return bucketKey;

projectMetadataFile = await makeProjectMetadataFileAsync(projectTarball.path);

const metadataLocation = await uploadFileAtPathToGCSAsync(
ctx.graphqlClient,
UploadSessionType.EasBuildGcsProjectSources,
projectMetadataFile.path,
createProgressTracker({
total: projectMetadataFile.size,
message: ratio =>
`Uploading metadata to EAS Build (${formatBytes(
projectMetadataFile.size * ratio
)} / ${formatBytes(projectMetadataFile.size)})`,
completedMessage: (duration: string) => `Uploaded to EAS ${chalk.dim(duration)}`,
})
);

return { bucketKey, metadataLocation };
},
{
attemptEvent: BuildEvent.PROJECT_UPLOAD_ATTEMPT,
Expand All @@ -284,15 +311,26 @@ async function uploadProjectAsync<TPlatform extends Platform>(
}
);
} catch (err: any) {
let errMessage = 'Failed to upload the project tarball to EAS Build';
let errMessage = bucketKey
? 'Failed to upload metadata to EAS Build'
: 'Failed to upload the project tarball to EAS Build';

if (err.message) {
errMessage += `\n\nReason: ${err.message}`;
}

if (bucketKey) {
Log.warn(errMessage);
return { bucketKey };
}
throw new EasBuildProjectArchiveUploadError(errMessage);
} finally {
if (projectTarballPath) {
await fs.remove(projectTarballPath);
}
if (projectMetadataFile) {
await fs.remove(projectMetadataFile.path);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/eas-cli/src/build/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function transformProjectArchive(archiveSource: ArchiveSource): ProjectAr
return {
type: ProjectArchiveSourceType.S3,
bucketKey: archiveSource.bucketKey,
metadataLocation: archiveSource.metadataLocation,
};
} else if (archiveSource.type === ArchiveSourceType.GCS) {
return {
Expand Down
44 changes: 44 additions & 0 deletions packages/eas-cli/src/build/utils/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,50 @@ export async function commitPromptAsync(
});
}

export async function makeProjectMetadataFileAsync(
archivePath: string
): Promise<{ path: string; size: number }> {
const spinner = ora('Creating project metadata file');
const timerLabel = 'makeProjectMetadataFileAsync';
const timer = setTimeout(
() => {
spinner.start();
},
Log.isDebug ? 1 : 1000
);
startTimer(timerLabel);

const metadataLocation = path.join(getTmpDirectory(), `${uuidv4()}-eas-build-metadata.json`);
const archiveContent: string[] = [];

try {
await tar.list({
file: archivePath,
onentry: (entry: tar.ReadEntry) => {
if (entry.type === 'File' && !entry.path.includes('.git')) {
archiveContent.push(entry.path);
}
},
});

await fs.writeJSON(metadataLocation, {
archiveContent,
});
} catch (e) {
clearTimeout(timer);
if (spinner.isSpinning) {
spinner.fail();
}
throw e;
}

const duration = endTimer(timerLabel);
const prettyTime = formatMilliseconds(duration);
spinner.succeed(`Created project metadata file ${chalk.dim(prettyTime)}`);

return { path: metadataLocation, size: await fs.stat(metadataLocation).then(stat => stat.size) };
}

export async function makeProjectTarballAsync(
vcsClient: Client
): Promise<{ path: string; size: number }> {
Expand Down
1 change: 1 addition & 0 deletions packages/eas-cli/src/graphql/generated.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7995c38

Please sign in to comment.