Skip to content

Commit aecae61

Browse files
feat(qwik-nx): build executor (#78)
* feat(qwik-nx): build executor * feat(qwik-nx): build executor migration and test coverage * feat(qwik-nx): update target & configuration names
1 parent 4e59c85 commit aecae61

File tree

18 files changed

+809
-63
lines changed

18 files changed

+809
-63
lines changed

e2e/qwik-nx-e2e/tests/application-basic-behavior.suite.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
runCommandUntil,
1010
promisifiedTreeKill,
1111
killPort,
12+
stripConsoleColors,
1213
} from '@qwikifiers/e2e/utils';
1314

1415
export function testApplicationBasicBehavior(generator: 'app' | 'preset') {
@@ -35,9 +36,18 @@ export function testApplicationBasicBehavior(generator: 'app' | 'preset') {
3536
});
3637

3738
it('should create qwik-nx', async () => {
38-
const result = await runNxCommandAsync(`build-ssr ${project}`);
39+
const result = await runNxCommandAsync(`build ${project}`);
40+
expect(stripConsoleColors(result.stdout.replace(/\n|\s/g, ''))).toContain(
41+
[
42+
'Targets to be executed:',
43+
`${project}:build.client`,
44+
`${project}:build.ssr`,
45+
]
46+
.join('')
47+
.replace(/\n|\s/g, '')
48+
);
3949
expect(result.stdout).toContain(
40-
`Successfully ran target build-ssr for project ${project}`
50+
`Successfully ran target build for project ${project}`
4151
);
4252
expect(() =>
4353
checkFilesExist(`dist/apps/${project}/client/q-manifest.json`)
@@ -47,6 +57,25 @@ export function testApplicationBasicBehavior(generator: 'app' | 'preset') {
4757
).not.toThrow();
4858
}, 200000);
4959

60+
it('should run build with a specified configuration', async () => {
61+
// TODO: cloudflare pages or custom configurations should also be tested
62+
const result = await runNxCommandAsync(
63+
`build ${project} --configuration=preview`
64+
);
65+
expect(stripConsoleColors(result.stdout.replace(/\n|\s/g, ''))).toContain(
66+
[
67+
'Targets to be executed:',
68+
`${project}:build.client:preview`,
69+
`${project}:build.ssr:preview`,
70+
]
71+
.join('')
72+
.replace(/\n|\s/g, '')
73+
);
74+
expect(result.stdout).toContain(
75+
`Successfully ran target build for project ${project}`
76+
);
77+
}, 200000);
78+
5079
it('should serve application in dev mode with custom port', async () => {
5180
const port = 4212;
5281
const p = await runCommandUntil(

e2e/qwik-nx-e2e/tests/qwik-nx-vite.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ describe('qwikNxVite plugin e2e', () => {
106106
}, 200000);
107107

108108
it('should be able to successfully build the application', async () => {
109-
const result = await runNxCommandAsync(`build-ssr ${project}`);
109+
const result = await runNxCommandAsync(`build ${project}`);
110110
expect(result.stdout).toContain(
111-
`Successfully ran target build-ssr for project ${project}`
111+
`Successfully ran target build for project ${project}`
112112
);
113113
expect(() =>
114114
checkFilesExist(`dist/apps/${project}/client/q-manifest.json`)

e2e/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export function getEnvironmentVariables() {
186186
* @param log
187187
* @returns
188188
*/
189-
function stripConsoleColors(log: string): string {
189+
export function stripConsoleColors(log: string): string {
190190
return log.replace(
191191
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
192192
''

packages/qwik-nx/.eslintrc.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
"rules": {}
1616
},
1717
{
18-
"files": ["./package.json", "./generators.json", "./executors.json"],
18+
"files": [
19+
"./package.json",
20+
"./generators.json",
21+
"./executors.json",
22+
"./migrations.json"
23+
],
1924
"parser": "jsonc-eslint-parser",
2025
"rules": {
2126
"@nrwl/nx/nx-plugin-checks": "error"

packages/qwik-nx/executors.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
{
22
"$schema": "http://json-schema.org/schema",
3-
"executors": {}
3+
"executors": {
4+
"build": {
5+
"implementation": "./src/executors/build/executor",
6+
"schema": "./src/executors/build/schema.json",
7+
"description": "build executor"
8+
}
9+
}
410
}

packages/qwik-nx/migrations.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"generators": {
3+
"switch-to-qwik-nx:build-executor": {
4+
"version": "0.11.0",
5+
"description": "switch-to-qwik-nx:build-executor",
6+
"cli": "nx",
7+
"implementation": "./src/migrations/switch-to-qwik-nx:build-executor/switch-to-qwik-nx:build-executor"
8+
}
9+
}
10+
}

packages/qwik-nx/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@
2828
"vitest": "^0.25.0",
2929
"@playwright/test": "^1.30.0",
3030
"undici": "^5.18.0"
31+
},
32+
"nx-migrations": {
33+
"migrations": "./migrations.json"
3134
}
3235
}

packages/qwik-nx/project.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
"input": "./packages/qwik-nx",
3838
"glob": "executors.json",
3939
"output": "."
40+
},
41+
{
42+
"input": "./packages/qwik-nx",
43+
"glob": "migrations.json",
44+
"output": "."
4045
}
4146
]
4247
}
@@ -49,7 +54,8 @@
4954
"packages/qwik-nx/**/*.ts",
5055
"packages/qwik-nx/generators.json",
5156
"packages/qwik-nx/executors.json",
52-
"packages/qwik-nx/package.json"
57+
"packages/qwik-nx/package.json",
58+
"packages/qwik-nx/migrations.json"
5359
]
5460
}
5561
},
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { BuildExecutorSchema } from './schema';
2+
import executor from './executor';
3+
import { ExecutorContext, runExecutor, Target } from '@nrwl/devkit';
4+
5+
// eslint-disable-next-line @typescript-eslint/no-var-requires
6+
const devkit: { runExecutor: typeof runExecutor } = require('@nrwl/devkit');
7+
8+
describe('Build Executor', () => {
9+
let runExecutorPayloads: Target[] = [];
10+
11+
jest.spyOn(devkit, 'runExecutor').mockImplementation((target: Target) =>
12+
Promise.resolve(
13+
(async function* () {
14+
runExecutorPayloads.push(target);
15+
yield { success: true, target }; // yielding target for debugging purposes
16+
})()
17+
)
18+
);
19+
20+
afterEach(() => {
21+
runExecutorPayloads = [];
22+
});
23+
24+
it('should execute targets sequentially', async () => {
25+
const context = {
26+
root: '/root',
27+
projectName: 'my-app',
28+
targetName: 'build',
29+
configurationName: 'production',
30+
} as ExecutorContext;
31+
32+
const options: BuildExecutorSchema = {
33+
runSequence: ['my-app:target1:development', 'my-app:target2'],
34+
};
35+
const iterable = executor(options, context);
36+
await iterable.next();
37+
expect(runExecutorPayloads.map((p) => p.target)).toEqual(['target1']);
38+
await iterable.next();
39+
expect(runExecutorPayloads.map((p) => p.target)).toEqual([
40+
'target1',
41+
'target2',
42+
]);
43+
const result = await iterable.next();
44+
expect(runExecutorPayloads).toEqual([
45+
{ project: 'my-app', target: 'target1', configuration: 'development' },
46+
{ project: 'my-app', target: 'target2', configuration: 'production' },
47+
]);
48+
expect(result.done).toEqual(true);
49+
});
50+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {
2+
ExecutorContext,
3+
output,
4+
parseTargetString,
5+
runExecutor,
6+
targetToTargetString,
7+
} from '@nrwl/devkit';
8+
import { BuildExecutorSchema } from './schema';
9+
import * as chalk from 'chalk';
10+
11+
export default async function* runBuildExecutor(
12+
options: BuildExecutorSchema,
13+
context: ExecutorContext
14+
) {
15+
const configs = options.runSequence.map((target) => {
16+
const cfg = parseTargetString(target, context.projectGraph!);
17+
cfg.configuration ??= context.configurationName;
18+
return cfg;
19+
});
20+
21+
output.log({
22+
title: `Building the ${context.projectName} project`,
23+
bodyLines: [
24+
'\nTargets to be executed:',
25+
...configs.map((t) => chalk.dim(targetToTargetString(t))),
26+
],
27+
});
28+
29+
for (const target of configs) {
30+
const step = await runExecutor(target, {}, context);
31+
32+
for await (const result of step) {
33+
if (!result.success) {
34+
return result;
35+
}
36+
yield {
37+
success: true,
38+
};
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)