mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-05 12:22:45 +02:00
feat: allow GIT_USER env var to be unset if SSH is used (#5840)
* feat: allow GIT_USER env var to be unset if SSH is used * fix: packages/docusaurus/src/commands/deploy.ts Co-authored-by: Joshua Chen <sidachen2003@gmail.com> * feat: allow user to specify deploymentBranch property in docusaurus.config.js (#5841) * feat: allow user to specify deploymentBranch property in docusaurus.config.js * docs: remove extra backtick * docs: fix broken code block * docs: fix i18n routes to feature requests (#5843) * docs: fix i18n routes to feature requests * Add redirect rules * feat: allow GIT_USER env var to be unset if SSH is used * fix: packages/docusaurus/src/commands/deploy.ts Co-authored-by: Joshua Chen <sidachen2003@gmail.com> * fix: avoid escaping hyphen in regex * Refactor * Update deployment.mdx * Make SSH higher priority * Only infer but not override * Add tests * Fix tests * Fix Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
parent
ecce576bbc
commit
f5732e7589
7 changed files with 166 additions and 151 deletions
|
@ -26,8 +26,16 @@ This command generates static content into the `build` directory and can be serv
|
|||
|
||||
### Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
|
||||
$ USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
|
|
|
@ -26,8 +26,16 @@ This command generates static content into the `build` directory and can be serv
|
|||
|
||||
### Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
|
||||
$ USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* 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 {buildUrl} from '../buildRemoteBranchUrl';
|
||||
|
||||
describe('remoteeBranchUrl', () => {
|
||||
test('should build a normal ssh url', async () => {
|
||||
const url = buildUrl(
|
||||
'github.com',
|
||||
undefined,
|
||||
undefined,
|
||||
'facebook',
|
||||
'docusaurus',
|
||||
true,
|
||||
);
|
||||
expect(url).toEqual('git@github.com:facebook/docusaurus.git');
|
||||
});
|
||||
test('should build a ssh url with port', async () => {
|
||||
const url = buildUrl(
|
||||
'github.com',
|
||||
'422',
|
||||
undefined,
|
||||
'facebook',
|
||||
'docusaurus',
|
||||
true,
|
||||
);
|
||||
expect(url).toEqual('ssh://git@github.com:422/facebook/docusaurus.git');
|
||||
});
|
||||
test('should build a normal http url', async () => {
|
||||
const url = buildUrl(
|
||||
'github.com',
|
||||
undefined,
|
||||
'user:pass',
|
||||
'facebook',
|
||||
'docusaurus',
|
||||
false,
|
||||
);
|
||||
expect(url).toEqual('https://user:pass@github.com/facebook/docusaurus.git');
|
||||
});
|
||||
test('should build a normal http url', async () => {
|
||||
const url = buildUrl(
|
||||
'github.com',
|
||||
'5433',
|
||||
'user:pass',
|
||||
'facebook',
|
||||
'docusaurus',
|
||||
false,
|
||||
);
|
||||
expect(url).toEqual(
|
||||
'https://user:pass@github.com:5433/facebook/docusaurus.git',
|
||||
);
|
||||
});
|
||||
});
|
62
packages/docusaurus/src/commands/__tests__/deploy.test.ts
Normal file
62
packages/docusaurus/src/commands/__tests__/deploy.test.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* 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 {buildSshUrl, buildHttpsUrl, hasSSHProtocol} from '../deploy';
|
||||
|
||||
describe('remoteBranchUrl', () => {
|
||||
test('should build a normal ssh url', () => {
|
||||
const url = buildSshUrl('github.com', 'facebook', 'docusaurus');
|
||||
expect(url).toEqual('git@github.com:facebook/docusaurus.git');
|
||||
});
|
||||
test('should build a ssh url with port', () => {
|
||||
const url = buildSshUrl('github.com', 'facebook', 'docusaurus', '422');
|
||||
expect(url).toEqual('ssh://git@github.com:422/facebook/docusaurus.git');
|
||||
});
|
||||
test('should build a normal http url', () => {
|
||||
const url = buildHttpsUrl(
|
||||
'user:pass',
|
||||
'github.com',
|
||||
'facebook',
|
||||
'docusaurus',
|
||||
);
|
||||
expect(url).toEqual('https://user:pass@github.com/facebook/docusaurus.git');
|
||||
});
|
||||
test('should build a normal http url', () => {
|
||||
const url = buildHttpsUrl(
|
||||
'user:pass',
|
||||
'github.com',
|
||||
'facebook',
|
||||
'docusaurus',
|
||||
'5433',
|
||||
);
|
||||
expect(url).toEqual(
|
||||
'https://user:pass@github.com:5433/facebook/docusaurus.git',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasSSHProtocol', () => {
|
||||
test('should recognize explicit SSH protocol', () => {
|
||||
const url = 'ssh://git@github.com:422/facebook/docusaurus.git';
|
||||
expect(hasSSHProtocol(url)).toEqual(true);
|
||||
});
|
||||
|
||||
test('should recognize implied SSH protocol', () => {
|
||||
const url = 'git@github.com:facebook/docusaurus.git';
|
||||
expect(hasSSHProtocol(url)).toEqual(true);
|
||||
});
|
||||
|
||||
test('should not recognize HTTPS with credentials', () => {
|
||||
const url = 'https://user:pass@github.com/facebook/docusaurus.git';
|
||||
expect(hasSSHProtocol(url)).toEqual(false);
|
||||
});
|
||||
|
||||
test('should not recognize plain HTTPS URL', () => {
|
||||
const url = 'https://github.com:5433/facebook/docusaurus.git';
|
||||
expect(hasSSHProtocol(url)).toEqual(false);
|
||||
});
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export function buildUrl(
|
||||
githubHost: string,
|
||||
githubPort: string | undefined,
|
||||
gitCredentials: string | undefined,
|
||||
organizationName: string,
|
||||
projectName: string,
|
||||
useSSH: boolean | undefined,
|
||||
): string {
|
||||
return useSSH
|
||||
? buildSshUrl(githubHost, organizationName, projectName, githubPort)
|
||||
: buildHttpsUrl(
|
||||
gitCredentials,
|
||||
githubHost,
|
||||
organizationName,
|
||||
projectName,
|
||||
githubPort,
|
||||
);
|
||||
}
|
||||
|
||||
function buildSshUrl(
|
||||
githubHost: string,
|
||||
organizationName: string,
|
||||
projectName: string,
|
||||
githubPort: string | undefined,
|
||||
) {
|
||||
if (githubPort) {
|
||||
return `ssh://git@${githubHost}:${githubPort}/${organizationName}/${projectName}.git`;
|
||||
}
|
||||
return `git@${githubHost}:${organizationName}/${projectName}.git`;
|
||||
}
|
||||
|
||||
function buildHttpsUrl(
|
||||
gitCredentials: string | undefined,
|
||||
githubHost: string,
|
||||
organizationName: string,
|
||||
projectName: string,
|
||||
githubPort: string | undefined,
|
||||
) {
|
||||
if (githubPort) {
|
||||
return `https://${gitCredentials}@${githubHost}:${githubPort}/${organizationName}/${projectName}.git`;
|
||||
}
|
||||
return `https://${gitCredentials}@${githubHost}/${organizationName}/${projectName}.git`;
|
||||
}
|
|
@ -13,7 +13,6 @@ import build from './build';
|
|||
import {BuildCLIOptions} from '@docusaurus/types';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import {buildUrl} from './buildRemoteBranchUrl';
|
||||
|
||||
// GIT_PASS env variable should not appear in logs
|
||||
function obfuscateGitPass(str: string) {
|
||||
|
@ -38,6 +37,43 @@ function shellExecLog(cmd: string) {
|
|||
}
|
||||
}
|
||||
|
||||
export function buildSshUrl(
|
||||
githubHost: string,
|
||||
organizationName: string,
|
||||
projectName: string,
|
||||
githubPort?: string,
|
||||
): string {
|
||||
if (githubPort) {
|
||||
return `ssh://git@${githubHost}:${githubPort}/${organizationName}/${projectName}.git`;
|
||||
}
|
||||
return `git@${githubHost}:${organizationName}/${projectName}.git`;
|
||||
}
|
||||
|
||||
export function buildHttpsUrl(
|
||||
gitCredentials: string,
|
||||
githubHost: string,
|
||||
organizationName: string,
|
||||
projectName: string,
|
||||
githubPort?: string,
|
||||
): string {
|
||||
if (githubPort) {
|
||||
return `https://${gitCredentials}@${githubHost}:${githubPort}/${organizationName}/${projectName}.git`;
|
||||
}
|
||||
return `https://${gitCredentials}@${githubHost}/${organizationName}/${projectName}.git`;
|
||||
}
|
||||
|
||||
export function hasSSHProtocol(sourceRepoUrl: string): boolean {
|
||||
try {
|
||||
if (new URL(sourceRepoUrl).protocol === 'ssh:') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
// Fails when there isn't a protocol
|
||||
return /^([\w-]+@)?[\w.-]+:[\w./_-]+(\.git)?/.test(sourceRepoUrl); // git@github.com:facebook/docusaurus.git
|
||||
}
|
||||
}
|
||||
|
||||
export default async function deploy(
|
||||
siteDir: string,
|
||||
cliOptions: Partial<BuildCLIOptions> = {},
|
||||
|
@ -63,15 +99,32 @@ This behavior can have SEO impacts and create relative link issues.
|
|||
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!');
|
||||
}
|
||||
// Source repo is the repo from where the command is invoked
|
||||
const sourceRepoUrl = shell
|
||||
.exec('git config --get remote.origin.url', {silent: true})
|
||||
.stdout.trim();
|
||||
|
||||
// The branch that contains the latest docs changes that will be deployed.
|
||||
const currentBranch =
|
||||
// The source branch; defaults to the currently checked out branch
|
||||
const sourceBranch =
|
||||
process.env.CURRENT_BRANCH ||
|
||||
shell.exec('git rev-parse --abbrev-ref HEAD').stdout.trim();
|
||||
shell.exec('git rev-parse --abbrev-ref HEAD', {silent: true}).stdout.trim();
|
||||
|
||||
const gitUser = process.env.GIT_USER;
|
||||
|
||||
let useSSH =
|
||||
process.env.USE_SSH !== undefined &&
|
||||
process.env.USE_SSH.toLowerCase() === 'true';
|
||||
|
||||
if (!gitUser && !useSSH) {
|
||||
// If USE_SSH is unspecified: try inferring from repo URL
|
||||
if (process.env.USE_SSH === undefined && hasSSHProtocol(sourceRepoUrl)) {
|
||||
useSSH = true;
|
||||
} else {
|
||||
throw new Error(
|
||||
'Please set the GIT_USER environment variable, or explicitly specify USE_SSH instead!',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const organizationName =
|
||||
process.env.ORGANIZATION_NAME ||
|
||||
|
@ -107,8 +160,7 @@ This behavior can have SEO impacts and create relative link issues.
|
|||
// Organization deploys looks like:
|
||||
// - Git repo: https://github.com/<organization>/<organization>.github.io
|
||||
// - Site url: https://<organization>.github.io
|
||||
const isGitHubPagesOrganizationDeploy =
|
||||
projectName.indexOf('.github.io') !== -1;
|
||||
const isGitHubPagesOrganizationDeploy = projectName.includes('.github.io');
|
||||
if (
|
||||
isGitHubPagesOrganizationDeploy &&
|
||||
!process.env.DEPLOYMENT_BRANCH &&
|
||||
|
@ -127,38 +179,39 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
|
|||
process.env.GITHUB_HOST || siteConfig.githubHost || 'github.com';
|
||||
const githubPort = process.env.GITHUB_PORT || siteConfig.githubPort;
|
||||
|
||||
const gitPass: string | undefined = process.env.GIT_PASS;
|
||||
let gitCredentials = `${gitUser}`;
|
||||
if (gitPass) {
|
||||
gitCredentials = `${gitCredentials}:${gitPass}`;
|
||||
}
|
||||
|
||||
const useSSH = process.env.USE_SSH;
|
||||
const remoteBranch = buildUrl(
|
||||
let remoteBranch: string;
|
||||
if (useSSH) {
|
||||
remoteBranch = buildSshUrl(
|
||||
githubHost,
|
||||
githubPort,
|
||||
gitCredentials,
|
||||
organizationName,
|
||||
projectName,
|
||||
useSSH !== undefined && useSSH.toLowerCase() === 'true',
|
||||
githubPort,
|
||||
);
|
||||
} else {
|
||||
const gitPass = process.env.GIT_PASS;
|
||||
const gitCredentials = gitPass ? `${gitUser!}:${gitPass}` : gitUser!;
|
||||
remoteBranch = buildHttpsUrl(
|
||||
gitCredentials,
|
||||
githubHost,
|
||||
organizationName,
|
||||
projectName,
|
||||
githubPort,
|
||||
);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`${chalk.cyan('Remote branch:')} ${obfuscateGitPass(remoteBranch)}`,
|
||||
);
|
||||
|
||||
// Check if this is a cross-repo publish.
|
||||
const currentRepoUrl = shell
|
||||
.exec('git config --get remote.origin.url')
|
||||
.stdout.trim();
|
||||
const crossRepoPublish = !currentRepoUrl.endsWith(
|
||||
const crossRepoPublish = !sourceRepoUrl.endsWith(
|
||||
`${organizationName}/${projectName}.git`,
|
||||
);
|
||||
|
||||
// We don't allow deploying to the same branch unless it's a cross publish.
|
||||
if (currentBranch === deploymentBranch && !crossRepoPublish) {
|
||||
if (sourceBranch === deploymentBranch && !crossRepoPublish) {
|
||||
throw new Error(
|
||||
`You cannot deploy from this branch (${currentBranch}).` +
|
||||
`You cannot deploy from this branch (${sourceBranch}).` +
|
||||
'\nYou will need to checkout to a different branch!',
|
||||
);
|
||||
}
|
||||
|
|
|
@ -138,19 +138,12 @@ By default, GitHub Pages runs published files through [Jekyll](https://jekyllrb.
|
|||
|
||||
### Environment settings {#environment-settings}
|
||||
|
||||
Specify the Git user as an environment variable.
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| `GIT_USER` | The username for a GitHub account that **has push access to the deployment repo**. For your own repositories, this will usually be your GitHub username. |
|
||||
|
||||
Optional parameters, also set as environment variables:
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| `USE_SSH` | Set to `true` to use SSH instead of the default HTTPS for the connection to the GitHub repo. |
|
||||
| `USE_SSH` | Set to `true` to use SSH instead of the default HTTPS for the connection to the GitHub repo. If the source repo URL is an SSH URL (e.g. `git@github.com:facebook/docusaurus.git`), `USE_SSH` is inferred to be `true`. |
|
||||
| `GIT_USER` | The username for a GitHub account that **has push access to the deployment repo**. For your own repositories, this will usually be your GitHub username. Required if not using SSH, and ignored otherwise. |
|
||||
| `GIT_PASS` | Personal access token of the git user (specified by `GIT_USER`), to facilitate non-interactive deployment (e.g. continuous deployment) |
|
||||
| `CURRENT_BRANCH` | The source branch. Usually, the branch will be `main` or `master`, but it could be any branch except for `gh-pages`. If nothing is set for this variable, then the current branch from which `docusaurus deploy` is invoked will be used. |
|
||||
| `GIT_PASS` | Personal access token of the `git` user (specified by `GIT_USER`), to facilitate non-interactive deployment (e.g. continuous deployment) |
|
||||
|
||||
GitHub enterprise installations should work in the same manner as github.com; you only need to set the organization's GitHub Enterprise host as an environment variable:
|
||||
|
||||
|
@ -362,7 +355,6 @@ jobs:
|
|||
- name: Deploy to GitHub Pages
|
||||
env:
|
||||
USE_SSH: true
|
||||
GIT_USER: git
|
||||
run: |
|
||||
git config --global user.email "actions@github.com"
|
||||
git config --global user.name "gh-actions"
|
||||
|
@ -492,7 +484,6 @@ trigger:
|
|||
- yarn deploy
|
||||
environment:
|
||||
USE_SSH: true
|
||||
GIT_USER: $DRONE_COMMIT_AUTHOR
|
||||
GITHUB_PRIVATE_KEY:
|
||||
from_secret: git_deploy_private_key
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue