diff --git a/packages/angular-cli/commands/github-pages-deploy.run.ts b/packages/angular-cli/commands/github-pages-deploy.run.ts index 6173d6f2c2dc..305e473e02dd 100644 --- a/packages/angular-cli/commands/github-pages-deploy.run.ts +++ b/packages/angular-cli/commands/github-pages-deploy.run.ts @@ -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() { @@ -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 { + 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 { + return execPromise('git remote -v') + .then((stdout) => { + let match = stdout.match(/origin\s+(?:https:\/\/|git@)github\.com(?:\:|\/)([^\/]+)/m); + return match[1].toLowerCase(); + }); + } } diff --git a/packages/angular-cli/commands/github-pages-deploy.ts b/packages/angular-cli/commands/github-pages-deploy.ts index de8ff0e5c6c5..8acab427c701 100644 --- a/packages/angular-cli/commands/github-pages-deploy.ts +++ b/packages/angular-cli/commands/github-pages-deploy.ts @@ -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); + } }); diff --git a/tests/acceptance/github-pages-deploy.spec.js b/tests/acceptance/github-pages-deploy.spec.js index 3f8d0d851de6..34c270d421a9 100644 --- a/tests/acceptance/github-pages-deploy.spec.js +++ b/tests/acceptance/github-pages-deploy.spec.js @@ -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'; @@ -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 git@github.com:${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);