From 63c7eed2a9f954757c0c244337a734f98972f3a9 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Fri, 31 Mar 2017 16:00:59 +0100 Subject: [PATCH] chore: add a require() checking script (#1237) * chore: Add a require() checking script This adds another sanity-check bash script to scan the Etcher source files and check all required node modules are available. * Workaround for jq crash on Windows --- Makefile | 1 + scripts/ci/builtin-modules.json | 35 ++++++ .../ensure-all-node-requirements-available.sh | 112 ++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 scripts/ci/builtin-modules.json create mode 100755 scripts/ci/ensure-all-node-requirements-available.sh diff --git a/Makefile b/Makefile index d39bc7fd..670943cc 100644 --- a/Makefile +++ b/Makefile @@ -498,6 +498,7 @@ info: @echo "Target arch : $(TARGET_ARCH)" sanity-checks: + ./scripts/ci/ensure-all-node-requirements-available.sh ./scripts/ci/ensure-staged-sass.sh ./scripts/ci/ensure-npm-dependencies-compatibility.sh ./scripts/ci/ensure-npm-shrinkwrap-versions.sh diff --git a/scripts/ci/builtin-modules.json b/scripts/ci/builtin-modules.json new file mode 100644 index 00000000..72670f6b --- /dev/null +++ b/scripts/ci/builtin-modules.json @@ -0,0 +1,35 @@ +[ + "assert", + "buffer", + "child_process", + "cluster", + "console", + "constants", + "crypto", + "dgram", + "dns", + "domain", + "events", + "fs", + "http", + "https", + "module", + "net", + "os", + "path", + "process", + "punycode", + "querystring", + "readline", + "repl", + "stream", + "string_decoder", + "timers", + "tls", + "tty", + "url", + "util", + "v8", + "vm", + "zlib" +] diff --git a/scripts/ci/ensure-all-node-requirements-available.sh b/scripts/ci/ensure-all-node-requirements-available.sh new file mode 100755 index 00000000..c5ff1b59 --- /dev/null +++ b/scripts/ci/ensure-all-node-requirements-available.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +### +# Copyright 2017 resin.io +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +### + +set -u +set -e + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +"$HERE/../build/check-dependency.sh" jq +"$HERE/../build/check-dependency.sh" git + +PACKAGE_JSON=package.json + +# builtin-modules.json from https://github.com/sindresorhus/builtin-modules +#NODE_MODULES=($(jq -r '.[]' "$HERE/builtin-modules.json")) +# workaround for path-length bug in jq that only affects Windows https://github.com/stedolan/jq/issues/1155 +NODE_MODULES=($(cat "$HERE/builtin-modules.json" | jq -r '.[]')) +NPM_MODULES=($(jq -r '.dependencies | keys | .[]' "$PACKAGE_JSON")) +NPM_OPTIONAL_MODULES=($(jq -r '.optionalDependencies | keys | .[]' "$PACKAGE_JSON")) +NPM_DEV_MODULES=($(jq -r '.devDependencies | keys | .[]' "$PACKAGE_JSON")) + + +DEV_FILES_REGEX=^\(tests\|scripts\)/ + +# need to do a non-greedy match, which is why we're not using (.*) +REQUIRE_REGEX=require\\\(\'\([-_/\.a-z0-9]+\)\'\\\) + +# Check all js files stored in the repo can require() the packages they need +git ls-tree -r HEAD | while IFS='' read line; do + if [[ "$(echo $line | cut -d ' ' -f 2)" == "blob" ]]; then + # the cut delimiter in the line below is actually a tab character, not a space + fullpath=$(echo "$line" | cut -d ' ' -f 2) + filename=$(basename $fullpath) + extension=${filename##*.} + if [[ "$extension" == "js" ]]; then + # 'grep -v' to filter out any comment-blocks + grep 'require(' "$fullpath" | grep -v "^ \* " | while IFS='' read line; do + if [[ "$line" =~ $REQUIRE_REGEX ]]; then + required=${BASH_REMATCH[1]} + fi + requirement_found=0 + if [[ "$required" =~ "/" ]]; then + localpath="$(dirname "$fullpath")/$required" + if [[ -f "$localpath" ]] || [[ -f "$localpath.js" ]] || [[ -f "$localpath/index.js" ]]; then + requirement_found=1 + fi + else + # electron is implictly available + if [[ "$required" == "electron" ]]; then + requirement_found=1 + fi + # Check builtin modules + if [[ $requirement_found -eq 0 ]]; then + for module in "${NODE_MODULES[@]}"; do + if [[ "$required" == "$module" ]]; then + requirement_found=1 + break + fi + done + fi + # Check dependencies from package.json + if [[ $requirement_found -eq 0 ]]; then + for module in "${NPM_MODULES[@]}"; do + if [[ "$required" == "$module" ]]; then + requirement_found=1 + break + fi + done + fi + # Check optionalDependencies from package.json + if [[ $requirement_found -eq 0 ]]; then + for module in "${NPM_OPTIONAL_MODULES[@]}"; do + if [[ "$required" == "$module" ]]; then + requirement_found=1 + break + fi + done + fi + # Check devDependencies from package.json if it's in particular subdirectories + if [[ $requirement_found -eq 0 ]] && [[ "$fullpath" =~ $DEV_FILES_REGEX ]]; then + for module in "${NPM_DEV_MODULES[@]}"; do + if [[ "$required" == "$module" ]]; then + requirement_found=1 + break + fi + done + fi + fi + if [[ $requirement_found -eq 0 ]]; then + echo "$fullpath requires '$required' module which can't be located" + exit 1 + fi + done + fi + fi +done +