mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-16 18:43:42 +08:00
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:
parent
d2f8ca7215
commit
0f8689b42a
32
README.md
32
README.md
@ -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
|
||||
|
||||
|
@ -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.
|
@ -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,
|
||||
|
@ -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).
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
@ -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;
|
@ -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({
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user