├── .gitignore ├── package.json ├── README.md ├── LICENSE.md └── lib └── GitSHAPlugin.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-sha-webpack-plugin", 3 | "version": "0.0.6", 4 | "description": "Tag your webpack bundles with a Git SHA linked to the latest commit on that bundle", 5 | "main": "lib/GitSHAPlugin.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Jason Anderson", 11 | "email": "diurnalist@gmail.com", 12 | "url": "http://diurnal.st" 13 | }, 14 | "license": "MIT", 15 | "dependencies": { 16 | "async": "^0.9.0", 17 | "git-bundle-sha": "^0.0.2" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/diurnalist/git-sha-webpack-plugin.git" 22 | }, 23 | "homepage": "https://github.com/diurnalist/git-sha-webpack-plugin", 24 | "bugs": { 25 | "url": "https://github.com/diurnalist/git-sha-webpack-plugin/issues" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # git-sha-webpack-plugin 2 | 3 | Allows tagging a webpack bundle or chunk with the Git SHA of the latest commit affecting that bundle. Useful for when you want to use long-term caching of your bundles, but want to tie the hash to something real and traceable. 4 | 5 | ## Usage 6 | 7 | Install via npm: 8 | 9 | ```shell 10 | npm install git-sha-webpack-plugin 11 | ``` 12 | 13 | And then require for use in webpack: 14 | 15 | ```javascript 16 | // in webpack.config.js (or similar) 17 | var GitSHAPlugin = require('git-sha-webpack-plugin'); 18 | 19 | module.exports = { 20 | 21 | // your config values here 22 | 23 | output: { 24 | filename: '[chunkgitsha].js' 25 | }, 26 | plugins: [ 27 | new GitSHAPlugin({shaLength: 7}) 28 | ] 29 | } 30 | ``` 31 | 32 | ### Options 33 | 34 | #### `shaLength` 35 | 36 | Allows truncating the SHA to a specific character length. 7 by default. 37 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 SoundCloud 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /lib/GitSHAPlugin.js: -------------------------------------------------------------------------------- 1 | var async = require('async'), 2 | gitsha = require('git-bundle-sha'), 3 | path = require('path'), 4 | 5 | CHUNKGITSHA_REGEXP = /\[chunkgitsha\]/gi, 6 | STRIP_QUERY_REGEXP = /\?.*$/; 7 | 8 | function GitSHAPlugin(options) { 9 | options = options || {}; 10 | this.shaLength = options.shaLength || 7; 11 | } 12 | module.exports = GitSHAPlugin; 13 | 14 | GitSHAPlugin.prototype.constructor = GitSHAPlugin; 15 | GitSHAPlugin.prototype.apply = function(compiler) { 16 | var replaceSha = this.replaceSha.bind(this); 17 | var projectRoot = path.resolve(); 18 | var cwdToProjectRoot = path.relative(process.cwd(), projectRoot) || '.'; 19 | compiler.plugin("compilation", function(compilation) { 20 | // we need an async hook because we are calling out to asynchronous 21 | // processes to get the git SHA of the chunks. optimize-tree runs before 22 | // final hashes and asset paths are computed, so it's most appropriate. 23 | compilation.plugin("optimize-tree", function(chunks, modules, done) { 24 | var tasks = chunks.map(function (chunk) { 25 | var files = chunk.modules.map(function (m) { 26 | return m.resource 27 | && m.resource.indexOf(projectRoot) === 0 28 | // trim paths a bit - we can give git relative paths, and this 29 | // helps us avoid argument length limits 30 | && m.resource 31 | .replace(projectRoot, cwdToProjectRoot) 32 | .replace(STRIP_QUERY_REGEXP, ''); 33 | }).filter(Boolean); 34 | 35 | return gitsha.bind(null, files); 36 | }); 37 | 38 | async.parallel(tasks, function(err, res) { 39 | if (err) return done(err); 40 | 41 | res.forEach(function (chunkSha, i) { 42 | chunks[i].gitsha = chunkSha; 43 | }); 44 | done(); 45 | }); 46 | }); 47 | 48 | compilation.mainTemplate.plugin("asset-path", replaceSha); 49 | }); 50 | }; 51 | 52 | GitSHAPlugin.prototype.replaceSha = function(path, data) { 53 | var sha = data.chunk && data.chunk.gitsha; 54 | return path.replace(CHUNKGITSHA_REGEXP, (sha || "").slice(0, this.shaLength)); 55 | }; 56 | --------------------------------------------------------------------------------