Merge pull request #3469 from backstage/rugvip/scopeconf
cli: only load config schema that applies to the target package
This commit is contained in:
@@ -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 <name>` flag to scope the config schema used by the `config:print` and `config:check` commands.
|
||||
@@ -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
|
||||
Vendored
-7
@@ -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;
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
})),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -141,6 +141,10 @@ export function registerCommands(program: CommanderStatic) {
|
||||
|
||||
program
|
||||
.command('config:print')
|
||||
.option(
|
||||
'--package <name>',
|
||||
'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 <name>',
|
||||
'Only load config schema that applies to the given package',
|
||||
)
|
||||
.option(...configOption)
|
||||
.description(
|
||||
'Validate that the given configuration loads and matches schema',
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<string>();
|
||||
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);
|
||||
}
|
||||
|
||||
Vendored
+45
@@ -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;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
@@ -28,6 +28,8 @@
|
||||
"@types/jest": "^26.0.7"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
"dist",
|
||||
"config.d.ts"
|
||||
],
|
||||
"configSchema": "config.d.ts"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user