diff --git a/packages/cli/package.json b/packages/cli/package.json index 1791b1ef6ee..3bb72f0cd74 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -82,6 +82,7 @@ "typescript-json-schema": "^0.64.0", "webpack": "^5.89.0", "webpack-dev-server": "^4.15.1", + "yaml": "^2.5.1", "yml-loader": "^2.1.0", "yn": "^4.0.0" }, diff --git a/packages/cli/src/commands/package-dynamic-plugins/command.ts b/packages/cli/src/commands/package-dynamic-plugins/command.ts index 7dc4487dcc5..ef67cb70bd7 100644 --- a/packages/cli/src/commands/package-dynamic-plugins/command.ts +++ b/packages/cli/src/commands/package-dynamic-plugins/command.ts @@ -1,7 +1,9 @@ import { PackageRoles } from '@backstage/cli-node'; +import chalk from 'chalk'; import { OptionValues } from 'commander'; import fs from 'fs-extra'; +import YAML from 'yaml'; import os from 'os'; import path from 'path'; @@ -73,6 +75,7 @@ export async function command(opts: OptionValues): Promise { path.join(os.tmpdir(), 'package-dynamic-plugins'), ); const pluginRegistryMetadata = []; + const pluginConfigs: Record = {}; try { // copy the dist-dynamic output folder for each plugin to some temp directory and generate the metadata entry for each plugin for (const pluginPkg of packages) { @@ -121,6 +124,27 @@ export async function command(opts: OptionValues): Promise { keywords, }, }); + // some plugins include configuration snippets in an app-config.janus-idp.yaml + const pluginConfigPath = path.join( + packageDirectory, + 'app-config.janus-idp.yaml', + ); + if (fs.existsSync(pluginConfigPath)) { + try { + const pluginConfig = fs.readFileSync(pluginConfigPath); + pluginConfigs[packageName] = YAML.parse( + pluginConfig.toLocaleString(), + ); + } catch (err) { + Task.log( + `Encountered an error parsing configuration at ${pluginConfigPath}, no example configuration will be displayed`, + ); + } + } else { + Task.log( + `No plugin configuration found at ${pluginConfigPath} create this file as needed if this plugin requires configuration`, + ); + } } catch (err) { Task.log( `Encountered an error copying static assets for plugin ${packageFilePath}, the plugin will not be packaged. The error was ${err}`, @@ -143,6 +167,31 @@ COPY . . `, { cwd: tmpDir }, ); + Task.log(`Successfully built image ${tag} with following plugins:`); + for (const plugin of pluginRegistryMetadata) { + Task.log(` ${chalk.white(Object.keys(plugin)[0])}`); + } + // print out a configuration example based on available plugin data + try { + const configurationExample = YAML.stringify({ + plugins: pluginRegistryMetadata.map(plugin => { + const pluginName = Object.keys(plugin)[0]; + const pluginConfig = pluginConfigs[pluginName]; + return { + package: `oci://${tag}!${pluginName}`, + disabled: false, + ...(pluginConfig ? { pluginConfig } : {}), + }; + }), + }); + Task.log( + `\nHere is an example dynamic-plugins.yaml for these plugins: \n\n${chalk.white(configurationExample)}\n\n`, + ); + } catch (err) { + Task.error( + `An error occurred while creating configuration example: ${err}`, + ); + } } catch (e) { Task.error(`Error encountered while packaging dynamic plugins: ${e}`); } finally { @@ -153,22 +202,6 @@ COPY . . if (preserveTempDir) { Task.log(`Keeping temporary directory ${tmpDir}`); } - - Task.log(`Successfully built image ${tag} with following plugins:`); - for (const plugin of pluginRegistryMetadata) { - Task.log(` ${Object.keys(plugin)[0]}`); - } - Task.log(` -Configuration example for the dynamic-plugins.yaml: - -packages:`); - for (const plugin of pluginRegistryMetadata) { - Task.log(`- package: oci://${tag}!${Object.keys(plugin)[0]} - disabled: false - pluginConfig: - # add required plugin configuration here -`); - } } catch (err) { Task.error( `An error occurred while removing the temporary staging directory: ${err}`, diff --git a/yarn.lock b/yarn.lock index 1f2614cda60..7c82aa0c0dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33198,7 +33198,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -33293,7 +33302,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -33307,6 +33316,13 @@ strip-ansi@5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -36076,7 +36092,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -36094,6 +36110,15 @@ wrap-ansi@^6.0.1: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -36290,6 +36315,11 @@ yaml@^2.0.0, yaml@^2.2.1, yaml@^2.2.2, yaml@^2.3.3, yaml@~2.4.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.2.tgz#7a2b30f2243a5fc299e1f14ca58d475ed4bc5362" integrity sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA== +yaml@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.1.tgz#c9772aacf62cb7494a95b0c4f1fb065b563db130" + integrity sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q== + yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"