From 8a51daf280ebb252ef51a979e3f18dd5be84c6c9 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 15 Dec 2014 18:18:27 +0000 Subject: [PATCH] Compile with Ruby Sass or libsass. * Separate configs for libsass and sass. * Sass compiler selected based on `process.env.TWBS_SASS`. * Travis: * Use Gemfile to manage ruby dependencies. * Run core tests with both Sass compilers. * Only install/cache ruby gems required by the test subset. * Grunt: `update-gemfile-lock` task a la `update-shrinkwrap`. --- .gitignore | 8 ++- .travis.yml | 12 ++--- Gemfile | 7 ++- Gemfile.lock | 78 +++++++++++++++++++++++++++ Gruntfile.js | 43 +++++++-------- grunt/bs-sass-compile/libsass.js | 26 +++++++++ grunt/bs-sass-compile/sass.js | 30 +++++++++++ package.json | 1 + test-infra/S3Cachefile.json | 6 +-- test-infra/gemfiles/core.gemfile | 7 +++ test-infra/gemfiles/core.gemfile.lock | 15 ++++++ 11 files changed, 200 insertions(+), 33 deletions(-) create mode 100644 Gemfile.lock create mode 100644 grunt/bs-sass-compile/libsass.js create mode 100644 grunt/bs-sass-compile/sass.js create mode 100644 test-infra/gemfiles/core.gemfile create mode 100644 test-infra/gemfiles/core.gemfile.lock diff --git a/.gitignore b/.gitignore index d60e71a5fd..042d47047f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ # Ignore docs files _gh_pages _site + +# Ignore ruby files .ruby-version -Gemfile.lock +.bundle +vendor/cache # Numerous always-ignore extensions *.diff @@ -41,6 +44,9 @@ validation-status.json # SCSS-Lint scss-lint-report.xml +# grunt-contrib-sass cache +.sass-cache + # Folders to ignore bower_components node_modules diff --git a/.travis.yml b/.travis.yml index 5899bbf0f7..bb85115f61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,15 +15,12 @@ before_install: install: - npm install -g grunt-cli - ./test-infra/s3_cache.py download npm-modules - - if [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py download rubygems; fi + - if [ -n "$BUNDLE_GEMFILE" ]; then ./test-infra/s3_cache.py download rubygems; fi after_script: - if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ "$TWBS_TEST" = core ]; then ./test-infra/s3_cache.py upload npm-modules; fi - - if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py upload rubygems; fi + - if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ -n "$BUNDLE_GEMFILE" ]; then ./test-infra/s3_cache.py upload rubygems; fi env: global: - - JEKYLL_VERSION="2.5.1" - - ROUGE_VERSION="1.7.2" - - SCSS_LINT_VERSION="0.30.0" - SAUCE_USERNAME="bootstrap" - secure: "pJkBwnuae9dKU5tEcCqccfS1QQw7/meEcfz63fM7ba7QJNjoA6BaXj08L5Z3Vb5vBmVPwBawxo5Hp0jC0r/Z/O0hGnAmz/Cz09L+cy7dSAZ9x4hvZePSja/UAusaB5ogMoO8l2b773MzgQeSmrLbExr9BWLeqEfjC2hFgdgHLaQ=" - secure: "gqjqISbxBJK6byFbsmr1AyP1qoWH+rap06A2gI7v72+Tn2PU2nYkIMUkCvhZw6K889jv+LhQ/ybcBxDOXHpNCExCnSgB4dcnmYp+9oeNZb37jSP0rQ+Ib4OTLjzc3/FawE/fUq5kukZTC7porzc/k0qJNLAZRx3YLALmK1GIdUY=" @@ -35,8 +32,9 @@ env: - secure: "PabpUdG2dE40hHUkMCdxk1e9Ak3BOo0h7Y5/uekosLKOz5N60Xmn/ooyrSkvicLthXO4cfONFhO3/xSVRKQOxlUw4on5i0VuNK+QSqxJk0IDaRSZnTCcC8J7083K0YL+FvMdGQwcYwMY9LiwS8aS014IRkSQjsa+mjo3owP+dOU=" - secure: "G4/f4PVyVi9o6UbZMqw9YFmDu7cHqe9iymiXYd1RcnPXwhWAePX12m0PWMhUj5itJ180PTEddVip8PNOgBdqyrDxEPKkcgAW2EElVAPIKJXVfvDW64UjQ0H7NS7XvF7iLQUJp/XfmR7NJ7tT393AQdh8SGmuQpJhgYbwIWbES/k=" matrix: - - TWBS_TEST=core - - TWBS_TEST=validate-html + - TWBS_TEST=core TWBS_SASS=libsass BUNDLE_GEMFILE=test-infra/gemfiles/core.gemfile + - TWBS_TEST=core TWBS_SASS=sass BUNDLE_GEMFILE=test-infra/gemfiles/core.gemfile + - TWBS_TEST=validate-html BUNDLE_GEMFILE=Gemfile - TWBS_TEST=sauce-js-unit matrix: fast_finish: true diff --git a/Gemfile b/Gemfile index eb9646efef..23068bdfeb 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,11 @@ +# Ruby Gems for building and testing Bootstrap +# Run `grunt update-gemfile-lock` to update to the latest compatible versions + source 'https://rubygems.org' -group :development do +group :development, :test do gem 'jekyll', '~> 2.5.2' gem 'rouge', '~> 1.7.4' + gem 'sass', '~> 3.4.9' + gem 'scss-lint', '~> 0.31' end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..725379399c --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,78 @@ +GEM + remote: https://rubygems.org/ + specs: + blankslate (2.1.2.4) + celluloid (0.16.0) + timers (~> 4.0.0) + classifier-reborn (2.0.2) + fast-stemmer (~> 1.0) + coffee-script (2.3.0) + coffee-script-source + execjs + coffee-script-source (1.8.0) + colorator (0.1) + execjs (2.2.2) + fast-stemmer (1.0.2) + ffi (1.9.6) + hitimes (1.2.2) + jekyll (2.5.2) + classifier-reborn (~> 2.0) + colorator (~> 0.1) + jekyll-coffeescript (~> 1.0) + jekyll-gist (~> 1.0) + jekyll-paginate (~> 1.0) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 1.1) + kramdown (~> 1.3) + liquid (~> 2.6.1) + mercenary (~> 0.3.3) + pygments.rb (~> 0.6.0) + redcarpet (~> 3.1) + safe_yaml (~> 1.0) + toml (~> 0.1.0) + jekyll-coffeescript (1.0.1) + coffee-script (~> 2.2) + jekyll-gist (1.1.0) + jekyll-paginate (1.1.0) + jekyll-sass-converter (1.3.0) + sass (~> 3.2) + jekyll-watch (1.2.0) + listen (~> 2.7) + kramdown (1.5.0) + liquid (2.6.1) + listen (2.8.4) + celluloid (>= 0.15.2) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + mercenary (0.3.5) + parslet (1.5.0) + blankslate (~> 2.0) + posix-spawn (0.3.9) + pygments.rb (0.6.0) + posix-spawn (~> 0.3.6) + yajl-ruby (~> 1.1.0) + rainbow (2.0.0) + rb-fsevent (0.9.4) + rb-inotify (0.9.5) + ffi (>= 0.5.0) + redcarpet (3.2.2) + rouge (1.7.4) + safe_yaml (1.0.4) + sass (3.4.9) + scss-lint (0.31.0) + rainbow (~> 2.0) + sass (~> 3.4.1) + timers (4.0.1) + hitimes + toml (0.1.2) + parslet (~> 1.5.0) + yajl-ruby (1.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + jekyll (~> 2.5.2) + rouge (~> 1.7.4) + sass (~> 3.4.9) + scss-lint (~> 0.31) diff --git a/Gruntfile.js b/Gruntfile.js index d09e6f5606..582f4ac308 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -17,6 +17,7 @@ module.exports = function (grunt) { var fs = require('fs'); var path = require('path'); + var glob = require('glob'); var npmShrinkwrap = require('npm-shrinkwrap'); var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js'); @@ -144,25 +145,6 @@ module.exports = function (grunt) { files: 'js/tests/index.html' }, - sass: { - options: { - includePaths: ['scss'], - precision: 6, - sourceComments: false, - sourceMap: true - }, - core: { - files: { - 'dist/css/<%= pkg.name %>.css': 'scss/<%= pkg.name %>.scss' - } - }, - docs: { - files: { - 'docs/assets/css/docs.min.css': 'docs/assets/scss/docs.scss' - } - } - }, - scsslint: { scss: ['scss/*.scss', '!scss/_normalize.scss'], options: { @@ -342,13 +324,23 @@ module.exports = function (grunt) { exec: { npmUpdate: { command: 'npm update' + }, + bundleUpdate: { + command: function () { + // Update dev gems and all the test gemsets + return 'bundle update && ' + glob.sync('test-infra/gemfiles/*.gemfile').map(function (gemfile) { + return 'BUNDLE_GEMFILE=' + gemfile + ' bundle update'; + }).join(' && '); + } } } }); // These plugins provide necessary tasks. - require('load-grunt-tasks')(grunt, { scope: 'devDependencies' }); + require('load-grunt-tasks')(grunt, { scope: 'devDependencies', + // Exclude Sass compilers. We choose the one to load later on. + pattern: ['grunt-*', '!grunt-sass', '!grunt-contrib-sass'] }); require('time-grunt')(grunt); // Docs HTML validation task @@ -366,7 +358,8 @@ module.exports = function (grunt) { // Skip core tests if running a different subset of the test suite if (runSubset('core') && // Skip core tests if this is a Savage build - process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'test-js', 'docs']); + process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { + testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'test-js', 'docs']); } // Skip HTML validation if running a different subset of the test suite if (runSubset('validate-html') && @@ -392,7 +385,12 @@ module.exports = function (grunt) { grunt.registerTask('test-scss', ['scsslint:scss']); // CSS distribution task. + // Supported Compilers: sass (Ruby) and libsass. + (function (sassCompilerName) { + require('./grunt/bs-sass-compile/' + sassCompilerName + '.js')(grunt); + })(process.env.TWBS_SASS || 'libsass'); grunt.registerTask('sass-compile', ['sass:core', 'sass:docs']); + grunt.registerTask('dist-css', ['sass-compile', 'autoprefixer:core', 'usebanner', 'csscomb:dist', 'cssmin:core', 'cssmin:docs']); // Full distribution task. @@ -435,4 +433,7 @@ module.exports = function (grunt) { done(); }); }); + // Task for updating the cached RubyGem packages used by the Travis build (which are controlled by test-infra/Gemfile.lock). + // This task should be run and the updated file should be committed whenever Bootstrap's RubyGem dependencies change. + grunt.registerTask('update-gemfile-lock', ['exec:bundleUpdate']); }; diff --git a/grunt/bs-sass-compile/libsass.js b/grunt/bs-sass-compile/libsass.js new file mode 100644 index 0000000000..e3d13a989f --- /dev/null +++ b/grunt/bs-sass-compile/libsass.js @@ -0,0 +1,26 @@ +// Compile Bootstrap with [libsass][1] using [grunt-sass][2] +// [1]: https://github.com/sass/libsass +// [2]: https://github.com/sindresorhus/grunt-sass +module.exports = function configureLibsass(grunt) { + grunt.config.merge({ + sass: { + options: { + includePaths: ['scss'], + precision: 6, + sourceComments: false, + sourceMap: true + }, + core: { + files: { + 'dist/css/<%= pkg.name %>.css': 'scss/<%= pkg.name %>.scss' + } + }, + docs: { + files: { + 'docs/assets/css/docs.min.css': 'docs/assets/scss/docs.scss' + } + } + } + }); + grunt.loadNpmTasks('grunt-sass'); +}; diff --git a/grunt/bs-sass-compile/sass.js b/grunt/bs-sass-compile/sass.js new file mode 100644 index 0000000000..d7743515d8 --- /dev/null +++ b/grunt/bs-sass-compile/sass.js @@ -0,0 +1,30 @@ +// Compile Bootstrap with [Ruby Sass][1] using [grunt-contrib-sass][2] +// [1]: https://github.com/sass/sass +// [2]: https://github.com/gruntjs/grunt-contrib-sass +module.exports = function configureRubySass(grunt) { + var options = { + loadPath: ['scss'], + precision: 6, + sourcemap: 'auto', + style: 'expanded', + trace: true, + bundleExec: true + }; + grunt.config.merge({ + sass: { + core: { + options: options, + files: { + 'dist/css/<%= pkg.name %>.css': 'scss/<%= pkg.name %>.scss' + } + }, + docs: { + options: options, + files: { + 'docs/assets/css/docs.min.css': 'docs/assets/scss/docs.scss' + } + } + } + }); + grunt.loadNpmTasks('grunt-contrib-sass'); +}; diff --git a/package.json b/package.json index 049eec9999..8d0502a83e 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "grunt-contrib-jade": "~0.13.0", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-qunit": "~0.5.2", + "grunt-contrib-sass": "^0.8.1", "grunt-contrib-uglify": "~0.6.0", "grunt-contrib-watch": "~0.6.1", "grunt-csscomb": "~3.0.0", diff --git a/test-infra/S3Cachefile.json b/test-infra/S3Cachefile.json index 04d8092467..90eae796dc 100644 --- a/test-infra/S3Cachefile.json +++ b/test-infra/S3Cachefile.json @@ -5,8 +5,8 @@ "generate": "./uncached-npm-install.sh" }, "rubygems": { - "key": "../pseudo_Gemfile.lock", - "cache": "$GEMDIR", - "generate": "gem install -N scss-lint -v $SCSS_LINT_VERSION && gem install -N jekyll -v $JEKYLL_VERSION && gem install -N rouge -v $ROUGE_VERSION" + "key": "$BUNDLE_GEMFILE", + "cache": "../vendor/cache", + "generate": "cd .. ; bundle install --path=\"`pwd`/vendor/cache\"" } } diff --git a/test-infra/gemfiles/core.gemfile b/test-infra/gemfiles/core.gemfile new file mode 100644 index 0000000000..6a83726919 --- /dev/null +++ b/test-infra/gemfiles/core.gemfile @@ -0,0 +1,7 @@ +# Ruby Gems for the 'core' set of tests +# Run `grunt update-gemfile-lock` to update to the latest compatible versions + +source 'https://rubygems.org' + +gem 'sass', '~> 3.4.9' +gem 'scss-lint', '~> 0.31' diff --git a/test-infra/gemfiles/core.gemfile.lock b/test-infra/gemfiles/core.gemfile.lock new file mode 100644 index 0000000000..03580d83bb --- /dev/null +++ b/test-infra/gemfiles/core.gemfile.lock @@ -0,0 +1,15 @@ +GEM + remote: https://rubygems.org/ + specs: + rainbow (2.0.0) + sass (3.4.9) + scss-lint (0.31.0) + rainbow (~> 2.0) + sass (~> 3.4.1) + +PLATFORMS + ruby + +DEPENDENCIES + sass (~> 3.4.9) + scss-lint (~> 0.31)