Skip to content

feat(github): support usage of gh-token for deployment from external env #3121

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

Merged
merged 1 commit into from
Jan 12, 2017
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
78 changes: 53 additions & 25 deletions packages/angular-cli/commands/github-pages-deploy.run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,20 @@ export default function githubPagesDeployRun(options: GithubPagesDeployOptions,

function createGitHubRepoIfNeeded() {
return execPromise('git remote -v')
.then(function (stdout) {
if (!/origin\s+(https:\/\/|git@)github\.com/m.test(stdout)) {
return createGithubRepoTask.run(createGithubRepoOptions)
.then(() => {
// only push starting branch if it's not the destinationBranch
// this happens commonly when using github user pages, since
// they require the destination branch to be 'master'
if (destinationBranch !== initialBranch) {
execPromise(`git push -u origin ${initialBranch}`);
}
});
}
});
.then(function(stdout) {
if (!/origin\s+(https:\/\/|git@)github\.com/m.test(stdout)) {
return createGithubRepoTask.run(createGithubRepoOptions)
.then(() => generateRemoteUrl())
.then((upstream: string) => {
// only push starting branch if it's not the destinationBranch
// this happens commonly when using github user pages, since
// they require the destination branch to be 'master'
if (destinationBranch !== initialBranch) {
execPromise(`git push -u ${upstream} ${initialBranch}`);
}
});
}
});
}

function checkoutGhPages() {
Expand Down Expand Up @@ -191,30 +192,57 @@ export default function githubPagesDeployRun(options: GithubPagesDeployOptions,
}

function pushToGitRepo() {
return execPromise(`git push origin ${ghPagesBranch}:${destinationBranch}`)
.catch((err) => returnStartingBranch()
.catch(() => Promise.reject(err)));
return generateRemoteUrl()
.then(upstream => {
return execPromise(`git push ${upstream} ${ghPagesBranch}:${destinationBranch}`);
})
.catch((err) => returnStartingBranch()
.catch(() => Promise.reject(err) ));
}

function printProjectUrl() {
return execPromise('git remote -v')
.then((stdout) => {
let match = stdout.match(/origin\s+(?:https:\/\/|git@)github\.com(?:\:|\/)([^\/]+)/m);
let userName = match[1].toLowerCase();
let url = `https://${userName}.github.io/${options.userPage ? '' : (baseHref + '/')}`;
ui.writeLine(chalk.green(`Deployed! Visit ${url}`));
ui.writeLine('Github pages might take a few minutes to show the deployed site.');
});
return getUsernameFromGitOrigin()
.then((userName) => {
let url = `https://${userName}.github.io/${options.userPage ? '' : (baseHref + '/')}`;
ui.writeLine(chalk.green(`Deployed! Visit ${url}`));
ui.writeLine('Github pages might take a few minutes to show the deployed site.');
});
}

function failGracefully(error: Error) {
if (error && (/git clean/.test(error.message) || /Permission denied/.test(error.message))) {
ui.writeLine(error.message);
let msg = 'There was a permissions error during git file operations, ' +
'please close any open project files/folders and try again.';
'please close any open project files/folders and try again.';
msg += `\nYou might also need to return to the ${initialBranch} branch manually.`;
return Promise.reject(new SilentError(msg.concat(branchErrMsg)));
} else {
return Promise.reject(error);
}
}

function generateRemoteUrl(): Promise<String> {
if (createGithubRepoOptions.ghToken && createGithubRepoOptions.ghUsername) {
return Promise.resolve(`https://${createGithubRepoOptions.ghToken}@github.com/` +
`${createGithubRepoOptions.ghUsername}/${createGithubRepoOptions.projectName}.git`);
}

if (createGithubRepoOptions.ghToken && !createGithubRepoOptions.ghUsername) {
return getUsernameFromGitOrigin()
.then(username => {
return Promise.resolve(`https://${createGithubRepoOptions.ghToken}@github.com/` +
`${username}/${createGithubRepoOptions.projectName}.git`);
});
}

return Promise.resolve('origin');
}

function getUsernameFromGitOrigin(): Promise<String> {
return execPromise('git remote -v')
.then((stdout) => {
let match = stdout.match(/origin\s+(?:https:\/\/|git@)github\.com(?:\:|\/)([^\/]+)/m);
return match[1].toLowerCase();
});
}
}
114 changes: 57 additions & 57 deletions packages/angular-cli/commands/github-pages-deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,71 @@ const Command = require('../ember-cli/lib/models/command');
import { oneLine } from 'common-tags';

export interface GithubPagesDeployOptions {
message?: string;
target?: string;
environment?: string;
userPage?: boolean;
skipBuild?: boolean;
ghToken?: string;
ghUsername?: string;
baseHref?: string;
message?: string;
target?: string;
environment?: string;
userPage?: boolean;
skipBuild?: boolean;
ghToken?: string;
ghUsername?: string;
baseHref?: string;
}

const githubPagesDeployCommand = Command.extend({
name: 'github-pages:deploy',
aliases: ['gh-pages:deploy'],
description: oneLine`
name: 'github-pages:deploy',
aliases: ['gh-pages:deploy'],
description: oneLine`
Build the test app for production, commit it into a git branch,
setup GitHub repo and push to it
`,
works: 'insideProject',
works: 'insideProject',

availableOptions: [
{
name: 'message',
type: String,
default: 'new gh-pages version',
description: 'The commit message to include with the build, must be wrapped in quotes.'
}, {
name: 'target',
type: String,
default: 'production',
aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }]
}, {
name: 'environment',
type: String,
default: '',
aliases: ['e']
}, {
name: 'user-page',
type: Boolean,
default: false,
description: 'Deploy as a user/org page'
}, {
name: 'skip-build',
type: Boolean,
default: false,
description: 'Skip building the project before deploying'
}, {
name: 'gh-token',
type: String,
default: '',
description: 'Github token'
}, {
name: 'gh-username',
type: String,
default: '',
description: 'Github username'
}, {
name: 'base-href',
type: String,
default: null,
aliases: ['bh']
}],
availableOptions: [
{
name: 'message',
type: String,
default: 'new gh-pages version',
description: 'The commit message to include with the build, must be wrapped in quotes.'
}, {
name: 'target',
type: String,
default: 'production',
aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }]
}, {
name: 'environment',
type: String,
default: '',
aliases: ['e']
}, {
name: 'user-page',
type: Boolean,
default: false,
description: 'Deploy as a user/org page'
}, {
name: 'skip-build',
type: Boolean,
default: false,
description: 'Skip building the project before deploying'
}, {
name: 'gh-token',
type: String,
default: '',
description: 'Github token'
}, {
name: 'gh-username',
type: String,
default: '',
description: 'Github username'
}, {
name: 'base-href',
type: String,
default: null,
aliases: ['bh']
}],

run: function(options: GithubPagesDeployOptions, rawArgs: string[]) {
return require('./github-pages-deploy.run').default.call(this, options, rawArgs);
}
run: function(options: GithubPagesDeployOptions, rawArgs: string[]) {
return require('./github-pages-deploy.run').default.call(this, options, rawArgs);
}
});


Expand Down
42 changes: 40 additions & 2 deletions tests/acceptance/github-pages-deploy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,44 @@ describe('Acceptance: ng github-pages:deploy', function() {
return ng(['github-pages:deploy', '--skip-build']);
});

it('should deploy with token and username', function () {
let token = 'token',
username = 'bar';

execStub.addExecSuccess('git status --porcelain')
.addExecSuccess('git rev-parse --abbrev-ref HEAD', initialBranch)
.addExecSuccess('git remote -v', remote)
.addExecSuccess(`git checkout ${ghPagesBranch}`)
.addExecSuccess('git ls-files')
.addExecSuccess('git rm -r ')
.addExecSuccess('git add .')
.addExecSuccess(`git commit -m "${message}"`)
.addExecSuccess(`git checkout ${initialBranch}`)
.addExecSuccess(`git push https://${token}@github.com/${username}/${project}.git ${ghPagesBranch}:${ghPagesBranch}`)
.addExecSuccess('git remote -v', remote);

return ng(['github-pages:deploy', '--skip-build', `--gh-token=${token}`, `--gh-username=${username}`]);
})

it('should deploy with token only', function () {
let token = 'token';

execStub.addExecSuccess('git status --porcelain')
.addExecSuccess('git rev-parse --abbrev-ref HEAD', initialBranch)
.addExecSuccess('git remote -v', remote)
.addExecSuccess(`git checkout ${ghPagesBranch}`)
.addExecSuccess('git ls-files')
.addExecSuccess('git rm -r ')
.addExecSuccess('git add .')
.addExecSuccess(`git commit -m "${message}"`)
.addExecSuccess(`git checkout ${initialBranch}`)
.addExecSuccess('git remote -v', remote)
.addExecSuccess(`git push https://${token}@github.com/username/${project}.git ${ghPagesBranch}:${ghPagesBranch}`)
.addExecSuccess('git remote -v', remote);

return ng(['github-pages:deploy', '--skip-build', `--gh-token=${token}`]);
});

it('should deploy with changed defaults', function() {
let userPageBranch = 'master',
message = 'not new gh-pages version';
Expand Down Expand Up @@ -126,14 +164,14 @@ describe('Acceptance: ng github-pages:deploy', function() {
.addExecSuccess('git rev-parse --abbrev-ref HEAD', initialBranch)
.addExecSuccess('git remote -v', noRemote)
.addExecSuccess(`git remote add origin [email protected]:${username}/${project}.git`)
.addExecSuccess(`git push -u origin ${initialBranch}`)
.addExecSuccess(`git push -u https://${token}@github.com/${username}/${project}.git ${initialBranch}`)
.addExecSuccess(`git checkout ${ghPagesBranch}`)
.addExecSuccess('git ls-files')
.addExecSuccess('git rm -r ')
.addExecSuccess('git add .')
.addExecSuccess(`git commit -m "${message}"`)
.addExecSuccess(`git checkout ${initialBranch}`)
.addExecSuccess(`git push origin ${ghPagesBranch}:${ghPagesBranch}`)
.addExecSuccess(`git push https://${token}@github.com/${username}/${project}.git ${ghPagesBranch}:${ghPagesBranch}`)
.addExecSuccess('git remote -v', remote);

var httpsStub = sinon.stub(https, 'request', httpsRequestStubFunc);
Expand Down