From 7153a20e11c665fb23877b5440cd08c58f855aa3 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> Date: Fri, 20 Jan 2023 12:16:34 -0500 Subject: [PATCH] feat!: allow publishing to subset of jsii target languages for experimental modules (#12) * add missing test * add jsii target language option and remove from cdklabs ts project * fix import order * add test suite --- API.md | 75 ++++++++++++++++++++++--------- src/cdklabs.ts | 99 +++++++++++++++++++++++++---------------- test/cdk.test.ts | 25 +++++++++-- test/cdklabs.test.ts | 96 +++++++++++++++++++++++++++++++++++++-- test/private-helpers.ts | 2 +- 5 files changed, 230 insertions(+), 67 deletions(-) diff --git a/API.md b/API.md index 13658a6..0fd6d05 100644 --- a/API.md +++ b/API.md @@ -2665,6 +2665,7 @@ const cdklabsConstructLibraryOptions: CdklabsConstructLibraryOptions = { ... } | lambdaOptions | projen.awscdk.LambdaFunctionCommonOptions | Common options for all AWS Lambda functions. | | private | boolean | Whether or not this package is private. | | cdklabsPublishingDefaults | boolean | Set default publishing properties. | +| jsiiTargetLanguages | JsiiLanguage[] | Specify specific languages to publish to. | --- @@ -4995,6 +4996,24 @@ This should be set to false only if you do not plan on releasing the package. --- +##### `jsiiTargetLanguages`Optional + +```typescript +public readonly jsiiTargetLanguages: JsiiLanguage[]; +``` + +- *Type:* JsiiLanguage[] +- *Default:* all jsii target languages + +Specify specific languages to publish to. + +This can be used when the library +is experimental only, because stable libraries must publish to all jsii languages. +This should be used in conjunction with `cdklabsPublishingDefaults: true`; otherwise +it is a no-op. + +--- + ### CdklabsTypeScriptProjectOptions #### Initializer @@ -5142,7 +5161,6 @@ const cdklabsTypeScriptProjectOptions: CdklabsTypeScriptProjectOptions = { ... } | tsconfigDevFile | string | The name of the development tsconfig.json file. | | typescriptVersion | string | TypeScript version to use. | | private | boolean | Whether or not this module is private. | -| cdklabsPublishingDefaults | boolean | Set default publishing properties. | --- @@ -7040,27 +7058,6 @@ for private repositories. --- -##### `cdklabsPublishingDefaults`Optional - -```typescript -public readonly cdklabsPublishingDefaults: boolean; -``` - -- *Type:* boolean -- *Default:* true - -Set default publishing properties. - -Setting this property guarantees -that your project will have reasonable publishing names. You can choose -to modify them however you wish with the traditional `publishToPypi`, -`publishToMaven`, `publishToNuget`, and `publishToGo` properties, and -your configuration will be respected. - -This should be set to false only if you do not plan on releasing the package. - ---- - ### CdkTypeScriptProjectOptions #### Initializer @@ -14710,3 +14707,37 @@ this task should synthesize the project files. --- +## Enums + +### JsiiLanguage + +#### Members + +| **Name** | **Description** | +| --- | --- | +| PYTHON | *No description.* | +| JAVA | *No description.* | +| DOTNET | *No description.* | +| GO | *No description.* | + +--- + +##### `PYTHON` + +--- + + +##### `JAVA` + +--- + + +##### `DOTNET` + +--- + + +##### `GO` + +--- + diff --git a/src/cdklabs.ts b/src/cdklabs.ts index 245a6b0..0dfdf7e 100644 --- a/src/cdklabs.ts +++ b/src/cdklabs.ts @@ -1,6 +1,13 @@ import { UpdateSnapshot } from 'projen/lib/javascript'; import { deepMerge } from 'projen/lib/util'; +export enum JsiiLanguage { + PYTHON, + JAVA, + DOTNET, + GO, +}; + import { CdkConstructLibrary, CdkConstructLibraryOptions, @@ -30,27 +37,46 @@ const cdklabsDefaultProps = { defaultReleaseBranch: 'main', }; -function createCdklabsPublishingDefaults(npmPackageName: string) { +function createCdklabsPublishingDefaults(npmPackageName: string, langs?: JsiiLanguage[]) { return { - publishToPypi: { - distName: npmPackageName, - module: changeDelimiter(npmPackageName, '_'), - }, - publishToMaven: { - javaPackage: `io.github.cdklabs.${changeDelimiter(npmPackageName, '.')}`, - mavenGroupId: 'io.github.cdklabs', - mavenArtifactId: npmPackageName, - mavenEndpoint: 'https://s01.oss.sonatype.org', - }, - publishToNuget: { - dotNetNamespace: `Cdklabs${upperCaseName(npmPackageName)}`, - packageId: `Cdklabs${upperCaseName(npmPackageName)}`, - }, - publishToGo: { - moduleName: `github.com/cdklabs/${npmPackageName}-go`, - }, + ...publishLanguageWrapper(JsiiLanguage.PYTHON, { + publishToPypi: { + distName: npmPackageName, + module: changeDelimiter(npmPackageName, '_'), + }, + }), + ...publishLanguageWrapper(JsiiLanguage.JAVA, { + publishToMaven: { + javaPackage: `io.github.cdklabs.${changeDelimiter(npmPackageName, '.')}`, + mavenGroupId: 'io.github.cdklabs', + mavenArtifactId: npmPackageName, + mavenEndpoint: 'https://s01.oss.sonatype.org', + }, + }), + ...publishLanguageWrapper(JsiiLanguage.DOTNET, { + publishToNuget: { + dotNetNamespace: `Cdklabs${upperCaseName(npmPackageName)}`, + packageId: `Cdklabs${upperCaseName(npmPackageName)}`, + }, + }), + ...publishLanguageWrapper(JsiiLanguage.GO, { + publishToGo: { + moduleName: `github.com/cdklabs/${npmPackageName}-go`, + }, + }), }; + function publishLanguageWrapper(lang: JsiiLanguage, obj: Record) { + return publishLanguage(lang) ? obj : {}; + } + + function publishLanguage(lang: JsiiLanguage): boolean { + // langs not specified === all languages published + if (!langs) { return true; } + if (langs.includes(lang)) { return true; } + return false; + } + function upperCaseName(str: string) { let words = str.split('-'); words = words.map((w) => w[0].toUpperCase() + w.substring(1)); @@ -75,6 +101,16 @@ export interface CdklabsConstructLibraryOptions extends CdkConstructLibraryOptio * @default true */ readonly cdklabsPublishingDefaults?: boolean; + + /** + * Specify specific languages to publish to. This can be used when the library + * is experimental only, because stable libraries must publish to all jsii languages. + * This should be used in conjunction with `cdklabsPublishingDefaults: true`; otherwise + * it is a no-op. + * + * @default - all jsii target languages + */ + readonly jsiiTargetLanguages?: JsiiLanguage[]; } /** @@ -84,10 +120,12 @@ export interface CdklabsConstructLibraryOptions extends CdkConstructLibraryOptio */ export class CdklabsConstructLibrary extends CdkConstructLibrary { constructor(options: CdklabsConstructLibraryOptions) { - const cdklabsPublishingDefaultProps = (options.cdklabsPublishingDefaults ?? true) ? - createCdklabsPublishingDefaults(options.name) : {}; + const cdklabsPublishingDefaultProps: Record = (options.cdklabsPublishingDefaults ?? true) ? + createCdklabsPublishingDefaults(options.name, options.jsiiTargetLanguages) : {}; + // the leftmost object is mutated and returned by deepMerge const mergedOptions = deepMerge([ + {}, cdklabsDefaultProps, cdklabsPublishingDefaultProps, options, @@ -98,20 +136,7 @@ export class CdklabsConstructLibrary extends CdkConstructLibrary { } } -export interface CdklabsTypeScriptProjectOptions extends CdkTypeScriptProjectOptions { - /** - * Set default publishing properties. Setting this property guarantees - * that your project will have reasonable publishing names. You can choose - * to modify them however you wish with the traditional `publishToPypi`, - * `publishToMaven`, `publishToNuget`, and `publishToGo` properties, and - * your configuration will be respected. - * - * This should be set to false only if you do not plan on releasing the package. - * - * @default true - */ - readonly cdklabsPublishingDefaults?: boolean; -} +export interface CdklabsTypeScriptProjectOptions extends CdkTypeScriptProjectOptions { } /** * Create a Cdklabs TypeScript Project @@ -120,12 +145,10 @@ export interface CdklabsTypeScriptProjectOptions extends CdkTypeScriptProjectOpt */ export class CdklabsTypeScriptProject extends CdkTypeScriptProject { constructor(options: CdklabsTypeScriptProjectOptions) { - const cdklabsPublishingDefaultProps = (options.cdklabsPublishingDefaults ?? true) ? - createCdklabsPublishingDefaults(options.name) : {}; - + // the leftmost object is mutated and returned by deepMerge const mergedOptions = deepMerge([ + {}, cdklabsDefaultProps, - cdklabsPublishingDefaultProps, options, cdklabsForcedProps, ]) as CdkConstructLibraryOptions; diff --git a/test/cdk.test.ts b/test/cdk.test.ts index 354cf7a..bdaf10c 100644 --- a/test/cdk.test.ts +++ b/test/cdk.test.ts @@ -6,7 +6,6 @@ import { CdkConstructLibrary, CdkConstructLibraryOptions, CdkTypeScriptProject, describe('CdkConstructLibrary', () => { test('synthesizes with default settings', () => { const project = new TestCdkConstructLibrary(); - const outdir = Testing.synth(project); // defaults to private @@ -39,8 +38,28 @@ describe('CdkConstructLibrary', () => { ].join('\n')); }); - test('thorws when a publishing to a subset of languages', () => { - + test('throws when a publishing to a subset of languages', () => { + expect(() => { + new TestCdkConstructLibrary({ + stability: Stability.STABLE, + publishToPypi: { + distName: 'distName', + module: 'module', + }, + publishToMaven: { + javaPackage: 'javaPackage', + mavenArtifactId: 'mavenArtifactId', + mavenGroupId: 'mavenGroupId', + }, + publishToNuget: { + dotNetNamespace: 'dotNetNamespace', + packageId: 'packageId', + }, + }); + }).toThrowError([ + 'The project does not pass stability requirements due to the following errors:', + ' Publishing Error: project not configured to publish to Go', + ].join('\n')); }); }); }); diff --git a/test/cdklabs.test.ts b/test/cdklabs.test.ts index f2bb4ef..af31758 100644 --- a/test/cdklabs.test.ts +++ b/test/cdklabs.test.ts @@ -1,11 +1,32 @@ import { Testing } from 'projen'; +import { Stability } from 'projen/lib/cdk'; import * as YAML from 'yaml'; -import { CdklabsConstructLibrary, CdklabsConstructLibraryOptions, CdklabsTypeScriptProject, CdklabsTypeScriptProjectOptions } from '../src/cdklabs'; +import { CdklabsConstructLibrary, CdklabsConstructLibraryOptions, CdklabsTypeScriptProject, CdklabsTypeScriptProjectOptions, JsiiLanguage } from '../src/cdklabs'; + +const publishingTargets = { + java: { + package: 'io.github.cdklabs.test.construct.library', + maven: { + groupId: 'io.github.cdklabs', + artifactId: 'test-construct-library', + }, + }, + python: { + distName: 'test-construct-library', + module: 'test_construct_library', + }, + dotnet: { + namespace: 'CdklabsTestConstructLibrary', + packageId: 'CdklabsTestConstructLibrary', + }, + go: { + moduleName: 'github.com/cdklabs/test-construct-library-go', + }, +}; describe('CdklabsConstructLibrary', () => { test('synthesizes with default settings', () => { const project = new TestCdkLabsConstructLibrary(); - const outdir = Testing.synth(project); const packageJson = outdir['package.json']; @@ -38,6 +59,75 @@ describe('CdklabsConstructLibrary', () => { expect(outdir).toMatchSnapshot(); }); + + describe('cdklabsPublishingDefaults', () => { + test('created by default', () => { + const project = new TestCdkLabsConstructLibrary(); + const outdir = Testing.synth(project); + const packageJson = outdir['package.json']; + + // jsii publishing + expect(packageJson.jsii?.targets).toEqual(publishingTargets); + }); + + describe('limiting publishing to a subset of languages', () => { + test('can be done in experimental modules', () => { + const project = new TestCdkLabsConstructLibrary({ + stability: Stability.EXPERIMENTAL, + jsiiTargetLanguages: [JsiiLanguage.JAVA, JsiiLanguage.PYTHON], + }); + const outdir = Testing.synth(project); + const packageJson = outdir['package.json']; + + // jsii publishing + expect(packageJson.jsii?.targets).toEqual({ + ...{ java: publishingTargets.java }, + ...{ python: publishingTargets.python }, + }); + }); + + test('throws if done in stable modules', () => { + expect(() => { + new TestCdkLabsConstructLibrary({ + stability: Stability.STABLE, + jsiiTargetLanguages: [JsiiLanguage.JAVA, JsiiLanguage.PYTHON], + }); + }).toThrowError([ + 'The project does not pass stability requirements due to the following errors:', + ' Publishing Error: project not configured to publish to Nuget', + ' Publishing Error: project not configured to publish to Go', + ].join('\n')); + }); + + test('does not throw if custom publishing set', () => { + expect(() => { + new TestCdkLabsConstructLibrary({ + stability: Stability.STABLE, + jsiiTargetLanguages: [JsiiLanguage.JAVA, JsiiLanguage.PYTHON], + publishToNuget: { + dotNetNamespace: 'custom-namespace', + packageId: 'custom-package', + }, + publishToGo: { + moduleName: 'github.com/custom-name', + }, + }); + }).not.toThrow(); + }); + + test('ignored if cdklabsPublishingDefaults is false', () => { + const project = new TestCdkLabsConstructLibrary({ + cdklabsPublishingDefaults: false, + jsiiTargetLanguages: [JsiiLanguage.JAVA, JsiiLanguage.PYTHON], + }); + const outdir = Testing.synth(project); + const packageJson = outdir['package.json']; + + // jsii publishing + expect(packageJson.jsii?.targets).toEqual({}); + }); + }); + }); }); describe('CdklabsTypeScriptProject', () => { @@ -100,4 +190,4 @@ class TestCdkLabsTypeScriptProject extends CdklabsTypeScriptProject { ...options, }); } -} \ No newline at end of file +} diff --git a/test/private-helpers.ts b/test/private-helpers.ts index 1ed64eb..044f544 100644 --- a/test/private-helpers.ts +++ b/test/private-helpers.ts @@ -8,4 +8,4 @@ export function expectNotPrivate(outdir: Record) { expect(outdir['.npmignore']).toBeDefined(); expect(outdir['.mergify.yml']).toBeDefined(); expect(outdir['package.json'].private).toBeFalsy(); -} \ No newline at end of file +}