diff --git a/.changeset/clever-lizards-whisper.md b/.changeset/clever-lizards-whisper.md new file mode 100644 index 0000000000..4f2820c347 --- /dev/null +++ b/.changeset/clever-lizards-whisper.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +When building a backend package with dependencies any `--config ` options will now be forwarded to any dependent app package builds, unless the build script in the app package already contains a `--config` option. diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index 88c22afb9b..f96204b413 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -37,10 +37,6 @@ The required steps in the host build are to install dependencies with `yarn install`, generate type definitions using `yarn tsc`, and build the backend package with `yarn build:backend`. -> NOTE: If you created your app prior to 2021-02-18, follow the -> [migration step](https://github.com/backstage/backstage/releases/tag/release-2021-02-18) -> to move from `backend:build` to `backend:bundle`. - In a CI workflow it might look something like this: ```bash @@ -50,7 +46,8 @@ yarn install --frozen-lockfile yarn tsc # Build the backend, which bundles it all up into the packages/backend/dist folder. -yarn build:backend +# The configuration files here should match the one you use inside the Dockerfile below. +yarn build:backend --config app-config.yaml ``` Once the host build is complete, we are ready to build our image. The following diff --git a/packages/cli/src/commands/build/buildBackend.ts b/packages/cli/src/commands/build/buildBackend.ts index 7e61f9ae85..5d42aa18d4 100644 --- a/packages/cli/src/commands/build/buildBackend.ts +++ b/packages/cli/src/commands/build/buildBackend.ts @@ -28,10 +28,11 @@ const SKELETON_FILE = 'skeleton.tar.gz'; interface BuildBackendOptions { targetDir: string; skipBuildDependencies: boolean; + configPaths?: string[]; } export async function buildBackend(options: BuildBackendOptions) { - const { targetDir, skipBuildDependencies } = options; + const { targetDir, skipBuildDependencies, configPaths } = options; const pkg = await fs.readJson(resolvePath(targetDir, 'package.json')); // We build the target package without generating type declarations. @@ -45,6 +46,7 @@ export async function buildBackend(options: BuildBackendOptions) { try { await createDistWorkspace([pkg.name], { targetDir: tmpDir, + configPaths, buildDependencies: !skipBuildDependencies, buildExcludes: [pkg.name], parallelism: getEnvironmentParallelism(), diff --git a/packages/cli/src/commands/build/command.ts b/packages/cli/src/commands/build/command.ts index fcaf58e1ee..90b76545ce 100644 --- a/packages/cli/src/commands/build/command.ts +++ b/packages/cli/src/commands/build/command.ts @@ -20,20 +20,29 @@ import { findRoleFromCommand, getRoleInfo } from '../../lib/role'; import { paths } from '../../lib/paths'; import { buildFrontend } from './buildFrontend'; import { buildBackend } from './buildBackend'; +import { isValidUrl } from '../../lib/urls'; export async function command(opts: OptionValues): Promise { const role = await findRoleFromCommand(opts); - if (role === 'frontend') { - return buildFrontend({ - targetDir: paths.targetDir, - configPaths: opts.config as string[], - writeStats: Boolean(opts.stats), + if (role === 'frontend' || role === 'backend') { + const configPaths = (opts.config as string[]).map(arg => { + if (isValidUrl(arg)) { + return arg; + } + return paths.resolveTarget(arg); }); - } - if (role === 'backend') { + + if (role === 'frontend') { + return buildFrontend({ + targetDir: paths.targetDir, + configPaths, + writeStats: Boolean(opts.stats), + }); + } return buildBackend({ targetDir: paths.targetDir, + configPaths, skipBuildDependencies: Boolean(opts.skipBuildDependencies), }); } diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index 2d2967fc44..601f442a73 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -60,6 +60,11 @@ type Options = { */ targetDir?: string; + /** + * Configuration files to load during packaging. + */ + configPaths?: string[]; + /** * Files to copy into the target workspace. * @@ -127,13 +132,18 @@ export async function createDistWorkspace( if (options.buildDependencies) { const exclude = options.buildExcludes ?? []; + const configPaths = options.configPaths ?? []; const toBuild = new Set( targets.map(_ => _.name).filter(name => !exclude.includes(name)), ); const standardBuilds = new Array(); - const customBuild = new Array<{ dir: string; name: string }>(); + const customBuild = new Array<{ + dir: string; + name: string; + args?: string[]; + }>(); for (const pkg of packages) { if (!toBuild.has(pkg.packageJson.name)) { @@ -166,7 +176,10 @@ export async function createDistWorkspace( console.warn( `Building ${pkg.packageJson.name} separately because it is a bundled package`, ); - customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name }); + const args = buildScript.includes('--config') + ? [] + : configPaths.map(p => ['--config', p]).flat(); + customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name, args }); continue; } @@ -193,8 +206,8 @@ export async function createDistWorkspace( if (customBuild.length > 0) { await runParallelWorkers({ items: customBuild, - worker: async ({ name, dir }) => { - await run('yarn', ['run', 'build'], { + worker: async ({ name, dir, args }) => { + await run('yarn', ['run', 'build', ...(args || [])], { cwd: dir, stdoutLogFunc: prefixLogFunc(`${name}: `, 'stdout'), stderrLogFunc: prefixLogFunc(`${name}: `, 'stderr'),