UNPKG

6.19 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3/**
4 * Copyright (c) 2017-present, Facebook, Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
8 */
9
10const fs = require('fs-extra');
11const path = require('path');
12const shell = require('shelljs');
13
14if (!shell.which('git')) {
15 shell.echo('Sorry, this script requires git');
16 shell.exit(1);
17}
18
19const siteConfig = require(`${process.cwd()}/siteConfig.js`);
20const GIT_USER = process.env.GIT_USER;
21const CURRENT_BRANCH =
22 process.env.CIRCLE_BRANCH ||
23 shell.exec('git rev-parse --abbrev-ref HEAD').stdout.trim();
24const ORGANIZATION_NAME =
25 process.env.ORGANIZATION_NAME ||
26 process.env.CIRCLE_PROJECT_USERNAME ||
27 siteConfig.organizationName;
28const PROJECT_NAME =
29 process.env.PROJECT_NAME ||
30 process.env.CIRCLE_PROJECT_REPONAME ||
31 siteConfig.projectName;
32const IS_PULL_REQUEST =
33 process.env.CI_PULL_REQUEST || process.env.CIRCLE_PULL_REQUEST;
34const USE_SSH = process.env.USE_SSH;
35// github.io indicates organization repos that deploy via master. All others use gh-pages.
36const DEPLOYMENT_BRANCH =
37 PROJECT_NAME.indexOf('.github.io') !== -1 ? 'master' : 'gh-pages';
38const GITHUB_DOMAIN = 'github.com';
39// For GitHub enterprise, allow specifying a different host.
40const GITHUB_HOST =
41 process.env.GITHUB_HOST || siteConfig.githubHost || GITHUB_DOMAIN;
42const CUSTOM_COMMIT_MESSAGE = process.env.CUSTOM_COMMIT_MESSAGE;
43
44if (!ORGANIZATION_NAME) {
45 shell.echo(
46 "Missing project organization name. Did you forget to define 'organizationName' in siteConfig.js? You may also export it via the ORGANIZATION_NAME environment variable.",
47 );
48 shell.exit(0);
49}
50
51if (!PROJECT_NAME) {
52 shell.echo(
53 "Missing project name. Did you forget to define 'projectName' in siteConfig.js? You may also export it via the PROJECT_NAME environment variable.",
54 );
55 shell.exit(0);
56}
57
58if (USE_SSH !== 'true' && !GIT_USER) {
59 shell.echo(
60 "Missing git user. Did you forget to export the 'GIT_USER' environment variable?",
61 );
62 shell.exit(0);
63}
64
65let remoteBranch;
66if (USE_SSH === 'true') {
67 remoteBranch = `git@${GITHUB_HOST}:${ORGANIZATION_NAME}/${PROJECT_NAME}.git`;
68} else {
69 remoteBranch = `https://${GIT_USER}@${GITHUB_HOST}/${ORGANIZATION_NAME}/${PROJECT_NAME}.git`;
70}
71
72if (IS_PULL_REQUEST) {
73 shell.echo('Skipping deploy on a pull request');
74 shell.exit(0);
75}
76
77// When we want to do a cross repo publish (#717), we can allow publishing to the same branch.
78const currentRepoUrl = shell
79 .exec('git config --get remote.origin.url')
80 .stdout.trim();
81const crossRepoPublish = !currentRepoUrl.endsWith(
82 `${ORGANIZATION_NAME}/${PROJECT_NAME}.git`,
83);
84
85// build static html files, then push to DEPLOYMENT_BRANCH branch of specified repo
86
87if (CURRENT_BRANCH === DEPLOYMENT_BRANCH && !crossRepoPublish) {
88 shell.echo(`Cannot deploy from a ${DEPLOYMENT_BRANCH} branch. Only to it`);
89 shell.exit(1);
90}
91
92if (
93 shell.exec(
94 `node ${path.join(__dirname, 'build-files.js')} ${process.argv
95 .slice(2)
96 .join(' ')}`,
97 ).code
98) {
99 shell.echo('Error: generating html failed');
100 shell.exit(1);
101}
102
103// Save the commit hash that triggers publish-gh-pages before checking out to deployment branch
104const currentCommit = shell.exec('git rev-parse HEAD').stdout.trim();
105
106shell.cd(process.cwd());
107shell.cd('build');
108
109if (
110 shell.exec(`git clone ${remoteBranch} ${PROJECT_NAME}-${DEPLOYMENT_BRANCH}`)
111 .code !== 0
112) {
113 shell.echo('Error: git clone failed');
114 shell.exit(1);
115}
116
117shell.cd(`${PROJECT_NAME}-${DEPLOYMENT_BRANCH}`);
118
119// If the default branch is the one we're deploying to, then we'll fail to create it.
120// This is the case of a cross-repo publish, where we clone a github.io repo with a default master branch.
121const defaultBranch = shell
122 .exec('git rev-parse --abbrev-ref HEAD')
123 .stdout.trim();
124if (defaultBranch !== DEPLOYMENT_BRANCH) {
125 if (shell.exec(`git checkout origin/${DEPLOYMENT_BRANCH}`).code !== 0) {
126 if (shell.exec(`git checkout --orphan ${DEPLOYMENT_BRANCH}`).code !== 0) {
127 shell.echo(`Error: Git checkout ${DEPLOYMENT_BRANCH} failed`);
128 shell.exit(1);
129 }
130 } else if (
131 shell.exec(`git checkout -b ${DEPLOYMENT_BRANCH}`).code +
132 shell.exec(`git branch --set-upstream-to=origin/${DEPLOYMENT_BRANCH}`)
133 .code !==
134 0
135 ) {
136 shell.echo(`Error: Git checkout ${DEPLOYMENT_BRANCH} failed`);
137 shell.exit(1);
138 }
139}
140
141shell.exec('git rm -rf .');
142
143shell.cd('../..');
144
145const fromPath = path.join('build', `${PROJECT_NAME}`);
146const toPath = path.join('build', `${PROJECT_NAME}-${DEPLOYMENT_BRANCH}`);
147// In github.io case, project is deployed to root. Need to not recursively
148// copy the deployment-branch to be.
149const excludePath = `${PROJECT_NAME}-${DEPLOYMENT_BRANCH}`;
150
151// cannot use shell.cp because it doesn't support copying dotfiles and we
152// need to copy directories like .circleci, for example
153// https://github.com/shelljs/shelljs/issues/79
154fs.copy(
155 fromPath,
156 toPath,
157 src => {
158 if (src.indexOf('.DS_Store') !== -1) {
159 return false;
160 }
161 if (src.indexOf(excludePath) !== -1) {
162 return false;
163 }
164
165 return true;
166 },
167 error => {
168 if (error) {
169 shell.echo(`Error: Copying build assets failed with error '${error}'`);
170 shell.exit(1);
171 }
172
173 shell.cd(path.join('build', `${PROJECT_NAME}-${DEPLOYMENT_BRANCH}`));
174 shell.exec('git add --all');
175
176 const commitMessage = CUSTOM_COMMIT_MESSAGE || 'Deploy website';
177 const commitResults = shell.exec(
178 `git commit -m "${commitMessage}" -m "Deploy website version based on ${currentCommit}"`,
179 );
180 if (shell.exec(`git push origin ${DEPLOYMENT_BRANCH}`).code !== 0) {
181 shell.echo('Error: Git push failed');
182 shell.exit(1);
183 } else if (commitResults.code === 0) {
184 // The commit might return a non-zero value when site is up to date.
185 const websiteURL =
186 GITHUB_HOST === GITHUB_DOMAIN
187 ? `https://${ORGANIZATION_NAME}.github.io/${PROJECT_NAME}` // gh-pages hosted repo
188 : `https://${GITHUB_HOST}/pages/${ORGANIZATION_NAME}/${PROJECT_NAME}`; // GitHub enterprise hosting.
189 shell.echo(`Website is live at: ${websiteURL}`);
190 shell.exit(0);
191 }
192 },
193);