Skip to content
This repository was archived by the owner on Feb 27, 2019. It is now read-only.

Commit df1b6ca

Browse files
SwiipMehdy Dara
authored and
Mehdy Dara
committed
Publish binaries of all combinations (#43)
* add script generating binaries for all combinations * zip each folder * test configuration for travis and upload script * first version of github upload script * deploy bin with node * correct boolean test * try to detect dist bug * move deploy in script to be before the cache cleanup * new upload script * new token * add strict mode for node 4 * switch to spawned curl commands * show api responses * fix json body arg * fix curl file upload * add tag on meta repo when publishing to trigger deployment * free up integration test before deployment * log github upload responses * try a sleep between uploads as a workaround of github errors * unmute yeoman to understand why dist fails * bump submodules and rollback mute yeoman * bump submodules * bump submodules (again) * add ci option in publish combinations * Indent travis.yml, move archiver dep into devDep
1 parent 4a47ca9 commit df1b6ca

24 files changed

+267
-25
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
test/deps
33
test/work
44
*.creds.json
5+
dist
6+
.DS_Store

.travis.yml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ node_js:
88
git:
99
submodules: false
1010

11-
before_install:
12-
- export DISPLAY=:99.0
13-
- sh -e /etc/init.d/xvfb start
11+
env:
12+
global:
13+
- GIT_NAME: Travis CI
14+
- GIT_EMAIL: nobody@nobody.org
15+
- GITHUB_REPO: FountainJS/fountain
16+
- secure: 3JCPrv2VfF2GE7O/tfbCsjXhg3vNKO7EsQ63aXf65g3iy1oWZGLchhzYJkJgfbYPp83PEicMF19ByAaa5x8nlxn9z/Ea75cSQzKZgsORcy/sA+6urM0jWwocSN6y7x2bUB5lGYXV1UdsM+UwFSoWB4IF/jNIpmHh31UaRHOGSoH3WiTYW4aR/59QXQqPECohnwy8B+5TMr88fCM7ZodMF6SHEAj+LAHHR3Sp+xRjHzt3S17VrWryvp7XC3rvxTZ2DoBvTNfZcs8mr45BIdKbg/Pa5CsvlnIy3EpZDuMQPePrXdTHpxhRs6/vMmUZnmiwzrgJN7Ne8hvpgNLRl6o3+4UAUGeOYfYgj0/22oQy5U2ojz1/fykBQGXxcKLrTHzptYXkBGyFIuKD2HuU2eSMGSo+PoELmJpg5nbwfGR22BHJOsF1H1/dYNvAhPGfagRvgDZE0xoY0GQPPj5M/Rlqi/WOqX3xnlHxnuAucmNrNFknPf+S5u/aGMOcvq5ivsZ7oDI0S874MdDZQO2z6MakhAa0QChCzM/usoqB38PSHfu/5WHqbY0AHWiNyFphkuejhw/ad3GKhX9YBTt3D5YaxH5bchgQrAyAeDF8MnPV+lbIw+eBoLIcfayic5C3dd3hSFXFZx2Kqs4VXbv52hR0JvgpU82AS4WwU+lah1vwbjw=
1417

1518
# Enable cache for all node_modules
1619
cache:
@@ -34,13 +37,20 @@ cache:
3437

3538
addons:
3639
# Install Firefox
37-
firefox: "46.0"
40+
firefox: '46.0'
3841
# Configure Sauce Labs fot e2e tests
3942
sauce_connect:
4043
username: "zckrs"
4144
access_key:
4245
secure: "GRCFdTA5lYr51KaW4UAMV/oDxnm0CoPeYs1hZ2fynvv24X9KJhpukCNZNfYBVRg31gMUxGSzPOllFaHNBoExwb7/F7nndpG2FtBMlp8K22iGYDr8flRFJhd+5KJJRO4ed7z7hfHrbIwq3E2anoByh0NIFn5YO4FDwnf2ObFlFLAtyGppcTvr/UWpqzovFZLlAwU89YRZIFh7nzFUT2IU2BEWlR0TvVIhhNflpw7oScQDNtptZbGVKrJAMWT5VO15gTd97LKjyluHedZ6xWsN8TlOG2PSykI+7YYbz5Sat9l6PfBV2G4Nk5MOXivvW5mHZmXKcdGTfAoDGu9VSYFC+JdeW6DfOvS/ALagDaqmqKUyUY9eWRmt0UEMNoKhiCCe8agW2J3SiVaGVcobtCoB01nEU9iBmaVKAoZu9HbirSyEyc4j3DuQl8gAHEm/JOoTRFVIB/R7t9DPOjuFN5tHnGwO1tjkQtjCVuIz+feC3+EL819zuYCjzJ39MbQJZIiDtrsuBTkWj/SU5ECJgLyTM+qsI87XGVhtsD4UaWTCehvjs915yyLmGwm/D7dRHtno624e0zJo2Y4HHFOcKj1YXf2DaJI8NsApcyfOSWHg/O3yTURcNC/hKQ1avPDtaLpPYG3b4bpU4ubfyZCjzgjELEC7SpiL3AV17ieBCr2h3tM="
4346

47+
before_install:
48+
- export DISPLAY=:99.0
49+
- sh -e /etc/init.d/xvfb start
50+
51+
before_cache:
52+
- npm run unlinkAll
53+
4454
# Prepare build:
4555
# * Backup node_modules in ./temp/ provided by caches Travis
4656
# * Remove all fountain directories
@@ -58,10 +68,6 @@ before_script:
5868
- npm install --global npm@latest
5969
- npm run linkAll
6070

61-
# Run test
6271
script:
6372
- npm test
64-
65-
# Avoid failed caching by Travis
66-
before_cache:
67-
- npm run unlinkAll
73+
- node ./scripts/bin/deploy

fountain-generator

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"node": ">=4.0"
1616
},
1717
"devDependencies": {
18+
"archiver": "^1.0.1",
1819
"babel-eslint": "^6.0.0",
1920
"bluebird": "^3.3.5",
2021
"cartesian-product": "^2.1.2",
@@ -29,11 +30,14 @@
2930
"eslint-plugin-angular": "^1.3.0",
3031
"eslint-plugin-babel": "^3.1.0",
3132
"eslint-plugin-react": "^4.3.0",
33+
"fixture-stdout": "^0.2.1",
34+
"form-data": "^1.0.0-rc4",
3235
"globby": "^4.0.0",
3336
"lodash": "^4.6.1",
34-
"mkdirp": "^0.5.1",
37+
"mkdirp-promise": "^2.0.0",
3538
"mocha": "^2.4.5",
3639
"mz": "^2.4.0",
40+
"rimraf-promise": "^2.0.0",
3741
"sauce-connect-launcher": "^0.14.0",
3842
"semver": "^5.1.0",
3943
"through2-spy": "^2.0.0",
@@ -50,9 +54,9 @@
5054
},
5155
"license": "MIT",
5256
"eslintConfig": {
57+
"extends": "xo-space/esnext",
5358
"env": {
5459
"mocha": true
55-
},
56-
"extends": "xo-space/esnext"
60+
}
5761
}
5862
}

scripts/bin/deploy.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const co = require('co');
2+
const path = require('path');
3+
4+
const exec = require('../exec');
5+
6+
const cwd = path.join(__dirname, '../..');
7+
8+
try {
9+
co(function *() {
10+
if (!process.env.TRAVIS_TAG || !/.*\.1/.test(process.env.TRAVIS_JOB_NUMBER)) {
11+
console.log('Deploy on GitHub only on tags and first build');
12+
return;
13+
}
14+
15+
console.log('Deploying to GitHub for', process.env.TRAVIS_JOB_NUMBER, 'tag', process.env.TRAVIS_TAG);
16+
17+
yield exec('node', ['scripts/dist'], {cwd}).promise;
18+
yield exec('node', ['scripts/upload'], {cwd}).promise;
19+
});
20+
} catch (error) {
21+
console.log('Something went wrong', error);
22+
}

scripts/dist.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const co = require('co');
5+
const helpers = require('yeoman-test');
6+
const mkdirp = require('mkdirp-promise');
7+
const rimraf = require('rimraf-promise');
8+
const Promise = require('bluebird');
9+
10+
const output = require('./helpers/mute');
11+
const combinations = require('./helpers/combinations');
12+
const zip = require('./helpers/zip');
13+
14+
const generatorPath = path.join(__dirname, '../generator-fountain-webapp/generators/app');
15+
16+
co(function *() {
17+
try {
18+
yield rimraf(path.join(__dirname, `../dist`));
19+
20+
for (const options of combinations.full()) {
21+
const combinationPath = path.join(__dirname, `../dist/${options.framework}-${options.modules}-${options.js}-${options.css}-${options.router}-${options.sample}`);
22+
yield mkdirp(combinationPath);
23+
const fountain = helpers.createGenerator('fountain-webapp:app', [generatorPath], null, {
24+
'skipInstall': true,
25+
'skip-welcome-message': true
26+
});
27+
fountain.env.cwd = combinationPath;
28+
helpers.mockPrompt(fountain, options);
29+
const run = Promise.promisify(fountain.run.bind(fountain));
30+
output.mute();
31+
yield run();
32+
output.unmute();
33+
yield zip.zipFolder(combinationPath, `${combinationPath}.zip`);
34+
console.log('Generated', combinationPath);
35+
}
36+
} catch (error) {
37+
console.log('Something went wrong', error);
38+
}
39+
});

scripts/helpers/combinations.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const product = require('cartesian-product');
2+
3+
const frameworks = ['react', 'angular1', 'angular2'];
4+
const modules = ['webpack', 'systemjs', 'inject'];
5+
const js = ['babel', 'js', 'typescript'];
6+
const css = ['css', 'scss', 'less', 'styl'];
7+
const sample = ['hello', 'techs', 'todoMVC'];
8+
9+
// Angular 2 and Bower are not supported right now
10+
const ng2bowerFilter = combination => combination[0] !== 'angular2' || combination[1] !== 'inject';
11+
12+
exports.full = function full() {
13+
return product([frameworks, modules, js, css, sample])
14+
.filter(ng2bowerFilter)
15+
.map(combination => ({
16+
framework: combination[0],
17+
modules: combination[1],
18+
js: combination[2],
19+
css: combination[3],
20+
sample: combination[4],
21+
router: combination[0] === 'angular1' ? 'uirouter' : 'router',
22+
ci: []
23+
}));
24+
};

scripts/helpers/mute.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Silence Yeoman during tests
3+
* uses github.com/balderdashy/fixture-stdout
4+
*
5+
* Usage:
6+
* ```
7+
* // test-something.js
8+
* var Output = require( './mute' );
9+
*
10+
* // beforeEach() test:
11+
* this.app.on( 'start', Output.mute );
12+
* this.app.on( 'end', Output.unmute );
13+
* ```
14+
*/
15+
'use strict';
16+
17+
const Fixture = require('fixture-stdout');
18+
const fixtureOut = new Fixture();
19+
const fixtureErr = new Fixture({
20+
stream: process.stderr
21+
});
22+
23+
const writesOut = [];
24+
const writesErr = [];
25+
26+
// Mute
27+
module.exports.mute = function () {
28+
fixtureOut.capture(string => {
29+
writesOut.push({string});
30+
31+
// Prevent original write
32+
return false;
33+
});
34+
35+
fixtureErr.capture(string => {
36+
writesErr.push({string});
37+
38+
// Prevent original write
39+
return false;
40+
});
41+
};
42+
43+
// Unmute
44+
module.exports.unmute = function () {
45+
fixtureOut.release();
46+
fixtureErr.release();
47+
};
48+
49+
// Return the output that was captured
50+
module.exports.getMutedWrites = function () {
51+
return {
52+
out: writesOut,
53+
err: writesErr
54+
};
55+
};

