Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node-project): Added ability to provide scoped private packages #1688

Merged
merged 24 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c6c78e1
feat(node-project): Added ability to provide private packages
AminFazlMondo Dec 16, 2021
499149b
Added tests
AminFazlMondo Mar 15, 2022
4799153
Updated documentation
AminFazlMondo Mar 15, 2022
b55fb65
Updated the API docs
AminFazlMondo Mar 15, 2022
bdb25f7
Updated inventory test snapshot
AminFazlMondo Mar 15, 2022
9ed7801
moved some functions to util
AminFazlMondo Mar 16, 2022
5bea522
Updated the test to use shared variable
AminFazlMondo Mar 16, 2022
9af0b45
Updated the type
AminFazlMondo Mar 16, 2022
e45d241
Fixed test
AminFazlMondo Mar 16, 2022
da56c75
Updataed API docs
AminFazlMondo Mar 16, 2022
b40e870
Updated the manual docs
AminFazlMondo Mar 17, 2022
f2ca082
Update docs/node.md
AminFazlMondo Mar 29, 2022
c870439
Update docs/node.md
AminFazlMondo Mar 29, 2022
d26e668
Update src/javascript/node-package.ts
AminFazlMondo Mar 29, 2022
9cc4091
made getScopedPackageSteps a private function
AminFazlMondo Mar 29, 2022
6683c16
removed redundant inputs to create project in tests
AminFazlMondo Mar 29, 2022
bd27269
Updated the docs
AminFazlMondo Mar 29, 2022
29cefc2
Changed the scope packages to use code artifact options
AminFazlMondo Mar 29, 2022
e437f12
Added check for AWS cli installed
AminFazlMondo Mar 29, 2022
92a07db
updated inventory snapshot
AminFazlMondo Mar 29, 2022
d04ad7f
Updated the docs
AminFazlMondo Mar 30, 2022
db6410b
Apply suggestions from code review
charliehart-mondo Apr 12, 2022
2186306
use region and domain owner from the scoped packages registryUrl and …
charliehart-mondo Apr 12, 2022
63c600f
Merge branch 'main' into feature/ScopedPackagesAuth
Chriscbr Apr 12, 2022
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
Prev Previous commit
Next Next commit
Changed the scope packages to use code artifact options
Co-authored-by: Charlie Hart <charlie.hart@mondo.com.au>
Co-authored-by: Kevin <MondoKevin@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 30, 2022
commit 29cefc2f93000fff36ca52981715fca7a1d7f1e2
38 changes: 1 addition & 37 deletions docs/api/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,14 +297,12 @@ Name|Description
[javascript.NodePackageOptions](#projen-javascript-nodepackageoptions)|*No description*
[javascript.NodeProjectOptions](#projen-javascript-nodeprojectoptions)|*No description*
[javascript.NpmConfigOptions](#projen-javascript-npmconfigoptions)|Options to configure the local NPM config.
[javascript.ParsedScopedPackagesOptions](#projen-javascript-parsedscopedpackagesoptions)|*No description*
[javascript.PeerDependencyOptions](#projen-javascript-peerdependencyoptions)|*No description*
[javascript.PrettierOptions](#projen-javascript-prettieroptions)|Options for Prettier.
[javascript.PrettierOverride](#projen-javascript-prettieroverride)|*No description*
[javascript.PrettierSettings](#projen-javascript-prettiersettings)|Options to set in Prettier directly or through overrides.
[javascript.ProjenrcOptions](#projen-javascript-projenrcoptions)|*No description*
[javascript.RenderWorkflowSetupOptions](#projen-javascript-renderworkflowsetupoptions)|Options for `renderInstallSteps()`.
[javascript.ScopedPackagesBaseOptions](#projen-javascript-scopedpackagesbaseoptions)|Options for scoped packages.
[javascript.ScopedPackagesOptions](#projen-javascript-scopedpackagesoptions)|Options for scoped packages.
[javascript.TypeScriptCompilerOptions](#projen-javascript-typescriptcompileroptions)|*No description*
[javascript.TypescriptConfigOptions](#projen-javascript-typescriptconfigoptions)|*No description*
Expand Down Expand Up @@ -8320,7 +8318,7 @@ Name | Type | Description
**maxNodeVersion**?🔹 | <code>string</code> | Maximum node version required by this pacakge.<br/>__*Default*__: no maximum.
**minNodeVersion**?🔹 | <code>string</code> | Minimum node.js version required by this package.<br/>__*Default*__: no minimum
**npmTokenSecret**?🔹 | <code>string</code> | GitHub secret which contains the NPM token to use when publishing packages.<br/>__*Optional*__
**scopedPackagesOptions**?🔹 | <code>Array<[javascript.ParsedScopedPackagesOptions](#projen-javascript-parsedscopedpackagesoptions)></code> | Options for privately hosted scoped packages.<br/>__*Default*__: undefined
**scopedPackagesOptions**?🔹 | <code>Array<[javascript.ScopedPackagesOptions](#projen-javascript-scopedpackagesoptions)></code> | Options for privately hosted scoped packages.<br/>__*Default*__: undefined

### Methods

Expand Down Expand Up @@ -20175,23 +20173,6 @@ Name | Type | Description



## struct ParsedScopedPackagesOptions 🔹 <a id="projen-javascript-parsedscopedpackagesoptions"></a>






Name | Type | Description
-----|------|-------------
**accessKeyIdSecret**🔹 | <code>string</code> | GitHub secret which contains the AWS access key ID to use when publishing packages to AWS CodeArtifact.
**registryUrl**🔹 | <code>string</code> | Url of the registry for scoped packages.
**scope**🔹 | <code>string</code> | scope of the packages.
**secretAccessKeySecret**🔹 | <code>string</code> | GitHub secret which contains the AWS secret access key to use when publishing packages to AWS CodeArtifact.
**roleToAssume**?🔹 | <code>string</code> | ARN of AWS role to be assumed prior to get authorization token from AWS CodeArtifact This property must be specified only when publishing to AWS CodeArtifact (`registry` contains AWS CodeArtifact URL).<br/>__*Default*__: undefined



## struct PeerDependencyOptions 🔹 <a id="projen-javascript-peerdependencyoptions"></a>


Expand Down Expand Up @@ -20298,20 +20279,6 @@ Name | Type | Description



## struct ScopedPackagesBaseOptions 🔹 <a id="projen-javascript-scopedpackagesbaseoptions"></a>


Options for scoped packages.



Name | Type | Description
-----|------|-------------
**registryUrl**🔹 | <code>string</code> | Url of the registry for scoped packages.
**scope**🔹 | <code>string</code> | scope of the packages.



## struct ScopedPackagesOptions 🔹 <a id="projen-javascript-scopedpackagesoptions"></a>


Expand All @@ -20323,9 +20290,6 @@ Name | Type | Description
-----|------|-------------
**registryUrl**🔹 | <code>string</code> | Url of the registry for scoped packages.
**scope**🔹 | <code>string</code> | scope of the packages.
**accessKeyIdSecret**?🔹 | <code>string</code> | GitHub secret which contains the AWS access key ID to use when publishing packages to AWS CodeArtifact.<br/>__*Default*__: "AWS_ACCESS_KEY_ID"
**roleToAssume**?🔹 | <code>string</code> | ARN of AWS role to be assumed prior to get authorization token from AWS CodeArtifact This property must be specified only when publishing to AWS CodeArtifact (`registry` contains AWS CodeArtifact URL).<br/>__*Default*__: undefined
**secretAccessKeySecret**?🔹 | <code>string</code> | GitHub secret which contains the AWS secret access key to use when publishing packages to AWS CodeArtifact.<br/>__*Default*__: "AWS_SECRET_ACCESS_KEY"



Expand Down
93 changes: 45 additions & 48 deletions src/javascript/node-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Project } from "../project";
import { isAwsCodeArtifactRegistry } from "../release";
import { Task } from "../task";
import { exec, isTruthy, sorted, writeFile } from "../util";
import { extractCodeArtifactDetails } from "./util";

const UNLICENSED = "UNLICENSED";
const DEFAULT_NPM_REGISTRY_URL = "https://registry.npmjs.org/";
Expand Down Expand Up @@ -324,7 +325,7 @@ export interface CodeArtifactOptions {
/**
* Options for scoped packages
*/
export interface ScopedPackagesBaseOptions {
export interface ScopedPackagesOptions {
/**
* scope of the packages
charliehart-mondo marked this conversation as resolved.
Show resolved Hide resolved
*
Expand All @@ -338,39 +339,6 @@ export interface ScopedPackagesBaseOptions {
readonly registryUrl: string;
}

/**
* Options for scoped packages
*/
export interface ScopedPackagesOptions
extends ScopedPackagesBaseOptions,
CodeArtifactOptions {}

export interface ParsedScopedPackagesOptions extends ScopedPackagesBaseOptions {
/**
* GitHub secret which contains the AWS access key ID to use when publishing packages to AWS CodeArtifact.
* This property must be specified only when publishing to AWS CodeArtifact (`npmRegistryUrl` contains AWS CodeArtifact URL).
*
* @default "AWS_ACCESS_KEY_ID"
*/
readonly accessKeyIdSecret: string;

/**
* GitHub secret which contains the AWS secret access key to use when publishing packages to AWS CodeArtifact.
* This property must be specified only when publishing to AWS CodeArtifact (`npmRegistryUrl` contains AWS CodeArtifact URL).
*
* @default "AWS_SECRET_ACCESS_KEY"
*/
readonly secretAccessKeySecret: string;

/**
* ARN of AWS role to be assumed prior to get authorization token from AWS CodeArtifact
* This property must be specified only when publishing to AWS CodeArtifact (`registry` contains AWS CodeArtifact URL).
*
* @default undefined
*/
readonly roleToAssume?: string;
}

/**
* Represents the npm `package.json` file.
*/
Expand Down Expand Up @@ -444,7 +412,7 @@ export class NodePackage extends Component {
*
* @default undefined
*/
readonly scopedPackagesOptions?: ParsedScopedPackagesOptions[];
readonly scopedPackagesOptions?: ScopedPackagesOptions[];

/**
* npm package access level.
Expand Down Expand Up @@ -495,6 +463,8 @@ export class NodePackage extends Component {

this.processDeps(options);

this.addCodeArtifactLoginScript();

const prev = this.readPackageJson() ?? {};

// empty objects are here to preserve order for backwards compatibility
Expand Down Expand Up @@ -858,6 +828,10 @@ export class NodePackage extends Component {
}

const isAwsCodeArtifact = isAwsCodeArtifactRegistry(npmRegistryUrl);
const hasScopedPackage =
options.scopedPackagesOptions &&
options.scopedPackagesOptions.length !== 0;

if (isAwsCodeArtifact) {
if (options.npmTokenSecret) {
throw new Error(
Expand All @@ -866,19 +840,20 @@ export class NodePackage extends Component {
}
} else {
if (
options.codeArtifactOptions?.accessKeyIdSecret ||
options.codeArtifactOptions?.secretAccessKeySecret ||
options.codeArtifactOptions?.roleToAssume
(options.codeArtifactOptions?.accessKeyIdSecret ||
options.codeArtifactOptions?.secretAccessKeySecret ||
options.codeArtifactOptions?.roleToAssume) &&
!hasScopedPackage
) {
throw new Error(
"codeArtifactOptions must only be specified when publishing AWS CodeArtifact."
"codeArtifactOptions must only be specified when publishing AWS CodeArtifact or used in scoped packages."
);
}
}

// apply defaults for AWS CodeArtifact
let codeArtifactOptions: CodeArtifactOptions | undefined;
if (isAwsCodeArtifact) {
if (isAwsCodeArtifact || hasScopedPackage) {
codeArtifactOptions = {
accessKeyIdSecret:
options.codeArtifactOptions?.accessKeyIdSecret ?? "AWS_ACCESS_KEY_ID",
Expand All @@ -903,12 +878,12 @@ export class NodePackage extends Component {

private parseScopedPackagesOptions(
scopedPackagesOptions?: ScopedPackagesOptions[]
): ParsedScopedPackagesOptions[] {
): ScopedPackagesOptions[] | undefined {
if (!scopedPackagesOptions) {
return [];
return undefined;
}

return scopedPackagesOptions.map((option): ParsedScopedPackagesOptions => {
return scopedPackagesOptions.map((option): ScopedPackagesOptions => {
if (!isScoped(option.scope)) {
throw new Error(
`Scope must start with "@" in options, found ${option.scope}`
Expand All @@ -921,19 +896,41 @@ export class NodePackage extends Component {
);
}

const result: ParsedScopedPackagesOptions = {
const result: ScopedPackagesOptions = {
registryUrl: option.registryUrl,
scope: option.scope,
accessKeyIdSecret: option.accessKeyIdSecret ?? "AWS_ACCESS_KEY_ID",
secretAccessKeySecret:
option.secretAccessKeySecret ?? "AWS_SECRET_ACCESS_KEY",
roleToAssume: option.roleToAssume,
};

return result;
});
}

private addCodeArtifactLoginScript() {
if (
!this.scopedPackagesOptions ||
this.scopedPackagesOptions.length === 0
) {
return;
}

this.project.addTask("ca:login", {
requiredEnv: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
steps: this.scopedPackagesOptions.map((scopedPackagesOption) => {
const { registryUrl, scope } = scopedPackagesOption;
const { domain, repository } = extractCodeArtifactDetails(registryUrl);
const commands = [
`npm config set ${scope}:registry ${registryUrl}`,
`CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-repository-endpoint --domain ${domain} --repository ${repository})`,
`npm config set //${registryUrl}:_authToken=$CODEARTIFACT_AUTH_TOKEN`,
`npm config set //${registryUrl}:always-auth=true`,
];
return {
exec: commands.join("; "),
};
}),
});
}

private addNodeEngine() {
if (!this.minNodeVersion && !this.maxNodeVersion) {
return;
Expand Down
Loading