Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/shared-lib-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"prettier": "@willbooster/prettier-config",
"dependencies": {
"dotenv": "17.2.3",
"dotenv-expand": "12.0.3",
"tree-kill": "1.2.2"
},
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion packages/shared-lib-node/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';

import { config } from 'dotenv';
import { expand } from 'dotenv-expand';
import type { ArgumentsCamelCase, InferredOptionTypes } from 'yargs';

export const yargsOptionsBuilderForEnv = {
Expand Down Expand Up @@ -104,7 +105,7 @@ export function readEnvironmentVariables(
throw new Error(`Missing environment variables in [${envPaths.join(', ')}]: [${missingKeys.join(', ')}]`);
}
}
return [envVars, envPathAndEnvVarCountPairs];
return [expand({ parsed: envVars, processEnv: {} }).parsed ?? envVars, envPathAndEnvVarCountPairs];
}

/**
Expand Down
10 changes: 5 additions & 5 deletions packages/shared-lib-node/test/env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ describe('readAndApplyEnvironmentVariables()', () => {

it('should load env vars with --auto-cascade-env', () => {
const envVars = readAndApplyEnvironmentVariables({ autoCascadeEnv: true }, 'test/fixtures/app1');
expect(envVars).toEqual({ NAME: 'app1', ENV: 'development1' });
expect(envVars).toEqual({ ENV: 'development1', PORT: '3001', NAME: 'app1' });
});

it('should load env vars with --cascade-env=production', () => {
const envVars = readAndApplyEnvironmentVariables({ cascadeEnv: 'production', env: ['.env'] }, 'test/fixtures/app1');
expect(envVars).toEqual({ NAME: 'app1', ENV: 'production1' });
expect(envVars).toEqual({ ENV: 'production1', PORT: '3003', NAME: 'app1' });
});

it('should load env vars with --cascade-node-env and NODE_ENV=""', () => {
process.env.NODE_ENV = '';
const envVars = readAndApplyEnvironmentVariables({ cascadeNodeEnv: true, env: ['.env'] }, 'test/fixtures/app1');
expect(envVars).toEqual({ NAME: 'app1', ENV: 'development1' });
expect(envVars).toEqual({ ENV: 'development1', PORT: '3001', NAME: 'app1' });
});

it('should load env vars with --cascade-node-env and NODE_ENV=test', () => {
process.env.NODE_ENV = 'test';
const envVars = readAndApplyEnvironmentVariables({ cascadeNodeEnv: true, env: ['.env'] }, 'test/fixtures/app1');
expect(envVars).toEqual({ NAME: 'app1', ENV: 'test1' });
expect(envVars).toEqual({ ENV: 'test1', PORT: '3002', NAME: 'app1' });
});

it('should load env vars with --env=test/fixtures/app2/.env --auto-cascade-env, WB_ENV=test and NODE_ENV=production', () => {
Expand All @@ -42,6 +42,6 @@ describe('readAndApplyEnvironmentVariables()', () => {
{ autoCascadeEnv: true, env: ['../app2/.env'] },
'test/fixtures/app1'
);
expect(envVars).toEqual({ NAME: 'app2', ENV: 'test2' });
expect(envVars).toEqual({ ENV: 'test2', PORT: '4002', NAME: 'app2' });
});
});
1 change: 1 addition & 0 deletions packages/shared-lib-node/test/fixtures/app1/.env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
NAME=app1
PORT=3000
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ENV=development1
PORT=3001
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ENV=production1
PORT=3003
1 change: 1 addition & 0 deletions packages/shared-lib-node/test/fixtures/app1/.env.test
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ENV=test1
PORT=3002
1 change: 1 addition & 0 deletions packages/shared-lib-node/test/fixtures/app2/.env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
NAME=app2
PORT=4000
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ENV=development2
PORT=4001
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ENV=production2
PORT=4003
1 change: 1 addition & 0 deletions packages/shared-lib-node/test/fixtures/app2/.env.test
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ENV=test2
PORT=4002
33 changes: 6 additions & 27 deletions packages/wb/src/commands/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,25 @@ export const startCommand: CommandModule<unknown, InferredOptionTypes<typeof bui
switch (argv.mode ?? 'dev') {
case 'dev':
case 'development': {
const prefix = configureEnvironmentVariables(deps, 'development');
await runWithSpawn(`${prefix}${scripts.start(project, argv)}`, project, argv);
await runWithSpawn(await scripts.startDev(project, argv), project, argv);
break;
}
case 'staging': {
const prefix = configureEnvironmentVariables(deps, 'staging');
const port = Number(project.env.PORT) || 8080;
await runWithSpawn(`${prefix}${scripts.startProduction(project, argv, port)}`, project, argv);
await runWithSpawn(await scripts.startProduction(project, argv), project, argv);
break;
}
case 'docker': {
const prefix = configureEnvironmentVariables(deps, 'staging');
await runWithSpawn(`${prefix}${scripts.startDocker(project, argv)}`, project, argv);
await runWithSpawn(await scripts.startDocker(project, argv), project, argv);
break;
}
case 'docker-debug': {
const prefix = configureEnvironmentVariables(deps, 'staging');
argv.normalizedArgsText = `'/bin/bash'`;
await runWithSpawn(`${prefix}${scripts.startDocker(project, argv)}`, project, argv);
await runWithSpawn(await scripts.startDocker(project, argv), project, argv);
break;
}
case 'test': {
const prefix = configureEnvironmentVariables(deps, 'test');
const script = `${prefix}${scripts.startTest(project, argv)}`;
await runWithSpawn(addServerLogRedirection(script), project, argv);
const script = await scripts.startTest(project, argv);
await runWithSpawn(script, project, argv);
break;
}
default: {
Expand All @@ -95,18 +89,3 @@ export const startCommand: CommandModule<unknown, InferredOptionTypes<typeof bui
}
},
};

function addServerLogRedirection(script: string): string {
const trimmedScript = script.trimEnd();
return `${trimmedScript} > test.log 2>&1`;
}

function configureEnvironmentVariables(deps: Partial<Record<string, string>>, wbEnv: string): string {
process.env.WB_ENV ||= wbEnv;
let prefix = `WB_ENV=${process.env.WB_ENV} `;
if (deps.next) {
process.env.NEXT_PUBLIC_WB_ENV = process.env.WB_ENV;
prefix += `NEXT_PUBLIC_WB_ENV=${process.env.WB_ENV} `;
}
return prefix;
}
20 changes: 10 additions & 10 deletions packages/wb/src/commands/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,11 @@ export async function test(

switch (argv.e2e) {
case 'headless': {
await runWithSpawn(scripts.testE2E(project, e2eArgv, {}), project, argv);
await runWithSpawn(await scripts.testE2EProduction(project, e2eArgv, {}), project, argv);
continue;
}
case 'headless-dev': {
await runWithSpawn(scripts.testE2EDev(project, e2eArgv, {}), project, argv);
await runWithSpawn(await scripts.testE2EDev(project, e2eArgv, {}), project, argv);
continue;
}
case 'docker': {
Expand All @@ -154,32 +154,33 @@ export async function test(
switch (argv.e2e) {
case 'headed': {
await runWithSpawn(
scripts.testE2E(project, e2eArgv, { playwrightArgs: `test ${e2eTarget} --headed` }),
await scripts.testE2EProduction(project, e2eArgv, { playwrightArgs: `test ${e2eTarget} --headed` }),
project,
argv
);
break;
}
case 'headed-dev': {
await runWithSpawn(
scripts.testE2EDev(project, e2eArgv, { playwrightArgs: `test ${e2eTarget} --headed` }),
await scripts.testE2EDev(project, e2eArgv, { playwrightArgs: `test ${e2eTarget} --headed` }),
project,
argv
);
break;
}
case 'debug': {
await runWithSpawn(
scripts.testE2E(project, e2eArgv, { playwrightArgs: `test ${e2eTarget} --debug` }),
await scripts.testE2EProduction(project, e2eArgv, { playwrightArgs: `test ${e2eTarget} --debug` }),
project,
argv
);
break;
}
case 'generate': {
const port = project.env.PORT || '8080';
await runWithSpawn(
scripts.testE2E(project, e2eArgv, { playwrightArgs: `codegen http://localhost:${port}` }),
await scripts.testE2EProduction(project, e2eArgv, {
playwrightArgs: `codegen http://localhost:${project.env.PORT}`,
}),
project,
argv
);
Expand All @@ -200,12 +201,11 @@ async function testOnDocker(
scripts: BaseScripts,
playwrightArgs?: string
): Promise<void> {
process.env.WB_DOCKER ??= '1';
project.env.WB_DOCKER ||= '1';
await runWithSpawn(`${scripts.buildDocker(project, 'test')}${toDevNull(argv)}`, project, argv);
process.exitCode = await runWithSpawn(
scripts.testE2E(project, argv, {
await scripts.testE2EDocker(project, argv, {
playwrightArgs,
startCommand: `${dockerScripts.stopAndStart(project, true)}${toDevNull(argv)}`,
}),
project,
argv,
Expand Down
19 changes: 11 additions & 8 deletions packages/wb/src/commands/testOnCi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ import { promisePool } from '../utils/promisePool.js';

import { httpServerPackages } from './httpServerPackages.js';

const testOnCiBuilder = {} as const;
const testOnCiBuilder = {
silent: {
description: 'Reduce redundant outputs',
type: 'boolean',
},
} as const;
export const testOnCiCommand: CommandModule<
unknown,
InferredOptionTypes<typeof testOnCiBuilder & typeof sharedOptionsBuilder>
Expand Down Expand Up @@ -72,17 +77,15 @@ export async function testOnCi(
await promisePool.promiseAll();
if (fs.existsSync(path.join(project.dirPath, 'test', 'e2e'))) {
if (project.hasDockerfile) {
process.env.WB_DOCKER ??= '1';
project.env.WB_DOCKER ||= '1';
await runWithSpawn(`${scripts.buildDocker(project, 'test')}${toDevNull(argv)}`, project, argv);
}
const options = project.hasDockerfile
? {
startCommand: dockerScripts.stopAndStart(project, true),
}
: {};
const script = project.hasDockerfile
? await scripts.testE2EDocker(project, argv, {})
: await scripts.testE2EProduction(project, argv, {});
process.exitCode = await runWithSpawn(
// CI mode disallows `only` to avoid including debug tests
scripts.testE2E(project, argv, options).replaceAll(' --allowOnly', ''),
script.replaceAll(' --allowOnly', ''),
project,
argv,
{
Expand Down
4 changes: 2 additions & 2 deletions packages/wb/src/scripts/dockerScripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { spawnSyncOnExit } from '../utils/process.js';
* Note that `YARN zzz` is replaced with `yarn zzz` or `node_modules/.bin/zzz`.
*/
class DockerScripts {
buildDevImage(project: Project, version: string): string {
buildImage(project: Project, version: string): string {
// e.g. coding-booster uses `"docker/build/prepare": "touch drill-users.csv",`
const prefix = project.dockerPackageJson.scripts?.['docker/build/prepare']
? 'YARN run docker/build/prepare && '
Expand All @@ -31,7 +31,7 @@ class DockerScripts {

start(project: Project, additionalOptions = '', additionalArgs = ''): string {
spawnSyncOnExit(this.stop(project), project);
return `docker run --rm -it -p \${PORT:-8080}:8080 --name ${project.dockerImageName} ${additionalOptions} ${project.dockerImageName} ${additionalArgs}`;
return `docker run --rm -it --publish ${project.env.PORT}:8080 --name ${project.dockerImageName} ${additionalOptions} ${project.dockerImageName} ${additionalArgs}`;
}

stop(project: Project): string {
Expand Down
Loading