diff --git a/.circleci/config.yml b/.circleci/config.yml index 328faa1561..25f0d08b77 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -49,9 +49,18 @@ jobs: - run: name: Report coverage command: bash <(curl -s https://codecov.io/bash) + + - restore_cache: + key: v1-vuln-scans-{{ checksum "yarn.lock" }} - run: name: Vulnerability Tests command: yarn test:vulns + # https://discuss.circleci.com/t/add-mechanism-to-update-existing-cache-key/9014/12 + - save_cache: + key: v1-vuln-scans-{{ checksum "yarn.lock" }}-{{ epoch }} + paths: + - .vuln-scans + - run: name: Visual Tests command: yarn test:visual diff --git a/build/gulp/tasks/test-vulns.ts b/build/gulp/tasks/test-vulns.ts new file mode 100644 index 0000000000..b20351292e --- /dev/null +++ b/build/gulp/tasks/test-vulns.ts @@ -0,0 +1,65 @@ +import * as fs from 'fs' +import { task } from 'gulp' +import * as path from 'path' +import debug from 'debug' + +import config from '../../../config' +import sh from '../sh' + +const { paths } = config + +const SCAN_RESULTS_DIR_NAME = '.vuln-scans' +const SCAN_RESULTS_DIR_PATH = paths.base(SCAN_RESULTS_DIR_NAME) + +const log = message => debug.log(message) +log.success = message => debug.log(`✔ ${message}`) + +const ensureDirExists = path => { + if (!fs.existsSync(path)) { + sh(`mkdir -p ${path}`) + } +} + +const getTodayScanFilePath = () => { + const now = new Date() + + const year = now.getUTCFullYear() + const month = now.getUTCMonth() + 1 + const date = now.getUTCDate() + + const fileName = `snyk-scanned-${year}-${month}-${date}` + + return path.resolve(SCAN_RESULTS_DIR_PATH, fileName) +} + +const recentlyChecked = () => { + const recentCheckFilePath = getTodayScanFilePath() + return fs.existsSync(recentCheckFilePath) +} + +const registerRecentSucessfulScan = async () => { + ensureDirExists(SCAN_RESULTS_DIR_PATH) + + const recentScanFilePath = getTodayScanFilePath() + await sh(`touch ${recentScanFilePath}`) +} + +/** + * The following strategy is used to perform vulnerabilites scan + * - check if there is marker of recent sucessful scan + * - if this marker exists, skip checks + * - if there is no marker, perform check + * - if check is successful, create successful check marker + */ +task('test:vulns', async () => { + if (recentlyChecked()) { + log.success('Vulnerabilities check was already performed recently, skipping..') + return + } + + log('Scanning dependency packages for vulnerabilities..') + await sh(`yarn snyk test`) + log.success('Vulnerability scan is successfully passed.') + + registerRecentSucessfulScan() +}) diff --git a/gulpfile.ts b/gulpfile.ts index ba23bc51e9..c34184f67a 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -14,6 +14,7 @@ require('./build/gulp/tasks/screener') require('./build/gulp/tasks/git') require('./build/gulp/tasks/test-unit') require('./build/gulp/tasks/test-projects') +require('./build/gulp/tasks/test-vulns') // global tasks task('build', series('dll', parallel('dist', 'build:docs'))) diff --git a/package.json b/package.json index a9d2b60649..d645944e84 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "pretest": "yarn satisfied", "test": "gulp test", "test:watch": "gulp test:watch", - "test:vulns": "snyk test", + "test:vulns": "gulp test:vulns", "test:visual": "gulp screener", "test:projects": "gulp test:projects", "generate:component": "gulp generate:component"