diff --git a/.changeset/calm-bottles-rest.md b/.changeset/calm-bottles-rest.md new file mode 100644 index 0000000000..56321279e0 --- /dev/null +++ b/.changeset/calm-bottles-rest.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Internal change to move the `migrate` and `version:*` commands into a new migrate module. diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index 7673a2e905..02051b69f7 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -19,10 +19,10 @@ Commands: config:schema [options] repo [command] package [command] - migrate [command] - build-workspace [options] [packages...] versions:bump [options] versions:migrate [options] + migrate [command] + build-workspace [options] [packages...] create-github-app info help [command] diff --git a/packages/cli/src/alpha.ts b/packages/cli/src/alpha.ts index 8f197767bb..85a8763974 100644 --- a/packages/cli/src/alpha.ts +++ b/packages/cli/src/alpha.ts @@ -26,5 +26,6 @@ import chalk from 'chalk'; const initializer = new CliInitializer(); initializer.add(import('./modules/config/alpha')); initializer.add(import('./modules/build/alpha')); + initializer.add(import('./modules/migrate/alpha')); await initializer.run(); })(); diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 31bf4ef669..ee2af9541c 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -25,6 +25,7 @@ import { registerRepoCommands as registerRepoBuildCommands, registerCommands as registerBuildCommands, } from '../modules/build'; +import { registerCommands as registerMigrateCommand } from '../modules/migrate'; export function registerRepoCommand(program: Command) { const command = program @@ -171,41 +172,6 @@ export function registerScriptCommand(program: Command) { .action(lazy(() => import('./pack'), 'post')); } -export function registerMigrateCommand(program: Command) { - const command = program - .command('migrate [command]') - .description('Migration utilities'); - - command - .command('package-roles') - .description(`Add package role field to packages that don't have it`) - .action(lazy(() => import('./migrate/packageRole'), 'default')); - - command - .command('package-scripts') - .description('Set package scripts according to each package role') - .action(lazy(() => import('./migrate/packageScripts'), 'command')); - - command - .command('package-exports') - .description('Synchronize package subpath export definitions') - .action(lazy(() => import('./migrate/packageExports'), 'command')); - - command - .command('package-lint-configs') - .description( - 'Migrates all packages to use @backstage/cli/config/eslint-factory', - ) - .action(lazy(() => import('./migrate/packageLintConfigs'), 'command')); - - command - .command('react-router-deps') - .description( - 'Migrates the react-router dependencies for all packages to be peer dependencies', - ) - .action(lazy(() => import('./migrate/reactRouterDeps'), 'command')); -} - export function registerCommands(program: Command) { program .command('new') @@ -249,37 +215,6 @@ export function registerCommands(program: Command) { registerMigrateCommand(program); registerBuildCommands(program); - program - .command('versions:bump') - .option( - '--pattern ', - 'Override glob for matching packages to upgrade', - ) - .option( - '--release ', - 'Bump to a specific Backstage release line or version', - 'main', - ) - .option('--skip-install', 'Skips yarn install step') - .option('--skip-migrate', 'Skips migration of any moved packages') - .description('Bump Backstage packages to the latest versions') - .action(lazy(() => import('./versions/bump'), 'default')); - - program - .command('versions:migrate') - .option( - '--pattern ', - 'Override glob for matching packages to upgrade', - ) - .option( - '--skip-code-changes', - 'Skip code changes and only update package.json files', - ) - .description( - 'Migrate any plugins that have been moved to the @backstage-community namespace automatically', - ) - .action(lazy(() => import('./versions/migrate'), 'default')); - program .command('create-github-app ') .description('Create new GitHub App in your organization.') diff --git a/packages/cli/src/modules/migrate/alpha.ts b/packages/cli/src/modules/migrate/alpha.ts new file mode 100644 index 0000000000..ac56c06b7a --- /dev/null +++ b/packages/cli/src/modules/migrate/alpha.ts @@ -0,0 +1,135 @@ +/* + * Copyright 2024 The Backstage Authors + * + * 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. + */ +import { createCliPlugin } from '../../wiring/factory'; +import { Command } from 'commander'; +import { lazy } from '../../lib/lazy'; + +export default createCliPlugin({ + pluginId: 'migrate', + init: async reg => { + reg.addCommand({ + path: ['versions:migrate'], + description: + 'Migrate any plugins that have been moved to the @backstage-community namespace automatically', + execute: async ({ args }) => { + const command = new Command(); + const defaultCommand = command + .option( + '--pattern ', + 'Override glob for matching packages to upgrade', + ) + .option( + '--skip-code-changes', + 'Skip code changes and only update package.json files', + ) + .action(lazy(() => import('./commands/versions/migrate'), 'default')); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + + reg.addCommand({ + path: ['versions:bump'], + description: 'Bump Backstage packages to the latest versions', + execute: async ({ args }) => { + const command = new Command(); + + const defaultCommand = command + .option( + '--pattern ', + 'Override glob for matching packages to upgrade', + ) + .option( + '--release ', + 'Bump to a specific Backstage release line or version', + 'main', + ) + .option('--skip-install', 'Skips yarn install step') + .option('--skip-migrate', 'Skips migration of any moved packages') + .action(lazy(() => import('./commands/versions/bump'), 'default')); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + + reg.addCommand({ + path: ['migrate', 'package-roles'], + description: `Add package role field to packages that don't have it`, + execute: async ({ args }) => { + const command = new Command(); + const defaultCommand = command.action( + lazy(() => import('./commands/packageRole'), 'default'), + ); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + + reg.addCommand({ + path: ['migrate', 'package-scripts'], + description: 'Set package scripts according to each package role', + execute: async ({ args }) => { + const command = new Command(); + const defaultCommand = command.action( + lazy(() => import('./commands/packageScripts'), 'command'), + ); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + + reg.addCommand({ + path: ['migrate', 'package-exports'], + description: 'Synchronize package subpath export definitions', + execute: async ({ args }) => { + const command = new Command(); + const defaultCommand = command.action( + lazy(() => import('./commands/packageExports'), 'command'), + ); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + + reg.addCommand({ + path: ['migrate', 'package-lint-configs'], + description: + 'Migrates all packages to use @backstage/cli/config/eslint-factory', + execute: async ({ args }) => { + const command = new Command(); + const defaultCommand = command.action( + lazy(() => import('./commands/packageLintConfigs'), 'command'), + ); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + + reg.addCommand({ + path: ['migrate', 'react-router-deps'], + description: + 'Migrates the react-router dependencies for all packages to be peer dependencies', + execute: async ({ args }) => { + const command = new Command(); + const defaultCommand = command.action( + lazy(() => import('./commands/reactRouterDeps'), 'command'), + ); + + await defaultCommand.parseAsync(args, { from: 'user' }); + }, + }); + }, +}); diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/modules/migrate/commands/packageExports.ts similarity index 96% rename from packages/cli/src/commands/migrate/packageExports.ts rename to packages/cli/src/modules/migrate/commands/packageExports.ts index 6757d01bbe..c54422ceb9 100644 --- a/packages/cli/src/commands/migrate/packageExports.ts +++ b/packages/cli/src/modules/migrate/commands/packageExports.ts @@ -18,7 +18,7 @@ import { fixPackageExports, readFixablePackages, writeFixedPackages, -} from '../repo/fix'; +} from '../../../commands/repo/fix'; export async function command() { console.log( diff --git a/packages/cli/src/commands/migrate/packageLintConfigs.ts b/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts similarity index 98% rename from packages/cli/src/commands/migrate/packageLintConfigs.ts rename to packages/cli/src/modules/migrate/commands/packageLintConfigs.ts index 03d42846e8..c8e8ef3a42 100644 --- a/packages/cli/src/commands/migrate/packageLintConfigs.ts +++ b/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts @@ -17,7 +17,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'path'; import { PackageGraph } from '@backstage/cli-node'; -import { runPlain } from '../../lib/run'; +import { runPlain } from '../../../lib/run'; const PREFIX = `module.exports = require('@backstage/cli/config/eslint-factory')`; diff --git a/packages/cli/src/commands/migrate/packageRole.ts b/packages/cli/src/modules/migrate/commands/packageRole.ts similarity index 98% rename from packages/cli/src/commands/migrate/packageRole.ts rename to packages/cli/src/modules/migrate/commands/packageRole.ts index e7abbd3dcd..9a4bb08f6a 100644 --- a/packages/cli/src/commands/migrate/packageRole.ts +++ b/packages/cli/src/modules/migrate/commands/packageRole.ts @@ -18,7 +18,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'path'; import { getPackages } from '@manypkg/get-packages'; import { PackageRoles } from '@backstage/cli-node'; -import { paths } from '../../lib/paths'; +import { paths } from '../../../lib/paths'; export default async () => { const { packages } = await getPackages(paths.targetDir); diff --git a/packages/cli/src/commands/migrate/packageScripts.ts b/packages/cli/src/modules/migrate/commands/packageScripts.ts similarity index 100% rename from packages/cli/src/commands/migrate/packageScripts.ts rename to packages/cli/src/modules/migrate/commands/packageScripts.ts diff --git a/packages/cli/src/commands/migrate/reactRouterDeps.ts b/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts similarity index 100% rename from packages/cli/src/commands/migrate/reactRouterDeps.ts rename to packages/cli/src/modules/migrate/commands/reactRouterDeps.ts diff --git a/packages/cli/src/commands/versions/bump.test.ts b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts similarity index 99% rename from packages/cli/src/commands/versions/bump.test.ts rename to packages/cli/src/modules/migrate/commands/versions/bump.test.ts index d3ff0c1fbe..bce9888842 100644 --- a/packages/cli/src/commands/versions/bump.test.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts @@ -16,10 +16,10 @@ import fs from 'fs-extra'; import { Command } from 'commander'; -import * as runObj from '../../lib/run'; +import * as runObj from '../../../../lib/run'; import bump, { bumpBackstageJsonVersion, createVersionFinder } from './bump'; import { registerMswTestHooks, withLogCollector } from '@backstage/test-utils'; -import { YarnInfoInspectData } from '../../lib/versioning/packages'; +import { YarnInfoInspectData } from '../../../../lib/versioning/packages'; import { setupServer } from 'msw/node'; import { rest } from 'msw'; import { NotFoundError } from '@backstage/errors'; @@ -73,15 +73,15 @@ jest.mock('@backstage/cli-common', () => ({ }), })); -jest.mock('../../lib/run', () => { +jest.mock('../../../../lib/run', () => { return { run: jest.fn(), }; }); const mockFetchPackageInfo = jest.fn(); -jest.mock('../../lib/versioning/packages', () => { - const actual = jest.requireActual('../../lib/versioning/packages'); +jest.mock('../../../../lib/versioning/packages', () => { + const actual = jest.requireActual('../../../../lib/versioning/packages'); return { ...actual, fetchPackageInfo: (name: string) => mockFetchPackageInfo(name), diff --git a/packages/cli/src/commands/versions/bump.ts b/packages/cli/src/modules/migrate/commands/versions/bump.ts similarity index 98% rename from packages/cli/src/commands/versions/bump.ts rename to packages/cli/src/modules/migrate/commands/versions/bump.ts index 6f8ce0a8a0..23202ee1b5 100644 --- a/packages/cli/src/commands/versions/bump.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.ts @@ -24,23 +24,23 @@ import yaml from 'yaml'; import z from 'zod'; import { isError, NotFoundError } from '@backstage/errors'; import { resolve as resolvePath } from 'path'; -import { paths } from '../../lib/paths'; +import { paths } from '../../../../lib/paths'; import { mapDependencies, fetchPackageInfo, Lockfile, YarnInfoInspectData, -} from '../../lib/versioning'; +} from '../../../../lib/versioning'; import { BACKSTAGE_JSON } from '@backstage/cli-common'; -import { runParallelWorkers } from '../../lib/parallel'; +import { runParallelWorkers } from '../../../../lib/parallel'; import { getManifestByReleaseLine, getManifestByVersion, ReleaseManifest, } from '@backstage/release-manifests'; import { migrateMovedPackages } from './migrate'; -import { runYarnInstall } from './utils'; -import { run } from '../../lib/run'; +import { runYarnInstall } from '../../lib/utils'; +import { run } from '../../../../lib/run'; function maybeBootstrapProxy() { // see https://www.npmjs.com/package/global-agent diff --git a/packages/cli/src/commands/versions/migrate.test.ts b/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts similarity index 99% rename from packages/cli/src/commands/versions/migrate.test.ts rename to packages/cli/src/modules/migrate/commands/versions/migrate.test.ts index 919eb18278..7a0a1269c4 100644 --- a/packages/cli/src/commands/versions/migrate.test.ts +++ b/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts @@ -17,7 +17,7 @@ import { MockDirectory, createMockDirectory, } from '@backstage/backend-test-utils'; -import * as run from '../../lib/run'; +import * as run from '../../../../lib/run'; import migrate from './migrate'; import { withLogCollector } from '@backstage/test-utils'; import fs from 'fs-extra'; @@ -45,7 +45,7 @@ jest.mock('@backstage/cli-common', () => ({ }), })); -jest.mock('../../lib/run', () => { +jest.mock('../../../../lib/run', () => { return { run: jest.fn(), }; diff --git a/packages/cli/src/commands/versions/migrate.ts b/packages/cli/src/modules/migrate/commands/versions/migrate.ts similarity index 98% rename from packages/cli/src/commands/versions/migrate.ts rename to packages/cli/src/modules/migrate/commands/versions/migrate.ts index 8415de0f57..7825ea31cb 100644 --- a/packages/cli/src/commands/versions/migrate.ts +++ b/packages/cli/src/modules/migrate/commands/versions/migrate.ts @@ -19,7 +19,7 @@ import { resolve as resolvePath, join as joinPath } from 'path'; import { OptionValues } from 'commander'; import { readJson, writeJson } from 'fs-extra'; import { minimatch } from 'minimatch'; -import { runYarnInstall } from './utils'; +import { runYarnInstall } from '../../lib/utils'; import replace from 'replace-in-file'; declare module 'replace-in-file' { diff --git a/packages/cli/src/modules/migrate/index.ts b/packages/cli/src/modules/migrate/index.ts new file mode 100644 index 0000000000..10e96ad173 --- /dev/null +++ b/packages/cli/src/modules/migrate/index.ts @@ -0,0 +1,84 @@ +/* + * Copyright 2025 The Backstage Authors + * + * 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. + */ + +import { lazy } from '../../lib/lazy'; +import { Command } from 'commander'; + +export function registerCommands(program: Command) { + program + .command('versions:bump') + .option( + '--pattern ', + 'Override glob for matching packages to upgrade', + ) + .option( + '--release ', + 'Bump to a specific Backstage release line or version', + 'main', + ) + .option('--skip-install', 'Skips yarn install step') + .option('--skip-migrate', 'Skips migration of any moved packages') + .description('Bump Backstage packages to the latest versions') + .action(lazy(() => import('./commands/versions/bump'), 'default')); + + program + .command('versions:migrate') + .option( + '--pattern ', + 'Override glob for matching packages to upgrade', + ) + .option( + '--skip-code-changes', + 'Skip code changes and only update package.json files', + ) + .description( + 'Migrate any plugins that have been moved to the @backstage-community namespace automatically', + ) + .action(lazy(() => import('./commands/versions/migrate'), 'default')); + + const command = program + .command('migrate [command]') + .description('Migration utilities'); + + command + .command('package-roles') + .description(`Add package role field to packages that don't have it`) + .action(lazy(() => import('./commands/packageRole'), 'default')); + + command + .command('package-scripts') + .description('Set package scripts according to each package role') + .action(lazy(() => import('./commands/packageScripts'), 'command')); + + command + .command('package-exports') + .description('Synchronize package subpath export definitions') + .action(lazy(() => import('./commands/packageExports'), 'command')); + + command + .command('package-lint-configs') + .description( + 'Migrates all packages to use @backstage/cli/config/eslint-factory', + ) + .action(lazy(() => import('./commands/packageLintConfigs'), 'command')); + + command + .command('react-router-deps') + .description( + 'Migrates the react-router dependencies for all packages to be peer dependencies', + ) + .action(lazy(() => import('./commands/reactRouterDeps'), 'command')); +} diff --git a/packages/cli/src/commands/versions/utils.ts b/packages/cli/src/modules/migrate/lib/utils.ts similarity index 97% rename from packages/cli/src/commands/versions/utils.ts rename to packages/cli/src/modules/migrate/lib/utils.ts index 22c5f0c028..5b7b544c87 100644 --- a/packages/cli/src/commands/versions/utils.ts +++ b/packages/cli/src/modules/migrate/lib/utils.ts @@ -16,7 +16,7 @@ import ora from 'ora'; import chalk from 'chalk'; -import { run } from '../../lib/run'; +import { run } from '../../../lib/run'; export async function runYarnInstall() { const spinner = ora({