diff --git a/.circleci/config.yml b/.circleci/config.yml index a18a9039981..1be70b87a1a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,7 @@ jobs: - packages/patternfly-4/react-charts/node_modules - packages/patternfly-4/react-styles/node_modules - packages/patternfly-3/patternfly-react/node_modules + - .cache # Incremental builds key: v{{ .Environment.CACHE_VERSION }}-deps-{{ .Branch }}-{{ checksum "yarn.lock" }} - run: name: Build Dist diff --git a/.travis.yml b/.travis.yml index f0c53f7b402..ec0289e2a21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ cache: - packages/patternfly-4/react-tokens/dist - packages/patternfly-4/react-inline-edit-extension/dist - packages/patternfly-4/react-docs/public # To cache PF4 docs + - .cache # For incremental builds git: depth: 10 branches: diff --git a/package.json b/package.json index 69c25e39281..3e28ae623af 100644 --- a/package.json +++ b/package.json @@ -94,10 +94,13 @@ }, "scripts": { "bootstrap": "lerna bootstrap", - "build": "lerna run build --stream", + "build": "node scripts/incrementalBuild.js", + "build:pf3": "yarn build pf3", + "build:pf4": "yarn build pf4", "build:docs": "lerna run build:docs --stream", "build:storybook": "build-storybook -c storybook -o .out", - "clean": "lerna run clean --parallel", + "clean": "yarn clean:build && lerna run clean --parallel", + "clean:build": "shx rm -rf .cache", "commit": "git-cz", "generate": "yarn plop", "lint": "lerna run lint --parallel", @@ -106,7 +109,7 @@ "prettier": "prettier --write 'storybook/**/*.js' 'packages/**/*.js' 'scripts/**/*.js'", "start": "yarn start:pf3", "start:pf3": "concurrently 'yarn storybook' 'yarn storybook:openurl'", - "start:pf4": "lerna run develop --scope='@patternfly/react-docs' --scope='@patternfly/react-core' --parallel --stream", + "start:pf4": "yarn build:pf4 && lerna run develop --parallel --stream", "storybook:openurl": "node ./storybook/openBrowser.js", "storybook": "start-storybook -c storybook -p 6006", "test": "jest packages", @@ -127,5 +130,8 @@ "packages": [ "packages/**" ] + }, + "dependencies": { + "folder-hash": "^3.0.0" } -} \ No newline at end of file +} diff --git a/packages/patternfly-4/react-charts/package.json b/packages/patternfly-4/react-charts/package.json index 316a0351f09..899e2a261bb 100644 --- a/packages/patternfly-4/react-charts/package.json +++ b/packages/patternfly-4/react-charts/package.json @@ -37,7 +37,8 @@ "build:babel": "concurrently 'yarn build:babel:cjs' 'yarn build:babel:esm'", "build:babel:cjs": "cross-env BABEL_ENV=production:cjs babel src --out-dir dist/js", "build:babel:esm": "cross-env BABEL_ENV=production:esm babel src --out-dir dist/esm", - "clean": "rimraf dist" + "clean": "rimraf dist", + "develop": "yarn build:babel:esm --skip-initial-build --watch --verbose" }, "optionalDependencies": { "@types/victory": "^0.9.19", diff --git a/packages/patternfly-4/react-inline-edit-extension/package.json b/packages/patternfly-4/react-inline-edit-extension/package.json index 8b8e8b8b739..47c571e396c 100644 --- a/packages/patternfly-4/react-inline-edit-extension/package.json +++ b/packages/patternfly-4/react-inline-edit-extension/package.json @@ -47,6 +47,7 @@ "build:babel:cjs": "cross-env BABEL_ENV=production:cjs babel src --out-dir dist/js", "build:babel:esm": "cross-env BABEL_ENV=production:esm babel src --out-dir dist/esm", "build:ts": "node ./scripts/copyTS.js", + "develop": "yarn build:babel:esm --skip-initial-build --watch --verbose", "postbuild": "node ./build/copyStyles.js" }, "optionalDependencies": { diff --git a/packages/patternfly-4/react-styled-system/package.json b/packages/patternfly-4/react-styled-system/package.json index 8a01cd15d95..61e575b3f9a 100644 --- a/packages/patternfly-4/react-styled-system/package.json +++ b/packages/patternfly-4/react-styled-system/package.json @@ -30,7 +30,8 @@ "build:babel": "concurrently 'yarn build:babel:cjs' 'yarn build:babel:esm'", "build:babel:cjs": "cross-env BABEL_ENV=production:cjs babel src --out-dir dist/js", "build:babel:esm": "cross-env BABEL_ENV=production:esm babel src --out-dir dist/esm", - "clean": "rimraf dist" + "clean": "rimraf dist", + "develop": "yarn build:babel:esm --skip-initial-build --watch --verbose" }, "dependencies": { "@patternfly/react-styles": "^3.0.2", diff --git a/packages/patternfly-4/react-styles/package.json b/packages/patternfly-4/react-styles/package.json index d438e556ee2..4c8ea6102ba 100644 --- a/packages/patternfly-4/react-styles/package.json +++ b/packages/patternfly-4/react-styles/package.json @@ -17,7 +17,8 @@ "build:babel:cjs": "cross-env BABEL_ENV=production:cjs babel src --out-dir dist/js", "build:babel:esm": "cross-env BABEL_ENV=production:esm babel src --out-dir dist/esm", "build:babel:umd": "cross-env BABEL_ENV=production:umd babel dist/esm --out-dir dist/umd --plugins transform-es2015-modules-umd", - "clean": "rimraf dist" + "clean": "rimraf dist", + "develop": "yarn build:babel:esm --skip-initial-build --watch --verbose" }, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0-beta.48", diff --git a/packages/patternfly-4/react-table/package.json b/packages/patternfly-4/react-table/package.json index 1f647474e37..c69894c37cd 100644 --- a/packages/patternfly-4/react-table/package.json +++ b/packages/patternfly-4/react-table/package.json @@ -44,7 +44,8 @@ "build:babel": "concurrently 'yarn build:babel:cjs' 'yarn build:babel:esm'", "build:babel:cjs": "cross-env BABEL_ENV=production:cjs babel src --out-dir dist/js", "build:babel:esm": "cross-env BABEL_ENV=production:esm babel src --out-dir dist/esm", - "clean": "rimraf dist" + "clean": "rimraf dist", + "develop": "yarn build:babel:esm --skip-initial-build --watch --verbose" }, "devDependencies": { "@patternfly/react-tokens": "^2.3.4", diff --git a/packages/patternfly-4/react-tokens/package.json b/packages/patternfly-4/react-tokens/package.json index 701daa22c34..7da53141a62 100644 --- a/packages/patternfly-4/react-tokens/package.json +++ b/packages/patternfly-4/react-tokens/package.json @@ -25,7 +25,7 @@ }, "homepage": "https://github.com/patternfly/patternfly-react#readme", "scripts": { - "build": "node build/generateTokens.js && yarn build:babel:umd", + "build": "node src/generateTokens.js && yarn build:babel:umd", "build:babel:umd": "cross-env BABEL_ENV=production:umd babel dist/esm --out-dir dist/umd --plugins transform-es2015-modules-umd", "clean": "rimraf dist" }, diff --git a/packages/patternfly-4/react-tokens/build/__snapshots__/generateTokens.test.js.snap b/packages/patternfly-4/react-tokens/src/__snapshots__/generateTokens.test.js.snap similarity index 100% rename from packages/patternfly-4/react-tokens/build/__snapshots__/generateTokens.test.js.snap rename to packages/patternfly-4/react-tokens/src/__snapshots__/generateTokens.test.js.snap diff --git a/packages/patternfly-4/react-tokens/build/generateTokens.js b/packages/patternfly-4/react-tokens/src/generateTokens.js similarity index 100% rename from packages/patternfly-4/react-tokens/build/generateTokens.js rename to packages/patternfly-4/react-tokens/src/generateTokens.js diff --git a/packages/patternfly-4/react-tokens/build/generateTokens.test.js b/packages/patternfly-4/react-tokens/src/generateTokens.test.js similarity index 100% rename from packages/patternfly-4/react-tokens/build/generateTokens.test.js rename to packages/patternfly-4/react-tokens/src/generateTokens.test.js diff --git a/packages/patternfly-4/react-tokens/build/templates/cjs.js b/packages/patternfly-4/react-tokens/src/templates/cjs.js similarity index 100% rename from packages/patternfly-4/react-tokens/build/templates/cjs.js rename to packages/patternfly-4/react-tokens/src/templates/cjs.js diff --git a/packages/patternfly-4/react-tokens/build/templates/d.ts.js b/packages/patternfly-4/react-tokens/src/templates/d.ts.js similarity index 100% rename from packages/patternfly-4/react-tokens/build/templates/d.ts.js rename to packages/patternfly-4/react-tokens/src/templates/d.ts.js diff --git a/packages/patternfly-4/react-tokens/build/templates/esm.js b/packages/patternfly-4/react-tokens/src/templates/esm.js similarity index 100% rename from packages/patternfly-4/react-tokens/build/templates/esm.js rename to packages/patternfly-4/react-tokens/src/templates/esm.js diff --git a/scripts/incrementalBuild.js b/scripts/incrementalBuild.js new file mode 100644 index 00000000000..7525b10a77c --- /dev/null +++ b/scripts/incrementalBuild.js @@ -0,0 +1,72 @@ +const fs = require('fs'); +const { hashElement } = require("folder-hash"); +const Project = require('@lerna/project'); +const RunCommand = require('@lerna/run') + +// Load cache +const cacheFile = '.cache/incrementalCache' +let cache = {} +if (fs.existsSync(cacheFile)) { + cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8')); +} + +// Package filtering +const isPf3 = process.argv.length > 2 && process.argv[2] === 'pf3'; +const isPf4 = process.argv.length > 2 && process.argv[2] === 'pf4'; + +const commonPackages = [ + '@patternfly/react-icons' +]; +// Assume src directory gets made into dist +const getDir = (packageName) => { + switch(packageName) { + case '@patternfly/react-icons': + return 'build' + default: + return 'src' + } +}; + +// These are packages we need to rebuild +async function getInvalidPackages() { + const packages = (await new Project(__dirname).getPackages()) + .filter(p => p.scripts.build) // Only packages that have a build target + .filter(p => isPf3 + ? p.location.indexOf('patternfly-3') !== -1 || commonPackages.indexOf(p.name) !== -1 + : true) // Based off argv + .filter(p => isPf4 + ? p.location.indexOf('patternfly-4') !== -1 || commonPackages.indexOf(p.name) !== -1 + : true) // Based off argv + + for (let p of packages) { + const watchDir = getDir(p.name); + p.hash = (await hashElement(`${p.location}/${watchDir}`)).hash; + p.valid = cache && cache[p.name] === p.hash; + if (p.valid) { + console.info('Skipping', p.name, '(already built).'); + } + } + + return packages.filter(p => !p.valid); +} + +async function incrementalBuild() { + const packages = await getInvalidPackages(); + + if (packages.length > 0) { + // Run for all invalid packages + await RunCommand({ + cwd: '.', + script: 'build', + npmClient: 'yarn', + scope: packages.map(p => p.name)}); + // Mark as valid + packages.forEach(p => cache[p.name] = p.hash); + if (!fs.existsSync('.cache')) { + fs.mkdirSync('.cache'); + } + fs.writeFileSync(cacheFile, JSON.stringify(cache, null, 4)); + } +} + +incrementalBuild().then(); diff --git a/yarn.lock b/yarn.lock index fb2398ef00b..42264cde5a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7832,7 +7832,7 @@ eslint-plugin-node@^6.0.1: semver "^5.4.1" "eslint-plugin-patternfly-react@file:packages/eslint-plugin-patternfly-react": - version "0.2.2" + version "0.2.3" dependencies: babel-eslint "^9.0.0" eslint-config-airbnb "^16.1.0" @@ -8784,6 +8784,15 @@ focus-trap@^3.0.0: tabbable "^3.1.0" xtend "^4.0.1" +folder-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/folder-hash/-/folder-hash-3.0.0.tgz#ba9489e74044f63a943d74a3be5e10eb0d03b0ab" + integrity sha512-wyAJJO+h09XC7ZUM47RZIefAZlpTmdxidp98aoSd/BapfjFIx3Z7bJOO3cPy/WNep5WtX7vjBJhdTPKhFfRKMQ== + dependencies: + debug "^4.1.1" + graceful-fs "~4.1.11" + minimatch "~3.0.4" + follow-redirects@^1.0.0: version "1.7.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" @@ -9668,7 +9677,7 @@ got@^8.3.2: url-parse-lax "^3.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@~4.1.11: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" @@ -13128,7 +13137,7 @@ minimatch@3.0.3: dependencies: brace-expansion "^1.0.0" -minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2, minimatch@~3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: