Private GIT

Skip to content
Snippets Groups Projects
Commit 3824d7c4 authored by sharkykh's avatar sharkykh Committed by GitHub
Browse files

Auto grunt and update translations (#3557)

Make Travis do chores like running `grunt` and updating translations, then push them to master.
parent de7628f8
Branches
No related tags found
No related merge requests found
......@@ -10,7 +10,8 @@ env:
- TRAVIS_NODE_VERSION="5.6.0"
before_install:
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm &&
git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
- npm install -g grunt-cli
- npm install -g bower
- npm install --quiet
......@@ -19,6 +20,7 @@ before_install:
install:
- pip install --upgrade pip
- pip install --upgrade tox
- pip install --upgrade babel mako crowdin-cli-py
script:
- grunt travis
......@@ -33,6 +35,16 @@ cache:
after_failure:
- cat ./Logs/sickrage.log
after_success:
- if ! { [[ ! -z "$CROWDIN_API_KEY" ]] && [[ "$GH_CRED" =~ ^.+:.+$ ]] && [[ "$TRAVIS_PULL_REQUEST" == "false" ]]
&& [[ "$TRAVIS_BRANCH" == "master" ]]; }; then exit 0; fi;
- git config --global user.name "SickRage"
- git config --global user.email sickrage2@gmail.com
- git config --global push.default current
- git remote rm origin
- git remote add origin https://$GH_CRED@github.com/SickRage/SickRage.git
- grunt travis:update
notifications:
irc: "irc.freenode.net#sickrage-builds"
email:
......
'use strict';
module.exports = function(grunt) {
grunt.registerTask('default', [
'clean',
......@@ -11,11 +13,32 @@ module.exports = function(grunt) {
'mocha'
]);
grunt.registerTask('travis', [
grunt.registerTask('travis', 'Alias for "jshint", "mocha" tasks.', function(update) {
if (!update) {
grunt.task.run([
'jshint',
'mocha'
]);
grunt.registerTask('update_trans', 'update translations', function() {
} else {
if (process.env.TRAVIS) {
grunt.log.writeln('Running grunt and updating translations...'.magenta);
grunt.task.run([
// 'exec:git:checkout:master', // should be on 'master' branch
'default', // Run default task
'update_trans', // Update translations
'exec:commit_changed_files:yes', // Determine what we need to commit if needed, stop if nothing to commit.
'exec:git:"reset --hard"', // Reset unstaged changes (to allow for a rebase)
'exec:git:checkout:develop', 'exec:git:rebase:master', // FF develop to the updated master
'exec:git_push:origin:"master develop"' // Push master and develop
]);
} else {
grunt.fatal('This task is only for Travis-CI!');
}
}
});
grunt.registerTask('update_trans', 'Update translations', function() {
grunt.log.writeln('Updating translations...'.magenta);
var tasks = [
'exec:babel_extract',
'exec:babel_update',
......@@ -26,21 +49,46 @@ module.exports = function(grunt) {
if (process.env.CROWDIN_API_KEY) {
tasks.splice(2, 0, 'exec:crowdin_upload', 'exec:crowdin_download'); // insert items at index 2
} else {
grunt.log.warn('WARNING: Env variable `CROWDIN_API_KEY` is not set, not syncing with Crowdin.');
grunt.log.warn('Environment variable `CROWDIN_API_KEY` is not set, not syncing with Crowdin.'.bold);
}
grunt.task.run(tasks);
});
/****************************************
* Admin only *
* Admin only tasks *
****************************************/
grunt.registerTask('publish', 'create a release tag and generate CHANGES.md\n(alias for newrelease and genchanges)', [
grunt.registerTask('publish', 'ADMIN: Create a new release tag and generate new CHANGES.md', [
'travis',
// 'update_trans', // blocks git pull in newrelease
'newrelease',
'genchanges'
'newrelease', // Pull and merge develop to master, create and push a new release
'genchanges' // Update CHANGES.md
]);
grunt.registerTask('newrelease', "Pull and merge develop to master, create and push a new release", [
'exec:git:checkout:develop', 'exec:git:pull', // Pull develop
'exec:git:checkout:master', 'exec:git:pull', // Pull master
'exec:git:merge:develop', // Merge develop into master
'exec:git_get_last_tag', 'exec:git_list_changes', // List changes from since last tag
'_get_next_tag', 'exec:git_tag_new', // Create new release tag
'exec:git_push:origin:master:tags', // Push master + tags
'exec:git:checkout:develop' // Go back to develop
]);
grunt.registerTask('genchanges', "Generate CHANGES.md file", function() {
var file = grunt.option('file'); // --file=path/to/sickrage.github.io/sickrage-news/CHANGES.md
if (!file) {
file = process.env.SICKRAGE_CHANGES_FILE;
}
if (file && grunt.file.exists(file)) {
grunt.config('changesmd_file', file.replace(/\\/g, '/')); // Use forward slashes only.
} else {
grunt.fatal('\tYou must provide a path to CHANGES.md to generate changes.\n' +
'\t\tUse --file=path/to/sickrage.github.io/sickrage-news/CHANGES.md\n' +
'\t\tor set the path in SICKRAGE_CHANGES_FILE (environment variable)');
}
grunt.task.run(['exec:git_list_tags', '_genchanges', 'exec:commit_changelog']);
});
/****************************************
* Task configurations *
****************************************/
......@@ -207,31 +255,80 @@ module.exports = function(grunt) {
'babel_compile': {cmd: 'python setup.py compile_catalog'},
// Publish/Releases
'git_checkout': {
cmd: function (b) { return 'git checkout ' + b; }
'git': {
cmd: function (cmd, branch) {
branch = branch ? ' ' + branch : '';
return 'git ' + cmd + branch;
}
},
'commit_changed_files': { // Choose what to commit.
cmd: function(travis) {
grunt.config('stop_no_changes', Boolean(travis));
return 'git status -s -- locale/ gui/';
},
'git_pull': {
cmd: 'git pull'
stdout: false,
callback: function(err, stdout) {
stdout = stdout.trim();
if (!stdout.length) {
grunt.fatal('No changes to commit.', 0);
}
var commitMsg = [];
var commitPaths = [];
if (stdout.match(/gui\/.*(vender|core)\.min\.(js|css)$/gm)) {
commitMsg.push('Grunt');
commitPaths.push('gui/**/vender.min.*');
commitPaths.push('gui/**/core.min.*');
}
if (stdout.match(/locale\/.*(pot|po|mo|json)$/gm)) {
commitMsg.push('Update translations');
commitPaths.push('locale/');
}
if (!commitMsg.length || !commitPaths.length) {
if (grunt.config('stop_no_changes')) {
grunt.fatal('Nothing to commit, aborting', 0);
} else {
grunt.log.ok('No extra changes to commit'.green);
}
} else {
commitMsg = commitMsg.join(', ');
if (process.env.TRAVIS_BUILD_NUMBER) {
commitMsg += ' (build ' + process.env.TRAVIS_BUILD_NUMBER + ') [skip ci]';
}
grunt.config('commit_msg', commitMsg);
grunt.config('commit_paths', commitPaths.join(' '));
grunt.task.run('exec:commit_combined');
}
}
},
'git_merge': {
cmd: function (b) { return 'git merge ' + b; }
'commit_combined': {
cmd: function() {
var message = grunt.config('commit_msg');
var paths = grunt.config('commit_paths');
if (!message || !paths) {
grunt.fatal('Call exec:commit_changed_files instead!');
}
return ['git add -- ' + paths, 'git commit -m "' + message + '"'].join(' && ');
}
},
'git_get_last_tag': {
cmd: 'git for-each-ref --sort=-refname --count=1 --format "%(refname:short)" refs/tags',
cmd: 'git for-each-ref --sort=-refname --count=1 --format "%(refname:short)" refs/tags/v20[0-9][0-9]*',
stdout: false,
callback: function(err, stdout) {
if (/v\d{4}\.\d{2}\.\d{2}-\d+/.test(stdout.trim())) {
grunt.config('last_tag', stdout.trim());
stdout = stdout.trim();
if (/^v\d{4}.\d{1,2}.\d{1,2}.\d+$/.test(stdout)) {
grunt.config('last_tag', stdout);
} else {
grunt.fatal('Could not get the last tag name. We got: ' + stdout.trim());
grunt.fatal('Could not get the last tag name. We got: ' + stdout);
}
}
},
'git_list_changes': {
cmd: function() { return 'git log --oneline ' + grunt.config('last_tag') + '..HEAD'; },
cmd: function() { return 'git log --oneline --pretty=format:%s ' + grunt.config('last_tag') + '..HEAD'; },
stdout: false,
callback: function(err, stdout) {
var commits = stdout.replace(/^[a-f0-9]{9}\s/gm, '').trim() // removes commit hashes
var commits = stdout.trim()
.replace(/`/gm, '').replace(/^\([\w\d\s,.\-+_/>]+\)\s/gm, ''); // removes ` and tag information
if (commits) {
grunt.config('commits', commits);
......@@ -249,11 +346,21 @@ module.exports = function(grunt) {
},
'git_push': {
cmd: function (remote, branch, tags) {
return 'git push ' + remote + ' ' + branch + (tags === 'true'?' --tags':'');
var pushCmd = 'git push ' + remote + ' ' + branch;
if (tags) {
pushCmd += ' --tags';
}
if (grunt.option('no-push')) {
grunt.log.warn('Pushing with --dry-run ...'.magenta);
pushCmd += ' --dry-run';
}
return pushCmd;
}
},
'git_list_tags': {
cmd: 'git for-each-ref --sort=refname --format="%(refname:short)|||%(objectname)|||%(contents)@@@" refs/tags',
cmd: 'git for-each-ref --sort=refname ' +
'--format="%(refname:short)|||%(objectname)|||%(contents)\xB6\xB6\xB6" ' +
'refs/tags/v20[0-9][0-9]*',
stdout: false,
callback: function(err, stdout) {
if (!stdout) {
......@@ -262,23 +369,25 @@ module.exports = function(grunt) {
if (err) {
grunt.fatal('Git command failed to execute.');
}
var allTags = stdout.replace(/-{5}BEGIN PGP SIGNATURE-{5}(.*\n)+?-{5}END PGP SIGNATURE-{5}\n/g, '').split('@@@');
var allTags = stdout
.replace(/-{5}BEGIN PGP SIGNATURE-{5}(.*\n)+?-{5}END PGP SIGNATURE-{5}\n/g, '')
.split('\xB6\xB6\xB6');
var foundTags = [];
for (var i = 0; i < allTags.length; i++) {
if (allTags[i].length) {
var explode = allTags[i].split('|||');
allTags.forEach(function(curTag) {
if (curTag.length) {
var explode = curTag.split('|||');
if (explode[0] && explode[1] && explode[2]) {
foundTags.push({
tag: explode[0].trim(),
hash: explode[1].trim(),
message: explode[2].trim().split('\n'),
previous: (foundTags.length ? foundTags[foundTags.length - 1].tag : null)
previous: (foundTags.length ? foundTags.slice(-1)[0].tag : null)
});
}
}
}
});
if (foundTags.length) {
grunt.config('all_tags', foundTags);
grunt.config('all_tags', foundTags.reverse()); // LIFO
} else {
grunt.fatal('Could not get existing tags information');
}
......@@ -294,74 +403,38 @@ module.exports = function(grunt) {
if (!path) {
grunt.fatal('path = "' + path + '"');
}
return 'cd ' + path + ' && git commit -asm "Update changelog"' +
' && git fetch origin && git rebase && git push origin master';
var pushCmd = 'git push origin master';
if (grunt.option('no-push')) {
grunt.log.warn('Pushing with --dry-run ...'.magenta);
pushCmd += ' --dry-run';
}
return ['cd ' + path, 'git commit -asm "Update changelog"', 'git fetch origin', 'git rebase',
pushCmd].join(' && ');
},
stdout: true
}
}
});
/****************************************
* Sub-tasks of publish task *
****************************************/
grunt.registerTask('newrelease', "pull and merge develop to master, create and push a new release", [
'exec:git_checkout:develop', 'exec:git_pull',
'exec:git_checkout:master', 'exec:git_pull', 'exec:git_merge:develop',
'exec:git_get_last_tag', 'exec:git_list_changes', '_get_next_tag',
'exec:git_tag_new', 'exec:git_push:origin:master:true', 'exec:git_checkout:develop']);
grunt.registerTask('genchanges', "generate CHANGES.md file", function() {
var file = grunt.option('file'); // --file=path/to/sickrage.github.io/sickrage-news/CHANGES.md
if (!file) {
file = process.env.SICKRAGE_CHANGES_FILE;
}
if (file && grunt.file.exists(file)) {
grunt.config('changesmd_file', file.replace(/\\/g, '/')); // Use forward slashes only.
} else {
grunt.fatal('\tYou must provide a path to CHANGES.md to generate changes.\n' +
'\t\tUse --file=path/to/sickrage.github.io/sickrage-news/CHANGES.md');
}
grunt.task.run(['exec:git_get_last_tag', 'exec:git_list_tags', '_genchanges',
'exec:commit_changelog']);
});
/****************************************
* Internal tasks *
*****************************************/
grunt.registerTask('_get_next_tag', '(internal) do not run', function() {
function leadingZeros(number) {
return ('0' + parseInt(number)).slice(-2);
}
grunt.config.requires('last_tag');
var lastTag = grunt.config('last_tag');
if (!lastTag) {
grunt.fatal('internal task');
}
lastTag = lastTag.split('v')[1].split('-');
var lastPatch = lastTag[1];
lastTag = lastTag[0].split('.');
var d = new Date();
var year = d.getFullYear().toString();
var month = leadingZeros(d.getMonth() + 1);
var day = leadingZeros(d.getDate());
var patch = '1';
var lastPatch = lastTag.match(/[0-9]+$/)[0];
lastTag = grunt.template.date(lastTag.replace(/^v|-[0-9]*-?$/g, ''), 'yyyy.mm.dd');
var today = grunt.template.today('yyyy.mm.dd');
var patch = lastTag === today ? (parseInt(lastPatch) + 1).toString() : '1';
if (year === lastTag[0] && month === leadingZeros(lastTag[1]) && day === leadingZeros(lastTag[2])) {
patch = (parseInt(lastPatch) + 1).toString();
}
var nextTag = 'v' + year + '.' + month + '.' + day + '-' + patch;
grunt.log.writeln('Creating tag ' + nextTag);
var nextTag = 'v' + today + '-' + patch;
grunt.log.ok(('Creating tag ' + nextTag).green);
grunt.config('next_tag', nextTag);
});
grunt.registerTask('_genchanges', "(internal) do not run", function() {
// actual generate changes
var currentTag = grunt.config('last_tag');
if (!currentTag) {
grunt.fatal('No current tag information was received.');
}
var allTags = grunt.config('all_tags');
if (!allTags) {
grunt.fatal('No tags information was received.');
......@@ -373,7 +446,7 @@ module.exports = function(grunt) {
}
var contents = "";
allTags.reverse().forEach(function(tag) {
allTags.forEach(function(tag) {
contents += '### ' + tag.tag + '\n';
contents += '\n';
if (tag.previous) {
......@@ -383,8 +456,8 @@ module.exports = function(grunt) {
contents += '\n';
tag.message.forEach(function (row) {
contents += row
// link issue numbers, style links it issues and pull requests
.replace(/([\w\d\-_.]+[/]{1}[\w\d\-_.]+)?#([0-9]+)|https?:\/\/github.com\/([\w\d\-_.]+[/]{1}[\w\d\-_.]+)\/(issues|pull)\/([0-9]+)/gm,
// link issue numbers, style links of issues and pull requests
.replace(/([\w\d\-.]+\/[\w\d\-.]+)?#(\d+)|https?:\/\/github.com\/([\w\d\-.]+\/[\w\d\-.]+)\/(issues|pull)\/(\d+)/gm,
function(all, repoL, numL, repoR, typeR, numR) {
if (numL) { // repoL, numL = user/repo#1234 style
return '[' + (repoL ? repoL : '') + '#' + numL + '](https://github.com/' +
......@@ -399,13 +472,11 @@ module.exports = function(grunt) {
return '[' + sha1.substr(0, 7) + '](https://github.com/SickRage/SickRage/commit/' + sha1 + ')';
})
// remove tag information
.replace(/^\([\w\d\s,.\-+_/>]+\)\s/gm, '')
.replace(/^\([\w\d\s,.\-+/>]+\)\s/gm, '')
// remove commit hashes from start
.replace(/^[a-f0-9]{7} /gm, '')
// style messages that contain lists
.replace(/( {3,}\*{1})(?!\*)/g, '\n -')
// style messages that contain multiple lines
.replace(/( {3,}\*{1})(?!\*)/g, '\n -')
.replace(/( {3,}\*)(?!\*)/g, '\n -')
// escapes markdown __ tags
.replace(/__/gm, '\\_\\_')
// add * to the first line only
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment