Skip to content

Commit

Permalink
feat(core): add integration with nx powerpack (#27972)
Browse files Browse the repository at this point in the history
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

There is no Nx Powerpack product.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

Integration with Nx Powerpack is added. Nx Powerpack is optional, stay
tuned for more information which will be released soon.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #

---------

Co-authored-by: Craigory Coppola <[email protected]>
Co-authored-by: JamesHenry <[email protected]>
  • Loading branch information
3 people authored Sep 18, 2024
1 parent fb91ed5 commit b06f515
Show file tree
Hide file tree
Showing 24 changed files with 454 additions and 31 deletions.
25 changes: 25 additions & 0 deletions docs/generated/cli/activate-powerpack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: 'activate-powerpack - CLI command'
description: 'Activate a Nx Powerpack license.'
---

# activate-powerpack

Activate a Nx Powerpack license.

## Usage

```shell
nx activate-powerpack <license>
```

Install `nx` globally to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpm nx`.

## Options

| Option | Type | Description |
| ----------- | ------- | ---------------------------------------------------------------------- |
| `--help` | boolean | Show help. |
| `--license` | string | This is a License Key for Nx Powerpack. |
| `--verbose` | boolean | Prints additional information about the commands (e.g., stack traces). |
| `--version` | boolean | Show version number. |
8 changes: 8 additions & 0 deletions docs/generated/manifests/menus.json
Original file line number Diff line number Diff line change
Expand Up @@ -8753,6 +8753,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "activate-powerpack",
"path": "/nx-api/nx/documents/activate-powerpack",
"id": "activate-powerpack",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "reset",
"path": "/nx-api/nx/documents/reset",
Expand Down
11 changes: 11 additions & 0 deletions docs/generated/manifests/nx-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -1880,6 +1880,17 @@
"tags": ["cache-task-results", "distribute-task-execution"],
"originalFilePath": "generated/cli/connect"
},
"/nx-api/nx/documents/activate-powerpack": {
"id": "activate-powerpack",
"name": "activate-powerpack",
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
"file": "generated/packages/nx/documents/activate-powerpack",
"itemList": [],
"isExternal": false,
"path": "/nx-api/nx/documents/activate-powerpack",
"tags": ["cache-task-results"],
"originalFilePath": "generated/cli/activate-powerpack"
},
"/nx-api/nx/documents/reset": {
"id": "reset",
"name": "reset",
Expand Down
7 changes: 7 additions & 0 deletions docs/generated/manifests/tags.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@
"name": "connect-to-nx-cloud",
"path": "/nx-api/nx/documents/connect-to-nx-cloud"
},
{
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
"file": "generated/packages/nx/documents/activate-powerpack",
"id": "activate-powerpack",
"name": "activate-powerpack",
"path": "/nx-api/nx/documents/activate-powerpack"
},
{
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
"file": "generated/packages/nx/documents/reset",
Expand Down
11 changes: 11 additions & 0 deletions docs/generated/packages-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,17 @@
"tags": ["cache-task-results", "distribute-task-execution"],
"originalFilePath": "generated/cli/connect"
},
{
"id": "activate-powerpack",
"name": "activate-powerpack",
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
"file": "generated/packages/nx/documents/activate-powerpack",
"itemList": [],
"isExternal": false,
"path": "nx/documents/activate-powerpack",
"tags": ["cache-task-results"],
"originalFilePath": "generated/cli/activate-powerpack"
},
{
"id": "reset",
"name": "reset",
Expand Down
25 changes: 25 additions & 0 deletions docs/generated/packages/nx/documents/activate-powerpack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: 'activate-powerpack - CLI command'
description: 'Activate a Nx Powerpack license.'
---

# activate-powerpack

Activate a Nx Powerpack license.

## Usage

```shell
nx activate-powerpack <license>
```

Install `nx` globally to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpm nx`.

## Options

| Option | Type | Description |
| ----------- | ------- | ---------------------------------------------------------------------- |
| `--help` | boolean | Show help. |
| `--license` | string | This is a License Key for Nx Powerpack. |
| `--verbose` | boolean | Prints additional information about the commands (e.g., stack traces). |
| `--version` | boolean | Show version number. |
6 changes: 6 additions & 0 deletions docs/map.json
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,12 @@
"tags": ["cache-task-results", "distribute-task-execution"],
"file": "generated/cli/connect"
},
{
"name": "activate-powerpack",
"tags": ["cache-task-results"],
"id": "activate-powerpack",
"file": "generated/cli/activate-powerpack"
},
{
"name": "reset",
"id": "reset",
Expand Down
1 change: 1 addition & 0 deletions docs/shared/reference/sitemap.md
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@
- [report](/nx-api/nx/documents/report)
- [list](/nx-api/nx/documents/list)
- [connect-to-nx-cloud](/nx-api/nx/documents/connect-to-nx-cloud)
- [activate-powerpack](/nx-api/nx/documents/activate-powerpack)
- [reset](/nx-api/nx/documents/reset)
- [repair](/nx-api/nx/documents/repair)
- [sync](/nx-api/nx/documents/sync)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { workspaceRoot } from '../../utils/workspace-root';
import { ActivatePowerpackOptions } from './command-object';
import { prompt } from 'enquirer';
import { execSync } from 'child_process';
import { getPackageManagerCommand } from '../../utils/package-manager';

export async function handleActivatePowerpack(
options: ActivatePowerpackOptions
) {
const license =
options.license ??
(await prompt({
type: 'input',
name: 'license',
message: 'Enter your License Key',
}));
const { activatePowerpack } = await requirePowerpack();
activatePowerpack(workspaceRoot, license);
}

async function requirePowerpack(): Promise<any> {
// @ts-ignore
return import('@nx/powerpack-license').catch(async (e) => {
if ('code' in e && e.code === 'MODULE_NOT_FOUND') {
try {
execSync(
`${getPackageManagerCommand().addDev} @nx/powerpack-license@latest`
);

// @ts-ignore
return await import('@nx/powerpack-license');
} catch (e) {
throw new Error(
'Failed to install @nx/powerpack-license. Please install @nx/powerpack-license and try again.'
);
}
}
});
}
38 changes: 38 additions & 0 deletions packages/nx/src/command-line/activate-powerpack/command-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { CommandModule } from 'yargs';
import { withVerbose } from '../yargs-utils/shared-options';
import { handleErrors } from '../../utils/handle-errors';

export interface ActivatePowerpackOptions {
license: string;
verbose: boolean;
}

export const yargsActivatePowerpackCommand: CommandModule<
{},
ActivatePowerpackOptions
> = {
command: 'activate-powerpack <license>',
describe: 'Activate a Nx Powerpack license.',
builder: (yargs) =>
withVerbose(yargs)
.parserConfiguration({
'strip-dashed': true,
'unknown-options-as-args': true,
})
.positional('license', {
type: 'string',
description: 'This is a License Key for Nx Powerpack.',
})
.example(
'$0 activate-powerpack <license key>',
'Activate a Nx Powerpack license'
),
handler: async (args) => {
const exitCode = await handleErrors(args.verbose as boolean, async () => {
return (await import('./activate-powerpack')).handleActivatePowerpack(
args
);
});
process.exit(exitCode);
},
};
5 changes: 1 addition & 4 deletions packages/nx/src/command-line/add/command-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ export interface AddOptions {
__overrides_unparsed__: string[];
}

export const yargsAddCommand: CommandModule<
Record<string, unknown>,
AddOptions
> = {
export const yargsAddCommand: CommandModule<{}, AddOptions> = {
command: 'add <packageSpecifier>',
describe: 'Install a plugin and initialize it.',
builder: (yargs) =>
Expand Down
2 changes: 2 additions & 0 deletions packages/nx/src/command-line/list/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
listPlugins,
} from '../../utils/plugins';
import { workspaceRoot } from '../../utils/workspace-root';
import { listPowerpackPlugins } from '../../utils/plugins/output';

export interface ListArgs {
/** The name of an installed plugin to query */
Expand Down Expand Up @@ -46,6 +47,7 @@ export async function listHandler(args: ListArgs): Promise<void> {
}
listPlugins(installedPlugins, 'Installed plugins:');
listAlsoAvailableCorePlugins(installedPlugins);
listPowerpackPlugins();

output.note({
title: 'Community Plugins',
Expand Down
20 changes: 20 additions & 0 deletions packages/nx/src/command-line/nx-commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as chalk from 'chalk';
import * as yargs from 'yargs';

import { yargsActivatePowerpackCommand } from './activate-powerpack/command-object';
import {
yargsAffectedBuildCommand,
yargsAffectedCommand,
Expand Down Expand Up @@ -63,6 +64,7 @@ export const commandsObject = yargs
.parserConfiguration(parserConfiguration)
.usage(chalk.bold('Smart Monorepos · Fast CI'))
.demandCommand(1, '')
.command(yargsActivatePowerpackCommand)
.command(yargsAddCommand)
.command(yargsAffectedBuildCommand)
.command(yargsAffectedCommand)
Expand Down Expand Up @@ -98,9 +100,27 @@ export const commandsObject = yargs
.command(yargsNxInfixCommand)
.command(yargsLoginCommand)
.command(yargsLogoutCommand)
.command(resolveConformanceCommandObject())
.scriptName('nx')
.help()
// NOTE: we handle --version in nx.ts, this just tells yargs that the option exists
// so that it shows up in help. The default yargs implementation of --version is not
// hit, as the implementation in nx.ts is hit first and calls process.exit(0).
.version();

function resolveConformanceCommandObject() {
try {
const { yargsConformanceCommand } = require('@nx/powerpack-conformance');
return yargsConformanceCommand;
} catch (e) {
return {
command: 'conformance',
// Hide from --help output in the common case of not having the plugin installed
describe: false,
handler: () => {
// TODO: Add messaging to help with learning more about powerpack and conformance
process.exit(1);
},
};
}
}
52 changes: 52 additions & 0 deletions packages/nx/src/command-line/report/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { getNxRequirePaths } from '../../utils/installation-directory';
import { NxJsonConfiguration, readNxJson } from '../../config/nx-json';
import { ProjectGraph } from '../../config/project-graph';
import { ProjectGraphError } from '../../project-graph/error-types';
import { getPowerpackLicenseInformation } from '../../utils/powerpack';

const nxPackageJson = readJsonFile<typeof import('../../../package.json')>(
join(__dirname, '../../../package.json')
Expand All @@ -39,6 +40,7 @@ export const packagesWeCareAbout = [

export const patternsWeIgnoreInCommunityReport: Array<string | RegExp> = [
...packagesWeCareAbout,
new RegExp('@nx/powerpack*'),
'@schematics/angular',
new RegExp('@angular/*'),
'@nestjs/schematics',
Expand All @@ -58,7 +60,9 @@ export async function reportHandler() {
const {
pm,
pmVersion,
powerpackLicense,
localPlugins,
powerpackPlugins,
communityPlugins,
registeredPlugins,
packageVersionsWeCareAbout,
Expand Down Expand Up @@ -88,6 +92,36 @@ export async function reportHandler() {
);
});

if (powerpackLicense) {
bodyLines.push(LINE_SEPARATOR);
bodyLines.push(chalk.green('Nx Powerpack'));

bodyLines.push(
`Licensed to ${powerpackLicense.organizationName} for ${
powerpackLicense.seatCount
} user${powerpackLicense.seatCount > 1 ? 's' : ''} in ${
powerpackLicense.workspaceCount
} workspace${
powerpackLicense.workspaceCount > 1 ? 's' : ''
} until ${new Date(powerpackLicense.expiresAt).toLocaleDateString()}`
);
bodyLines.push('');

padding =
Math.max(
...powerpackPlugins.map(
(powerpackPlugin) => powerpackPlugin.name.length
)
) + 1;
for (const powerpackPlugin of powerpackPlugins) {
bodyLines.push(
`${chalk.green(powerpackPlugin.name.padEnd(padding))} : ${chalk.bold(
powerpackPlugin.version
)}`
);
}
}

if (registeredPlugins.length) {
bodyLines.push(LINE_SEPARATOR);
bodyLines.push('Registered Plugins:');
Expand Down Expand Up @@ -147,6 +181,9 @@ export async function reportHandler() {
export interface ReportData {
pm: PackageManager;
pmVersion: string;
// TODO(@FrozenPandaz): Provide the right type here.
powerpackLicense: any | null;
powerpackPlugins: PackageJson[];
localPlugins: string[];
communityPlugins: PackageJson[];
registeredPlugins: string[];
Expand Down Expand Up @@ -174,6 +211,7 @@ export async function getReportData(): Promise<ReportData> {

const nxJson = readNxJson();
const localPlugins = await findLocalPlugins(graph, nxJson);
const powerpackPlugins = findInstalledPowerpackPlugins();
const communityPlugins = findInstalledCommunityPlugins();
const registeredPlugins = findRegisteredPluginsBeingUsed(nxJson);

Expand All @@ -193,8 +231,15 @@ export async function getReportData(): Promise<ReportData> {

const native = isNativeAvailable();

let powerpackLicense = null;
try {
powerpackLicense = await getPowerpackLicenseInformation();
} catch {}

return {
pm,
powerpackLicense,
powerpackPlugins,
pmVersion,
localPlugins,
communityPlugins,
Expand Down Expand Up @@ -294,6 +339,13 @@ export function findMisalignedPackagesForPackage(
: undefined;
}

export function findInstalledPowerpackPlugins(): PackageJson[] {
const installedPlugins = findInstalledPlugins();
return installedPlugins.filter((dep) =>
new RegExp('@nx/powerpack*').test(dep.name)
);
}

export function findInstalledCommunityPlugins(): PackageJson[] {
const installedPlugins = findInstalledPlugins();
return installedPlugins.filter(
Expand Down
Loading

0 comments on commit b06f515

Please sign in to comment.