diff --git a/package.json b/package.json index e7bd58fab..c30fa2b6d 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "eslint-plugin-react": "^6.9.0", "file-loader": "^0.10.0", "front-matter": "^2.1.2", - "git-repository": "^0.1.4", "glob": "^7.1.1", "json-loader": "^0.5.4", "lint-staged": "^3.3.0", @@ -217,7 +216,7 @@ "copy": "babel-node tools/run copy", "bundle": "babel-node tools/run bundle", "build": "babel-node tools/run build", - "deploy": "babel-node tools/run deployToAzureWebApps", + "deploy": "babel-node tools/run deploy", "render": "babel-node tools/run render", "serve": "babel-node tools/run runServer", "start": "babel-node tools/run start" diff --git a/tools/deploy.js b/tools/deploy.js new file mode 100644 index 000000000..5c609ced1 --- /dev/null +++ b/tools/deploy.js @@ -0,0 +1,86 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import path from 'path'; +import fetch from 'node-fetch'; +import { spawn } from './lib/cp'; +import { makeDir } from './lib/fs'; +import run from './run'; + +// GitHub Pages +const remote = { + name: 'github', + url: 'https://github.com//.git', + branch: 'gh-pages', + website: 'https://.github.io//', + static: true, +}; + +// Azure Web Apps +// const remote = { +// name: 'azure', +// url: 'https://@.scm.azurewebsites.net:443/.git', +// branch: 'master', +// website: `http://.azurewebsites.net`, +// }; + +const options = { + cwd: path.resolve(__dirname, '../build', remote.static ? 'public' : ''), + stdio: ['ignore', 'inherit', 'inherit'], +}; + +/** + * Deploy the contents of the `/build` folder to a remote server via Git. + */ +async function deploy() { + // Initialize a new repository + await makeDir('build/public'); + await spawn('git', ['init', '--quiet'], options); + + // Changing a remote's URL + let isRemoteExists = false; + try { + await spawn('git', ['config', '--get', `remote.${remote.name}.url`], options); + isRemoteExists = true; + } catch (error) { + /* skip */ + } + await spawn('git', ['remote', isRemoteExists ? 'set-url' : 'add', remote.name, remote.url], options); + + // Fetch the remote repository if it exists + let isRefExists = false; + try { + await spawn('git', ['ls-remote', '--exit-code', remote.url, remote.branch], options); + isRefExists = true; + } catch (error) { + /* skip */ + } + if (isRefExists) { + await spawn('git', ['fetch', remote.name], options); + await spawn('git', ['reset', `${remote.name}/${remote.branch}`, '--hard'], options); + await spawn('git', ['clean', '--force'], options); + } + + // Build the project in RELEASE mode which + // generates optimized and minimized bundles + process.argv.push('--release'); + if (remote.static) process.argv.push('--static'); + await run(require('./build').default); + + // Push the contents of the build folder to the remote server via Git + await spawn('git', ['add', '.', '--all'], options); + await spawn('git', ['commit', '--message', `Update ${new Date().toISOString()}`], options); + await spawn('git', ['push', remote.name, `master:${remote.branch}`, '--force', '--set-upstream'], options); + + // Check if the site was successfully deployed + const response = await fetch(remote.website); + console.log(`${remote.website} => ${response.status} ${response.statusText}`); +} + +export default deploy; diff --git a/tools/deployToAzureWebApps.js b/tools/deployToAzureWebApps.js deleted file mode 100644 index c0f2809f8..000000000 --- a/tools/deployToAzureWebApps.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * React Starter Kit (https://www.reactstarterkit.com/) - * - * Copyright © 2014-present Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - -import GitRepo from 'git-repository'; -import fetch from 'node-fetch'; -import run from './run'; - -// For more information visit http://gitolite.com/deploy.html -function getRemote(slot) { - return { - name: slot || 'production', - url: `https://example${slot ? `-${slot}` : ''}.scm.azurewebsites.net:443/example.git`, - branch: 'master', - website: `http://example${slot ? `-${slot}` : ''}.azurewebsites.net`, - }; -} - -/** - * Deploy the contents of the `/build` folder to a remote - * server via Git. Example: `yarn run deploy -- --production` - */ -async function deployToAzureWebApps() { - // By default deploy to the staging deployment slot - const remote = getRemote(process.argv.includes('--production') ? null : 'staging'); - - // Initialize a new Git repository inside the `/build` folder - // if it doesn't exist yet - const repo = await GitRepo.open('build', { init: true }); - await repo.setRemote(remote.name, remote.url); - - // Fetch the remote repository if it exists - const isRefExists = await repo.hasRef(remote.url, remote.branch); - if (isRefExists) { - await repo.fetch(remote.name); - await repo.reset(`${remote.name}/${remote.branch}`, { hard: true }); - await repo.clean({ force: true }); - } - - // Build the project in RELEASE mode which - // generates optimized and minimized bundles - process.argv.push('--release'); - await run(require('./build')); - - // Push the contents of the build folder to the remote server via Git - await repo.add('--all .'); - await repo.commit(`Update ${new Date().toISOString()}`); - await repo.push(remote.name, `master:${remote.branch}`); - - // Check if the site was successfully deployed - const response = await fetch(remote.website); - console.log(`${remote.website} -> ${response.status}`); -} - -export default deployToAzureWebApps; diff --git a/tools/deployToGitHubPages.js b/tools/deployToGitHubPages.js deleted file mode 100644 index 3946dca35..000000000 --- a/tools/deployToGitHubPages.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * React Starter Kit (https://www.reactstarterkit.com/) - * - * Copyright © 2014-present Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - -import GitRepo from 'git-repository'; -import run from './run'; -import build from './build'; - -const remote = { - name: 'github', - url: 'https://github.com/{user}/{repo}.git', - branch: 'gh-pages', -}; - -/** - * Deploy the contents of the `/build/public` folder to GitHub Pages. - */ -async function deployToGitHubPages() { - // Initialize a new Git repository inside the `/build` folder - // if it doesn't exist yet - const repo = await GitRepo.open('build/public', { init: true }); - await repo.setRemote(remote.name, remote.url); - const isRefExists = await repo.hasRef(remote.url, remote.branch); - if (isRefExists) { - await repo.fetch(remote.name); - await repo.reset(`${remote.name}/${remote.branch}`, { hard: true }); - await repo.clean({ force: true }); - } - - // Build the project in RELEASE mode which - // generates optimized and minimized bundles - process.argv.push('--static', '--release'); - await run(build); - - // Push the contents of the build folder to the remote server via Git - await repo.add('--all .'); - await repo.commit(`Update ${new Date().toISOString()}`); - await repo.push(remote.name, `master:${remote.branch}`); -} - -export default deployToGitHubPages; diff --git a/tools/lib/cp.js b/tools/lib/cp.js new file mode 100644 index 000000000..3cce0b7b4 --- /dev/null +++ b/tools/lib/cp.js @@ -0,0 +1,22 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import cp from 'child_process'; + +export const spawn = (command, args, options) => new Promise((resolve, reject) => { + cp.spawn(command, args, options).on('close', (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`${command} ${args.join(' ')} => ${code} (error)`)); + } + }); +}); + +export default { spawn }; diff --git a/tools/lib/fs.js b/tools/lib/fs.js index 410cceeed..ec4971e1a 100644 --- a/tools/lib/fs.js +++ b/tools/lib/fs.js @@ -67,3 +67,13 @@ export const copyDir = async (source, target) => { export const cleanDir = (pattern, options) => new Promise((resolve, reject) => rimraf(pattern, { glob: options }, (err, result) => (err ? reject(err) : resolve(result))), ); + +export default { + readFile, + writeFile, + copyFile, + readDir, + makeDir, + copyDir, + cleanDir, +}; diff --git a/tools/runServer.js b/tools/runServer.js index 17f23505a..132eeb7c3 100644 --- a/tools/runServer.js +++ b/tools/runServer.js @@ -16,7 +16,7 @@ const RUNNING_REGEXP = /The server is running at http:\/\/(.*?)\//; let server; let pending = true; -const { output } = webpackConfig.find(x => x.target === 'node'); +const { output } = webpackConfig.find(x => x.name === 'server'); const serverPath = path.join(output.path, output.filename); // Launch or restart the Node.js server diff --git a/tools/start.js b/tools/start.js index 065b09d05..9a49ab556 100644 --- a/tools/start.js +++ b/tools/start.js @@ -34,7 +34,7 @@ async function start() { await new Promise((resolve) => { // Save the server-side bundle files to the file system after compilation // https://github.com/webpack/webpack-dev-server/issues/62 - webpackConfig.find(x => x.target === 'node').plugins.push( + webpackConfig.find(x => x.name === 'server').plugins.push( new WriteFilePlugin({ log: false }), ); diff --git a/yarn.lock b/yarn.lock index 500e26f10..944ef011f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2949,10 +2949,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -git-repository@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/git-repository/-/git-repository-0.1.4.tgz#678391ab6e0c8b3c24f73762ecebb63c769474ac" - glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -4041,7 +4037,7 @@ lodash.uniq@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.12.0: +lodash@4.12.0, lodash@^4.2.0: version "4.12.0" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.12.0.tgz#2bd6dc46a040f59e686c972ed21d93dc59053258" @@ -4053,7 +4049,7 @@ lodash@^3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1: +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"