Skip to content

Commit e0887e9

Browse files
committed
refactor(jobs-lifter): enable providing lifters targeted at specific jobs
1 parent 8271878 commit e0887e9

10 files changed

Lines changed: 82 additions & 60 deletions

File tree

src/job/lifter.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
11
import {lift as liftSteps} from '../steps/index.js';
22

3-
function enginesShouldBeUpdated(inRangeNodeVersions, job) {
4-
return inRangeNodeVersions && job.strategy?.matrix?.node;
5-
}
3+
export default function ([jobName, job], enhancers, options) {
4+
const enhancer = enhancers.find(({test}) => test({jobName}));
5+
6+
const jobWithLiftedSteps = {...job, ...job.steps && {steps: liftSteps(job.steps)}};
67

7-
export default function ([jobName, job], inRangeNodeVersions) {
8-
return [
9-
jobName,
10-
{
11-
...job,
12-
...job.steps && {steps: liftSteps(job.steps)},
13-
...enginesShouldBeUpdated(inRangeNodeVersions, job) && {strategy: {matrix: {node: inRangeNodeVersions}}}
14-
}
15-
];
8+
return [jobName, enhancer ? enhancer.lift(jobWithLiftedSteps, options) : jobWithLiftedSteps];
169
}

src/job/lifter.test.js

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {describe, it, expect, afterEach, vi} from 'vitest';
1+
import {describe, expect, it, vi} from 'vitest';
22
import any from '@travi/any';
33
import {when} from 'jest-when';
44

@@ -9,60 +9,44 @@ vi.mock('../steps/index.js');
99

1010
describe('job lifter', () => {
1111
const jobName = any.word();
12-
const updatedSupportedNodeVersions = any.listOf(any.simpleObject);
13-
14-
afterEach(() => {
15-
vi.clearAllMocks();
16-
});
12+
const jobSteps = any.listOf(any.simpleObject);
13+
const liftedSteps = any.listOf(any.simpleObject);
14+
const enhancerOptions = any.simpleObject();
15+
const nonApplicableEnhancerFactory = () => ({test: () => false});
1716

1817
it('should lift the steps of a job', () => {
1918
const jobWithoutSteps = any.simpleObject();
20-
const jobSteps = any.listOf(any.simpleObject);
21-
const liftedSteps = any.listOf(any.simpleObject);
2219
when(liftSteps).calledWith(jobSteps).mockReturnValue(liftedSteps);
2320

24-
expect(liftJob([jobName, {...jobWithoutSteps, steps: jobSteps}]))
21+
expect(liftJob([jobName, {...jobWithoutSteps, steps: jobSteps}], any.listOf(nonApplicableEnhancerFactory)))
2522
.toEqual([jobName, {...jobWithoutSteps, steps: liftedSteps}]);
2623
});
2724

2825
it('should lift a job that calls a reusable workflow', () => {
2926
const jobThatCallsReusableWorkflow = {...any.simpleObject(), uses: any.string()};
30-
const liftedJob = liftJob([jobName, jobThatCallsReusableWorkflow]);
27+
const liftedJob = liftJob([jobName, jobThatCallsReusableWorkflow], any.listOf(nonApplicableEnhancerFactory));
3128

3229
expect(liftSteps).not.toHaveBeenCalled();
3330
expect(liftedJob).toEqual([jobName, jobThatCallsReusableWorkflow]);
3431
});
3532

36-
it('should replace the node versions in an existing matrix job', () => {
37-
const [, updatedJobDefinition] = liftJob(
38-
[jobName, {...any.simpleObject(), strategy: {matrix: {node: any.listOf(any.integer)}}}],
39-
updatedSupportedNodeVersions
40-
);
41-
42-
expect(updatedJobDefinition.strategy.matrix.node).toEqual(updatedSupportedNodeVersions);
43-
});
44-
45-
it('should not add a test strategy to a job that does not already have one defined', () => {
46-
const [, updatedJobDefinition] = liftJob([jobName, any.simpleObject()], updatedSupportedNodeVersions);
47-
48-
expect(updatedJobDefinition.strategy).toBe(undefined);
49-
});
50-
51-
it('should not add a test matrix to a job that does not already have one defined', () => {
52-
const [, updatedJobDefinition] = liftJob(
53-
[jobName, {...any.simpleObject(), strategy: any.simpleObject()}],
54-
updatedSupportedNodeVersions
55-
);
56-
57-
expect(updatedJobDefinition.strategy.matrix).toBe(undefined);
58-
});
33+
it('should apply a related enhancer', () => {
34+
const jobLifter = vi.fn();
35+
const applicableEnhancer = {test: () => true, lift: jobLifter};
36+
const enhancers = [
37+
...any.listOf(nonApplicableEnhancerFactory),
38+
applicableEnhancer,
39+
...any.listOf(nonApplicableEnhancerFactory)
40+
];
41+
const existingJobDetails = {...any.simpleObject(), steps: jobSteps};
42+
const liftedJobDetails = any.simpleObject();
43+
when(liftSteps).calledWith(jobSteps).mockReturnValue(liftedSteps);
44+
when(jobLifter)
45+
.calledWith({...existingJobDetails, steps: liftedSteps}, enhancerOptions)
46+
.mockReturnValue(liftedJobDetails);
5947

60-
it('should not add a list of supported node versions to a job that does not already have one defined', () => {
61-
const [, updatedJobDefinition] = liftJob(
62-
[jobName, {...any.simpleObject(), strategy: {...any.simpleObject(), matrix: any.simpleObject()}}],
63-
updatedSupportedNodeVersions
64-
);
48+
const [, updatedJobDefinition] = liftJob(['verify-matrix', existingJobDetails], enhancers, enhancerOptions);
6549

66-
expect(updatedJobDefinition.strategy.matrix.node).toBe(undefined);
50+
expect(updatedJobDefinition).toEqual(liftedJobDetails);
6751
});
6852
});

src/jobs/lifter.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import buildNodeVersionMatrix from './node-version-matrix-builder.js';
22
import insertMissingJobs from './missing-job-inserter.js';
3+
import * as matrixVerificationJobEnhancer from './verify-matrix/index.js';
34
import {lift as liftJob} from '../job/index.js';
45

56
export default function ({jobs, engines, runner}) {
67
const nodeEnginesMatrix = buildNodeVersionMatrix(engines);
78

8-
const liftedJobs = Object.entries(jobs).map(([jobName, job]) => liftJob([jobName, job], nodeEnginesMatrix));
9+
const liftedJobs = Object.entries(jobs).map(([jobName, job]) => liftJob(
10+
[jobName, job],
11+
[matrixVerificationJobEnhancer],
12+
{inRangeNodeVersions: nodeEnginesMatrix}
13+
));
914

1015
return Object.fromEntries(insertMissingJobs({versions: nodeEnginesMatrix, jobs: liftedJobs, runner}));
1116
}

src/jobs/lifter.test.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
import zip from 'lodash.zip';
22

3-
import {describe, it, expect, afterEach, vi} from 'vitest';
3+
import {describe, expect, it, vi} from 'vitest';
44
import any from '@travi/any';
55
import {when} from 'jest-when';
66

7+
import {lift as liftJob} from '../job/index.js';
8+
import * as matrixVerificationJobEnhancer from './verify-matrix/index.js';
79
import insertMissingJob from './missing-job-inserter.js';
810
import buildNodeVersionMatrix from './node-version-matrix-builder.js';
9-
import {lift as liftJob} from '../job/index.js';
1011
import liftJobs from './lifter.js';
1112

1213
vi.mock('./missing-job-inserter.js');
1314
vi.mock('./node-version-matrix-builder.js');
1415
vi.mock('../job/index.js');
1516

1617
describe('steps lifter', () => {
17-
afterEach(() => {
18-
vi.clearAllMocks();
19-
});
20-
2118
it('should lift the steps', async () => {
2219
const jobNames = any.listOf(any.word);
2320
const jobDefinitions = jobNames.map(any.simpleObject);
@@ -32,7 +29,7 @@ describe('steps lifter', () => {
3229
.mockReturnValue(jobPairsWithMissingInjected);
3330
zip(jobDefinitions, liftedJobDefinitions, jobNames).forEach(
3431
([job, liftedJob, jobName]) => when(liftJob)
35-
.calledWith([jobName, job], supportedNodeVersions)
32+
.calledWith([jobName, job], [matrixVerificationJobEnhancer], {inRangeNodeVersions: supportedNodeVersions})
3633
.mockReturnValue([jobName, liftedJob])
3734
);
3835

src/jobs/verify-matrix/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export {default as scaffold} from './scaffolder.js';
2+
export {default as test} from './tester.js';
3+
export {default as lift} from './lifter.js';

src/jobs/verify-matrix/lifter.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function (job, {inRangeNodeVersions}) {
2+
if (!inRangeNodeVersions) return job;
3+
4+
return {...job, strategy: {matrix: {node: inRangeNodeVersions}}};
5+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {describe, it, expect} from 'vitest';
2+
import any from '@travi/any';
3+
4+
import liftMatrixVerificationJob from './lifter.js';
5+
6+
describe('matrix verification job lifter', () => {
7+
const existingJobDetails = any.simpleObject();
8+
9+
it('should define the node version matrix for the job', () => {
10+
const inRangeNodeVersions = any.listOf(any.simpleObject);
11+
12+
expect(liftMatrixVerificationJob(existingJobDetails, {inRangeNodeVersions}))
13+
.toEqual({...existingJobDetails, strategy: {matrix: {node: inRangeNodeVersions}}});
14+
});
15+
16+
it('should not modify the job if node versions are not provided', () => {
17+
expect(liftMatrixVerificationJob(existingJobDetails, {})).toEqual(existingJobDetails);
18+
});
19+
});

src/jobs/verify-matrix/tester.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function ({jobName}) {
2+
return 'verify-matrix' === jobName;
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import any from '@travi/any';
2+
import {it, describe, expect} from 'vitest';
3+
4+
import jobIsMatrixVerification from './tester.js';
5+
6+
describe('verify-matrix predicate', () => {
7+
it('should return `true` when the job name is `verify-matrix`', () => {
8+
expect(jobIsMatrixVerification({jobName: 'verify-matrix'})).toBe(true);
9+
});
10+
11+
it('should return `false` when the job name is not `verify-matrix`', () => {
12+
expect(jobIsMatrixVerification({jobName: any.word()})).toBe(false);
13+
});
14+
});

test/integration/features/step_definitions/node-versions-steps.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Given('the version is read from the nvmrc and passed as a value to the setup-nod
6969
});
7070

7171
Given('the node version is based on a matrix {string} caching enabled', async function (cachingEnabled) {
72-
this.existingJobName = any.word();
72+
this.existingJobName = 'verify-matrix';
7373
this.existingNodeVersions = any.listOf(any.integer);
7474
this.existingJobSteps = [
7575
{uses: 'actions/checkout@v3'},

0 commit comments

Comments
 (0)