242 lines
7.5 KiB
TypeScript
242 lines
7.5 KiB
TypeScript
import {
|
|
cleanupProject,
|
|
listFiles,
|
|
newProject,
|
|
rmDist,
|
|
runCLI,
|
|
uniq,
|
|
updateFile,
|
|
updateProjectConfig,
|
|
} from '@nrwl/e2e/utils';
|
|
|
|
describe('cache', () => {
|
|
beforeEach(() => newProject());
|
|
|
|
afterEach(() => cleanupProject());
|
|
|
|
it('should cache command execution', async () => {
|
|
const myapp1 = uniq('myapp1');
|
|
const myapp2 = uniq('myapp2');
|
|
runCLI(`generate @nrwl/web:app ${myapp1}`);
|
|
runCLI(`generate @nrwl/web:app ${myapp2}`);
|
|
const files = `--files="apps/${myapp1}/src/main.ts,apps/${myapp2}/src/main.ts"`;
|
|
|
|
// run build with caching
|
|
// --------------------------------------------
|
|
const outputThatPutsDataIntoCache = runCLI(`affected:build ${files}`);
|
|
const filesApp1 = listFiles(`dist/apps/${myapp1}`);
|
|
const filesApp2 = listFiles(`dist/apps/${myapp2}`);
|
|
// now the data is in cache
|
|
expect(outputThatPutsDataIntoCache).not.toContain(
|
|
'read the output from the cache'
|
|
);
|
|
|
|
rmDist();
|
|
|
|
const outputWithBothBuildTasksCached = runCLI(`affected:build ${files}`);
|
|
expect(outputWithBothBuildTasksCached).toContain(
|
|
'read the output from the cache'
|
|
);
|
|
expectCached(outputWithBothBuildTasksCached, [myapp1, myapp2]);
|
|
expect(listFiles(`dist/apps/${myapp1}`)).toEqual(filesApp1);
|
|
expect(listFiles(`dist/apps/${myapp2}`)).toEqual(filesApp2);
|
|
|
|
// run with skipping cache
|
|
const outputWithBothBuildTasksCachedButSkipped = runCLI(
|
|
`affected:build ${files} --skip-nx-cache`
|
|
);
|
|
expect(outputWithBothBuildTasksCachedButSkipped).not.toContain(
|
|
`read the output from the cache`
|
|
);
|
|
|
|
// touch myapp1
|
|
// --------------------------------------------
|
|
updateFile(`apps/${myapp1}/src/main.ts`, (c) => {
|
|
return `${c}\n//some comment`;
|
|
});
|
|
const outputWithBuildApp2Cached = runCLI(`affected:build ${files}`);
|
|
expect(outputWithBuildApp2Cached).toContain(
|
|
'read the output from the cache'
|
|
);
|
|
expectMatchedOutput(outputWithBuildApp2Cached, [myapp2]);
|
|
|
|
// touch package.json
|
|
// --------------------------------------------
|
|
updateFile(`package.json`, (c) => {
|
|
const r = JSON.parse(c);
|
|
r.description = 'different';
|
|
return JSON.stringify(r);
|
|
});
|
|
const outputWithNoBuildCached = runCLI(`affected:build ${files}`);
|
|
expect(outputWithNoBuildCached).not.toContain(
|
|
'read the output from the cache'
|
|
);
|
|
|
|
// build individual project with caching
|
|
const individualBuildWithCache = runCLI(`build ${myapp1}`);
|
|
expect(individualBuildWithCache).toContain(
|
|
'existing outputs match the cache'
|
|
);
|
|
|
|
// skip caching when building individual projects
|
|
const individualBuildWithSkippedCache = runCLI(
|
|
`build ${myapp1} --skip-nx-cache`
|
|
);
|
|
expect(individualBuildWithSkippedCache).not.toContain(
|
|
'existing outputs match the cache'
|
|
);
|
|
|
|
// run lint with caching
|
|
// --------------------------------------------
|
|
const outputWithNoLintCached = runCLI(`affected:lint ${files}`);
|
|
expect(outputWithNoLintCached).not.toContain(
|
|
'read the output from the cache'
|
|
);
|
|
|
|
const outputWithBothLintTasksCached = runCLI(`affected:lint ${files}`);
|
|
expect(outputWithBothLintTasksCached).toContain(
|
|
'read the output from the cache'
|
|
);
|
|
expectCached(outputWithBothLintTasksCached, [
|
|
myapp1,
|
|
myapp2,
|
|
`${myapp1}-e2e`,
|
|
`${myapp2}-e2e`,
|
|
]);
|
|
|
|
// cache task failures
|
|
// --------------------------------------------
|
|
// updateFile('workspace.json', (c) => {
|
|
// const workspaceJson = JSON.parse(c);
|
|
// workspaceJson.projects[myapp1].targets.lint = {
|
|
// executor: '@nrwl/workspace:run-commands',
|
|
// options: {
|
|
// command: 'echo hi && exit 1',
|
|
// },
|
|
// };
|
|
// return JSON.stringify(workspaceJson, null, 2);
|
|
// });
|
|
// const failingRun = runCLI(`lint ${myapp1}`, {
|
|
// silenceError: true,
|
|
// env: { ...process.env, NX_CACHE_FAILURES: 'true' },
|
|
// });
|
|
// expect(failingRun).not.toContain('[retrieved from cache]');
|
|
//
|
|
// const cachedFailingRun = runCLI(`lint ${myapp1}`, {
|
|
// silenceError: true,
|
|
// env: { ...process.env, NX_CACHE_FAILURES: 'true' },
|
|
// });
|
|
// expect(cachedFailingRun).toContain('[retrieved from cache]');
|
|
|
|
// run without caching
|
|
// --------------------------------------------
|
|
|
|
// disable caching
|
|
// --------------------------------------------
|
|
updateFile('nx.json', (c) => {
|
|
const nxJson = JSON.parse(c);
|
|
nxJson.tasksRunnerOptions = {
|
|
default: {
|
|
options: {
|
|
cacheableOperations: [],
|
|
},
|
|
},
|
|
};
|
|
return JSON.stringify(nxJson, null, 2);
|
|
});
|
|
|
|
const outputWithoutCachingEnabled1 = runCLI(`affected:build ${files}`);
|
|
|
|
expect(outputWithoutCachingEnabled1).not.toContain(
|
|
'read the output from the cache'
|
|
);
|
|
|
|
const outputWithoutCachingEnabled2 = runCLI(`affected:build ${files}`);
|
|
expect(outputWithoutCachingEnabled2).not.toContain(
|
|
'read the output from the cache'
|
|
);
|
|
}, 120000);
|
|
|
|
it('should only cache specific files if build outputs is configured with specific files', async () => {
|
|
const mylib1 = uniq('mylib1');
|
|
runCLI(`generate @nrwl/react:lib ${mylib1} --buildable`);
|
|
|
|
// Update outputs in workspace.json to just be a particular file
|
|
updateProjectConfig(mylib1, (config) => {
|
|
config.targets['build-base'] = {
|
|
...config.targets.build,
|
|
};
|
|
config.targets.build = {
|
|
executor: '@nrwl/workspace:run-commands',
|
|
outputs: [`dist/libs/${mylib1}/index.esm.js`],
|
|
options: {
|
|
commands: [
|
|
{
|
|
command: `npx nx run ${mylib1}:build-base`,
|
|
},
|
|
],
|
|
parallel: false,
|
|
},
|
|
};
|
|
return config;
|
|
});
|
|
|
|
// run build with caching
|
|
// --------------------------------------------
|
|
const outputThatPutsDataIntoCache = runCLI(`run ${mylib1}:build`);
|
|
// now the data is in cache
|
|
expect(outputThatPutsDataIntoCache).not.toContain('cache');
|
|
|
|
rmDist();
|
|
|
|
const outputWithBuildTasksCached = runCLI(`run ${mylib1}:build`);
|
|
expect(outputWithBuildTasksCached).toContain('cache');
|
|
expectCached(outputWithBuildTasksCached, [mylib1]);
|
|
// Ensure that only the specific file in outputs was copied to cache
|
|
expect(listFiles(`dist/libs/${mylib1}`)).toEqual([`index.esm.js`]);
|
|
}, 120000);
|
|
|
|
function expectCached(
|
|
actualOutput: string,
|
|
expectedCachedProjects: string[]
|
|
) {
|
|
expectProjectMatchTaskCacheStatus(actualOutput, expectedCachedProjects);
|
|
}
|
|
|
|
function expectMatchedOutput(
|
|
actualOutput: string,
|
|
expectedMatchedOutputProjects: string[]
|
|
) {
|
|
expectProjectMatchTaskCacheStatus(
|
|
actualOutput,
|
|
expectedMatchedOutputProjects,
|
|
'existing outputs match the cache'
|
|
);
|
|
}
|
|
|
|
function expectProjectMatchTaskCacheStatus(
|
|
actualOutput: string,
|
|
expectedProjects: string[],
|
|
cacheStatus: string = 'local cache'
|
|
) {
|
|
const matchingProjects = [];
|
|
const lines = actualOutput.split('\n');
|
|
lines.forEach((s) => {
|
|
if (s.trimStart().startsWith(`> nx run`)) {
|
|
const projectName = s
|
|
.trimStart()
|
|
.split(`> nx run `)[1]
|
|
.split(':')[0]
|
|
.trim();
|
|
if (s.indexOf(cacheStatus) > -1) {
|
|
matchingProjects.push(projectName);
|
|
}
|
|
}
|
|
});
|
|
|
|
matchingProjects.sort((a, b) => a.localeCompare(b));
|
|
expectedProjects.sort((a, b) => a.localeCompare(b));
|
|
expect(matchingProjects).toEqual(expectedProjects);
|
|
}
|
|
});
|