Skip to content

Commit

Permalink
[ENG-9500] Don't mix cacheManager with dynamic cache manager
Browse files Browse the repository at this point in the history
  • Loading branch information
khamilowicz committed Apr 16, 2024
1 parent 3a80812 commit 9800877
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 238 deletions.
10 changes: 2 additions & 8 deletions packages/build-tools/src/builders/android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ async function buildAsync(ctx: BuildContext<Android.Job>): Promise<void> {
});

await ctx.runBuildPhase(BuildPhase.RESTORE_CACHE, async () => {
await ctx.cacheManager?.restoreCache(
{ global: ctx, logger: ctx.logger, workingdir: ctx.workingdir },
ctx.job.cache
);
await ctx.cacheManager?.restoreCache(ctx);
});

await ctx.runBuildPhase(BuildPhase.POST_INSTALL_HOOK, async () => {
Expand Down Expand Up @@ -118,10 +115,7 @@ async function buildAsync(ctx: BuildContext<Android.Job>): Promise<void> {
});

await ctx.runBuildPhase(BuildPhase.SAVE_CACHE, async () => {
await ctx.cacheManager?.saveCache(
{ global: ctx, logger: ctx.logger, workingdir: ctx.workingdir },
ctx.job.cache
);
await ctx.cacheManager?.saveCache(ctx);
});

await ctx.runBuildPhase(BuildPhase.UPLOAD_APPLICATION_ARCHIVE, async () => {
Expand Down
10 changes: 2 additions & 8 deletions packages/build-tools/src/builders/ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,7 @@ async function buildAsync(ctx: BuildContext<Ios.Job>): Promise<void> {
});

await ctx.runBuildPhase(BuildPhase.RESTORE_CACHE, async () => {
await ctx.cacheManager?.restoreCache(
{ global: ctx, logger: ctx.logger, workingdir: ctx.workingdir },
ctx.job.cache
);
await ctx.cacheManager?.restoreCache(ctx);
});

await ctx.runBuildPhase(BuildPhase.INSTALL_PODS, async () => {
Expand Down Expand Up @@ -129,10 +126,7 @@ async function buildAsync(ctx: BuildContext<Ios.Job>): Promise<void> {
});

await ctx.runBuildPhase(BuildPhase.SAVE_CACHE, async () => {
await ctx.cacheManager?.saveCache(
{ global: ctx, logger: ctx.logger, workingdir: ctx.workingdir },
ctx.job.cache
);
await ctx.cacheManager?.saveCache(ctx);
});

await ctx.runBuildPhase(BuildPhase.UPLOAD_APPLICATION_ARCHIVE, async () => {
Expand Down
10 changes: 4 additions & 6 deletions packages/build-tools/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ import {
} from '@expo/eas-build-job';
import { BuildTrigger } from '@expo/eas-build-job/dist/common';
import { bunyan } from '@expo/logger';
import { CacheManager } from '@expo/steps';
import { SpawnOptions, SpawnPromise, SpawnResult } from '@expo/turtle-spawn';
import fs from 'fs-extra';
import { DynamicCacheManager } from '@expo/steps';

import { resolveBuildPhaseErrorAsync } from './buildErrors/detectError';
import { readAppConfig } from './utils/appConfig';
import { createTemporaryEnvironmentSecretFile } from './utils/environmentSecrets';
import { PackageManager, resolvePackageManager } from './utils/packageManager';
export { CacheManager } from '@expo/steps';

export type Artifacts = Partial<Record<ManagedArtifactType, string>>;

Expand Down Expand Up @@ -56,6 +55,7 @@ export interface BuildContextOptions {
logBuffer: LogBuffer;
env: Env;
cacheManager?: CacheManager;
dynamicCacheManager?: DynamicCacheManager;
/**
* @deprecated
*/
Expand All @@ -82,6 +82,7 @@ export class BuildContext<TJob extends Job = Job> {
public logger: bunyan;
public readonly logBuffer: LogBuffer;
public readonly cacheManager?: CacheManager;
public readonly dynamicCacheManager?: DynamicCacheManager;
/**
* @deprecated
*/
Expand Down Expand Up @@ -115,6 +116,7 @@ export class BuildContext<TJob extends Job = Job> {
this.logger = this.defaultLogger;
this.logBuffer = options.logBuffer;
this.cacheManager = options.cacheManager;
this.dynamicCacheManager = options.dynamicCacheManager;
this.runGlobalExpoCliCommand = options.runGlobalExpoCliCommand;
this._uploadArtifact = options.uploadArtifact;
this.reportError = options.reportError;
Expand All @@ -135,10 +137,6 @@ export class BuildContext<TJob extends Job = Job> {
: this.buildExecutablesDirectory;
}

get projectRootDirectory(): string | undefined {
return this.job.projectRootDirectory;
}

public get job(): TJob {
return this._job;
}
Expand Down
12 changes: 8 additions & 4 deletions packages/build-tools/src/customBuildContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ import {
Platform,
} from '@expo/eas-build-job';
import { bunyan } from '@expo/logger';
import { ExternalBuildContextProvider, BuildRuntimePlatform, CacheManager } from '@expo/steps';
import {
ExternalBuildContextProvider,
BuildRuntimePlatform,
DynamicCacheManager,
} from '@expo/steps';

import { ArtifactToUpload, BuildContext } from './context';
import { ArtifactToUpload, BuildContext, CacheManager } from './context';

const platformToBuildRuntimePlatform: Record<Platform, BuildRuntimePlatform> = {
[Platform.ANDROID]: BuildRuntimePlatform.LINUX,
Expand All @@ -23,6 +27,7 @@ const platformToBuildRuntimePlatform: Record<Platform, BuildRuntimePlatform> = {

export interface BuilderRuntimeApi {
uploadArtifact: (spec: { artifact: ArtifactToUpload; logger: bunyan }) => Promise<void>;
cacheManager?: DynamicCacheManager;
}

export class CustomBuildContext<TJob extends Job = Job> implements ExternalBuildContextProvider {
Expand Down Expand Up @@ -52,7 +57,6 @@ export class CustomBuildContext<TJob extends Job = Job> implements ExternalBuild
public metadata?: Metadata;
public readonly cacheManager?: CacheManager;
public readonly buildDirectory: string;
public readonly projectRootDirectory: string;

private _env: Env;

Expand All @@ -68,10 +72,10 @@ export class CustomBuildContext<TJob extends Job = Job> implements ExternalBuild
this.buildLogsDirectory = path.join(buildCtx.workingdir, 'logs');
this.runtimeApi = {
uploadArtifact: (...args) => buildCtx['uploadArtifact'](...args),
cacheManager: buildCtx.dynamicCacheManager,
};
this.cacheManager = buildCtx.cacheManager;
this.buildDirectory = buildCtx.buildDirectory;
this.projectRootDirectory = buildCtx.projectRootDirectory ?? '.';
}

public hasBuildJob(): this is CustomBuildContext<BuildJob> {
Expand Down
5 changes: 2 additions & 3 deletions packages/build-tools/src/steps/easFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ export function getEasFunctions(ctx: CustomBuildContext): BuildFunction[] {
createSetUpNpmrcBuildFunction(),
createInstallNodeModulesBuildFunction(),
createPrebuildBuildFunction(),
createFindAndUploadBuildArtifactsBuildFunction(ctx),
createSaveCacheBuildFunction(),
createRestoreCacheBuildFunction(),
createSaveCacheBuildFunction(ctx),
createRestoreCacheBuildFunction(ctx),
configureEASUpdateIfInstalledFunction(),
injectAndroidCredentialsFunction(),
configureAndroidVersionFunction(),
Expand Down
85 changes: 34 additions & 51 deletions packages/build-tools/src/steps/functions/__tests__/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,65 @@ import fs from 'fs/promises';
import os from 'os';
import path from 'path';

import { Job, Metadata } from '@expo/eas-build-job';
import {
BuildRuntimePlatform,
BuildStepGlobalContext,
Cache,
DynamicCacheManager,
ExternalBuildContextProvider,
CacheManager,
} from '@expo/steps';
import { anything, capture, instance, mock, reset, verify, when } from 'ts-mockito';

import { createLogger } from '../../../__mocks__/@expo/logger';
import { createTestIosJob } from '../../../__tests__/utils/job';
import { createMockLogger } from '../../../__tests__/utils/logger';
import { BuildContext } from '../../../context';
import { CustomBuildContext } from '../../../customBuildContext';
import { createRestoreCacheBuildFunction, createSaveCacheBuildFunction } from '../cache';

const cacheSaveBuildFunction = createSaveCacheBuildFunction();
const cacheRestoreBuildFunction = createRestoreCacheBuildFunction();
const dynamicCacheManagerMock = mock<DynamicCacheManager>();
const dynamicCacheManager = instance(dynamicCacheManagerMock);

const buildCtx = new BuildContext(createTestIosJob({}), {
env: {},
logBuffer: { getLogs: () => [], getPhaseLogs: () => [] },
logger: createMockLogger(),
uploadArtifact: jest.fn(),
workingdir: '',
dynamicCacheManager,
runGlobalExpoCliCommand: jest.fn(),
});
const customContext = new CustomBuildContext(buildCtx);

const cacheSaveBuildFunction = createSaveCacheBuildFunction(customContext);
const cacheRestoreBuildFunction = createRestoreCacheBuildFunction(customContext);

const providerMock = mock<ExternalBuildContextProvider>();
const cacheManagerMock = mock<CacheManager>();

const cacheManager = instance(cacheManagerMock);
const initialCache = { downloadUrls: {} };
const initialCache: Cache = { disabled: false, clear: false, paths: [] };

const provider = instance(providerMock);

let ctx: BuildStepGlobalContext;

const existingKey =
'c7d8e33243968f8675ec0463ad89e11c1e754723695ab9b23dfb8f9ddd389a28-value-8b6e2366e2a2ff8b43556a1dcc5f1cf97ddcf4cdf3c8f9a6d54e0efe2e747922';

describe('cache functions', () => {
let key: string;
let paths: string[];
beforeEach(async () => {
key = '${ hashFiles("./src/*") }-value';
paths = ['path1', 'path2'];
reset(cacheManagerMock);
reset(dynamicCacheManagerMock);
reset(providerMock);

const projectSourceDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'project-'));
when(providerMock.logger).thenReturn(createLogger());
when(providerMock.runtimePlatform).thenReturn(BuildRuntimePlatform.LINUX);
when(providerMock.staticContext()).thenReturn({ some: 'key', job: { cache: initialCache } });
when(providerMock.cacheManager).thenReturn(cacheManager);
when(providerMock.staticContext()).thenReturn({
metadata: {} as Metadata,
env: {},
job: { cache: initialCache } as Job,
});
when(providerMock.projectSourceDirectory).thenReturn(projectSourceDirectory);
when(providerMock.defaultWorkingDirectory).thenReturn(projectSourceDirectory);
when(providerMock.projectTargetDirectory).thenReturn(projectSourceDirectory);
Expand All @@ -62,9 +80,6 @@ describe('cache functions', () => {
});

test('restores cache if it exists', async () => {
when(cacheManagerMock.restoreCache(anything(), anything()));
initialCache.downloadUrls = { [existingKey]: 'url' };

const buildStep = cacheRestoreBuildFunction.createBuildStepFromFunctionCall(ctx, {
callInputs: { key, paths },
});
Expand All @@ -73,25 +88,12 @@ describe('cache functions', () => {

await buildStep.executeAsync();

verify(cacheManagerMock.restoreCache(anything(), anything())).once();
verify(dynamicCacheManagerMock.restoreCache(anything(), anything())).once();

const [, cache] = capture(cacheManagerMock.restoreCache).first();
const [, cache] = capture(dynamicCacheManagerMock.restoreCache).first();
expect(cache.key).toMatch(/^\w+-value/);
expect(cache.paths).toStrictEqual(paths);
});

test("doesn't restore cache if it doesn't exist", async () => {
when(cacheManagerMock.restoreCache(anything(), anything()));
initialCache.downloadUrls = { invalidkey: 'url' };

const buildStep = cacheRestoreBuildFunction.createBuildStepFromFunctionCall(ctx, {
callInputs: { key, paths },
});

await buildStep.executeAsync();

verify(cacheManagerMock.restoreCache(anything(), anything())).never();
});
});

describe('cacheSaveBuildFunction', () => {
Expand All @@ -102,35 +104,16 @@ describe('cache functions', () => {
});

test('saves cache if it does not exist', async () => {
when(cacheManagerMock.restoreCache(anything(), anything()));

initialCache.downloadUrls = {};

const buildStep = cacheSaveBuildFunction.createBuildStepFromFunctionCall(ctx, {
callInputs: { key, paths },
});

await buildStep.executeAsync();

verify(cacheManagerMock.saveCache(anything(), anything())).once();
verify(dynamicCacheManagerMock.saveCache(anything(), anything())).once();

const [, cache] = capture(cacheManagerMock.saveCache).first();
const [, cache] = capture(dynamicCacheManagerMock.saveCache).first();
expect(cache?.key).toMatch(/^\w+-value/);
expect(cache?.paths).toStrictEqual(paths);
});

test("doesn't save cache if it exists", async () => {
when(cacheManagerMock.restoreCache(anything(), anything()));

initialCache.downloadUrls = { [existingKey]: 'url' };

const buildStep = cacheSaveBuildFunction.createBuildStepFromFunctionCall(ctx, {
callInputs: { key, paths },
});

await buildStep.executeAsync();

verify(cacheManagerMock.saveCache(anything(), anything())).never();
});
});
});
Loading

0 comments on commit 9800877

Please sign in to comment.