├── app
└── .gitkeep
├── addon
└── .gitkeep
├── vendor
└── .gitkeep
├── tests
├── unit
│ ├── .gitkeep
│ └── index-test.js
├── integration
│ └── .gitkeep
├── dummy
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── styles
│ │ │ └── app.css
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── templates
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ └── application.hbs
│ │ ├── resolver.js
│ │ ├── router.js
│ │ ├── app.js
│ │ └── index.html
│ ├── public
│ │ └── robots.txt
│ └── config
│ │ ├── targets.js
│ │ └── environment.js
├── fixtures
│ └── dist
│ │ ├── assets
│ │ └── fixture.css
│ │ └── index.html
├── helpers
│ ├── destroy-app.js
│ ├── start-app.js
│ └── module-for-acceptance.js
├── test-helper.js
├── runner.js
└── index.html
├── .watchmanconfig
├── config
├── environment.js
└── ember-try.js
├── jsconfig.json
├── .vscodeignore
├── .ember-cli
├── .npmignore
├── .editorconfig
├── .gitignore
├── ember-cli-build.js
├── testem.js
├── .travis.yml
├── .eslintrc.js
├── .circleci
└── config.yml
├── LICENSE.md
├── package.json
├── README.md
└── index.js
/app/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/integration/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/tests/fixtures/dist/assets/fixture.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | margin: 0;
4 | padding: 0;
5 | }
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
Welcome to Ember
2 |
3 | {{outlet}}
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(/* environment, appConfig */) {
4 | return { };
5 | };
6 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {"compilerOptions":{"target":"es6","experimentalDecorators":true},"exclude":["node_modules","bower_components","tmp","vendor",".git","dist"]}
--------------------------------------------------------------------------------
/tests/helpers/destroy-app.js:
--------------------------------------------------------------------------------
1 | import { run } from '@ember/runloop';
2 |
3 | export default function destroyApp(application) {
4 | run(application, 'destroy');
5 | }
6 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | dist/**
2 | tmp/**
3 | build/**
4 | cache/**
5 | node_modules/**
6 | bower_components/**
7 | .sass-cache/**
8 | connect.lock/**
9 | coverage/*/**
10 | libpeerconnection.log
--------------------------------------------------------------------------------
/tests/dummy/config/targets.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | browsers: [
3 | 'ie 9',
4 | 'last 1 Chrome versions',
5 | 'last 1 Firefox versions',
6 | 'last 1 Safari versions'
7 | ]
8 | };
9 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import Application from '../app';
2 | import config from '../config/environment';
3 | import { setApplication } from '@ember/test-helpers';
4 | import { start } from 'ember-qunit';
5 |
6 | setApplication(Application.create(config.APP));
7 |
8 | start();
9 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import EmberRouter from '@ember/routing/router';
2 | import config from './config/environment';
3 |
4 | const Router = EmberRouter.extend({
5 | location: config.locationType,
6 | rootURL: config.rootURL
7 | });
8 |
9 | Router.map(function() {
10 | });
11 |
12 | export default Router;
13 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /bower_components
2 | /config/ember-try.js
3 | /dist
4 | /tests
5 | /tmp
6 | **/.gitkeep
7 | .bowerrc
8 | .editorconfig
9 | .ember-cli
10 | .eslintrc.js
11 | .gitignore
12 | .watchmanconfig
13 | .travis.yml
14 | bower.json
15 | ember-cli-build.js
16 | testem.js
17 |
18 | # ember-try
19 | .node_modules.ember-try/
20 | bower.json.ember-try
21 | package.json.ember-try
22 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Application from '@ember/application';
2 | import Resolver from './resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from './config/environment';
5 |
6 | const App = Application.extend({
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix,
9 | Resolver
10 | });
11 |
12 | loadInitializers(App, config.modulePrefix);
13 |
14 | export default App;
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.hbs]
17 | insert_final_newline = false
18 |
19 | [*.{diff,md}]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log*
17 | yarn-error.log
18 | testem.log
19 |
20 | # ember-try
21 | .node_modules.ember-try/
22 | bower.json.ember-try
23 | package.json.ember-try
24 |
25 | # code coverage
26 | /.nyc_output
27 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
4 |
5 | module.exports = function(defaults) {
6 | let app = new EmberAddon(defaults, {
7 | // Add options here
8 | });
9 |
10 | /*
11 | This build file specifies the options for the dummy test app of this
12 | addon, located in `/tests/dummy`
13 | This build file does *not* influence how the addon or the app using it
14 | behave. You most likely want to be modifying `./index.js` or app's build file
15 | */
16 |
17 | return app.toTree();
18 | };
19 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | test_page: 'tests/index.html?hidepassed',
3 | disable_watching: true,
4 | launch_in_ci: [
5 | 'Chrome'
6 | ],
7 | launch_in_dev: [
8 | 'Chrome'
9 | ],
10 | browser_args: {
11 | Chrome: {
12 | mode: 'ci',
13 | args: [
14 | // --no-sandbox is needed when running Chrome inside a container
15 | process.env.TRAVIS ? '--no-sandbox' : null,
16 |
17 | '--disable-gpu',
18 | '--headless',
19 | '--remote-debugging-port=0',
20 | '--window-size=1440,900'
21 | ].filter(Boolean)
22 | }
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Application from '../../app';
2 | import config from '../../config/environment';
3 | import { merge } from '@ember/polyfills';
4 | import { run } from '@ember/runloop';
5 |
6 | export default function startApp(attrs) {
7 | let attributes = merge({}, config.APP);
8 | attributes.autoboot = true;
9 | attributes = merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | return run(() => {
12 | const application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | return application;
16 | });
17 | }
18 |
--------------------------------------------------------------------------------
/tests/runner.js:
--------------------------------------------------------------------------------
1 | /* jshint: node: true */
2 |
3 | 'use strict';
4 |
5 | var glob = require('glob');
6 | var Mocha = require('mocha');
7 |
8 | var mocha = new Mocha({
9 | reporter: 'spec'
10 | });
11 |
12 | var arg = process.argv[2];
13 | var root = 'tests/';
14 |
15 | function addFiles(mocha, files) {
16 | glob.sync(`${root}${files}`).forEach(mocha.addFile.bind(mocha));
17 | }
18 |
19 | addFiles(mocha, '/**/*-test.js');
20 |
21 | if (arg === 'all') {
22 | addFiles(mocha, '/**/*-test-slow.js');
23 | }
24 |
25 | mocha.run(function (failures) {
26 | process.on('exit', function () {
27 | process.exit(failures);
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/tests/helpers/module-for-acceptance.js:
--------------------------------------------------------------------------------
1 | import { module } from 'qunit';
2 | import { resolve } from 'rsvp';
3 | import startApp from '../helpers/start-app';
4 | import destroyApp from '../helpers/destroy-app';
5 |
6 | export default function(name, options = {}) {
7 | module(name, {
8 | beforeEach() {
9 | this.application = startApp();
10 |
11 | if (options.beforeEach) {
12 | return options.beforeEach.apply(this, arguments);
13 | }
14 | },
15 |
16 | afterEach() {
17 | const afterEach = options.afterEach && options.afterEach.apply(this, arguments);
18 | return resolve(afterEach).then(() => destroyApp(this.application));
19 | }
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for "head"}}
11 |
12 |
13 |
14 |
15 | {{content-for "head-footer"}}
16 |
17 |
18 | {{content-for "body"}}
19 |
20 |
21 |
22 |
23 | {{content-for "body-footer"}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/fixtures/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Test Fixture
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | # we recommend testing addons with the same minimum supported node version as Ember CLI
5 | # so that your addon works for all apps
6 | - "8.10"
7 |
8 | sudo: false
9 | dist: trusty
10 |
11 | addons:
12 | chrome: stable
13 |
14 | cache:
15 | directories:
16 | - $HOME/.npm
17 |
18 | env:
19 | global:
20 | # See https://git.io/vdao3 for details.
21 | - JOBS=1
22 | matrix:
23 | # we recommend new addons test the current and previous LTS
24 | # as well as latest stable release (bonus points to beta/canary)
25 | - EMBER_TRY_SCENARIO=ember-lts-2.12
26 | - EMBER_TRY_SCENARIO=ember-lts-2.16
27 | - EMBER_TRY_SCENARIO=ember-release
28 | - EMBER_TRY_SCENARIO=ember-beta
29 | - EMBER_TRY_SCENARIO=ember-canary
30 | - EMBER_TRY_SCENARIO=ember-default
31 |
32 | matrix:
33 | fast_finish: true
34 | allow_failures:
35 | - env: EMBER_TRY_SCENARIO=ember-canary
36 |
37 | before_install:
38 | - npm config set spin false
39 | - npm install -g npm@8.10
40 | - npm --version
41 |
42 | script:
43 | - npm test
44 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for "head"}}
11 | {{content-for "test-head"}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for "head-footer"}}
18 | {{content-for "test-head-footer"}}
19 |
20 |
21 | {{content-for "body"}}
22 | {{content-for "test-body"}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{content-for "body-footer"}}
31 | {{content-for "test-body-footer"}}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | ecmaVersion: 2017,
5 | sourceType: 'module'
6 | },
7 | plugins: [
8 | 'ember'
9 | ],
10 | extends: [
11 | 'eslint:recommended',
12 | 'plugin:ember/recommended'
13 | ],
14 | env: {
15 | browser: true
16 | },
17 | rules: {
18 | },
19 | overrides: [
20 | // node files
21 | {
22 | files: [
23 | 'index.js',
24 | 'testem.js',
25 | 'ember-cli-build.js',
26 | 'config/**/*.js',
27 | 'tests/dummy/config/**/*.js'
28 | ],
29 | excludedFiles: [
30 | 'app/**',
31 | 'addon/**',
32 | 'tests/dummy/app/**'
33 | ],
34 | parserOptions: {
35 | sourceType: 'script',
36 | ecmaVersion: 2015
37 | },
38 | env: {
39 | browser: false,
40 | node: true
41 | },
42 | plugins: ['node'],
43 | rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, {
44 | // add your custom rules and overrides for node files here
45 | })
46 | },
47 |
48 | // test files
49 | {
50 | files: ['tests/**/*.js'],
51 | excludedFiles: ['tests/dummy/**/*.js'],
52 | env: {
53 | embertest: true
54 | }
55 | }
56 | ]
57 | };
58 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(environment) {
4 | let ENV = {
5 | modulePrefix: 'dummy',
6 | environment,
7 | rootURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | },
14 | EXTEND_PROTOTYPES: {
15 | // Prevent Ember Data from overriding Date.parse.
16 | Date: false
17 | }
18 | },
19 |
20 | APP: {
21 | // Here you can pass flags/options to your application instance
22 | // when it is created
23 | }
24 | };
25 |
26 | if (environment === 'development') {
27 | // ENV.APP.LOG_RESOLVER = true;
28 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
29 | // ENV.APP.LOG_TRANSITIONS = true;
30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
31 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
32 | }
33 |
34 | if (environment === 'test') {
35 | // Testem prefers this...
36 | ENV.locationType = 'none';
37 |
38 | // keep test console output quieter
39 | ENV.APP.LOG_ACTIVE_GENERATION = false;
40 | ENV.APP.LOG_VIEW_LOOKUPS = false;
41 |
42 | ENV.APP.rootElement = '#ember-testing';
43 | ENV.APP.autoboot = false;
44 | }
45 |
46 | if (environment === 'production') {
47 | // here you can enable a production-specific feature
48 | }
49 |
50 | return ENV;
51 | };
52 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | test:
4 | docker:
5 | - image: circleci/node:8.11
6 |
7 | working_directory: ~/ember-cli-deploy-ghpages
8 |
9 | steps:
10 | - checkout
11 | - restore_cache:
12 | keys:
13 | - v1-node-modules-{{ checksum "package.json" }}
14 | - v1-node-modules
15 | - run:
16 | name: Install dependencies
17 | command: npm install
18 | - save_cache:
19 | key: v1-node-modules-{{ checksum "package.json" }}
20 | paths:
21 | - node_modules
22 | - run:
23 | name: Change Git user
24 | command: |
25 | git config user.email "support@verdigris.co"
26 | git config user.name "Verdigris Technologies"
27 | - run:
28 | name: Run tests
29 | command: npm test
30 | build:
31 | docker:
32 | - image: circleci/node:8.11
33 |
34 | working_directory: ~/ember-cli-deploy-ghpages
35 |
36 | steps:
37 | - checkout
38 | - restore_cache:
39 | keys:
40 | - v1-node-modules-{{ checksum "package.json" }}
41 | - v1-node-modules
42 |
43 | workflows:
44 | version: 2
45 | test-build-deploy:
46 | jobs:
47 | - test:
48 | filters:
49 | branches:
50 | ignore: gh-pages
51 | - build:
52 | requires:
53 | - test
54 | filters:
55 | branches:
56 | ignore: /.*/
57 | tags:
58 | only: /v([0-9]\.*)+/
59 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, Verdigris Technologies Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | The views and conclusions contained in the software and documentation are those
25 | of the authors and should not be interpreted as representing official policies,
26 | either expressed or implied, of the FreeBSD Project.
27 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | scenarios: [
3 | {
4 | name: 'ember-lts-2.12',
5 | npm: {
6 | devDependencies: {
7 | 'ember-source': '~2.12.0'
8 | }
9 | }
10 | },
11 | {
12 | name: 'ember-lts-2.16',
13 | npm: {
14 | devDependencies: {
15 | 'ember-source': '~2.16.0'
16 | }
17 | }
18 | },
19 | {
20 | name: 'ember-release',
21 | bower: {
22 | dependencies: {
23 | 'ember': 'components/ember#release'
24 | },
25 | resolutions: {
26 | 'ember': 'release'
27 | }
28 | },
29 | npm: {
30 | devDependencies: {
31 | 'ember-source': null
32 | }
33 | }
34 | },
35 | {
36 | name: 'ember-beta',
37 | bower: {
38 | dependencies: {
39 | 'ember': 'components/ember#beta'
40 | },
41 | resolutions: {
42 | 'ember': 'beta'
43 | }
44 | },
45 | npm: {
46 | devDependencies: {
47 | 'ember-source': null
48 | }
49 | }
50 | },
51 | {
52 | name: 'ember-canary',
53 | bower: {
54 | dependencies: {
55 | 'ember': 'components/ember#canary'
56 | },
57 | resolutions: {
58 | 'ember': 'canary'
59 | }
60 | },
61 | npm: {
62 | devDependencies: {
63 | 'ember-source': null
64 | }
65 | }
66 | },
67 | {
68 | name: 'ember-default',
69 | npm: {
70 | devDependencies: {}
71 | }
72 | }
73 | ]
74 | };
75 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-deploy-ghpages",
3 | "version": "1.0.0",
4 | "description": "An ember-cli-deploy plugin to upload to GitHub Pages.",
5 | "keywords": [
6 | "ember-addon",
7 | "ember-cli-deploy-plugin"
8 | ],
9 | "license": "BSD-2-Clause",
10 | "author": "Andrew Jo (https://github.com/AndrewJo)",
11 | "contributors": [
12 | "Alon Bukai (http://www.alonbukai.com/)"
13 | ],
14 | "directories": {
15 | "doc": "doc",
16 | "test": "tests"
17 | },
18 | "repository": "https://github.com/VerdigrisTech/ember-cli-deploy-ghpages",
19 | "scripts": {
20 | "build": "ember build",
21 | "lint:js": "eslint ./*.js addon addon-test-support app config lib server test-support tests",
22 | "start": "ember serve",
23 | "test": "nyc --reporter=lcov node ./tests/runner.js",
24 | "test:try": "ember try:each"
25 | },
26 | "dependencies": {
27 | "denodeify": "^1.2.1",
28 | "ember-cli-babel": "^6.6.0",
29 | "ember-cli-deploy-plugin": "^0.2.5",
30 | "fs-extra": "^0.28.0",
31 | "gift": "^0.10.2",
32 | "rsvp": "^3.2.1"
33 | },
34 | "devDependencies": {
35 | "broccoli-asset-rev": "^2.4.5",
36 | "chai": "^3.5.0",
37 | "codecov": "^3.0.4",
38 | "ember-ajax": "^3.0.0",
39 | "ember-cli": "^2.18.2",
40 | "ember-cli-dependency-checker": "^2.0.0",
41 | "ember-cli-eslint": "^4.2.1",
42 | "ember-cli-htmlbars": "^2.0.1",
43 | "ember-cli-htmlbars-inline-precompile": "^1.0.0",
44 | "ember-cli-inject-live-reload": "^1.4.1",
45 | "ember-cli-shims": "^1.2.0",
46 | "ember-cli-sri": "^2.1.0",
47 | "ember-cli-uglify": "^2.0.0",
48 | "ember-disable-prototype-extensions": "^1.1.2",
49 | "ember-export-application-global": "^2.0.0",
50 | "ember-load-initializers": "^1.0.0",
51 | "ember-resolver": "^4.0.0",
52 | "ember-source": "~2.18.0",
53 | "eslint-plugin-ember": "^5.0.0",
54 | "eslint-plugin-node": "^5.2.1",
55 | "glob": "^7.0.3",
56 | "loader.js": "^4.2.3",
57 | "mocha": "^5.2.0",
58 | "nyc": "^12.0.2"
59 | },
60 | "engines": {
61 | "node": "^4.5 || 6.* || >= 7.*"
62 | },
63 | "ember-addon": {
64 | "configPath": "tests/dummy/config"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-cli-deploy-ghpages [](https://circleci.com/gh/VerdigrisTech/ember-cli-deploy-ghpages) [](https://codecov.io/gh/VerdigrisTech/ember-cli-deploy-ghpages)
2 |
3 | > An ember-cli-deploy-plugin to upload to GitHub pages.
4 |
5 | 
6 |
7 | This plugin uploads your built Ember dist files to GitHub pages.
8 |
9 | ## Getting Started
10 |
11 | To quickly get started with this plugin, follow the steps below:
12 |
13 | * Ensure [ember-cli-deploy-build](https://github.com/ember-cli-deploy/ember-cli-deploy-build)
14 | is installed.
15 | * Install this plugin.
16 |
17 | ```bash
18 | $ ember install ember-cli-deploy-ghpages
19 | ```
20 | * Place the following configuration into `config/deploy.js`.
21 |
22 | ```javascript
23 | ENV.ghpages = {
24 | gitRemoteUrl: ''
25 | }
26 | ```
27 | * Run the pipeline.
28 |
29 | ```bash
30 | $ ember deploy
31 | ```
32 |
33 | ## Browser History API Compatibility
34 |
35 | GitHub Pages is not compatible with browser's history API mode that Ember Router
36 | uses. This means you will not be able to use `pushState` to get to a URL hosted
37 | on GitHub pages. Please ensure your code is updated to use legacy `hash` mode.
38 |
39 | See [Ember Router documentation](http://emberjs.com/api/classes/Ember.Router.html#property_location)
40 | for more details.
41 |
42 | ## ember-cli-deploy Hooks Implemented
43 |
44 | For detailed information on what plugin hooks are and how they work, please
45 | refer to the [Plugin Documentation](http://ember-cli-deploy.github.io/ember-cli-deploy/docs/v0.6.x/plugins-overview).
46 |
47 | * `setup`
48 | * `didBuild`
49 | * `willUpload`
50 | * `upload`
51 | * `teardown`
52 |
53 | ## Configuration Options
54 |
55 | For more information on how to configure plugins, refer to the
56 | [Plugin Documentation](http://ember-cli-deploy.github.io/ember-cli-deploy/docs/v0.6.x/configuration-overview/).
57 |
58 | ### gitRemoteUrl (`required`)
59 |
60 | The URL that corresponds to your GitHub repository. The plugin will push the
61 | built dist files to the `gh-pages` branch on this repository.
62 |
63 | _Default:_ `undefined`
64 |
65 | ### domain
66 |
67 | Custom domain name of your project site. For more information on how to set up
68 | custom domain for your project site, refer to [GitHub](https://help.github.com/articles/using-a-custom-domain-with-github-pages/)
69 | documentation.
70 |
71 | _Default:_ `undefined`
72 |
73 | ## Running Tests
74 |
75 | * `npm test`
76 |
77 | ## License
78 |
79 | This software is distributed AS IS WITHOUT WARRANTY under [Simplified BSD](https://raw.githubusercontent.com/VerdigrisTech/green-button-data/master/LICENSE.md)
80 | license.
81 |
82 | Verdigris Technologies Inc. assumes NO RESPONSIBILITY OR LIABILITY
83 | UNDER ANY CIRCUMSTANCES for usage of this software. See the [LICENSE.md](https://raw.githubusercontent.com/VerdigrisTech/green-button-data/master/LICENSE.md)
84 | file for detailed legal information.
85 |
86 | Copyright © 2016, [Verdigris Technologies Inc](http://verdigris.co). All rights reserved.
87 |
--------------------------------------------------------------------------------
/tests/unit/index-test.js:
--------------------------------------------------------------------------------
1 | /* jshint mocha: true */
2 | 'use strict';
3 |
4 | var expect = require('chai').expect;
5 | var path = require('path');
6 | var fs = require('fs-extra');
7 | var git = require('gift');
8 | var RSVP = require('rsvp');
9 |
10 | describe('github pages plugin', function () {
11 | let subject;
12 | let stubProject;
13 | let plugin;
14 | let context;
15 | let mockUI;
16 | let repoPath;
17 |
18 | before(function () {
19 | subject = require('../../index');
20 | stubProject = {
21 | name: function () {
22 | return 'stubbed-project';
23 | },
24 | root: process.cwd()
25 | };
26 |
27 | mockUI = {
28 | verbose: true,
29 | messages: [],
30 | write: function () {},
31 | writeLine: function (message) {
32 | this.messages.push(message);
33 | }
34 | };
35 |
36 | context = {
37 | ui: mockUI,
38 | distDir: `${process.cwd()}/tests/fixtures/dist`,
39 | distFiles: [
40 | 'index.html',
41 | 'assets/fixture.css'
42 | ],
43 | project: stubProject,
44 | config: {
45 | ghpages: {
46 | gitRemoteUrl: 'https://github.com/VerdigrisTech/ember-cli-deploy-ghpages',
47 | gitRemoteName: 'ember-cli-deploy-test',
48 | domain: 'test.example.com'
49 | }
50 | }
51 | };
52 |
53 | repoPath = path.resolve(context.project.root, 'tmp/gh-pages');
54 | });
55 |
56 | beforeEach(function () {
57 | plugin = subject.createDeployPlugin({
58 | name: 'ghpages'
59 | });
60 | });
61 |
62 | it('has a name', function () {
63 | expect(plugin.name).to.equal('ghpages');
64 | });
65 |
66 | it('implements setup hook', function () {
67 | expect(plugin.setup).to.be.a('function');
68 | });
69 |
70 | it('implements didBuild hook', function () {
71 | expect(plugin.didBuild).to.be.a('function');
72 | });
73 |
74 | it('implements willUpload hook', function () {
75 | expect(plugin.willUpload).to.be.a('function');
76 | });
77 |
78 | it('implements upload hook', function () {
79 | expect(plugin.upload).to.be.a('function');
80 | });
81 |
82 | it('implements teardown hook', function () {
83 | expect(plugin.teardown).to.be.a('function');
84 | });
85 |
86 | describe('#setup hook', function () {
87 | this.timeout(5000);
88 |
89 | let repo;
90 |
91 | before(function (done) {
92 | plugin.beforeHook(context);
93 | plugin.configure(context);
94 | plugin.setup(context)
95 | .then(function () {
96 | repo = git(repoPath);
97 | done();
98 | });
99 | });
100 |
101 | it('creates a tmp directory', function (done) {
102 | fs.access(repoPath, fs.F_OK, function (error) {
103 | expect(error).to.be.null;
104 | done();
105 | });
106 | });
107 |
108 | it("creates an orphaned branch named 'gh-pages'", function (done) {
109 | /**
110 | * Using symbolic reference is the most reliable way to get an orphaned
111 | * branch name.
112 | */
113 | repo.git('symbolic-ref', { short: true }, ['HEAD'], (error, stdout) => {
114 | expect(error).to.be.null;
115 | expect(stdout.trim()).to.equal('gh-pages');
116 | done();
117 | });
118 | });
119 |
120 | it('removes all files in the branch', function (done) {
121 | repo.status((error, status) => {
122 | let files = Object.keys(status.files)
123 | .filter(key => status.files[key].tracked);
124 |
125 | expect(files).to.be.empty;
126 | done();
127 | });
128 | });
129 |
130 | it('creates a CNAME file if custom domain is specified', function (done) {
131 | let cnameFile = path.resolve(repoPath, 'CNAME');
132 | fs.readFile(cnameFile, { encoding: 'UTF-8' }, function (error, data) {
133 | expect(error).to.be.null;
134 | expect(data).to.be.equal('test.example.com');
135 | done(error);
136 | });
137 | });
138 | });
139 |
140 | describe('#didBuild hook', function () {
141 | this.timeout(5000);
142 |
143 | let repo;
144 |
145 | before(function (done) {
146 | plugin.beforeHook(context);
147 | plugin.configure(context);
148 | plugin.setup(context)
149 | .then(function () {
150 | return plugin.didBuild(context);
151 | })
152 | .then(function () {
153 | repo = git(repoPath);
154 | done();
155 | });
156 | });
157 |
158 | it('dist files are committed', function (done) {
159 | repo.ls_files((error, files) => {
160 | expect(files).to.be.eql([['CNAME'], ['assets/fixture.css'], ['index.html']]);
161 | done();
162 | });
163 | });
164 | });
165 |
166 | describe('#willUpload hook', function () {
167 | let repo;
168 |
169 | before(function (done) {
170 | plugin.beforeHook(context);
171 | plugin.configure(context);
172 | plugin.setup(context)
173 | .then(function () {
174 | return plugin.didBuild(context);
175 | })
176 | .then(function () {
177 | return plugin.willUpload(context);
178 | })
179 | .then(function () {
180 | repo = git(repoPath);
181 | done();
182 | });
183 | });
184 |
185 | it('adds remote repository for tracking', function (done) {
186 | repo.git('remote', {}, [], (error, stdout) => {
187 | expect(stdout).to.have.string('ember-cli-deploy-test');
188 | done();
189 | });
190 | });
191 | });
192 |
193 | describe('#upload hook', function () {
194 | this.timeout(30000);
195 | let repo;
196 |
197 | before(function (done) {
198 | plugin.beforeHook(context);
199 | plugin.configure(context);
200 | plugin.setup(context)
201 | .then(function () {
202 | return plugin.didBuild(context);
203 | })
204 | .then(function () {
205 | return plugin.willUpload(context);
206 | })
207 | .then(function () {
208 | return plugin.upload(context);
209 | })
210 | .then(function () {
211 | repo = git(repoPath);
212 | done();
213 | })
214 | .catch(function (error) {
215 | done(error);
216 | });
217 | });
218 |
219 | function revParse(branch) {
220 | return new RSVP.Promise((resolve, reject) => {
221 | repo.git('rev-parse', {}, [branch], (error, stdout) => {
222 | if (error) {
223 | return reject(error);
224 | }
225 |
226 | return resolve(stdout);
227 | });
228 | });
229 | }
230 |
231 | it('pushes branch to remote repository', function (done) {
232 | // Fetch from remote and see if local is up-to-date
233 | repo.remote_fetch('ember-cli-deploy-test', error => {
234 | expect(error).to.be.null;
235 |
236 | RSVP.all([
237 | revParse('gh-pages'),
238 | revParse('ember-cli-deploy-test/gh-pages')
239 | ]).then((shaHashes) => {
240 | expect(shaHashes[0]).to.be.equal(shaHashes[1]);
241 | done();
242 | });
243 | });
244 | });
245 | });
246 |
247 | describe('#teardown hook', function () {
248 | before(function (done) {
249 | plugin.beforeHook(context);
250 | plugin.teardown(context)
251 | .then(() => done());
252 | });
253 |
254 | it('performs cleanup', function () {
255 | function checkPath() {
256 | fs.accessSync(repoPath, fs.F_OK);
257 | }
258 |
259 | expect(checkPath).to.throw(Error);
260 | });
261 | });
262 | });
263 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var denodeify = require('denodeify');
4 | var fs = require('fs-extra');
5 | var ensureDir = denodeify(fs.ensureDir);
6 | var copy = denodeify(fs.copy);
7 | var path = require('path');
8 | var git = require('gift');
9 |
10 | var RSVP = require('rsvp');
11 | var Promise = RSVP.Promise;
12 |
13 | var DeployPluginBase = require('ember-cli-deploy-plugin');
14 |
15 | module.exports = {
16 | name: 'ember-cli-deploy-ghpages',
17 |
18 | createDeployPlugin(options) {
19 | /**
20 | * Private function for creating an orphan branch that does not have any
21 | * parents.
22 | *
23 | * @params {Repo} repository
24 | * @params {String} branch
25 | * @return {Promise}
26 | */
27 | function createOrphanBranch(repository, branch) {
28 | return new Promise((resolve, reject) => {
29 | repository.git('checkout', { orphan: true }, branch, (error, b) => {
30 | if (error) {
31 | return reject(error);
32 | }
33 |
34 | return resolve(b);
35 | });
36 | });
37 | }
38 |
39 | /**
40 | * Private function to delete a branch.
41 | *
42 | * @params {Repo} repository
43 | * @params {String} branch
44 | * @return {Promise}
45 | */
46 | function deleteBranch(repository, branch) {
47 | return new Promise((resolve, reject) => {
48 | repository.git('branch', { D: true }, branch, error => {
49 | if (error) {
50 | return reject(error);
51 | }
52 |
53 | return resolve();
54 | });
55 | });
56 | }
57 |
58 | /**
59 | * Private function for checking whether a branch exists.
60 | *
61 | * @params {Repo} repository
62 | * @params {String} branch
63 | * @return {Promise}
64 | */
65 | function branchExists(repository, branch) {
66 | return new Promise((resolve, reject) => {
67 | repository.branch(branch, (error) => {
68 | if (error) {
69 | return reject();
70 | }
71 |
72 | return resolve();
73 | });
74 | });
75 | }
76 |
77 | /**
78 | * Private function for deleting all files.
79 | *
80 | * @params {Repo} repository
81 | * @return {Promise}
82 | */
83 | function removeAll(repository) {
84 | return new Promise((resolve, reject) => {
85 | repository.remove('.', { r: true, f: true }, (error, output) => {
86 | if (error) {
87 | return reject(error);
88 | }
89 |
90 | return resolve(output);
91 | });
92 | });
93 | }
94 |
95 | /**
96 | * Private function for copying dist files to tmp directory.
97 | *
98 | * @params {String} srcDir
99 | * @params {Array} srcFiles
100 | * @params {String} dstDir
101 | * @return {Promise}
102 | */
103 | function copyDistFiles(srcDir, srcFiles, dstDir) {
104 | return RSVP.all(srcFiles.map(file => copy(
105 | path.resolve(srcDir, file),
106 | path.resolve(dstDir, file)
107 | )));
108 | }
109 |
110 | /**
111 | * Private function for staging all files to the repo.
112 | *
113 | * @params {Repo} repository
114 | * @returns {Promise}
115 | */
116 | function stageAllFiles(repository) {
117 | return new Promise((resolve, reject) => {
118 | repository.add('.', error => {
119 | if (error) {
120 | return reject(error);
121 | }
122 |
123 | return resolve();
124 | });
125 | });
126 | }
127 |
128 | /**
129 | * Private function for commiting.
130 | *
131 | * @params {Repo} repository
132 | * @return {Promise}
133 | */
134 | function commit(repository, message) {
135 | return new Promise((resolve, reject) => {
136 | repository.commit(message, error => {
137 | if (error) {
138 | return reject(error);
139 | }
140 |
141 | return resolve();
142 | });
143 | });
144 | }
145 |
146 | /**
147 | * Private function for adding remote repo.
148 | *
149 | * @params {Repo} repository
150 | * @params {String} remoteUrl
151 | * @return {Promise}
152 | */
153 | function addRemote(repository, remoteName, remoteUrl) {
154 | return new Promise((resolve, reject) => {
155 | repository.remote_add(remoteName, remoteUrl, error => {
156 | if (error) {
157 | return reject(error);
158 | }
159 |
160 | return resolve();
161 | });
162 | });
163 | }
164 |
165 | /**
166 | * Private function for setting upstream for a branch.
167 | *
168 | * @params {Repo} repository
169 | * @params {String} branch
170 | * @params {String} remoteName
171 | * @return {Promise}
172 | */
173 | function setUpstream(repository, branch, remoteName) {
174 | return new Promise((resolve, reject) => {
175 | let remoteBranch = `${remoteName}/${branch}`;
176 |
177 | repository.git('branch', { u: true }, [remoteBranch, branch], error => {
178 | if (error) {
179 | return reject(error);
180 | }
181 |
182 | return resolve();
183 | });
184 | });
185 | }
186 |
187 | /**
188 | * Private function for pushing to upstream branch.
189 | *
190 | * @params {Repo} repository
191 | * @params {String} branch
192 | * @params {String} remote
193 | * @params {Boolean} setUpstream
194 | * @return {Promise}
195 | */
196 | function pushUpstream(repository, branch, remote, setUpstream) {
197 | return new Promise((resolve, reject) => {
198 | repository.git('push', {
199 | u: setUpstream,
200 | f: true
201 | }, [remote, branch], error => {
202 | if (error) {
203 | return reject(error);
204 | }
205 |
206 | return resolve();
207 | });
208 | });
209 | }
210 |
211 | var GHPagesPlugin = DeployPluginBase.extend({
212 | name: options.name,
213 |
214 | defaultConfig: {
215 | projectTmpPath: 'tmp',
216 | repoTmpPath: 'gh-pages',
217 | commitMessage: 'Deploy dist files by ember-cli-deploy-ghpages',
218 | gitBranch: 'gh-pages',
219 | gitRemoteName: 'ember-cli-deploy',
220 | domain: undefined
221 | },
222 |
223 | requiredConfig: ['gitRemoteUrl'],
224 |
225 | setup: function (context) {
226 | let repo;
227 | let self = this;
228 | let branch = this.readConfig('gitBranch');
229 | let tmp = this.readConfig('projectTmpPath');
230 | let relativeRepoTmpPath = this.readConfig('repoTmpPath');
231 | let projectTmpPath = path.resolve(context.project.root, tmp);
232 | let repoTmpPath = path.resolve(projectTmpPath, relativeRepoTmpPath);
233 | let domain = this.readConfig('domain');
234 |
235 | return ensureDir(path.resolve(context.project.root, repoTmpPath))
236 | .then(function () {
237 | self.log('cloning project repository to tmp');
238 |
239 | // TODO: Replace with streams for faster copy.
240 | return copy(context.project.root, repoTmpPath, {
241 | // If you recursively copy the tmp directory, you'll have a bad
242 | // time.
243 | filter: path => (
244 | path !== projectTmpPath &&
245 | path.indexOf('node_modules') < 0 &&
246 | path.indexOf('bower_components') < 0
247 | )
248 | });
249 | })
250 | .then(function () {
251 | self.log('cloned project repository to tmp', { color: 'green' });
252 |
253 | repo = context.gitRepo = git(repoTmpPath);
254 |
255 | return branchExists(repo, branch);
256 | })
257 | .then(function () {
258 | self.log(`branch '${branch}' already exists`, { color: 'yellow' });
259 |
260 | return deleteBranch(repo, branch)
261 | .then(function () {
262 | return createOrphanBranch(repo, branch);
263 | });
264 | }, function () {
265 | return createOrphanBranch(repo, branch);
266 | })
267 | .then(function () {
268 | self.log(`successfully checked out '${branch}' branch`, {
269 | color: 'green'
270 | });
271 | self.log('removing all files');
272 |
273 | return removeAll(repo);
274 | })
275 | .then(function () {
276 | self.log(`all files removed on '${branch}' branch`, {
277 | color: 'green'
278 | });
279 |
280 | if (domain) {
281 | self.log(`setting up custom domain`);
282 | let cname = path.resolve(repoTmpPath, 'CNAME');
283 |
284 | fs.writeFile(cname, domain, () => {
285 | self.log(`custom domain set up at: ${domain}`);
286 | });
287 | }
288 | })
289 | .catch(function (error) {
290 | this.log(error, { color: 'red' });
291 | });
292 | },
293 |
294 | didBuild: function (context) {
295 | let self = this;
296 | let tmp = this.readConfig('projectTmpPath');
297 | let repoTmpPath = path.join(tmp, this.readConfig('repoTmpPath'));
298 | repoTmpPath = path.resolve(context.project.root, repoTmpPath);
299 |
300 | this.log('copying dist files to tmp');
301 |
302 | return copyDistFiles(context.distDir, context.distFiles, repoTmpPath)
303 | .then(function () {
304 | self.log('copied dist files to tmp', { color: 'green' });
305 | self.log('staging all files for commit');
306 | return stageAllFiles(context.gitRepo);
307 | })
308 | .then(function () {
309 | self.log('committing staged files');
310 | return commit(context.gitRepo, self.readConfig('commitMessage'));
311 | })
312 | .then(function () {
313 | self.log('committed all staged files', { color: 'green' });
314 | })
315 | .catch(error => self.log(error));
316 | },
317 |
318 | willUpload: function (context) {
319 | let remoteName = this.readConfig('gitRemoteName');
320 | let remoteUrl = this.readConfig('gitRemoteUrl');
321 | let branch = this.readConfig('gitBranch');
322 |
323 | return addRemote(context.gitRepo, remoteName, remoteUrl)
324 | .then(() => {
325 | this.log('remote repository added', { color: 'green' });
326 | return setUpstream(context.gitRepo, branch, remoteName);
327 | })
328 | .catch(() => {
329 | // Upstream branch does not exist. Mark it so we know during
330 | // upload stage.
331 | this.log('remote branch does not exist', { color: 'yellow' });
332 | context.setUpstreamOnPush = true;
333 | });
334 | },
335 |
336 | upload: function (context) {
337 | let repo = context.gitRepo;
338 | let branch = this.readConfig('gitBranch');
339 | let remoteName = this.readConfig('gitRemoteName');
340 | let setUpstream = context.setUpstreamOnPush;
341 |
342 | this.log('pushing to remote repository');
343 |
344 | return pushUpstream(repo, branch, remoteName, setUpstream)
345 | .then(() => {
346 | this.log('push success', { color: 'green' });
347 | })
348 | .catch(error => this.log(error, { color: 'red' }));
349 | },
350 |
351 | teardown: function (context) {
352 | let tmp = this.readConfig('projectTmpPath');
353 | let repoTmpPath = path.join(tmp, this.readConfig('repoTmpPath'));
354 | repoTmpPath = path.resolve(context.project.root, repoTmpPath);
355 |
356 | return new Promise((resolve, reject) => {
357 | this.log('cleaning up');
358 | fs.remove(repoTmpPath, error => {
359 | if (error) {
360 | this.log(error, { color: 'red' });
361 | reject(error);
362 | }
363 |
364 | this.log('cleanup complete', { color: 'green' });
365 | resolve();
366 | });
367 | });
368 | }
369 | });
370 |
371 | return new GHPagesPlugin();
372 | }
373 | };
374 |
--------------------------------------------------------------------------------