From 2c64d7545f10172b5fca9ae95bf99a495b5a91fe Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Mon, 24 Jun 2019 16:26:18 +0200 Subject: [PATCH] feat(publish): clear built files before building package and packing (#12516) * feat(publish): clear built files before building package and packing * Add some feedback message if dev doesn't confirm file deletion --- package.json | 5 +- scripts/clear-package-dir.js | 149 +++++++++++++++++++++++++++++++++++ yarn.lock | 5 ++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 scripts/clear-package-dir.js diff --git a/package.json b/package.json index 07bdba8ff519f..97777b66c26d8 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,10 @@ "@babel/core": "^7.0.0", "@babel/node": "^7.0.0", "@babel/runtime": "^7.0.0", + "@lerna/prompt": "3.6.0", "babel-eslint": "^10.0.1", "babel-jest": "^24.0.0", + "chalk": "^2.4.2", "chokidar": "^1.7.0", "cross-env": "^5.1.4", "danger": "^8.0.0", @@ -21,6 +23,7 @@ "fs-extra": "^7.0.0", "glob": "^7.1.1", "husky": "2.3.0", + "ignore": "^5.0.5", "jest": "^24.0.0", "jest-cli": "^24.0.0", "jest-environment-jsdom-fourteen": "^0.1.0", @@ -90,7 +93,7 @@ "plop": "plop", "prebootstrap": "yarn", "prettier": "prettier \"**/*.{md,css,scss,yaml,yml,ts}\"", - "publish": "node scripts/check-publish-access && lerna publish", + "publish": "node scripts/check-publish-access && node scripts/clear-package-dir --verbose && lerna publish", "publish-canary": "lerna publish --canary --yes", "publish-next": "lerna publish --npm-tag=next --bump=prerelease", "test": "npm-run-all -s lint jest", diff --git a/scripts/clear-package-dir.js b/scripts/clear-package-dir.js new file mode 100644 index 0000000000000..c978c5e3112f5 --- /dev/null +++ b/scripts/clear-package-dir.js @@ -0,0 +1,149 @@ +const ignore = require(`ignore`) +const fs = require(`fs-extra`) +const glob = require(`glob`) +const yargs = require(`yargs`) +const chalk = require(`chalk`) +const PromptUtilities = require(`@lerna/prompt`) +const _ = require(`lodash`) +const path = require(`path`) +const { execSync } = require(`child_process`) + +let argv = yargs + .option(`dry-run`, { + default: false, + describe: `Don't delete files - just show what would be deleted`, + }) + .option(`verbose`, { + default: false, + describe: `Show files that would be bundled and mark files that will be deleted`, + }) + .option(`force`, { + default: false, + describe: `Force deletion of file without prompting user to confirm`, + }).argv + +const verbose = argv[`dry-run`] || argv[`verbose`] || !argv[`force`] + +const buildIgnoreArray = str => + str + .split(`\n`) + .filter(line => { + // skip empty lines and comments + if (!line || line[0] === `#`) { + return false + } + + return true + }) + .reduce((acc, item) => { + acc.push(item) + + // add "/**" glob as ignore package need that to + // properly ignore entries like "node_modules" + if (!/\*\*$/.test(item)) { + acc.push(`${item}/**`) + } + return acc + }, []) + +const getListOfFilesToClear = ({ location, name }) => { + if (verbose) { + console.log(`Files that will be packed for ${chalk.bold(name)}:`) + } + + let gitignore = [] + try { + gitignore = buildIgnoreArray( + fs.readFileSync(path.join(location, `.gitignore`), `utf-8`) + ) + } catch { + // not all packages have .gitignore - see gatsby-plugin-no-sourcemap + } finally { + const notTrackedFiles = execSync( + `git ls-files --others --exclude-standard`, + { + cwd: location, + } + ) + .toString() + .split(`\n`) + + gitignore = gitignore.concat(notTrackedFiles) + + // we need main file - for now hardcode index + // that is used in most of our packages + // it should actually be in each package .gitignore + gitignore.push(`!/index.js`) + } + + let npmignore = [] + try { + npmignore = buildIgnoreArray( + fs.readFileSync(path.join(location, `.npmignore`), `utf-8`) + ) + } catch { + // not all packages have .npmignore - see gatsby-plugin-no-sourcemap + } finally { + npmignore = npmignore.concat([`node_modules/**`]) + } + + const result = glob.sync(`**/*`, { + nodir: true, + ignore: npmignore, + cwd: location, + }) + + const ig = ignore().add(gitignore) + + const filesToDelete = result + .filter(file => { + const willBeDeleted = ig.ignores(file) + if (verbose) { + console.log( + `[ ${willBeDeleted ? chalk.red(`DEL`) : chalk.green(` - `)} ] ${file}` + ) + } + + return willBeDeleted + }) + .map(file => path.join(location, file)) + + return filesToDelete +} + +const run = async () => { + try { + const changed = JSON.parse( + execSync( + `node_modules/.bin/lerna changed --json --loglevel=silent` + ).toString() + ) + const filesToDelete = _.flatten(changed.map(getListOfFilesToClear)) + + if (!argv[`dry-run`] && filesToDelete.length > 0) { + if ( + argv[`force`] || + (await PromptUtilities.confirm( + `Are you sure you want to delete those files?` + )) + ) { + filesToDelete.forEach(file => { + fs.removeSync(file) + }) + } else { + console.log( + `${chalk.red( + `Stopping publish` + )}: there are files that need to be cleared.\n\nIf this is a bug in check script and everything is fine, run:\n\n${chalk.green( + `yarn lerna publish` + )}\n\ndirectly to skip checks (and hopefully apply changes to clear-package-dir script to fix it).` + ) + process.exit(1) + } + } + } catch { + // if no packages are marked are changed, lerna will exit with non-zero + } +} + +run() diff --git a/yarn.lock b/yarn.lock index 4d1056a133e71..87f36ebf9a3b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11747,6 +11747,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" + integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== + image-size@^0.6.1: version "0.6.3" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2"