cli: load config schema and use to filter config + add --frontend flag to print
This commit is contained in:
@@ -76,6 +76,7 @@
|
||||
"jest": "^26.0.1",
|
||||
"jest-css-modules": "^2.1.0",
|
||||
"jest-esm-transformer": "^1.0.0",
|
||||
"lodash": "^4.17.19",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"ora": "^4.0.3",
|
||||
"raw-loader": "^4.0.1",
|
||||
|
||||
@@ -16,16 +16,43 @@
|
||||
|
||||
import { Command } from 'commander';
|
||||
import { stringify as stringifyYaml } from 'yaml';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { loadCliConfig } from '../../lib/config';
|
||||
import cloneDeepWith from 'lodash/cloneDeepWith';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const { config } = await loadCliConfig(cmd.config, cmd.withSecrets ?? false);
|
||||
const { schema, appConfigs } = await loadCliConfig(cmd.config);
|
||||
let data;
|
||||
|
||||
const flatConfig = config.get();
|
||||
if (cmd.frontend) {
|
||||
const frontendConfigs = schema.process(appConfigs, {
|
||||
visibilities: ['frontend'],
|
||||
});
|
||||
data = ConfigReader.fromConfigs(frontendConfigs).get();
|
||||
} else if (cmd.withSecrets) {
|
||||
data = ConfigReader.fromConfigs(appConfigs).get();
|
||||
} else {
|
||||
let secretConfigs = schema.process(appConfigs, {
|
||||
visibilities: ['secret'],
|
||||
});
|
||||
|
||||
secretConfigs = secretConfigs.map(entry => ({
|
||||
context: entry.context,
|
||||
data: cloneDeepWith(entry.data, value => {
|
||||
console.log('DEBUG: value =', value);
|
||||
if (typeof value !== 'object') {
|
||||
return '<secret>';
|
||||
}
|
||||
return undefined;
|
||||
}),
|
||||
}));
|
||||
|
||||
data = ConfigReader.fromConfigs(appConfigs.concat(secretConfigs)).get();
|
||||
}
|
||||
|
||||
if (cmd.format === 'json') {
|
||||
process.stdout.write(`${JSON.stringify(flatConfig, null, 2)}\n`);
|
||||
process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
|
||||
} else {
|
||||
process.stdout.write(`${stringifyYaml(flatConfig)}\n`);
|
||||
process.stdout.write(`${stringifyYaml(data)}\n`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -136,6 +136,7 @@ export function registerCommands(program: CommanderStatic) {
|
||||
|
||||
program
|
||||
.command('config:print')
|
||||
.option('--frontend', 'Print only the frontend configuration')
|
||||
.option('--with-secrets', 'Include secrets in the printed configuration')
|
||||
.option(
|
||||
'--format <format>',
|
||||
|
||||
@@ -40,7 +40,7 @@ export async function buildBundle(options: BuildOptions) {
|
||||
...options,
|
||||
checksEnabled: false,
|
||||
isDev: false,
|
||||
baseUrl: resolveBaseUrl(options.config),
|
||||
baseUrl: resolveBaseUrl(options.frontendConfig),
|
||||
});
|
||||
const compiler = webpack(config);
|
||||
|
||||
|
||||
@@ -74,11 +74,11 @@ export async function createConfig(
|
||||
paths: BundlingPaths,
|
||||
options: BundlingOptions,
|
||||
): Promise<webpack.Configuration> {
|
||||
const { checksEnabled, isDev } = options;
|
||||
const { checksEnabled, isDev, frontendConfig } = options;
|
||||
|
||||
const { plugins, loaders } = transforms(options);
|
||||
|
||||
const baseUrl = options.config.getString('app.baseUrl');
|
||||
const baseUrl = frontendConfig.getString('app.baseUrl');
|
||||
const validBaseUrl = new URL(baseUrl);
|
||||
|
||||
if (checksEnabled) {
|
||||
@@ -99,7 +99,7 @@ export async function createConfig(
|
||||
|
||||
plugins.push(
|
||||
new webpack.EnvironmentPlugin({
|
||||
APP_CONFIG: options.appConfigs,
|
||||
APP_CONFIG: options.frontendAppConfigs,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -109,9 +109,9 @@ export async function createConfig(
|
||||
templateParameters: {
|
||||
publicPath: validBaseUrl.pathname.replace(/\/$/, ''),
|
||||
app: {
|
||||
title: options.config.getString('app.title'),
|
||||
title: frontendConfig.getString('app.title'),
|
||||
baseUrl: validBaseUrl.href,
|
||||
googleAnalyticsTrackingId: options.config.getOptionalString(
|
||||
googleAnalyticsTrackingId: frontendConfig.getOptionalString(
|
||||
'app.googleAnalyticsTrackingId',
|
||||
),
|
||||
},
|
||||
|
||||
@@ -23,7 +23,7 @@ import { ServeOptions } from './types';
|
||||
import { resolveBundlingPaths } from './paths';
|
||||
|
||||
export async function serveBundle(options: ServeOptions) {
|
||||
const url = resolveBaseUrl(options.config);
|
||||
const url = resolveBaseUrl(options.frontendConfig);
|
||||
|
||||
const host =
|
||||
options.config.getOptionalString('app.listen.host') || url.hostname;
|
||||
|
||||
@@ -21,23 +21,23 @@ import { ParallelOption } from '../parallel';
|
||||
export type BundlingOptions = {
|
||||
checksEnabled: boolean;
|
||||
isDev: boolean;
|
||||
config: Config;
|
||||
appConfigs: AppConfig[];
|
||||
frontendConfig: Config;
|
||||
frontendAppConfigs: AppConfig[];
|
||||
baseUrl: URL;
|
||||
parallel?: ParallelOption;
|
||||
};
|
||||
|
||||
export type ServeOptions = BundlingPathsOptions & {
|
||||
checksEnabled: boolean;
|
||||
config: Config;
|
||||
appConfigs: AppConfig[];
|
||||
frontendConfig: Config;
|
||||
frontendAppConfigs: AppConfig[];
|
||||
};
|
||||
|
||||
export type BuildOptions = BundlingPathsOptions & {
|
||||
statsJsonEnabled: boolean;
|
||||
parallel?: ParallelOption;
|
||||
config: Config;
|
||||
appConfigs: AppConfig[];
|
||||
frontendConfig: Config;
|
||||
frontendAppConfigs: AppConfig[];
|
||||
};
|
||||
|
||||
export type BackendBundlingOptions = {
|
||||
|
||||
@@ -14,13 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
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));
|
||||
|
||||
// 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 schema = await loadConfigSchema({
|
||||
dependencies: localPackageNames,
|
||||
});
|
||||
|
||||
const appConfigs = await loadConfig({
|
||||
env: process.env.APP_ENV ?? process.env.NODE_ENV ?? 'production',
|
||||
configRoot: paths.targetRoot,
|
||||
@@ -31,8 +40,15 @@ export async function loadCliConfig(configArgs: string[]) {
|
||||
`Loaded config from ${appConfigs.map(c => c.context).join(', ')}`,
|
||||
);
|
||||
|
||||
const frontendAppConfigs = schema.process(appConfigs, {
|
||||
visibilities: ['frontend'],
|
||||
});
|
||||
const frontendConfig = ConfigReader.fromConfigs(frontendAppConfigs);
|
||||
|
||||
return {
|
||||
schema,
|
||||
appConfigs,
|
||||
config: ConfigReader.fromConfigs(appConfigs),
|
||||
frontendConfig,
|
||||
frontendAppConfigs,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user