Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow GIT_USER env var to be unset if SSH is used #5840

Merged
merged 17 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/create-docusaurus/templates/facebook/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ This command generates static content into the `build` directory and can be serv

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
$ 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.
Expand Down
10 changes: 9 additions & 1 deletion packages/create-docusaurus/templates/shared/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ This command generates static content into the `build` directory and can be serv

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
$ 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.

This file was deleted.

62 changes: 62 additions & 0 deletions packages/docusaurus/src/commands/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
@@ -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);
});
});
50 changes: 0 additions & 50 deletions packages/docusaurus/src/commands/buildRemoteBranchUrl.ts

This file was deleted.

113 changes: 83 additions & 30 deletions packages/docusaurus/src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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> = {},
Expand All @@ -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 ||
Expand Down Expand Up @@ -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 &&
Expand All @@ -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}`;
let remoteBranch: string;
if (useSSH) {
remoteBranch = buildSshUrl(
githubHost,
organizationName,
projectName,
githubPort,
);
} else {
const gitPass = process.env.GIT_PASS;
const gitCredentials = gitPass ? `${gitUser!}:${gitPass}` : gitUser!;
remoteBranch = buildHttpsUrl(
gitCredentials,
githubHost,
organizationName,
projectName,
githubPort,
);
}

const useSSH = process.env.USE_SSH;
const remoteBranch = buildUrl(
githubHost,
githubPort,
gitCredentials,
organizationName,
projectName,
useSSH !== undefined && useSSH.toLowerCase() === 'true',
);

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!',
);
}
Expand Down
Loading