From 29429545359f748b9caa0947b37105abf4be50bd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 26 Nov 2020 22:18:47 +0100 Subject: [PATCH 1/2] cli: only load config schema that applies to the target package --- .changeset/angry-bees-brush.md | 5 +++ packages/cli/src/commands/app/build.ts | 8 +++- packages/cli/src/commands/app/serve.ts | 8 +++- packages/cli/src/commands/config/print.ts | 5 ++- packages/cli/src/commands/config/validate.ts | 5 ++- packages/cli/src/commands/index.ts | 8 ++++ packages/cli/src/commands/plugin/serve.ts | 8 +++- packages/cli/src/lib/config.ts | 46 ++++++++++++++++++-- 8 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 .changeset/angry-bees-brush.md diff --git a/.changeset/angry-bees-brush.md b/.changeset/angry-bees-brush.md new file mode 100644 index 0000000000..aa42d6ef6b --- /dev/null +++ b/.changeset/angry-bees-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Only load config that applies to the target package for frontend build and serve tasks. Also added `--package ` flag to scope the config schema used by the `config:print` and `config:check` commands. diff --git a/packages/cli/src/commands/app/build.ts b/packages/cli/src/commands/app/build.ts index c5f5f5aa2f..21189e9427 100644 --- a/packages/cli/src/commands/app/build.ts +++ b/packages/cli/src/commands/app/build.ts @@ -14,16 +14,22 @@ * limitations under the License. */ +import fs from 'fs-extra'; import { Command } from 'commander'; import { buildBundle } from '../../lib/bundler'; import { parseParallel, PARALLEL_ENV_VAR } from '../../lib/parallel'; import { loadCliConfig } from '../../lib/config'; +import { paths } from '../../lib/paths'; export default async (cmd: Command) => { + const { name } = await fs.readJson(paths.resolveTarget('package.json')); await buildBundle({ entry: 'src/index', parallel: parseParallel(process.env[PARALLEL_ENV_VAR]), statsJsonEnabled: cmd.stats, - ...(await loadCliConfig(cmd.config)), + ...(await loadCliConfig({ + args: cmd.config, + fromPackage: name, + })), }); }; diff --git a/packages/cli/src/commands/app/serve.ts b/packages/cli/src/commands/app/serve.ts index c3f58774b5..dc165ecb90 100644 --- a/packages/cli/src/commands/app/serve.ts +++ b/packages/cli/src/commands/app/serve.ts @@ -14,15 +14,21 @@ * limitations under the License. */ +import fs from 'fs-extra'; import { Command } from 'commander'; import { serveBundle } from '../../lib/bundler'; import { loadCliConfig } from '../../lib/config'; +import { paths } from '../../lib/paths'; export default async (cmd: Command) => { + const { name } = await fs.readJson(paths.resolveTarget('package.json')); const waitForExit = await serveBundle({ entry: 'src/index', checksEnabled: cmd.check, - ...(await loadCliConfig(cmd.config)), + ...(await loadCliConfig({ + args: cmd.config, + fromPackage: name, + })), }); await waitForExit(); diff --git a/packages/cli/src/commands/config/print.ts b/packages/cli/src/commands/config/print.ts index 9649c70ef3..8148bfc9f8 100644 --- a/packages/cli/src/commands/config/print.ts +++ b/packages/cli/src/commands/config/print.ts @@ -21,7 +21,10 @@ import { loadCliConfig } from '../../lib/config'; import { ConfigSchema, ConfigVisibility } from '@backstage/config-loader'; export default async (cmd: Command) => { - const { schema, appConfigs } = await loadCliConfig(cmd.config); + const { schema, appConfigs } = await loadCliConfig({ + args: cmd.config, + fromPackage: cmd.package, + }); const visibility = getVisiblityOption(cmd); const data = serializeConfigData(appConfigs, schema, visibility); diff --git a/packages/cli/src/commands/config/validate.ts b/packages/cli/src/commands/config/validate.ts index 229f9e07e9..581e4bae43 100644 --- a/packages/cli/src/commands/config/validate.ts +++ b/packages/cli/src/commands/config/validate.ts @@ -18,5 +18,8 @@ import { Command } from 'commander'; import { loadCliConfig } from '../../lib/config'; export default async (cmd: Command) => { - await loadCliConfig(cmd.config); + await loadCliConfig({ + args: cmd.config, + fromPackage: cmd.package, + }); }; diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 7302559498..2b0e3e25b9 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -141,6 +141,10 @@ export function registerCommands(program: CommanderStatic) { program .command('config:print') + .option( + '--package ', + 'Only load config schema that applies to the given package', + ) .option('--frontend', 'Print only the frontend configuration') .option('--with-secrets', 'Include secrets in the printed configuration') .option( @@ -153,6 +157,10 @@ export function registerCommands(program: CommanderStatic) { program .command('config:check') + .option( + '--package ', + 'Only load config schema that applies to the given package', + ) .option(...configOption) .description( 'Validate that the given configuration loads and matches schema', diff --git a/packages/cli/src/commands/plugin/serve.ts b/packages/cli/src/commands/plugin/serve.ts index cb9def3158..27db824d2f 100644 --- a/packages/cli/src/commands/plugin/serve.ts +++ b/packages/cli/src/commands/plugin/serve.ts @@ -14,15 +14,21 @@ * limitations under the License. */ +import fs from 'fs-extra'; import { Command } from 'commander'; import { serveBundle } from '../../lib/bundler'; import { loadCliConfig } from '../../lib/config'; +import { paths } from '../../lib/paths'; export default async (cmd: Command) => { + const { name } = await fs.readJson(paths.resolveTarget('package.json')); const waitForExit = await serveBundle({ entry: 'dev/index', checksEnabled: cmd.check, - ...(await loadCliConfig(cmd.config)), + ...(await loadCliConfig({ + args: cmd.config, + fromPackage: name, + })), }); await waitForExit(); diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index 08a8193818..f6cc9c4269 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -18,14 +18,23 @@ import { loadConfig, loadConfigSchema } from '@backstage/config-loader'; import { ConfigReader } from '@backstage/config'; import { paths } from './paths'; -export async function loadCliConfig(configArgs: string[]) { - const configPaths = configArgs.map(arg => paths.resolveTarget(arg)); +type Options = { + args: string[]; + fromPackage?: string; +}; + +export async function loadCliConfig(options: Options) { + const configPaths = options.args.map(arg => paths.resolveTarget(arg)); // Consider all packages in the monorepo when loading in config const LernaProject = require('@lerna/project'); const project = new LernaProject(paths.targetDir); const packages = await project.getPackages(); - const localPackageNames = packages.map((p: any) => p.name); + + const localPackageNames = options.fromPackage + ? findPackages(packages, options.fromPackage) + : packages.map((p: any) => p.name); + const schema = await loadConfigSchema({ dependencies: localPackageNames, }); @@ -61,3 +70,34 @@ export async function loadCliConfig(configArgs: string[]) { throw error; } } + +function findPackages(packages: any[], fromPackage: string): string[] { + const PackageGraph = require('@lerna/package-graph'); + + const graph = new PackageGraph(packages); + + const targets = new Set(); + const searchNames = [fromPackage]; + + while (searchNames.length) { + const name = searchNames.pop()!; + + if (targets.has(name)) { + continue; + } + + const node = graph.get(name); + if (!node) { + throw new Error(`Package '${name}' not found`); + } + + targets.add(name); + + // Workaround for Backstage main repo only, since the CLI has some artificial devDependencies + if (name !== '@backstage/cli') { + searchNames.push(...node.localDependencies.keys()); + } + } + + return Array.from(targets); +} From b3d4e4e57a6c44da31bacf7df3e2dd1d3fbcb04f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 26 Nov 2020 22:27:22 +0100 Subject: [PATCH 2/2] backend-common: move the frontend visibility of config to @backstage/integration --- .changeset/sixty-eyes-shout.md | 6 ++++ packages/backend-common/config.d.ts | 7 ----- packages/integration/config.d.ts | 45 +++++++++++++++++++++++++++++ packages/integration/package.json | 6 ++-- 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 .changeset/sixty-eyes-shout.md create mode 100644 packages/integration/config.d.ts diff --git a/.changeset/sixty-eyes-shout.md b/.changeset/sixty-eyes-shout.md new file mode 100644 index 0000000000..36e1c93a26 --- /dev/null +++ b/.changeset/sixty-eyes-shout.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': patch +'@backstage/integration': patch +--- + +Move the frontend visibility declarations of integrations config from @backstage/backend-common to @backstage/integration diff --git a/packages/backend-common/config.d.ts b/packages/backend-common/config.d.ts index c4ec84ab62..8a6c6d1209 100644 --- a/packages/backend-common/config.d.ts +++ b/packages/backend-common/config.d.ts @@ -96,7 +96,6 @@ export interface Config { azure?: Array<{ /** * The hostname of the given Azure instance - * @visibility frontend */ host: string; /** @@ -110,7 +109,6 @@ export interface Config { bitbucket?: Array<{ /** * The hostname of the given Bitbucket instance - * @visibility frontend */ host: string; /** @@ -120,7 +118,6 @@ export interface Config { token?: string; /** * The base url for the BitBucket API, for example https://api.bitbucket.org/2.0 - * @visibility frontend */ apiBaseUrl?: string; /** @@ -139,7 +136,6 @@ export interface Config { github?: Array<{ /** * The hostname of the given GitHub instance - * @visibility frontend */ host: string; /** @@ -149,12 +145,10 @@ export interface Config { token?: string; /** * The base url for the GitHub API, for example https://api.github.com - * @visibility frontend */ apiBaseUrl?: string; /** * The base url for GitHub raw resources, for example https://raw.githubusercontent.com - * @visibility frontend */ rawBaseUrl?: string; }>; @@ -163,7 +157,6 @@ export interface Config { gitlab?: Array<{ /** * The hostname of the given GitLab instance - * @visibility frontend */ host: string; /** diff --git a/packages/integration/config.d.ts b/packages/integration/config.d.ts new file mode 100644 index 0000000000..a03a07409b --- /dev/null +++ b/packages/integration/config.d.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + integrations?: { + azure?: Array<{ + /** @visibility frontend */ + host: string; + }>; + + bitbucket?: Array<{ + /** @visibility frontend */ + host: string; + /** @visibility frontend */ + apiBaseUrl?: string; + }>; + + github?: Array<{ + /** @visibility frontend */ + host: string; + /** @visibility frontend */ + apiBaseUrl?: string; + /** @visibility frontend */ + rawBaseUrl?: string; + }>; + + gitlab?: Array<{ + /** @visibility frontend */ + host: string; + }>; + }; +} diff --git a/packages/integration/package.json b/packages/integration/package.json index 2bc65c46a3..119ce51370 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -28,6 +28,8 @@ "@types/jest": "^26.0.7" }, "files": [ - "dist" - ] + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" }