mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
feat: add deploy (formerly publish-gh-pages) command (#979)
This commit is contained in:
parent
9b6ec5b9bb
commit
604f02edeb
6 changed files with 218 additions and 2 deletions
|
@ -4,7 +4,7 @@ const chalk = require('chalk');
|
||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const program = require('commander');
|
const program = require('commander');
|
||||||
const {build, eject, init, start} = require('../lib');
|
const {build, eject, init, deploy, start} = require('../lib');
|
||||||
const requiredVersion = require('../package.json').engines.node;
|
const requiredVersion = require('../package.json').engines.node;
|
||||||
|
|
||||||
if (!semver.satisfies(process.version, requiredVersion)) {
|
if (!semver.satisfies(process.version, requiredVersion)) {
|
||||||
|
@ -56,6 +56,13 @@ program
|
||||||
wrapCommand(init)(path.resolve(projectDir));
|
wrapCommand(init)(path.resolve(projectDir));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('deploy [siteDir]')
|
||||||
|
.description('deploy website')
|
||||||
|
.action((siteDir = '.') => {
|
||||||
|
wrapCommand(deploy)(path.resolve(siteDir));
|
||||||
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('start [siteDir]')
|
.command('start [siteDir]')
|
||||||
.description('Start development server')
|
.description('Start development server')
|
||||||
|
|
175
v2/lib/commands/deploy.js
Normal file
175
v2/lib/commands/deploy.js
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
const path = require('path');
|
||||||
|
const shell = require('shelljs');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const build = require('./build');
|
||||||
|
const loadConfig = require('../load/config');
|
||||||
|
|
||||||
|
module.exports = async function deploy(siteDir) {
|
||||||
|
console.log('Deploy command invoked ...');
|
||||||
|
if (!shell.which('git')) {
|
||||||
|
throw new Error('Sorry, this script requires git');
|
||||||
|
}
|
||||||
|
|
||||||
|
const gitUser = process.env.GIT_USER;
|
||||||
|
if (!gitUser) {
|
||||||
|
throw new Error(`Please set the GIT_USER`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The branch that contains the latest docs changes that will be deployed
|
||||||
|
const currentBranch =
|
||||||
|
process.env.CURRENT_BRANCH ||
|
||||||
|
shell.exec('git rev-parse --abbrev-ref HEAD').stdout.trim();
|
||||||
|
|
||||||
|
const siteConfig = loadConfig(siteDir);
|
||||||
|
const organizationName =
|
||||||
|
process.env.ORGANIZATION_NAME ||
|
||||||
|
process.env.CIRCLE_PROJECT_USERNAME ||
|
||||||
|
siteConfig.organizationName;
|
||||||
|
if (!organizationName) {
|
||||||
|
throw new Error(
|
||||||
|
"Missing project organization name. Did you forget to define 'organizationName' in siteConfig.js? You may also export it via the organizationName environment variable.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const projectName =
|
||||||
|
process.env.PROJECT_NAME ||
|
||||||
|
process.env.CIRCLE_PROJECT_REPONAME ||
|
||||||
|
siteConfig.projectName;
|
||||||
|
if (!projectName) {
|
||||||
|
throw new Error(
|
||||||
|
"Missing project name. Did you forget to define 'projectName' in siteConfig.js? You may also export it via the projectName environment variable.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We never deploy on pull request
|
||||||
|
const isPullRequest =
|
||||||
|
process.env.CI_PULL_REQUEST || process.env.CIRCLE_PULL_REQUEST;
|
||||||
|
if (isPullRequest) {
|
||||||
|
shell.echo('Skipping deploy on a pull request');
|
||||||
|
shell.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// github.io indicates organization repos that deploy via master. All others use gh-pages.
|
||||||
|
const deploymentBranch =
|
||||||
|
projectName.indexOf('.github.io') !== -1 ? 'master' : 'gh-pages';
|
||||||
|
const githubHost =
|
||||||
|
process.env.GITHUB_HOST || siteConfig.githubHost || 'github.com';
|
||||||
|
|
||||||
|
const useSSH = process.env.USE_SSH;
|
||||||
|
const remoteBranch = useSSH
|
||||||
|
? `git@${githubHost}:${organizationName}/${projectName}.git`
|
||||||
|
: `https://${gitUser}@${githubHost}/${organizationName}/${projectName}.git`;
|
||||||
|
|
||||||
|
// Check if this is a cross-repo publish
|
||||||
|
const currentRepoUrl = shell
|
||||||
|
.exec('git config --get remote.origin.url')
|
||||||
|
.stdout.trim();
|
||||||
|
const crossRepoPublish = !currentRepoUrl.endsWith(
|
||||||
|
`${organizationName}/${projectName}.git`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// We don't allow deploying to the same branch unless it's a cross publish
|
||||||
|
if (currentBranch === deploymentBranch && !crossRepoPublish) {
|
||||||
|
throw new Error(
|
||||||
|
`Cannot deploy from a ${deploymentBranch} branch. Only to it`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the commit hash that triggers publish-gh-pages before checking out to deployment branch
|
||||||
|
const currentCommit = shell.exec('git rev-parse HEAD').stdout.trim();
|
||||||
|
|
||||||
|
// build static html files, then push to deploymentBranch branch of specified repo
|
||||||
|
build(siteDir)
|
||||||
|
.then(() => {
|
||||||
|
shell.cd(siteDir);
|
||||||
|
shell.cd('build');
|
||||||
|
|
||||||
|
if (
|
||||||
|
shell.exec(
|
||||||
|
`git clone ${remoteBranch} ${projectName}-${deploymentBranch}`,
|
||||||
|
).code !== 0
|
||||||
|
) {
|
||||||
|
throw new Error('Error: git clone failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
shell.cd(`${projectName}-${deploymentBranch}`);
|
||||||
|
|
||||||
|
// If the default branch is the one we're deploying to, then we'll fail to create it.
|
||||||
|
// This is the case of a cross-repo publish, where we clone a github.io repo with a default master branch.
|
||||||
|
const defaultBranch = shell
|
||||||
|
.exec('git rev-parse --abbrev-ref HEAD')
|
||||||
|
.stdout.trim();
|
||||||
|
if (defaultBranch !== deploymentBranch) {
|
||||||
|
if (shell.exec(`git checkout origin/${deploymentBranch}`).code !== 0) {
|
||||||
|
if (
|
||||||
|
shell.exec(`git checkout --orphan ${deploymentBranch}`).code !== 0
|
||||||
|
) {
|
||||||
|
throw new Error(`Error: Git checkout ${deploymentBranch} failed`);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
shell.exec(`git checkout -b ${deploymentBranch}`).code +
|
||||||
|
shell.exec(
|
||||||
|
`git branch --set-upstream-to=origin/${deploymentBranch}`,
|
||||||
|
).code !==
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
throw new Error(`Error: Git checkout ${deploymentBranch} failed`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shell.exec('git rm -rf .');
|
||||||
|
|
||||||
|
shell.cd('../..');
|
||||||
|
|
||||||
|
const fromPath = path.join('build');
|
||||||
|
const toPath = path.join('build', `${projectName}-${deploymentBranch}}`);
|
||||||
|
// In github.io case, project is deployed to root. Need to not recursively
|
||||||
|
// copy the deployment-branch to be.
|
||||||
|
const excludePath = `${projectName}-${deploymentBranch}`;
|
||||||
|
|
||||||
|
// cannot use shell.cp because it doesn't support copying dotfiles and we
|
||||||
|
// need to copy directories like .circleci, for example
|
||||||
|
// https://github.com/shelljs/shelljs/issues/79
|
||||||
|
fs.copy(
|
||||||
|
fromPath,
|
||||||
|
toPath,
|
||||||
|
src => {
|
||||||
|
if (src.indexOf('.DS_Store') !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (src.indexOf(excludePath) !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
if (error) {
|
||||||
|
throw new Error(
|
||||||
|
`Error: Copying build assets failed with error '${error}'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
shell.cd(path.join('build', `${projectName}-${deploymentBranch}`));
|
||||||
|
shell.exec('git add --all');
|
||||||
|
|
||||||
|
const commitResults = shell.exec(
|
||||||
|
`git commit -m "Deploy website" -m "Deploy website version based on ${currentCommit}"`,
|
||||||
|
);
|
||||||
|
if (shell.exec(`git push origin ${deploymentBranch}`).code !== 0) {
|
||||||
|
throw new Error('Error: Git push failed');
|
||||||
|
} else if (commitResults.code === 0) {
|
||||||
|
// The commit might return a non-zero value when site is up to date.
|
||||||
|
const websiteURL =
|
||||||
|
githubHost === 'github.com'
|
||||||
|
? `https://${organizationName}.github.io/${projectName}` // gh-pages hosted repo
|
||||||
|
: `https://${githubHost}/pages/${organizationName}/${projectName}`; // GitHub enterprise hosting.
|
||||||
|
shell.echo(`Website is live at: ${websiteURL}`);
|
||||||
|
shell.exit(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(buildError => {
|
||||||
|
console.error(buildError);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
};
|
|
@ -2,10 +2,12 @@ const build = require('./commands/build');
|
||||||
const init = require('./commands/init');
|
const init = require('./commands/init');
|
||||||
const start = require('./commands/start');
|
const start = require('./commands/start');
|
||||||
const eject = require('./commands/eject');
|
const eject = require('./commands/eject');
|
||||||
|
const deploy = require('./commands/deploy');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
build,
|
build,
|
||||||
eject,
|
eject,
|
||||||
init,
|
init,
|
||||||
start,
|
start,
|
||||||
|
deploy,
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@ module.exports = function loadConfig(siteDir, deleteCache = true) {
|
||||||
'chainWebpack',
|
'chainWebpack',
|
||||||
'docsUrl',
|
'docsUrl',
|
||||||
'customFields',
|
'customFields',
|
||||||
|
'githubHost',
|
||||||
];
|
];
|
||||||
const missingFields = requiredFields.filter(field => !config[field]);
|
const missingFields = requiredFields.filter(field => !config[field]);
|
||||||
if (missingFields && missingFields.length > 0) {
|
if (missingFields && missingFields.length > 0) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"start": "node bin/docusaurus start website",
|
"start": "node bin/docusaurus start website",
|
||||||
"build": "node bin/docusaurus build website",
|
"build": "node bin/docusaurus build website",
|
||||||
"eject": "node bin/docusaurus eject website",
|
"eject": "node bin/docusaurus eject website",
|
||||||
|
"deploy": "node bin/docusaurus deploy website",
|
||||||
"lint": "eslint --cache \"lib/**/*.js\" \"bin/**/*.js\" \"test/**/*.js\"",
|
"lint": "eslint --cache \"lib/**/*.js\" \"bin/**/*.js\" \"test/**/*.js\"",
|
||||||
"test": "jest --config test/jest.config.js"
|
"test": "jest --config test/jest.config.js"
|
||||||
},
|
},
|
||||||
|
@ -78,6 +79,7 @@
|
||||||
"react-youtube": "^7.6.0",
|
"react-youtube": "^7.6.0",
|
||||||
"remarkable": "^1.7.1",
|
"remarkable": "^1.7.1",
|
||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
|
"shelljs": "^0.8.2",
|
||||||
"static-site-generator-webpack-plugin": "endiliey/static-site-generator-webpack-plugin#master",
|
"static-site-generator-webpack-plugin": "endiliey/static-site-generator-webpack-plugin#master",
|
||||||
"style-loader": "^0.22.1",
|
"style-loader": "^0.22.1",
|
||||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||||
|
|
31
v2/yarn.lock
31
v2/yarn.lock
|
@ -2901,6 +2901,17 @@ glob-to-regexp@^0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
||||||
|
|
||||||
|
glob@^7.0.0:
|
||||||
|
version "7.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
|
glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
|
||||||
version "7.1.2"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||||
|
@ -3321,6 +3332,10 @@ inquirer@3.3.0, inquirer@^3.0.6:
|
||||||
strip-ansi "^4.0.0"
|
strip-ansi "^4.0.0"
|
||||||
through "^2.3.6"
|
through "^2.3.6"
|
||||||
|
|
||||||
|
interpret@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
|
||||||
|
|
||||||
invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
|
invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
|
||||||
version "2.2.4"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||||
|
@ -5719,6 +5734,12 @@ realpath-native@^1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
util.promisify "^1.0.0"
|
util.promisify "^1.0.0"
|
||||||
|
|
||||||
|
rechoir@^0.6.2:
|
||||||
|
version "0.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||||
|
dependencies:
|
||||||
|
resolve "^1.1.6"
|
||||||
|
|
||||||
recursive-readdir@2.2.1:
|
recursive-readdir@2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
|
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
|
||||||
|
@ -5949,7 +5970,7 @@ resolve@1.1.7:
|
||||||
version "1.1.7"
|
version "1.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||||
|
|
||||||
resolve@^1.5.0, resolve@^1.6.0:
|
resolve@^1.1.6, resolve@^1.5.0, resolve@^1.6.0:
|
||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6133,6 +6154,14 @@ shell-quote@1.6.1:
|
||||||
array-reduce "~0.0.0"
|
array-reduce "~0.0.0"
|
||||||
jsonify "~0.0.0"
|
jsonify "~0.0.0"
|
||||||
|
|
||||||
|
shelljs@^0.8.2:
|
||||||
|
version "0.8.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35"
|
||||||
|
dependencies:
|
||||||
|
glob "^7.0.0"
|
||||||
|
interpret "^1.0.0"
|
||||||
|
rechoir "^0.6.2"
|
||||||
|
|
||||||
shellwords@^0.1.1:
|
shellwords@^0.1.1:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue