Tuesday, July 21, 2015

JSCS for different platforms

We use jscs in our project. It's nice tool, and has nice feature, it allows to use configuration files from the other teams. We decided to take one from Airbnb. Everything was great, but there is one problem, some developers in our team use Windows environments, other Mac OS, and our build machine is hosted on Debian. It brings us the situation that some machine have CRLF line endings and some LF endings. And we need some way to use jscs on the all environments. Since we use gulp task manager, it was logical to include jscs check in our build process, and in order to make it work we just put one if statement that overrides line endings rule based on the OS where the script is executed.

.jscsrc file

{
  "preset": "airbnb",
  "fileExtensions": [ ".js" ],
  "validateLineBreaks": 'LF'
}

Function inside gulp files, that reads and adjust if need .jscsrc


function readRules() {
  return new Promise((resolve, reject) => fs.readFile('.jscsrc', (error, data) => {
    if (error) {
      reject(error);
    }
    else {
      let config = JSON.parse(data);
      if (os.platform() === 'win32') {
        config.validateLineBreaks = 'CRLF'
      }

      resolve(config);
    }
  }));
}

It was fine and worked fine for us. Another problem that we ran into was Webstorm support. Webstorm is a very cool IDE for javascript and turned out to be, that it also supports jscs validation out of the box. You just need go to the settings and enable it. But the same issue as before, we have different environments and Webstorm parses all sources and applies jscs config to each of them, but there is now way to apply any conditions. We didn't find any nice way to tune that behavior for Webstorm, We decided to simply ignore line endings during development process in IDE but still have it as a part of our build script. So we just disable that rule completely by setting  validateLineBreaks to null.

.jscsrc file that suppress validateLineBreaks from parent configuration(airbnb)

{
  "preset": "airbnb",
  "fileExtensions": [ ".js" ],
  "validateLineBreaks": null
}

It means that validation by Webstorm, which simply runs node.js under the hood and passes jscssrc.json as a parameter, will consider all line endings to be correct. OK, great, one small thing to change is gulp task, to put both line endings into play, instead of overriding as before, since now jscs has it to be set to NULL.

Adjusted function in gulp file that set correct line endings for both OS's


function readRules() {
  return new Promise((resolve, reject) => fs.readFile('.jscsrc', (error, data) => {
    if (error) {
      reject(error);
    }
    else {
      let config = JSON.parse(data);

      config.validateLineBreaks = os.platform() === 'win32' ? 'CRLF' : 'LF';

      resolve(config);
    }
  }));
}

Some things to mention:
1. Since we take Airbnb version as base one, we get settings where validateLineBreaks set to LF
2. Why do we care about line endings at all...well it's a good practice and we want to be consistent.
3. How does it work between environments?! Git does the magic. We simply set autocrlf setting to true. It means that every time somebody checkout sources under Windows OS git normalized all files and replace LF with CRLF, on *NIX environments git replace CRLF line endings with LF, of cause if there are such.

Summary:
1. There is no way to put some conditions into jscsrc
2. By setting jscs rule to null we can disable it completely
2. Some OS specific validation like validateLineBreaks could be a part of a build task(gulp, grunt, etc.)