From b986bd668cbfd57fe08d7c8c9697f607b1545989 Mon Sep 17 00:00:00 2001 From: DaAwesomeP Date: Tue, 12 Jan 2016 20:25:36 -0600 Subject: [PATCH 1/2] catch bad PNG error, cache NPM CLI dependencies, remove phantom from Travis (already included) --- .travis.yml | 25 ++++++++++++++++--------- bin/wappalyzer-build | 15 +++++++++++---- bin/wappalyzer-validate | 2 +- bin/wappalyzer-validate-icons | 6 +++++- docker/Dockerfile | 2 +- docker/node/package.json | 23 +++++++++++++++++++++-- 6 files changed, 55 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f3a3bc7e..3fda78932 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,21 @@ language: node_js node_js: - - "4.2" + - "4" sudo: false before_install: - - export WAPPALYZER_ROOT=$TRAVIS_BUILD_DIR - - export WAPPALYZER_NODE_PATH=$TRAVIS_BUILD_DIR - - export PATH=$PATH:$TRAVIS_BUILD_DIR/bin -install: - - npm install jsonlint jpm imagemin-cli svgo -g - - ln -s docker/node/package.json package.json && npm install - - mkdir phantomjs && curl -L https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-x86_64.tar.bz2 | tar xvjC phantomjs && ln -s $WAPPALYZER_ROOT/phantomjs/phantomjs-*-linux-x86_64/bin/phantomjs bin/phantomjs -script: wappalyzer build + - export WAPPALYZER_ROOT=$TRAVIS_BUILD_DIR + - export WAPPALYZER_NODE_PATH=$TRAVIS_BUILD_DIR + - export PATH=$PATH:$TRAVIS_BUILD_DIR/bin + - ln -s docker/node/package.json package.json after_script: ls -l --block-size=kB build +cache: + directories: + - node_modules +env: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 diff --git a/bin/wappalyzer-build b/bin/wappalyzer-build index 8eb689945..0d48405a1 100755 --- a/bin/wappalyzer-build +++ b/bin/wappalyzer-build @@ -7,21 +7,28 @@ then exit 1 fi +if [ -z $WAPPALYZER_NODE_PATH ] +then + echo "\$WAPPALYZER_NODE_PATH not set" + + exit 1 +fi + set -eu wappalyzer validate echo "Prettifying apps.json..." -jsonlint -ist $'\t' $WAPPALYZER_ROOT/src/apps.json +node $WAPPALYZER_NODE_PATH/node_modules/jsonlint/lib/cli.js -ist $'\t' $WAPPALYZER_ROOT/src/apps.json echo "Compressing PNG icons..." -imagemin $WAPPALYZER_ROOT/src/icons $WAPPALYZER_ROOT/src/icons -o 7 +node $WAPPALYZER_NODE_PATH/node_modules/imagemin-cli/cli.js $WAPPALYZER_ROOT/src/icons $WAPPALYZER_ROOT/src/icons -o 7 echo "Compressing SVG icons..." -svgo -q -f $WAPPALYZER_ROOT/src/icons $WAPPALYZER_ROOT/src/icons +node $WAPPALYZER_NODE_PATH/node_modules/svgo/bin/svgo -q -f $WAPPALYZER_ROOT/src/icons $WAPPALYZER_ROOT/src/icons wappalyzer links @@ -34,7 +41,7 @@ echo "Building Firefox driver..." pushd $WAPPALYZER_ROOT/src/drivers/firefox > /dev/null -jpm xpi && mv *.xpi $WAPPALYZER_ROOT/build/wappalyzer_firefox.xpi +node $WAPPALYZER_NODE_PATH/node_modules/jpm/bin/jpm xpi && mv *.xpi $WAPPALYZER_ROOT/build/wappalyzer_firefox.xpi popd > /dev/null diff --git a/bin/wappalyzer-validate b/bin/wappalyzer-validate index a6e8c691e..d9d09a617 100755 --- a/bin/wappalyzer-validate +++ b/bin/wappalyzer-validate @@ -27,7 +27,7 @@ path="$path/src" echo "Validating apps.json..." -jsonlint --quiet -V $WAPPALYZER_ROOT/schema.json $path/apps.json +node $WAPPALYZER_NODE_PATH/node_modules/jsonlint/lib/cli.js --quiet -V $WAPPALYZER_ROOT/schema.json $path/apps.json echo "Validating regular expressions..." diff --git a/bin/wappalyzer-validate-icons b/bin/wappalyzer-validate-icons index 38a8cb2bf..3ec796ac6 100755 --- a/bin/wappalyzer-validate-icons +++ b/bin/wappalyzer-validate-icons @@ -31,7 +31,11 @@ for (app in json.apps) { if (exists) { if (type === "PNG") { var buffer = fileType(readChunk.sync(path, 0, 262)); - if (buffer.mime !== 'image/png') { + if (buffer === null) { + var err = new Error('Unknown mimetype or bad file for "' + app + '": src/icons/' + iconPath); + throw err; + } + else if (buffer.mime !== 'image/png') { var err = new Error('Incorrect mimetype "' + buffer.mime + '" when expected PNG for app "' + app + '": src/icons/' + iconPath); throw err; } diff --git a/docker/Dockerfile b/docker/Dockerfile index 857cf65a6..625b6bf14 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -32,7 +32,7 @@ RUN su wappalyzer -c "mkdir $WAPPALYZER_NODE_PATH" ADD node/package.json $WAPPALYZER_NODE_PATH/package.json -RUN npm install jsonlint jpm imagemin-cli svgo -g && su wappalyzer -c "cd $WAPPALYZER_NODE_PATH && npm install" +RUN su wappalyzer -c "cd $WAPPALYZER_NODE_PATH && npm i" # PhantomJS diff --git a/docker/node/package.json b/docker/node/package.json index 9855b7b74..b75954434 100644 --- a/docker/node/package.json +++ b/docker/node/package.json @@ -1,7 +1,26 @@ { + "name": "wappalyzer-test", + "private": true, + "license": "GPLv3", + "bugs": { + "url": "https://github.com/AliasIO/Wappalyzer/issues" + }, + "homepage": "https://github.com/AliasIO/Wappalyzer", + "description": "Build test for Wappalyzer", + "repository": "AliasIO/Wappalyzer", + "scripts": { + "test": "./bin/wappalyzer build" + }, "devDependencies": { - "file-type": "3.3.*", + "file-type": "3.4.*", "is-svg": "1.1.*", - "read-chunk": "1.0.*" + "read-chunk": "1.0.*", + "jsonlint": "*", + "jpm": "*", + "imagemin-cli": "*", + "svgo": "*" + }, + "engines": { + "node": ">= 4" } } From e2091fee3cf5c9fb718edef84240a36860a0029b Mon Sep 17 00:00:00 2001 From: DaAwesomeP Date: Tue, 12 Jan 2016 22:27:53 -0600 Subject: [PATCH 2/2] Fix Anchor Cache image --- src/icons/anchorCache.png | Bin 1 -> 13085 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/icons/anchorCache.png b/src/icons/anchorCache.png index 8b137891791fe96927ad78e64b0aad7bded08bdc..9e160bce568dec04f5be109e8da7b1a71e6b013b 100644 GIT binary patch literal 13085 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