-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
/
Copy pathdeploy.ts
200 lines (176 loc) · 6.64 KB
/
deploy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import path from 'path';
import shell from 'shelljs';
import {CONFIG_FILE_NAME, GENERATED_FILES_DIR_NAME} from '../constants';
import {loadContext} from '../server';
import loadConfig from '../server/config';
import build from './build';
import {BuildCLIOptions} from '@docusaurus/types';
export default async function deploy(
siteDir: string,
cliOptions: Partial<BuildCLIOptions> = {},
): Promise<void> {
const {outDir} = loadContext(siteDir, cliOptions.outDir);
const tempDir = path.join(siteDir, GENERATED_FILES_DIR_NAME);
console.log('Deploy command invoked ...');
if (!shell.which('git')) {
throw new Error('Git not installed or on the PATH!');
}
const gitUser = process.env.GIT_USER;
if (!gitUser) {
throw new Error('Please set the GIT_USER environment variable!');
}
// 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 ${CONFIG_FILE_NAME}? 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 ${CONFIG_FILE_NAME}? 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 =
process.env.DEPLOYMENT_BRANCH || 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 && useSSH.toLowerCase() === 'true'
? `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(
`You cannot deploy from this branch (${currentBranch}).` +
'\nYou will need to checkout to a different branch!',
);
}
// 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();
const runDeploy = (outputDirectory) => {
if (shell.cd(tempDir).code !== 0) {
throw new Error(
`Temp dir ${GENERATED_FILES_DIR_NAME} does not exists. Run build website first.`,
);
}
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 = outputDirectory;
const toPath = path.join(
GENERATED_FILES_DIR_NAME,
`${projectName}-${deploymentBranch}`,
);
fs.copy(fromPath, toPath, (error) => {
if (error) {
throw new Error(
`Error: Copying build assets failed with error '${error}'`,
);
}
shell.cd(toPath);
shell.exec('git add --all');
const commitMessage =
process.env.CUSTOM_COMMIT_MESSAGE ||
`Deploy website - based on ${currentCommit}`;
const commitResults = shell.exec(`git commit -m "${commitMessage}"`);
if (
shell.exec(`git push --force 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.
let websiteURL = '';
if (githubHost === 'github.com') {
websiteURL = projectName.includes('.github.io')
? `https://${organizationName}.github.io/`
: `https://${organizationName}.github.io/${projectName}/`;
} else {
// GitHub enterprise hosting.
websiteURL = `https://${githubHost}/pages/${organizationName}/${projectName}/`;
}
shell.echo(`Website is live at ${websiteURL}`);
shell.exit(0);
}
});
};
if (!cliOptions.skipBuild) {
// Clear Docusaurus 2 cache dir for deploy consistency.
fs.removeSync(tempDir);
// Build static html files, then push to deploymentBranch branch of specified repo.
build(siteDir, cliOptions, false)
.then(runDeploy)
.catch((buildError) => {
console.error(buildError);
process.exit(1);
});
} else {
// Push current build to deploymentBranch branch of specified repo.
runDeploy(outDir);
}
}