Skip to content

Commit

Permalink
Lint Sass files using the rules in stylelint-config-edx
Browse files Browse the repository at this point in the history
Fixes
  • Loading branch information
andy-armstrong committed Sep 12, 2017
1 parent 76d3b62 commit e5cab61
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 8 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
"plato": "1.2.2",
"selenium-webdriver": "3.4.0",
"sinon": "2.3.5",
"squirejs": "^0.1.0"
"squirejs": "^0.1.0",
"@edx/stylelint-config-edx": "^1.1.0",
"stylelint-formatter-pretty": "^1.0.3"
}
}
8 changes: 4 additions & 4 deletions pavelib/paver_tests/test_eslint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Tests for paver quality tasks
Tests for Paver's Stylelint tasks.
"""
import unittest

Expand All @@ -9,13 +9,13 @@
import pavelib.quality


class TestPaverESLint(unittest.TestCase):
class TestPaverStylelint(unittest.TestCase):
"""
For testing run_eslint
For testing run_stylelint
"""

def setUp(self):
super(TestPaverESLint, self).setUp()
super(TestPaverStylelint, self).setUp()

# Mock the paver @needs decorator
self._mock_paver_needs = patch.object(pavelib.quality.run_eslint, 'needs').start()
Expand Down
37 changes: 37 additions & 0 deletions pavelib/paver_tests/test_stylelint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Tests for Paver's Stylelint tasks.
"""
import ddt
from mock import MagicMock, patch
from paver.easy import call_task

from .utils import PaverTestCase


@ddt.ddt
class TestPaverStylelint(PaverTestCase):
"""
Tests for Paver's Stylelint tasks.
"""

def setUp(self):
super(TestPaverStylelint, self).setUp()
pass

@ddt.data(
[0, False],
[99, False],
[100, True],
)
@ddt.unpack
def test_run_stylelint(self, violations_limit, should_pass):
"""
Verify that the quality task fails with Stylelint violations.
"""
_mock_stylelint_violations = MagicMock(return_value=100)
with patch('pavelib.quality._get_stylelint_violations', _mock_stylelint_violations):
if should_pass:
call_task('pavelib.quality.run_stylelint', options={"limit": violations_limit})
else:
with self.assertRaises(SystemExit):
call_task('pavelib.quality.run_stylelint', options={"limit": violations_limit})
66 changes: 63 additions & 3 deletions pavelib/quality.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# coding=utf-8

"""
Check code quality using pep8, pylint, and diff_quality.
"""
Expand All @@ -6,7 +8,7 @@
import re
from string import join

from paver.easy import BuildFailure, cmdopts, needs, sh, task
from paver.easy import BuildFailure, call_task, cmdopts, needs, sh, task

from openedx.core.djangolib.markup import HTML

Expand Down Expand Up @@ -189,7 +191,7 @@ def _get_pep8_violations():
"{report_dir}/pep8.report".format(report_dir=report_dir)
)

return (count, violations_list)
return count, violations_list


def _pep8_violations(report_file):
Expand Down Expand Up @@ -315,6 +317,64 @@ def run_eslint(options):
)


def _get_stylelint_violations():
"""
Returns the number of Stylelint violations.
"""
stylelint_report_dir = (Env.REPORT_DIR / "stylelint")
stylelint_report = stylelint_report_dir / "stylelint.report"
_prepare_report_dir(stylelint_report_dir)
formatter = 'node_modules/stylelint-formatter-pretty'

sh(
"stylelint **/*.scss --custom-formatter={formatter} | tee {stylelint_report}".format(
formatter=formatter,
stylelint_report=stylelint_report,
),
ignore_error=True
)

try:
return int(_get_count_from_last_line(stylelint_report, "eslint"))
except TypeError:
raise BuildFailure(
"Error. Number of eslint violations could not be found in {eslint_report}".format(
eslint_report=stylelint_report
)
)


@task
@needs('pavelib.prereqs.install_node_prereqs')
@cmdopts([
("limit=", "l", "limit for number of acceptable violations"),
])
@timed
def run_stylelint(options):
"""
Runs stylelint on Sass files.
If limit option is passed, fails build if more violations than the limit are found.
"""
violations_limit = int(getattr(options, 'limit', -1))
num_violations = _get_stylelint_violations()

# Record the metric
_write_metric(num_violations, (Env.METRICS_DIR / "stylelint"))

# Fail if number of violations is greater than the limit
if num_violations > violations_limit > -1:
raise BuildFailure(
"Stylelint failed with too many violations: ({count}).\nThe limit is {violations_limit}.".format(
count=num_violations,
violations_limit=violations_limit,
)
)
if num_violations > 0:
print("Stylelint succeeded with no more violations than {violations_limit}".format(
violations_limit=violations_limit,
))


@task
@needs('pavelib.prereqs.install_python_prereqs')
@cmdopts([
Expand Down Expand Up @@ -518,7 +578,7 @@ def _get_count_from_last_line(filename, file_type):
This will return the number in the last line of a file.
It is returning only the value (as a floating number).
"""
last_line = _get_report_contents(filename, last_line_only=True)
last_line = _get_report_contents(filename, last_line_only=True).strip()
if file_type is "python_complexity":
# Example of the last line of a complexity report: "Average complexity: A (1.93953443446)"
regex = r'\d+.\d+'
Expand Down
1 change: 1 addition & 0 deletions scripts/all-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set -e
# Violations thresholds for failing the build
export PYLINT_THRESHOLD=3600
export ESLINT_THRESHOLD=9134
export STYLELINT_THRESHOLD=18431

XSSLINT_THRESHOLDS=`cat scripts/xsslint_thresholds.json`
export XSSLINT_THRESHOLDS=${XSSLINT_THRESHOLDS//[[:space:]]/}
Expand Down
3 changes: 3 additions & 0 deletions scripts/circle-ci-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ else
echo "Finding ESLint violations and storing report..."
paver run_eslint -l $ESLINT_THRESHOLD > eslint.log || { cat eslint.log; EXIT=1; }

echo "Finding Stylelint violations and storing report..."
paver run_stylelint -l $STYLELINT_THRESHOLD > stylelint.log || { cat stylelint.log; EXIT=1; }

# Run quality task. Pass in the 'fail-under' percentage to diff-quality
paver run_quality -p 100 || EXIT=1

Expand Down
2 changes: 2 additions & 0 deletions scripts/generic-ci-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ case "$TEST_SUITE" in

echo "Finding ESLint violations and storing report..."
paver run_eslint -l $ESLINT_THRESHOLD > eslint.log || { cat eslint.log; EXIT=1; }
echo "Finding Stylelint violations and storing report..."
paver run_stylelint -l $STYLELINT_THRESHOLD > stylelint.log || { cat stylelint.log; EXIT=1; }
echo "Running code complexity report (python)."
paver run_complexity || echo "Unable to calculate code complexity. Ignoring error."
echo "Running xss linter report."
Expand Down
3 changes: 3 additions & 0 deletions stylelint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: '@edx/stylelint-config-edx'
};

0 comments on commit e5cab61

Please sign in to comment.