scripts/helpers/zip.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const fs = require('fs');
2+
const archiver = require('archiver');
3+
4+
exports.zipFolder = function zipFolder(source, destination) {
5+
return new Promise((resolve, reject) => {
6+
const output = fs.createWriteStream(destination);
7+
const archive = archiver('zip');
8+
9+
output.on('close', resolve);
10+
archive.on('error', reject);
11+
12+
archive.pipe(output);
13+
14+
archive.bulk([
15+
{expand: true, cwd: source, src: ['**'], dot: true}
16+
]);
17+
18+
archive.finalize();
19+
});
20+
};

scripts/publish.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ co(function *() {
8383

8484
console.log('Tagging git...');
8585
yield utils.execOnEach(`git tag v${version} && git push origin v${version}`);
86+
yield utils.exec(`git tag v${version} && git push origin v${version}`);
8687
console.log('ok!');
8788

8889
console.log('Publishing on NPM...');

scripts/upload.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const spawn = require('cross-spawn');
5+
6+
const combinations = require('./helpers/combinations');
7+
8+
const githubApiUrl = 'https://api.github.com/repos/FountainJS/fountain';
9+
const githubUploadUrl = 'https://uploads.github.com/repos/FountainJS/fountain';
10+
11+
function exec(command, args) {
12+
const result = spawn.sync(command, args);
13+
try {
14+
return JSON.parse(result.stdout.toString());
15+
} catch (error) {
16+
return result.stdout.toString();
17+
}
18+
}
19+
20+
function githubApiRequest(partialUrl, params) {
21+
console.log(params.method, githubApiUrl + partialUrl, params.body);
22+
return exec('curl', [
23+
'-H', `Authorization: token ${process.env.GITHUB_TOKEN}`,
24+
'-X', params.method,
25+
'-d', params.body,
26+
githubApiUrl + partialUrl
27+
]);
28+
}
29+
30+
function githubUploadRequest(partialUrl, params) {
31+
console.log(params.method, githubUploadUrl + partialUrl, params.filePath);
32+
return exec('curl', [
33+
'-H', `Authorization: token ${process.env.GITHUB_TOKEN}`,
34+
'-H', `Content-Type: application/zip`,
35+
'-X', params.method,
36+
'--data-binary', `@${params.filePath}`,
37+
githubUploadUrl + partialUrl
38+
]);
39+
}
40+
41+
const createTagResult = githubApiRequest('/releases', {
42+
method: 'POST',
43+
body: JSON.stringify({tag_name: process.env.TRAVIS_TAG}) // eslint-disable-line camelcase
44+
});
45+
46+
console.log(createTagResult);
47+
48+
const tag = githubApiRequest(`/releases/tags/${process.env.TRAVIS_TAG}`, {
49+
method: 'GET',
50+
body: ''
51+
});
52+
53+
console.log('Tag ID', tag.id);
54+
55+
combinations.full().forEach(options => {
56+
const fileName = `${options.framework}-${options.modules}-${options.js}-${options.css}-${options.router}-${options.sample}.zip`;
57+
const combinationPath = path.join(__dirname, `../dist/${fileName}`);
58+
59+
const uploadResponse = githubUploadRequest(`/releases/${tag.id}/assets?name=${fileName}`, {
60+
method: 'POST',
61+
filePath: combinationPath
62+
});
63+
if (uploadResponse.message) {
64+
console.log('Upload response has message', uploadResponse);
65+
}
66+
});

scripts/utils.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ exports.execOnEach = function *(command) {
4444
});
4545
return results;
4646
};
47+
exports.exec = function *(command) {
48+
return yield exec(command);
49+
};
4750

4851
exports.readVersion = function *(folder) {
4952
const file = yield fs.readFile(path.join(folder, 'package.json'));

0 commit comments

Comments
 (0)