name: Test Skins on: push: pull_request: jobs: link-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Validate links and assets shell: bash run: | set -uo pipefail RED="\033[31m" GREEN="\033[32m" RESET="\033[0m" ERRORS=() urldecode() { printf '%b' "${1//%/\\x}" } check_http() { local url="$1" echo " → Checking external: $url" # HEAD request if curl -Is --max-time 10 "$url" | head -n1 | grep -qE "HTTP/.* (200|30[0-9])"; then return 0 fi # GET fallback if curl -Is --max-time 10 -X GET "$url" | head -n1 | grep -qE "HTTP/.* (200|30[0-9])"; then return 0 fi return 1 } check_local() { local path="$1" path="${path#/}" local decoded decoded=$(urldecode "$path") echo " → Checking local: $decoded" if [[ ! -e "$decoded" ]]; then return 1 fi return 0 } extract_links() { local f="$1" grep -oE '\[[^]]*\]\([^)]*\)' "$f" \ | sed -E 's/.*\((.*)\).*/\1/' grep -oE '!\[[^]]*\]\([^)]*\)' "$f" \ | sed -E 's/.*\((.*)\).*/\1/' grep -oE 'https?://[^ )"]+' "$f" grep -oE ']*src="[^"]+"' "$f" \ | sed -E 's/.*src="([^"]*)".*/\1/' grep -oE ']*src="[^"]+"' "$f" \ | sed -E 's/.*src="([^"]*)".*/\1/' } echo "🔍 Scanning Markdown files..." echo find . -type f -name '*.md' | while IFS= read -r mdfile; do echo "📄 Checking: $mdfile" while IFS= read -r url; do [[ -z "$url" ]] && continue [[ "$url" == mailto:* ]] && continue # Skip tag links inside /docs → but **do NOT print them** if [[ "$mdfile" == ./docs/* ]] && [[ "$url" == *"/src/tag/"* ]]; then continue fi if [[ "$url" == http* ]]; then if ! check_http "$url"; then ERRORS+=("❌ Broken external link: $url (in $mdfile)") fi else if ! check_local "$url"; then ERRORS+=("❌ Missing local file: $url (in $mdfile)") fi fi done < <(extract_links "$mdfile") echo done echo if (( ${#ERRORS[@]} > 0 )); then echo -e "${RED}✖ Errors found:${RESET}" printf "%s\n" "${ERRORS[@]}" echo echo -e "${RED}❌ Failing job because broken links were found.${RESET}" exit 1 else echo -e "${GREEN}✔ All links OK!${RESET}" fi