refactor(@angular/cli): removed the github pages deploy command (#4385)

BREAKING CHANGE: This command is being removed from the core of the CLI
There are several options for deploying CLI-based applications outside the scope of this project.
One of which being https://github.com/angular-buch/angular-cli-ghpages
This functionality is likely to return in the form of an addon/plugin in the future
This commit is contained in:
Mike Brocchi 2017-02-03 00:08:00 -05:00 committed by Hans
parent d2f8ca7215
commit 0f8689b42a
9 changed files with 1 additions and 808 deletions

View File

@ -45,7 +45,6 @@ with NPM 3 or higher.
* [Running Unit Tests](#running-unit-tests)
* [Running End-to-End Tests](#running-end-to-end-tests)
* [Proxy To Backend](#proxy-to-backend)
* [Deploying the App via GitHub Pages](#deploying-the-app-via-github-pages)
* [Linting code](#linting-code)
* [Commands autocompletion](#commands-autocompletion)
* [Project assets](#project-assets)
@ -237,37 +236,6 @@ and then we edit the `package.json` file's start script to be
now run it with `npm start`
### Deploying the app via GitHub Pages
You can deploy your apps quickly via:
```bash
ng github-pages:deploy --message "Optional commit message"
```
This will do the following:
- creates GitHub repo for the current project if one doesn't exist
- rebuilds the app in production mode at the current `HEAD`
- creates a local `gh-pages` branch if one doesn't exist
- moves your app to the `gh-pages` branch and creates a commit
- edit the base tag in index.html to support GitHub Pages
- pushes the `gh-pages` branch to GitHub
- returns back to the original `HEAD`
Creating the repo requires a token from GitHub, and the remaining functionality
relies on ssh authentication for all git operations that communicate with github.com.
To simplify the authentication, be sure to [setup your ssh keys](https://help.github.com/articles/generating-ssh-keys/).
If you are deploying a [user or organization page](https://help.github.com/articles/user-organization-and-project-pages/), you can instead use the following command:
```bash
ng github-pages:deploy --user-page --message "Optional commit message"
```
This command pushes the app to the `master` branch on the GitHub repo instead
of pushing to `gh-pages`, since user and organization pages require this.
### Linting code

View File

@ -1,30 +0,0 @@
# Deploying the app via GitHub Pages
You can deploy your apps quickly via:
```bash
ng github-pages:deploy --message "Optional commit message"
```
This will do the following:
- creates GitHub repo for the current project if one doesn't exist
- rebuilds the app in production mode at the current `HEAD`
- creates a local `gh-pages` branch if one doesn't exist
- moves your app to the `gh-pages` branch and creates a commit
- edit the base tag in index.html to support GitHub Pages
- pushes the `gh-pages` branch to GitHub
- returns back to the original `HEAD`
Creating the repo requires a token from GitHub, and the remaining functionality
relies on ssh authentication for all git operations that communicate with github.com.
To simplify the authentication, be sure to [setup your ssh keys](https://help.github.com/articles/generating-ssh-keys/).
If you are deploying a [user or organization page](https://help.github.com/articles/user-organization-and-project-pages/), you can instead use the following command:
```bash
ng github-pages:deploy --user-page --message "Optional commit message"
```
This command pushes the app to the `master` branch on the GitHub repo instead
of pushing to `gh-pages`, since user and organization pages require this.

View File

@ -32,7 +32,6 @@ module.exports = {
'version': require('../commands/version').default,
'completion': require('../commands/completion').default,
'doc': require('../commands/doc').default,
'github-pages-deploy': require('../commands/github-pages-deploy').default,
// Easter eggs.
'make-this-awesome': require('../commands/easter-egg').default,

View File

@ -22,10 +22,6 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
Before running the tests make sure you are serving the app via `ng serve`.
## Deploying to GitHub Pages
Run `ng github-pages:deploy` to deploy to GitHub Pages.
## Further help
To get more help on the `angular-cli` use `ng help` or go check out the [Angular-CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@ -1,272 +0,0 @@
const SilentError = require('silent-error');
import denodeify = require('denodeify');
import { exec } from 'child_process';
import * as chalk from 'chalk';
import * as fs from 'fs';
import * as fse from 'fs-extra';
import * as path from 'path';
import Build from '../tasks/build';
import CreateGithubRepo from '../tasks/create-github-repo';
import { CliConfig } from '../models/config';
import { GithubPagesDeployOptions } from './github-pages-deploy';
const fsReadDir = <any>denodeify(fs.readdir);
const fsCopy = <any>denodeify(fse.copy);
const fsWriteFile = <any>denodeify(fse.writeFile);
export default function githubPagesDeployRun(options: GithubPagesDeployOptions, rawArgs: string[]) {
const ui = this.ui;
const root = this.project.root;
const execOptions = {
cwd: root
};
if (options.environment === '') {
if (options.target === 'development') {
options.environment = 'dev';
}
if (options.target === 'production') {
options.environment = 'prod';
}
}
const projectName = this.project.pkg.name;
const outDir = CliConfig.fromProject().config.apps[0].outDir;
const indexFilename = CliConfig.fromProject().config.apps[0].index;
let ghPagesBranch = 'gh-pages';
let destinationBranch = options.userPage ? 'master' : ghPagesBranch;
let initialBranch: string;
let branchErrMsg = ' You might also need to return to the initial branch manually.';
// declared here so that tests can stub exec
const execPromise = <(cmd: string, options?: any) => Promise<string>>denodeify(exec);
const buildTask = new Build({
ui: this.ui,
cliProject: this.project,
target: options.target,
environment: options.environment,
outputPath: outDir
});
/**
* BaseHref tag setting logic:
* First, no value if --custom-domain is provided.
* Second, use --base-href flag value if provided.
* Else if --user-page is true, then keep baseHref default as declared in index.html.
* Otherwise auto-replace with `/${projectName}/`.
*/
let baseHref: String = null;
if (!options.customDomain) {
baseHref = options.baseHref || (options.userPage ? null : `/${projectName}/`);
}
const buildOptions = {
target: options.target,
environment: options.environment,
outputPath: outDir,
baseHref: baseHref,
aot: options.aot,
vendorChunk: options.vendorChunk,
};
const createGithubRepoTask = new CreateGithubRepo({
ui: this.ui,
project: this.project
});
const createGithubRepoOptions = {
projectName,
ghUsername: options.ghUsername,
ghToken: options.ghToken
};
return checkForPendingChanges()
.then(build)
.then(saveStartingBranchName)
.then(createGitHubRepoIfNeeded)
.then(checkoutGhPages)
.then(cleanGhPagesBranch)
.then(copyFiles)
.then(createNotFoundPage)
.then(createCustomDomainFile)
.then(addAndCommit)
.then(returnStartingBranch)
.then(pushToGitRepo)
.then(printProjectUrl)
.catch(failGracefully);
function checkForPendingChanges() {
return execPromise('git status --porcelain')
.then((stdout: string) => {
if (/\w+/m.test(stdout)) {
let msg = 'Uncommitted file changes found! Please commit all changes before deploying.';
return Promise.reject(new SilentError(msg));
}
});
}
function build() {
if (options.skipBuild) { return Promise.resolve(); }
return buildTask.run(buildOptions);
}
function saveStartingBranchName() {
return execPromise('git rev-parse --abbrev-ref HEAD')
.then((stdout: string) => initialBranch = stdout.replace(/\s/g, ''));
}
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(() => 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() {
return execPromise(`git checkout ${ghPagesBranch}`)
.catch(createGhPagesBranch);
}
function createGhPagesBranch() {
return execPromise(`git checkout --orphan ${ghPagesBranch}`)
.then(() => execPromise('git rm --cached -r .', execOptions))
.then(() => execPromise('git add .gitignore', execOptions))
.then(() => execPromise('git clean -f -d', execOptions))
.then(() => execPromise(`git commit -m \"initial ${ghPagesBranch} commit\"`));
}
function cleanGhPagesBranch() {
return execPromise('git ls-files')
.then(function (stdout) {
let files = '';
stdout.split(/\n/).forEach(function (f) {
// skip .gitignore & 404.html
if ((f != '') && (f != '.gitignore') && (f != '404.html')) {
files = files.concat(`"${f}" `);
}
});
return execPromise(`git rm -r ${files}`)
.catch(() => {
// Ignoring errors when trying to erase files.
});
});
}
function copyFiles() {
return fsReadDir(outDir)
.then((files: string[]) => Promise.all(files.map((file) => {
if (file === '.gitignore') {
// don't overwrite the .gitignore file
return Promise.resolve();
}
return fsCopy(path.join(outDir, file), path.join('.', file));
})));
}
function createNotFoundPage() {
const indexHtml = path.join(root, indexFilename);
const notFoundPage = path.join(root, '404.html');
return fsCopy(indexHtml, notFoundPage);
}
function createCustomDomainFile() {
if (!options.customDomain) {
return;
}
const cnameFile = path.join(root, 'CNAME');
return fsWriteFile(cnameFile, options.customDomain);
}
function addAndCommit() {
return execPromise('git add .', execOptions)
.then(() => execPromise(`git commit -m "${options.message}"`))
.catch(() => {
let msg = 'No changes found. Deployment skipped.';
return returnStartingBranch()
.then(() => Promise.reject(new SilentError(msg)))
.catch(() => Promise.reject(new SilentError(msg.concat(branchErrMsg))));
});
}
function returnStartingBranch() {
return execPromise(`git checkout ${initialBranch}`);
}
function pushToGitRepo() {
return generateRemoteUrl()
.then(upstream => {
return execPromise(`git push ${upstream} ${ghPagesBranch}:${destinationBranch}`);
})
.catch((err) => returnStartingBranch()
.catch(() => Promise.reject(err) ));
}
function printProjectUrl() {
return getUsernameFromGitOrigin()
.then((userName) => {
let url = '';
if (options.customDomain) {
url = `http://${options.customDomain}/`;
} else {
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.';
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();
});
}
}

View File

@ -1,90 +0,0 @@
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;
customDomain?: string;
aot?: boolean;
vendorChunk?: boolean;
}
const GithubPagesDeployCommand = Command.extend({
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',
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']
}, {
name: 'custom-domain',
type: String,
default: null,
aliases: ['cd'],
description: 'Custom domain for Github Pages'
}, {
name: 'aot',
type: Boolean,
default: false,
}, {
name: 'vendor-chunk',
type: Boolean,
default: false,
}],
run: function(options: GithubPagesDeployOptions, rawArgs: string[]) {
return require('./github-pages-deploy.run').default.call(this, options, rawArgs);
}
});
export default GithubPagesDeployCommand;

View File

@ -7,8 +7,7 @@ const lookupCommand = require('../ember-cli/lib/cli/lookup-command');
const commandsToIgnore = [
'easter-egg',
'destroy',
'github-pages-deploy' // errors because there is no base github-pages command
'destroy'
];
const HelpCommand = Command.extend({

View File

@ -1,92 +0,0 @@
import * as denodeify from 'denodeify';
const Task = require('../ember-cli/lib/models/task');
const SilentError = require('silent-error');
import { exec } from 'child_process';
import * as https from 'https';
import { oneLine } from 'common-tags';
export default Task.extend({
run: function(commandOptions: any) {
const ui = this.ui;
let promise: Promise<any>;
// declared here so that tests can stub exec
const execPromise = denodeify(exec);
if (/.+/.test(commandOptions.ghToken) && /\w+/.test(commandOptions.ghUsername)) {
promise = Promise.resolve({
ghToken: commandOptions.ghToken,
ghUsername: commandOptions.ghUsername
});
} else {
ui.writeLine();
ui.writeLine(oneLine`
In order to deploy this project via GitHub Pages, we must first create a repository for it.
`);
ui.writeLine(oneLine`
It\'s safer to use a token than to use a password so you will need to create one
`);
ui.writeLine('Go to the following page and click "Generate new token".');
ui.writeLine('https://github.com/settings/tokens\n');
ui.writeLine('Choose "public_repo" as scope and then click "Generate token".\n');
promise = ui.prompt([
{
name: 'ghToken',
type: 'input',
message: oneLine`
Please enter GitHub token you just created
(used only once to create the repo):
`,
validate: function(token: string) {
return /.+/.test(token);
}
}, {
name: 'ghUsername',
type: 'input',
message: 'and your GitHub user name:',
validate: function(userName: string) {
return /\w+/.test(userName);
}
}]);
}
return promise
.then((answers) => {
return new Promise(function(resolve, reject) {
const postData = JSON.stringify({
'name': commandOptions.projectName
});
const req = https.request({
hostname: 'api.github.com',
port: 443,
path: '/user/repos',
method: 'POST',
headers: {
'Authorization': `token ${answers.ghToken}`,
'Content-Type': 'application/json',
'Content-Length': postData.length,
'User-Agent': 'angular-cli-github-pages'
}
});
req.on('response', function(response: any) {
if (response.statusCode === 201) {
resolve(execPromise(oneLine`
git remote add origin
git@github.com:${answers.ghUsername}/${commandOptions.projectName}.git
`));
} else {
reject(new SilentError(oneLine`
Failed to create GitHub repo. Error: ${response.statusCode} ${response.statusMessage}
`));
}
});
req.write(postData);
req.end();
});
});
}
});

View File

@ -1,285 +0,0 @@
/*eslint-disable no-console */
'use strict';
var ng = require('../helpers/ng');
var tmp = require('../helpers/tmp');
var Promise = require('@angular/cli/ember-cli/lib/ext/promise');
var fs = require('fs');
var path = require('path');
var chai = require('chai');
var sinon = require('sinon');
var ExecStub = require('../helpers/exec-stub');
var https = require('https');
var SilentError = require('silent-error');
const expect = chai.expect;
const fsWriteFile = Promise.denodeify(fs.writeFile);
const fsMkdir = Promise.denodeify(fs.mkdir);
describe('Acceptance: ng github-pages:deploy', function() {
let execStub;
let project = 'foo',
initialBranch = 'master',
ghPagesBranch = 'gh-pages',
message = 'new gh-pages version',
remote = 'origin git@github.com:username/project.git (fetch)';
function setupDist() {
return fsMkdir('./dist')
.then(() => {
let indexHtml = path.join(process.cwd(), 'dist', 'index.html');
let indexData = `<title>project</title>\n<base href="/">`;
return fsWriteFile(indexHtml, indexData, 'utf8');
});
}
beforeEach(function() {
this.timeout(10000);
return tmp.setup('./tmp')
.then(() => process.chdir('./tmp'))
.then(() => ng(['new', project, '--skip-npm']))
.then(() => setupDist())
.finally(() => execStub = new ExecStub());
});
afterEach(function() {
this.timeout(10000);
return tmp.teardown('./tmp')
.then(() => expect(execStub.hasFailed()).to.be.false)
.then(() => expect(execStub.hasEmptyStack()).to.be.true)
.finally(() => execStub.restore());
});
it('should fail with uncommited changes', function() {
this.timeout(10000);
execStub.addExecSuccess('git status --porcelain', 'M dir/file.ext');
return ng(['github-pages:deploy', '--skip-build'])
.then(() => {
throw new SilentError('Should fail with uncommited changes but passing.');
}, (ret) => {
expect(ret.name).to.equal('SilentError');
expect(ret.isSilentError).to.equal(true);
});
});
it('should deploy with defaults to existing remote', function () {
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 origin ${ghPagesBranch}:${ghPagesBranch}`)
.addExecSuccess('git remote -v', remote);
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';
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 origin ${ghPagesBranch}:${userPageBranch}`)
.addExecSuccess('git remote -v', remote);
return ng(['github-pages:deploy', '--skip-build', `--message=${message}`, '--user-page']);
});
it('should create branch if needed', function() {
execStub.addExecSuccess('git status --porcelain')
.addExecSuccess('git rev-parse --abbrev-ref HEAD', initialBranch)
.addExecSuccess('git remote -v', remote)
.addExecError(`git checkout ${ghPagesBranch}`)
.addExecSuccess(`git checkout --orphan ${ghPagesBranch}`)
.addExecSuccess('git rm --cached -r .')
.addExecSuccess('git add .gitignore')
.addExecSuccess('git clean -f -d')
.addExecSuccess(`git commit -m \"initial ${ghPagesBranch} commit\"`)
.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 remote -v', remote);
return ng(['github-pages:deploy', '--skip-build']);
});
it('should create repo if needed', function() {
let noRemote = '',
token = 'token',
username = 'username';
execStub.addExecSuccess('git status --porcelain')
.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 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 https://${token}@github.com/${username}/${project}.git ${ghPagesBranch}:${ghPagesBranch}`)
.addExecSuccess('git remote -v', remote);
var httpsStub = sinon.stub(https, 'request', httpsRequestStubFunc);
function httpsRequestStubFunc(req) {
let responseCb;
let expectedPostData = JSON.stringify({
'name': project
});
let expectedReq = {
hostname: 'api.github.com',
port: 443,
path: '/user/repos',
method: 'POST',
headers: {
'Authorization': `token ${token}`,
'Content-Type': 'application/json',
'Content-Length': expectedPostData.length,
'User-Agent': 'angular-cli-github-pages'
}
}
expect(req).to.eql(expectedReq);
return {
on: (event, cb) => responseCb = cb,
write: (postData) => expect(postData).to.eql(expectedPostData),
end: () => responseCb({ statusCode: 201 })
}
}
return ng(['github-pages:deploy', '--skip-build', `--gh-token=${token}`,
`--gh-username=${username}`])
.then(() => httpsStub.restore());
});
it('should stop deploy if create branch fails', function() {
let noRemote = '',
token = 'token',
username = 'username';
execStub.addExecSuccess('git status --porcelain')
.addExecSuccess('git rev-parse --abbrev-ref HEAD', initialBranch)
.addExecSuccess('git remote -v', noRemote);
var httpsStub = sinon.stub(https, 'request', httpsRequestStubFunc);
function httpsRequestStubFunc(req) {
let responseCb;
let expectedPostData = JSON.stringify({
'name': project
});
let expectedReq = {
hostname: 'api.github.com',
port: 443,
path: '/user/repos',
method: 'POST',
headers: {
'Authorization': `token ${token}`,
'Content-Type': 'application/json',
'Content-Length': expectedPostData.length,
'User-Agent': 'angular-cli-github-pages'
}
}
expect(req).to.eql(expectedReq);
return {
on: (event, cb) => responseCb = cb,
write: (postData) => expect(postData).to.eql(expectedPostData),
end: () => responseCb({ statusCode: 401, statusMessage: 'Unauthorized' })
}
}
return ng(['github-pages:deploy', '--skip-build', `--gh-token=${token}`,
`--gh-username=${username}`])
.then(() => {
throw new SilentError('Should not pass the deploy.');
}, (ret) => {
expect(ret.name).to.equal('SilentError');
expect(ret.isSilentError).to.equal(true);
})
.then(() => httpsStub.restore());
});
it('should fail gracefully when checkout has permissions failure', function() {
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}"`)
.addExecError(`git checkout ${initialBranch}`, 'error: cannot stat \'src/client\': Permission denied');
return ng(['github-pages:deploy', '--skip-build'])
.then(() => {
throw new SilentError('Should not pass the deploy.');
}, (ret) => {
expect(ret.name).to.equal('SilentError');
expect(ret.isSilentError).to.equal(true);
expect(ret.message).to.contain('There was a permissions error');
});
});
});