Skip to content

Commit

Permalink
Master deployment to root (#4)
Browse files Browse the repository at this point in the history
* Deploy to root on master branch

* Add default branch value of master

* Bump version to v1.0.0-beta.1
  • Loading branch information
oliverviljamaa authored Dec 1, 2019
1 parent 4b37048 commit c4dabcf
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 81 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# v1.0.0-beta.1
## Deploy to root on `master` branch

- when branch is `master`, the directory won't be deployed to `/branch/${branchName}`, but `/` instead, allowing consumers to only rely on this package and not need `gh-pages` in addition
- default `branch` value of `master` is added

# v0.2.8
## Fix deployment id error

Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
[![CircleCI](https://img.shields.io/circleci/project/github/oliverviljamaa/deploy-directory-on-branch-to-gh-pages/beta.svg)](https://circleci.com/gh/oliverviljamaa/deploy-directory-on-branch-to-gh-pages)
[![npm](https://img.shields.io/npm/l/deploy-directory-on-branch-to-gh-pages.svg)](https://github.com/oliverviljamaa/deploy-directory-on-branch-to-gh-pages/blob/beta/LICENSE)

A Node and CLI tool that makes deploying a directory on a branch to GitHub pages easy and automatic,
to help your peers QA your built docs/demos easily for better feedback.
A Node and CLI tool that makes deploying to GitHub pages **by branch** easy and automatic, best used as part of a CI process.

On `master`, your directory will be deployed to your GitHub page root similarly to other libraries, such as the wonderful [`gh-pages`](https://www.npmjs.com/package/gh-pages).
On other branches, it'll be deployed under `/branch/${branchName}`, allowing your peers to QA your built docs/demos easily for better feedback.

It also sends a status to a Pull request, if one exists:

Expand Down Expand Up @@ -42,7 +44,7 @@ deploy(options).catch(err => { console.log(err); })
| `token` | -t | [GitHub token](https://github.com/settings/tokens) | | `GITHUB_TOKEN` | * | * |
| `owner` | -o | GitHub repo owner/org | | | * | |
| `repo` | -r | GitHub repo name | | | * | |
| `branch` | -b | branch name | | | * | |
| `branch` | -b | branch name | `'master'` | | * | |
| `buildUrl` | -u | link displayed when deployment fails | | | | |

Therefore, if ran from CircleCI with a `GITHUB_TOKEN` environment variable present and the directory to be deployed is named `public`, _no configuration options are needed_, so just the following is enough:
Expand Down
45 changes: 17 additions & 28 deletions lib/deployment/preparation/preparation.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,39 @@
const shell = require('shelljs');
const path = require('path');

const DEPLOY_BRANCH_DIRECTORY = 'branch';
const BRANCH_DIRECTORY_NAME = 'branch';

shell.set('-e');

module.exports = { prepareDeployDirectory };

function prepareDeployDirectory(directory, options) {
checkoutPagesBranchToDeployDirectory(directory);
moveDirectoryContentToDeployDirectory(directory, options);
}

function checkoutPagesBranchToDeployDirectory(directory) {
createDeployDirectoryIfDoesNotExist(directory);
function prepareDeployDirectory(deployDirectory, { directory: sourceDirectory, branch }) {
createBranchDirectoryIfNeeded(deployDirectory, branch);

try {
pullGithubPagesBranchToDirectory(directory);
} catch (err) {
console.error(err);
console.log('gh-pages branch does not exist yet, it will be created automatically...');
}
copyContentWithReplacement(sourceDirectory, getTargetDirectory(deployDirectory, branch));
}

function createDeployDirectoryIfDoesNotExist(directory) {
shell.mkdir('-p', directory);
function createBranchDirectoryIfNeeded(deployDirectory, branch) {
if (!isMaster(branch)) {
shell.mkdir('-p', getBranchDirectory(deployDirectory));
}
}

function pullGithubPagesBranchToDirectory(directory) {
shell.exec(`git --work-tree=./${directory} checkout gh-pages -- .`, { silent: true });
function isMaster(branch) {
return branch === 'master';
}

function moveDirectoryContentToDeployDirectory(directory, options) {
createBranchDirectoryIfDoesNotExist(directory);

const source = options.directory;
const target = path.join(directory, DEPLOY_BRANCH_DIRECTORY, options.branch);

moveContent(source, target);
function getBranchDirectory(deployDirectory) {
return path.join(deployDirectory, BRANCH_DIRECTORY_NAME);
}

function createBranchDirectoryIfDoesNotExist(directory) {
shell.mkdir('-p', path.join(directory, DEPLOY_BRANCH_DIRECTORY));
function getTargetDirectory(deployDirectory, branch) {
return isMaster(branch)
? deployDirectory
: path.join(getBranchDirectory(deployDirectory), branch);
}

function moveContent(source, target) {
function copyContentWithReplacement(source, target) {
shell.rm('-rf', target);
shell.cp('-r', source, target);
}
77 changes: 36 additions & 41 deletions lib/deployment/preparation/preparation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,53 @@ const { prepareDeployDirectory } = require('./');
describe('Preparation', () => {
afterEach(jest.resetAllMocks);

it('sets shell to throw error when an operation fails', () => {
expect(shell.set).toBeCalledWith('-e');
describe('always', () => {
it('sets shell to throw error when an operation fails', () => {
expect(shell.set).toBeCalledWith('-e');
});
});

it('creates deploy directory if it does not exist', () => {
expect(shell.mkdir).not.toBeCalled();
prepareDeployDirectory('a-directory', {});
expect(shell.mkdir).toBeCalledWith('-p', 'a-directory');
});
describe('on master branch', () => {
const options = { directory: 'source', branch: 'master' };

it('pulls gh-pages branch content to deploy directory', () => {
expect(shell.exec).not.toBeCalled();
prepareDeployDirectory('a-directory', {});
expect(shell.exec).toBeCalledWith(`git --work-tree=./a-directory checkout gh-pages -- .`, {
silent: true,
it('does not create branch directory', () => {
expect(shell.mkdir).not.toBeCalled();
prepareDeployDirectory('deploy-directory', options);
expect(shell.mkdir).not.toBeCalled();
});
});

it('logs a message if pulling gh-pages branch content to deploy directory fails', () => {
console.log = jest.fn();

shell.exec.mockImplementation(() => {
throw new Error('An error');
it('removes deploy directory to allow copying with replacement', () => {
expect(shell.rm).not.toBeCalled();
prepareDeployDirectory('deploy-directory', options);
expect(shell.rm).toBeCalledWith('-rf', 'deploy-directory');
});

expect(console.log).not.toBeCalled();
prepareDeployDirectory('a-directory', {});
expect(console.log).toBeCalled();
it('moves content from source directory to deploy directory', () => {
expect(shell.cp).not.toBeCalled();
prepareDeployDirectory('deploy-directory', options);
expect(shell.cp).toBeCalledWith('-r', 'source', 'deploy-directory');
});
});

it('creates branch directory if it does not exist', () => {
expect(shell.mkdir).not.toBeCalled();
prepareDeployDirectory('a-directory', {});
expect(shell.mkdir).toBeCalledWith('-p', 'a-directory/branch');
});
describe('on a non-master branch', () => {
const options = { directory: 'source', branch: 'not-master' };

it('removes branch directory to be certain it is clean', () => {
expect(shell.rm).not.toBeCalled();
prepareDeployDirectory('a-directory', { branch: 'a-branch' });
expect(shell.rm).toBeCalledWith('-rf', 'a-directory/branch/a-branch');
});
it('creates branch directory ', () => {
expect(shell.mkdir).not.toBeCalled();
prepareDeployDirectory('deploy-directory', options);
expect(shell.mkdir).toBeCalledWith('-p', 'deploy-directory/branch');
});

it('removes current branch directory to allow copying with replacement', () => {
expect(shell.rm).not.toBeCalled();
prepareDeployDirectory('deploy-directory', options);
expect(shell.rm).toBeCalledWith('-rf', 'deploy-directory/branch/not-master');
});

it('moves content from directory to be deployed to branch directory', () => {
expect(shell.cp).not.toBeCalled();
prepareDeployDirectory('a-directory', {
directory: 'a-directory-to-be-deployed',
branch: 'a-branch',
it('moves content from source directory to branch directory', () => {
expect(shell.cp).not.toBeCalled();
prepareDeployDirectory('deploy-directory', options);
expect(shell.cp).toBeCalledWith('-r', 'source', 'deploy-directory/branch/not-master');
});
expect(shell.cp).toBeCalledWith(
'-r',
'a-directory-to-be-deployed',
'a-directory/branch/a-branch',
);
});
});
6 changes: 3 additions & 3 deletions lib/options/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ function createOptions(passedOptions) {
}

function extendPassedOptions(options) {
return extendWithCircleVariablesIfCircle(
extendWithGithubTokenVariable(extendWithDefaultOptions(options)),
return extendWithDefaultOptions(
extendWithGithubTokenVariable(extendWithCircleVariablesIfCircle(options)),
);
}

function extendWithDefaultOptions(options) {
return { directory: 'public', ...options };
return { directory: 'public', branch: 'master', ...options };
}

function extendWithGithubTokenVariable(options) {
Expand Down
19 changes: 14 additions & 5 deletions lib/options/options.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@ const { createOptions } = require('./');
describe('Options', () => {
beforeEach(cleanEnvironmentVariables);

it('extends passed options with default directory to deploy', () => {
it('extends passed options with default directory to deploy and master branch', () => {
const options = {
token: 'a-token',
owner: 'an-owner',
repo: 'a-repo',
};
expect(createOptions(options)).toEqual({ ...options, directory: 'public', branch: 'master' });
});

it('prefers passed options to default options', () => {
const options = {
token: 'a-token',
owner: 'an-owner',
repo: 'a-repo',
branch: 'a-branch',
directory: 'a-directory',
};
expect(createOptions(options)).toEqual({ ...options, directory: 'public' });
expect(createOptions(options)).toEqual(options);
});

it('extends passed options with github token variable if exists', () => {
Expand Down Expand Up @@ -45,14 +55,13 @@ describe('Options', () => {
});

it('throws if any required option is missing', () => {
expect.assertions(4);
expect.assertions(3);

const requiredOptions = ['token', 'owner', 'repo', 'branch'];
const requiredOptions = ['token', 'owner', 'repo'];
const fullOptions = () => ({
token: 'a-token',
owner: 'an-owner',
repo: 'a-repo',
branch: 'a-branch',
});

requiredOptions.forEach(name => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "deploy-directory-on-branch-to-gh-pages",
"version": "0.2.8",
"version": "1.0.0-beta.1",
"description": "A Node library that makes deploying a directory on a branch to GitHub pages easy and automatic.",
"bin": {
"deploy-directory-on-branch-to-gh-pages": "bin/deploy-directory-on-branch-to-gh-pages.js"
Expand Down

0 comments on commit c4dabcf

Please sign in to comment.