Skip to content

Commit

Permalink
feat(core): pickup global.json overrides at the project level
Browse files Browse the repository at this point in the history
To accomplish this `dotnet` must be launched from the project's root directories.

Closes #87
Closes #86
  • Loading branch information
AgentEnder committed Aug 23, 2021
1 parent 2dea7fc commit 49ce6bc
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 113 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
name: Run PR checks

on:
# Triggers the workflow on push or pull request events but only for the master branch
pull_request:
branches: [master, dev]
on: pull_request


env:
NX_BRANCH: ${{ github.event.number }}
Expand Down
4 changes: 4 additions & 0 deletions docs/core/executors/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,7 @@ Runs test via the dotnet cli
### verbosity

- (string): Sets the verbosity level of the command. For more information, see LoggerVerbosity.

### watch

- (boolean): Determines if `dotnet test` or `dotnet watch test` is used to execute tests.
12 changes: 10 additions & 2 deletions packages/core/src/executors/build/executor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExecutorContext } from '@nrwl/devkit';
import { appRootPath } from '@nrwl/tao/src/utils/app-root';

import {
dotnetBuildFlags,
Expand All @@ -9,6 +10,7 @@ import {
getExecutedProjectConfiguration,
getProjectFileForNxProject,
} from '@nx-dotnet/utils';
import { resolve } from 'path';

import { BuildExecutorSchema } from './schema';

Expand All @@ -18,9 +20,15 @@ export default async function runExecutor(
dotnetClient: DotNetClient = new DotNetClient(dotnetFactory()),
) {
const nxProjectConfiguration = getExecutedProjectConfiguration(context);
const projectFilePath = await getProjectFileForNxProject(
nxProjectConfiguration,
dotnetClient.cwd = resolve(appRootPath, nxProjectConfiguration.root);
dotnetClient.printSdkVersion();
const projectFilePath = resolve(
appRootPath,
await getProjectFileForNxProject(nxProjectConfiguration),
);
options.output = options.output
? resolve(appRootPath, options.output)
: undefined;

dotnetClient.build(
projectFilePath,
Expand Down
24 changes: 19 additions & 5 deletions packages/core/src/executors/publish/executor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jest.mock('../../../../dotnet/src/lib/core/dotnet.client');

describe('Publish Executor', () => {
let context: ExecutorContext;
let dotnetClient: DotNetClient;
let dotnetClient: jest.Mocked<DotNetClient>;

beforeEach(() => {
context = {
Expand All @@ -42,7 +42,9 @@ describe('Publish Executor', () => {
},
isVerbose: false,
};
dotnetClient = new DotNetClient(mockDotnetFactory());
dotnetClient = new DotNetClient(
mockDotnetFactory(),
) as jest.Mocked<DotNetClient>;
});

afterEach(async () => {
Expand Down Expand Up @@ -95,9 +97,21 @@ describe('Publish Executor', () => {
}

const res = await executor(options, context, dotnetClient);
expect(
(dotnetClient as jest.Mocked<DotNetClient>).publish,
).toHaveBeenCalled();
expect(dotnetClient.publish).toHaveBeenCalled();
expect(res.success).toBeTruthy();
});

it('should pass path relative to project root, not workspace root', async () => {
const directoryPath = `${root}/apps/my-app`;
try {
await fs.mkdir(directoryPath, { recursive: true });
await Promise.all([fs.writeFile(`${directoryPath}/1.csproj`, '')]);
} catch (e) {
console.warn(e.message);
}
const res = await executor(options, context, dotnetClient);
expect(dotnetClient.publish).toHaveBeenCalled();
expect(dotnetClient.cwd).toEqual(directoryPath);
expect(res.success).toBeTruthy();
});
});
7 changes: 6 additions & 1 deletion packages/core/src/executors/publish/executor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExecutorContext } from '@nrwl/devkit';
import { appRootPath } from '@nrwl/tao/src/utils/app-root';

import {
DotNetClient,
Expand All @@ -9,6 +10,7 @@ import {
getExecutedProjectConfiguration,
getProjectFileForNxProject,
} from '@nx-dotnet/utils';
import { resolve } from 'path';

import { PublishExecutorSchema } from './schema';

Expand All @@ -18,14 +20,17 @@ export default async function runExecutor(
dotnetClient: DotNetClient = new DotNetClient(dotnetFactory()),
) {
const nxProjectConfiguration = getExecutedProjectConfiguration(context);
const cwd = resolve(appRootPath, nxProjectConfiguration.root);
dotnetClient.cwd = cwd;
const projectFilePath = await getProjectFileForNxProject(
nxProjectConfiguration,
);

const { publishProfile, extraParameters, ...flags } = options;
flags.output = flags.output ? resolve(appRootPath, flags.output) : undefined;

dotnetClient.publish(
projectFilePath,
resolve(appRootPath, projectFilePath),
Object.keys(flags).map((x) => ({
flag: x as dotnetPublishFlags,
value: (options as Record<string, string | boolean>)[x],
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/executors/publish/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { dotnetPublishFlags } from '@nx-dotnet/dotnet';
export type PublishExecutorSchema = {
[key in dotnetPublishFlags]?: string | boolean;
} & {
output?: string;
publishProfile?: string;
extraParameters?: string;
};
91 changes: 14 additions & 77 deletions packages/core/src/executors/serve/executor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ExecutorContext } from '@nrwl/devkit';
import { appRootPath } from '@nrwl/tao/src/utils/app-root';

import { ChildProcess } from 'child_process';
import * as chockidar from 'chokidar';
import { resolve as pathResolve } from 'path';

import {
DotNetClient,
Expand All @@ -10,17 +11,15 @@ import {
dotnetRunOptions,
} from '@nx-dotnet/dotnet';
import {
getDependantProjectsForNxProject,
getExecutedProjectConfiguration,
getProjectFileForNxProject,
handleChildProcessPassthrough,
rimraf,
} from '@nx-dotnet/utils';

import { ServeExecutorSchema } from './schema';

let resolver: (returnObject: { success: boolean }) => void;
let childProcess: ChildProcess;
let timeout: NodeJS.Timeout;
let projectDirectory: string;

export default function dotnetRunExecutor(
Expand All @@ -29,90 +28,28 @@ export default function dotnetRunExecutor(
dotnetClient: DotNetClient = new DotNetClient(dotnetFactory()),
): Promise<{ success: boolean }> {
const nxProjectConfiguration = getExecutedProjectConfiguration(context);
const cwd = pathResolve(appRootPath, nxProjectConfiguration.root);
dotnetClient.cwd = cwd;

return getProjectFileForNxProject(nxProjectConfiguration).then((project) => {
projectDirectory = nxProjectConfiguration.root;

return new Promise((resolve) => {
resolver = resolve;

const watcher = chockidar.watch(nxProjectConfiguration.root);

getDependantProjectsForNxProject(
context.projectName as string,
context.workspace,
(dependency) => {
watcher.add(dependency.root);
},
);

watcher.on('all', (event, path) => {
if (path.includes('bin') || path.includes('obj')) {
return;
}

if (timeout) {
clearTimeout(timeout);
}

timeout = setTimeout(() => {
setupDotnetRun(dotnetClient, project, options);
}, 1000);

console.log(event, path);
});
});
});
return getProjectFileForNxProject(nxProjectConfiguration).then((project) =>
runDotnetRun(dotnetClient, pathResolve(appRootPath, project), options),
);
}

const setupDotnetRun = (
const runDotnetRun = (
dotnetClient: DotNetClient,
project: string,
options: ServeExecutorSchema,
) => {
if (childProcess) {
childProcess.kill('SIGTERM');
}

const opts: dotnetRunOptions = Object.keys(options).map((x) => ({
flag: x as dotnetRunFlags,
value: (options as Record<string, string | boolean>)[x],
}));

childProcess = dotnetClient.run(project, opts);

childProcess.on('error', (err) => {
console.error(err);
childProcess = dotnetClient.run(project, true, opts);
return handleChildProcessPassthrough(childProcess).then(async () => {
await rimraf(projectDirectory + '/bin');
await rimraf(projectDirectory + '/obj');
return { success: true };
});
};

const exitHandler = async (options: { exit: boolean }, exitCode = 0) => {
console.log('Exit Handler Called');

await rimraf(projectDirectory + '/bin');
await rimraf(projectDirectory + '/obj');

if (exitCode || exitCode === 0) console.log(exitCode);

if (childProcess) {
childProcess.kill('SIGINT');
}
resolver({
success: true,
});

if (options.exit) process.exit();
};

//do something when app is closing
process.on('exit', () => exitHandler({ exit: false }));

//catches ctrl+c event
process.on('SIGINT', () => exitHandler({ exit: true }));

// catches "kill pid" (for example: nodemon restart)
process.on('SIGUSR1', () => exitHandler({ exit: true }));
process.on('SIGUSR2', () => exitHandler({ exit: true }));

//catches uncaught exceptions
process.on('uncaughtException', () => exitHandler({ exit: true }));
25 changes: 21 additions & 4 deletions packages/core/src/executors/test/executor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ExecutorContext } from '@nrwl/devkit';
import { appRootPath } from '@nrwl/tao/src/utils/app-root';

import { resolve } from 'path';

import {
DotNetClient,
Expand All @@ -8,28 +11,42 @@ import {
import {
getExecutedProjectConfiguration,
getProjectFileForNxProject,
handleChildProcessPassthrough,
isChildProcess,
rimraf,
} from '@nx-dotnet/utils';

import { TestExecutorSchema } from './schema';

let projectDirectory: string;

export default async function runExecutor(
options: TestExecutorSchema,
context: ExecutorContext,
dotnetClient: DotNetClient = new DotNetClient(dotnetFactory()),
) {
): Promise<{ success: boolean }> {
const nxProjectConfiguration = getExecutedProjectConfiguration(context);
projectDirectory = resolve(appRootPath, nxProjectConfiguration.root);
const projectFilePath = await getProjectFileForNxProject(
nxProjectConfiguration,
);
dotnetClient.cwd = projectDirectory;
const { watch, ...parsedOptions } = options;

dotnetClient.test(
projectFilePath,
const result = dotnetClient.test(
resolve(appRootPath, projectFilePath),
watch,
Object.keys(options).map((x) => ({
flag: x as dotnetTestFlags,
value: (options as Record<string, string | boolean>)[x],
value: (parsedOptions as Record<string, string | boolean>)[x],
})),
);

if (watch && isChildProcess(result)) {
await handleChildProcessPassthrough(result);
await rimraf(projectDirectory + '/bin');
await rimraf(projectDirectory + '/obj');
}
return {
success: true,
};
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/executors/test/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ export interface TestExecutorSchema {
| 'detailed'
| 'diag'
| 'diagnostic';
watch?: boolean;
}
5 changes: 5 additions & 0 deletions packages/core/src/executors/test/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@
"diag",
"diagnostic"
]
},
"watch": {
"description": "Determines if `dotnet test` or `dotnet watch test` is used to execute tests.",
"type": "boolean",
"default": false
}
},
"required": []
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/tasks/check-module-boundaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,13 @@ export async function loadModuleBoundaries(
): Promise<ModuleBoundaries> {
const configured = readConfig(host).moduleBoundaries;
if (!configured) {
const result = await new ESLint().calculateConfigForFile(
`${root}/non-existant.ts`,
);
const result = await new ESLint()
.calculateConfigForFile(`${root}/non-existant.ts`)
.catch(() =>
Promise.resolve({
rules: { '@nrwl/nx/enforce-module-boundaries': [] },
}),
);
const [, moduleBoundaryConfig] =
result.rules['@nrwl/nx/enforce-module-boundaries'];
return moduleBoundaryConfig?.depConstraints ?? [];
Expand Down
2 changes: 1 addition & 1 deletion packages/dotnet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"main": "src/index.js",
"dependencies": {},
"license": "MIT",
"version": "1.2.0",
"version": "99.99.99",
"keywords": [
".NET",
"dotnet"
Expand Down
Loading

0 comments on commit 49ce6bc

Please sign in to comment.