diff --git a/.changeset/smart-squids-change.md b/.changeset/smart-squids-change.md new file mode 100644 index 0000000000..51396114c9 --- /dev/null +++ b/.changeset/smart-squids-change.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added a new `backstage-cli repo clean` command that cleans the repo root and runs the clean script in all packages. diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index dabab76850..14e548eeaf 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -415,6 +415,7 @@ Options: Commands: build [options] lint [options] + clean help [command] ``` @@ -429,6 +430,15 @@ Options: -h, --help ``` +### `backstage-cli repo clean` + +``` +Usage: backstage-cli repo clean [options] + +Options: + -h, --help +``` + ### `backstage-cli repo lint` ``` diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index def16900fa..9c543f8853 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -60,6 +60,11 @@ export function registerRepoCommand(program: Command) { .option('--fix', 'Attempt to automatically fix violations') .action(lazy(() => import('./repo/lint').then(m => m.command))); + command + .command('clean') + .description('Delete cache and output directories') + .action(lazy(() => import('./repo/clean').then(m => m.command))); + command .command('list-deprecations', { hidden: true }) .description('List deprecations. [EXPERIMENTAL]') diff --git a/packages/cli/src/commands/repo/clean.ts b/packages/cli/src/commands/repo/clean.ts new file mode 100644 index 0000000000..323746e089 --- /dev/null +++ b/packages/cli/src/commands/repo/clean.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2020 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 { execFile as execFileCb } from 'child_process'; +import fs from 'fs-extra'; +import { resolve as resolvePath } from 'path'; +import { promisify } from 'util'; +import { PackageGraph } from '../../lib/monorepo'; +import { paths } from '../../lib/paths'; + +const execFile = promisify(execFileCb); + +export async function command(): Promise { + const packages = await PackageGraph.listTargetPackages(); + + await fs.remove(paths.resolveTargetRoot('dist')); + await fs.remove(paths.resolveTargetRoot('dist-types')); + await fs.remove(paths.resolveTargetRoot('coverage')); + + await Promise.all( + Array.from(Array(10), async () => { + while (packages.length > 0) { + const pkg = packages.pop()!; + const cleanScript = pkg.packageJson.scripts?.clean; + + if ( + cleanScript === 'backstage-cli clean' || + cleanScript === 'backstage-cli package clean' + ) { + await fs.remove(resolvePath(pkg.dir, 'dist')); + await fs.remove(resolvePath(pkg.dir, 'dist-types')); + await fs.remove(resolvePath(pkg.dir, 'coverage')); + } else if (cleanScript) { + const result = await execFile('yarn', ['run', 'clean'], { + cwd: pkg.dir, + shell: true, + }); + process.stdout.write(result.stdout); + process.stderr.write(result.stderr); + } + } + }), + ); +}