Skip to content

Instantly share code, notes, and snippets.

@carwin
Last active December 26, 2019 14:14
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save carwin/5121862 to your computer and use it in GitHub Desktop.
Save carwin/5121862 to your computer and use it in GitHub Desktop.
Continuous Integration with Jenkins and SASS

Continuous Integration with SASS and Jenkins

This document explains how we can use Jenkins to solve some SASS/Git headaches.

The Problem at Hand

One of the problems that we deal with when working with SASS and Git is that the CSS added to the remote repository changes based on who compiled it.

That means every time someone commits to the remote repository before we can push our work up, HEAD will have changed and our push attempt will be rejected.

There are a few options for dealing with that scenario, including git stash, git pull --rebase, etc... but there will always be some extra step required where we must deal with the compiled CSS before we can commit our work to the remote repository. As soon as we do, other developers face the same situation which becomes a massive time-sink after a day or two.

At a higher level, the issue is that developers need to work with SASS locally, in whatever way is most efficient for them, without affecting the compiled output that exists in the remote repository. E.g., Developer A uses tools that require FireSASS to be used during compilation. Developer B doesn't use FireSASS, but does require CR LF line endings for his tools to behave properly. Both developers are compiling CSS that is both unsuitable for a production environment and nightmarish to diff or merge between branches.

The Solution

Simply "dealing with the problem" is not an efficient way to develop using a CSS preprocessor like SASS where compilation happens with nearly every commit.

One solution would be to standardize the way SASS compiles CSS. This, however, introduces a new kind of time-sink wherein developers must abandon their known workflows and toolsets in favor of working in exactly the same way, which reduces their efficiency further.

To suit the needs of developers working with SASS without impacting their productivity, we can use our already existing CI workflows using Jenkins.

The idea is to add a Jenkins job to watch a specific branch of the repository. When a commit is pushed to that branch, Jenkins merges that remote branch with its own local branch, compiles the SASS into CSS, commits the new CSS, merges with the master branch, and pushes its local master branch to the remote.

Technical Details

For explanations in this section, use this example scenario:

There are 2 Developers (A & B) and 3 branches (master, frontend, a-feature) of a repository. Jenkins is watching the frontend branch for changes.

So how do we deal with the .css and config.rb files?

  • The project's .gitignore file is be set to ignore *.css and config.rb.

  • An initial compilation of CSS is performed and forcefully committed to the master branch along with a config.rb suitable for the dev/staging server.

      git add --force css/*.css
    
  • After this point, only Jenkins builds will be pushing new CSS to master.1

  • Locally, developers can either tell git to ignore local modifications to their config.rb and the CSS they compile while developing or alternatively, they can simply ignore git's notices about untracked files by doing nothing.

      git update-index --assume-unchanged [<file>...]
    

[1](id: footnote1) If necessary, this could be done manually with a subsequent force push to the branch.

An example of workflow

  1. Developer A commits his final change to a-feature.
  2. Developer B has updated the remote frontend branch since a-feature was branched from it. Developer A now merges the branches locally.
  3. Now that Developer A's local clone of frontend is ahead of the remote, he pushes up to the remote repository.
  4. Jenkins sees that frontend has been changed and begins its job:
    • check out local frontend
    • pull remote frontend
    • rebase frontend on top of master to get config.rb
    • compile SASS into CSS
    • checkout local master
    • pull from remote master just in case
    • merge master with frontend
    • push local master to remote master.
  5. Both Developer A and Developer B dance around the council fires of their people.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment