From d131851373bb26b3fbedae8d5a3bc0651dbc15c1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 1 Jun 2021 21:36:46 +0200 Subject: [PATCH] packages: add initial codemods package Signed-off-by: Patrik Oldsberg --- packages/codemods/.eslintrc.js | 15 +++++ packages/codemods/README.md | 24 ++++++++ packages/codemods/bin/backstage-codemods | 29 +++++++++ packages/codemods/package.json | 40 +++++++++++++ packages/codemods/src/index.ts | 75 ++++++++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 packages/codemods/.eslintrc.js create mode 100644 packages/codemods/README.md create mode 100755 packages/codemods/bin/backstage-codemods create mode 100644 packages/codemods/package.json create mode 100644 packages/codemods/src/index.ts diff --git a/packages/codemods/.eslintrc.js b/packages/codemods/.eslintrc.js new file mode 100644 index 0000000000..7c8a092081 --- /dev/null +++ b/packages/codemods/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], + rules: { + 'no-console': 0, + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: true, + optionalDependencies: false, + peerDependencies: false, + bundledDependencies: false, + }, + ], + }, +}; diff --git a/packages/codemods/README.md b/packages/codemods/README.md new file mode 100644 index 0000000000..139213c0c1 --- /dev/null +++ b/packages/codemods/README.md @@ -0,0 +1,24 @@ +# e2e-test + +End-to-end test for verifying Backstage packages. + +## Usage + +This package is only meant for usage within the Backstage monorepo. + +All packages need to be installed and built before running the test. In a fresh clone of this repo you first need to run the following from the repo root: + +```sh +yarn install +yarn tsc +yarn build +``` + +Once those tasks have completed, you can now run the test using `yarn e2e-test run`. + +If you make changes to other packages you will need to rerun `yarn tsc && yarn build`. Changes to this package do not require a rebuild. + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/codemods/bin/backstage-codemods b/packages/codemods/bin/backstage-codemods new file mode 100755 index 0000000000..d6d449fe31 --- /dev/null +++ b/packages/codemods/bin/backstage-codemods @@ -0,0 +1,29 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('path'); + +require('ts-node').register({ + transpileOnly: true, + /* eslint-disable-next-line no-restricted-syntax */ + project: path.resolve(__dirname, '../../../tsconfig.json'), + compilerOptions: { + module: 'CommonJS', + }, +}); + +require('../src'); diff --git a/packages/codemods/package.json b/packages/codemods/package.json new file mode 100644 index 0000000000..4049715255 --- /dev/null +++ b/packages/codemods/package.json @@ -0,0 +1,40 @@ +{ + "name": "@backstage/codemods", + "description": "A collection of codemods for Backstage projects", + "version": "0.1.0", + "private": true, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/codemods" + }, + "keywords": [ + "backstage" + ], + "license": "Apache-2.0", + "main": "src/index.ts", + "scripts": { + "start": "nodemon --", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "test:e2e": "yarn start" + }, + "bin": { + "backstage-codemods": "bin/backstage-codemods" + }, + "dependencies": { + "chalk": "^4.0.0", + "jscodeshift": "^0.12.0" + }, + "devDependencies": { + "@types/node": "^14.14.32", + "commander": "^6.1.0", + "ts-node": "^9.1.1" + }, + "nodemonConfig": { + "watch": "./src", + "exec": "bin/e2e-test", + "ext": "ts" + } +} diff --git a/packages/codemods/src/index.ts b/packages/codemods/src/index.ts new file mode 100644 index 0000000000..541672a3dc --- /dev/null +++ b/packages/codemods/src/index.ts @@ -0,0 +1,75 @@ +/* + * 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. + */ + +import program, { Command } from 'commander'; +import chalk from 'chalk'; +import { version } from '../package.json'; + +const codemods = [ + { + name: 'core-imports', + description: + 'Updates @backstage/core imports to use @backstage/core-* imports instead.', + }, +]; + +function createCodemodAction(name: string) { + return (cmd: Command) => { + console.log(`Fake codemod ${cmd} ${name}`); + }; +} + +async function main(argv: string[]) { + program.name('backstage-codemods').version(version); + + for (const codemod of codemods) { + program + .command(codemod.name) + .description(codemod.description) + .option('-d, --dry', 'Dry run, no changes written to files') + .action(createCodemodAction(codemod.name)); + } + + program.on('command:*', () => { + console.log(); + console.log(chalk.red(`Invalid command: ${program.args.join(' ')}`)); + console.log(); + program.outputHelp(); + process.exit(1); + }); + + program.parse(argv); +} + +function exitWithError(err: Error & { code?: unknown }) { + process.stdout.write(`${err.name}: ${err.stack || err.message}\n`); + + if (typeof err.code === 'number') { + process.exit(err.code); + } else { + process.exit(1); + } +} + +process.on('unhandledRejection', (rejection: unknown) => { + if (rejection instanceof Error) { + exitWithError(rejection); + } else { + exitWithError(new Error(`Unknown rejection: '${rejection}'`)); + } +}); + +main(process.argv).catch(exitWithError);