Permalink
Browse files

feat(*) add git-rev-like support for heroku with SOURCE_VERSION

When pushing to heroku using git to deploy, the .git folder is deleted before compiling the slug, so git-rev-parse fails.
Though, the hash of the revision is provided by heroku in the env var SOURCE_VERSION during the compiling time.
The hash is saved into bannerInfos.json to be available to express so that it could render the hash in the html (at this time the app will already launched and the env var not available anymore).

Yes :-) All this to get the revision in a comment that nobody will ever read ! LOL
  • Loading branch information...
topheman committed Oct 19, 2015
1 parent 5581983 commit d7dd9c7e28dc3b475b0cdeb02538ebd50ef5f8ab
Showing with 51 additions and 14 deletions.
  1. +40 −13 common.js
  2. +1 −1 server/app.js
  3. +10 −0 webpack.config.js
View
@@ -18,39 +18,65 @@ function projectIsGitManaged(){
}
}
function getInfos(){
var gitActive = projectIsGitManaged();
/**
* Return the git revision if the project is git managed
* Also returns the git revision for a project just shipped to heroku at compile time
* If no git involved, returns null
* @param {String} mode 'short'|'long'
* @returns {String|null}
*/
function getGitRevision(mode){
var gitRev = require('git-rev-sync');
mode = mode || 'long';
if(['short','long'].indexOf(mode) === -1){
throw new Error("Only accepts 'short' or 'long' as argument");
}
if(projectIsGitManaged()){
return gitRev[mode]();
}
//case we are on heroku, process.env.SOURCE_VERSION contains the hash of the git revision (only at compile time)
else if(process.env.SOURCE_VERSION){
if(mode === 'short'){
return process.env.SOURCE_VERSION.slice(0,7);
}
return process.env.SOURCE_VERSION
}
return;
}
function getInfos(){
var moment = require('moment');
var pkg = require('./package.json');
var infos = {
pkg: pkg,
today: moment(new Date()).format('DD/MM/YYYY'),
year: new Date().toISOString().substr(0, 4),
gitRevisionShort: gitActive ? gitRev.short() : null,
gitRevisionLong: gitActive ? gitRev.long() : null,
urlToCommit: null
gitRevisionShort: getGitRevision('short'),
gitRevisionLong: getGitRevision('long'),
urlToCommit: undefined
};
infos.urlToCommit = gitActive ? _getUrlToCommit(pkg, infos.gitRevisionLong) : null;
infos.urlToCommit = infos.gitRevisionLong ? _getUrlToCommit(pkg, infos.gitRevisionLong) : undefined;
return infos;
}
/**
* Called in default mode by webpack (will format it correctly in comments)
* Called in formatted mode by gulp (for html comments)
* @param {String} mode default/formatted
* @param {Object} overrideInfos pass an object to override the properties to render
* @returns {String}
*/
function getBanner(mode){
function getBanner(mode, overrideInfos){
overrideInfos = overrideInfos || {};
var _ = require('lodash');
var infos = getInfos();
var infos = _.extend(getInfos(), overrideInfos);
var compiled = _.template([
'<%= pkg.name %>',
'',
'<%= pkg.description %>',
'',
'@version v<%= pkg.version %> - <%= today %>',
'<% if(gitRevisionShort !== null) { %>@revision #<%= gitRevisionShort %><% if (urlToCommit !== null) { %> - <%= urlToCommit %><% } %><% } %>',
'<% if(gitRevisionShort) { %>@revision #<%= gitRevisionShort %><% if (urlToCommit) { %> - <%= urlToCommit %><% } %><% } %>',
'@author <%= (pkg.author && pkg.author.name) ? pkg.author.name : pkg.author %>',
'@copyright <%= year %>(c) <%= (pkg.author && pkg.author.name) ? pkg.author.name : pkg.author %>',
'@license <%= pkg.license %>',
@@ -59,12 +85,13 @@ function getBanner(mode){
return compiled(infos);
}
function getBannerHtml(){
return '<!--\n * \n * ' + getBanner('formatted') + '\n-->\n';
function getBannerHtml(overrideInfos){
overrideInfos = overrideInfos || {};
return '<!--\n * \n * ' + getBanner('formatted', overrideInfos) + '\n-->\n';
}
function _getUrlToCommit(pkg, gitRevisionLong){
var urlToCommit = null;
var urlToCommit;
//retrieve and reformat repo url from package.json
if (typeof(pkg.repository) === 'string') {
urlToCommit = pkg.repository;
@@ -73,7 +100,7 @@ function _getUrlToCommit(pkg, gitRevisionLong){
urlToCommit = pkg.repository.url;
}
//check that there is a git repo specified in package.json & it is a github one
if (urlToCommit !== null && /^https:\/\/github.com/.test(urlToCommit)) {
if (urlToCommit && /^https:\/\/github.com/.test(urlToCommit)) {
urlToCommit = urlToCommit.replace(/.git$/, '/tree/' + gitRevisionLong);//remove the .git at the end
}
return urlToCommit;
View
@@ -31,7 +31,7 @@ app.use(cookieParser());
// available vars in all templates
app.locals.hash = '';
app.locals.bannerHtml = require('../common').getBannerHtml();
app.locals.bannerHtml = require('../common').getBannerHtml( app.get('env') === 'PROD' ? require('../build/bannerInfos.json') : {});
//@note don't really need to serve /public since every assets are bundle with webpack
//app.use(express.static(path.join(__dirname, 'public'))); //keeping it if any assets come out
View
@@ -62,9 +62,19 @@ if(MODE_DEV_SERVER === false){
//write infos about the build (to retrieve the hash) https://webpack.github.io/docs/long-term-caching.html#get-filenames-from-stats
plugins.push(function() {
this.plugin("done", function(stats) {
console.log('');//break line
require("fs").writeFileSync(
path.join(__dirname, "build", "stats.json"),
JSON.stringify(stats.toJson()));
console.log('Created /build/stats.json file');
//save the git revision hash (on heroku, it can only be retrieved at compile time), that way, it will be available to express after
var bannerInfos = require('./common').getInfos();
require("fs").writeFileSync(
path.join(__dirname, "build", "bannerInfos.json"),
JSON.stringify(bannerInfos));
console.log('Created /build/bannerInfos.json file');
});
});
}

0 comments on commit d7dd9c7

Please sign in to comment.