#!/bin/bash set -euo pipefail trap 'kill 0' SIGINT status=0 green='\e[1;32m'; red='\e[1;31m'; cyan='\e[1;36m'; yellow='\e[1;33m'; reset='\e[0m' user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" max_jobs=10 pids=() running_jobs() { jobs -rp | wc -l } while IFS=: read -r filepath url; do ( code=$(curl -k -gsLm30 --retry 3 --retry-delay 3 --retry-connrefused -o /dev/null -w "%{http_code}" -I "$url") || code=000 if [ "$code" -lt 200 ] || [ "$code" -ge 400 ]; then sleep 1 code=$(curl -k -gsLm30 --retry 3 --retry-delay 3 --retry-connrefused -o /dev/null -w "%{http_code}" -r 0-0 -A "$user_agent" -H "Accept-Language: en-US,en" -H "Connection: keep-alive" "$url") || code=000 fi if [ "$code" -lt 200 ] || [ "$code" -ge 400 ]; then sleep 1 request_id=$(curl -sS -G -H 'Accept: application/json' \ --data-urlencode "host=$url" \ --data-urlencode "max_nodes=1" \ --data-urlencode "node=us3.node.check-host.net" \ https://check-host.net/check-http \ | jq -r .request_id) || request_id="" if [ -n "$request_id" ]; then sleep 5 for _ in {1..5}; do new_code=$(curl -sS -H 'Accept: application/json' \ "https://check-host.net/check-result/$request_id" \ | jq -r -e '.[][0][3]') || new_code=000 [[ "$new_code" =~ ^[0-9]+$ ]] || new_code=000 if [ "$new_code" -ge 200 ] && [ "$new_code" -lt 400 ]; then code=$new_code break fi sleep 5 done fi fi # Treat Cloudflare JS-challenge and rate-limit as success. if [[ "$code" == "403" || "$code" == "429" || "$code" == "503" ]]; then printf "${yellow}WARN %s${reset} ${cyan}%s${reset} %s\n" "$code" "$url" "$filepath" exit 0 fi if [ "$code" -lt 200 ] || [ "$code" -ge 400 ]; then printf "${red}FAIL %s${reset} ${yellow}%s${reset} %s\n" "$code" "$url" "$filepath" >&2 exit 1 else printf "${green} OK %s${reset} ${cyan}%s${reset} %s\n" "$code" "$url" "$filepath" exit 0 fi ) & pids+=($!) while [ "$(running_jobs)" -ge "$max_jobs" ]; do sleep 1 done done < <( pattern='(?!.*@lint-ignore)(?\")]*[<>\{\}\$])[[:alnum:]][^[:space:]<>")\[\]\\|]*' excludes=( ':(exclude,glob)**/.*' ':(exclude,glob)**/*.lock' ':(exclude,glob)**/*.svg' ':(exclude,glob)**/*.xml' ':(exclude,glob)**/*.gradle*' ':(exclude,glob)**/*gradle*' ':(exclude,glob)**/third-party/**' ':(exclude,glob)**/third_party/**' ) if [ $# -eq 2 ]; then for filename in $(git diff --name-only --unified=0 "$1...$2"); do git diff --unified=0 "$1...$2" -- "$filename" "${excludes[@]}" \ | grep -E '^\+' \ | grep -Ev '^\+\+\+' \ | perl -nle 'print for m#'"$pattern"'#g' \ | sed 's|^|'"$filename"':|' done else git --no-pager grep --no-color -I -P -o "$pattern" -- . "${excludes[@]}" fi \ | sed -E 's/[^/[:alnum:]]+$//' \ | grep -Ev '://(0\.0\.0\.0|127\.0\.0\.1|localhost)([:/])' \ | grep -Ev '://[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' \ | grep -Ev 'fwdproxy:8080' \ || true ) for pid in "${pids[@]}"; do wait "$pid" 2>/dev/null || { case $? in 1) status=1 ;; 127) ;; # ignore "not a child" noise *) exit $? ;; esac } done exit $status