From 183c1a6600c8cedcc53df8b0e7a11286d9357d31 Mon Sep 17 00:00:00 2001 From: AuraMindNest Date: Thu, 18 Jun 2026 08:20:42 -0600 Subject: [PATCH 1/6] Extract secret validation to lib.sh. --- .github/workflows/add-submodules.yml | 16 ++------- .github/workflows/assets/lib.sh | 45 +++++++++++++++++++++++-- .github/workflows/start-translation.yml | 26 ++------------ 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/.github/workflows/add-submodules.yml b/.github/workflows/add-submodules.yml index 5d45a01..b82b99b 100644 --- a/.github/workflows/add-submodules.yml +++ b/.github/workflows/add-submodules.yml @@ -34,12 +34,9 @@ jobs: LANG_CODES: ${{ github.event.client_payload.lang_codes || vars.LANG_CODES }} run: | set -euo pipefail - [[ -z "${LANG_CODES:-}" ]] && { - echo "Error: lang_codes not set in client_payload or vars.LANG_CODES." >&2 - exit 1 - } # shellcheck source=assets/lib.sh source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" + require_lang_codes mapfile -t lang_codes_arr < <(parse_list "$LANG_CODES") [[ ${#lang_codes_arr[@]} -eq 0 ]] && { echo "Error: LANG_CODES parsed to empty list." >&2; exit 1 @@ -57,16 +54,6 @@ jobs: run: | set -euo pipefail - [[ -z "${GITHUB_TOKEN:-}" ]] && { - echo "Error: SYNC_TOKEN secret is not set." >&2 - exit 1 - } - - [[ -z "${LANG_CODES:-}" ]] && { - echo "Error: lang_codes not set in client_payload or vars.LANG_CODES." >&2 - exit 1 - } - UPDATES=() # Summary buckets (doc metadata / skips); printed after Step 2. META_MISSING=() @@ -87,6 +74,7 @@ jobs: source "$GITHUB_WORKSPACE/.github/workflows/assets/env.sh" # shellcheck source=assets/lib.sh source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" + validate_secrets # LIBS_REF: workflow env # shellcheck disable=SC2153 diff --git a/.github/workflows/assets/lib.sh b/.github/workflows/assets/lib.sh index 10e9f23..7cfd083 100644 --- a/.github/workflows/assets/lib.sh +++ b/.github/workflows/assets/lib.sh @@ -1,7 +1,10 @@ # shellcheck shell=bash # Shared shell library for add-submodules and start-translation workflows. -# Source this file after setting: ORG, MODULE_ORG, BOT_NAME, BOT_EMAIL, BOOST_ORG, MASTER_BRANCH, -# TRANSLATIONS_REPO, TRANS_DIR, GITHUB_WORKSPACE, UPDATES (array). +# Source env.sh before lib.sh so ORG, MODULE_ORG, BOT_NAME, BOT_EMAIL, BOOST_ORG, MASTER_BRANCH, +# and TRANSLATIONS_REPO are set. Workflows also set GITHUB_TOKEN, LANG_CODES, and (for +# start-translation) WEBLATE_URL / WEBLATE_TOKEN in the step env before sourcing. +# Call validate_secrets (or validate_secrets weblate) after sourcing env.sh and lib.sh. +# require_lang_codes may be called after sourcing lib.sh alone (early validation step). # ── Helpers ────────────────────────────────────────────────────────── @@ -249,3 +252,41 @@ validate_lang_codes() { exit 1 fi } + +# Exit 1 if LANG_CODES workflow env is unset or empty. +require_lang_codes() { + [[ -z "${LANG_CODES:-}" ]] && { + echo "Error: lang_codes not set in client_payload or vars.LANG_CODES." >&2 + exit 1 + } +} + +# Exit 1 if a named variable is unset or empty. +_require_nonempty() { + local var_name="$1" err_msg="$2" + # shellcheck disable=SC2154 + [[ -n "${!var_name:-}" ]] || { echo "$err_msg" >&2; exit 1; } +} + +# validate_secrets [weblate] +# Call after: source env.sh && source lib.sh +# Reads workflow env + env.sh globals; exits 1 with a clear message on first failure. +validate_secrets() { + local require_weblate=0 + [[ "${1:-}" == "weblate" ]] && require_weblate=1 + + _require_nonempty GITHUB_TOKEN "Error: SYNC_TOKEN secret is not set." + require_lang_codes + _require_nonempty ORG "Error: ORG is not set." + _require_nonempty MODULE_ORG "Error: MODULE_ORG is not set." + _require_nonempty BOT_NAME "Error: BOT_NAME is not set." + _require_nonempty BOT_EMAIL "Error: BOT_EMAIL is not set." + _require_nonempty BOOST_ORG "Error: BOOST_ORG is not set." + _require_nonempty MASTER_BRANCH "Error: MASTER_BRANCH is not set." + _require_nonempty TRANSLATIONS_REPO "Error: TRANSLATIONS_REPO is not set." + + if [[ "$require_weblate" -eq 1 ]]; then + _require_nonempty WEBLATE_URL "Error: WEBLATE_URL secret is not set." + _require_nonempty WEBLATE_TOKEN "Error: WEBLATE_TOKEN secret is not set." + fi +} diff --git a/.github/workflows/start-translation.yml b/.github/workflows/start-translation.yml index c053650..64220dc 100644 --- a/.github/workflows/start-translation.yml +++ b/.github/workflows/start-translation.yml @@ -44,12 +44,9 @@ jobs: LANG_CODES: ${{ github.event.client_payload.lang_codes || vars.LANG_CODES }} run: | set -euo pipefail - [[ -z "${LANG_CODES:-}" ]] && { - echo "Error: lang_codes not set in client_payload or vars.LANG_CODES." >&2 - exit 1 - } # shellcheck source=assets/lib.sh source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" + require_lang_codes mapfile -t lang_codes_arr < <(parse_list "$LANG_CODES") [[ ${#lang_codes_arr[@]} -eq 0 ]] && { echo "Error: LANG_CODES parsed to empty list." >&2; exit 1 @@ -72,26 +69,6 @@ jobs: run: | set -euo pipefail - [[ -z "${GITHUB_TOKEN:-}" ]] && { - echo "Error: SYNC_TOKEN secret is not set." >&2 - exit 1 - } - - [[ -z "${LANG_CODES:-}" ]] && { - echo "Error: lang_codes not set in client_payload or vars.LANG_CODES." >&2 - exit 1 - } - - [[ -z "${WEBLATE_URL:-}" ]] && { - echo "Error: WEBLATE_URL secret is not set." >&2 - exit 1 - } - - [[ -z "${WEBLATE_TOKEN:-}" ]] && { - echo "Error: WEBLATE_TOKEN secret is not set." >&2 - exit 1 - } - UPDATES=() declare -A add_or_update # Summary buckets (doc metadata / missing lib repo); printed after Step 2. @@ -115,6 +92,7 @@ jobs: source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" # shellcheck source=assets/translation.sh source "$GITHUB_WORKSPACE/.github/workflows/assets/translation.sh" + validate_secrets weblate # LIBS_REF: workflow env # shellcheck disable=SC2153 From 9d0706ddb09e7710183283fd40cf0ba330a72917 Mon Sep 17 00:00:00 2001 From: AuraMindNest Date: Thu, 18 Jun 2026 08:29:25 -0600 Subject: [PATCH 2/6] Fix CI lint fail. --- .github/workflows/start-translation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/start-translation.yml b/.github/workflows/start-translation.yml index 64220dc..b04d9f0 100644 --- a/.github/workflows/start-translation.yml +++ b/.github/workflows/start-translation.yml @@ -106,7 +106,7 @@ jobs: # POST to Weblate add-or-update (async: server returns 202 + task_id quickly). # Payload: {organization, add_or_update: {lang_code: [subs...]}, version, extensions} trigger_weblate() { - local weblate_url="$1" weblate_token="$2" libs_ref="$3" exts_json="$4" + local api_base_url="$1" api_token="$2" libs_ref="$3" exts_json="$4" # Build add_or_update JSON object from associative array. local add_or_update_json="{}" @@ -139,11 +139,11 @@ jobs: local resp http_code curl_exit=0 resp=$(mktemp) http_code=$(curl -sS -o "$resp" -w "%{http_code}" --max-time 120 -X POST \ - -H "Authorization: Token $weblate_token" \ + -H "Authorization: Token $api_token" \ -H "Content-Type: application/json" \ -H "User-Agent: BoostDocsSync/1.0" \ -d "$payload" \ - "${weblate_url%/}/boost-endpoint/add-or-update/" \ + "${api_base_url%/}/boost-endpoint/add-or-update/" \ ) || curl_exit=$? if [[ $curl_exit -ne 0 ]]; then From 1f8130ff7cf8c9385bcb338df927e97955a637e9 Mon Sep 17 00:00:00 2001 From: AuraMindNest Date: Thu, 18 Jun 2026 14:22:08 -0600 Subject: [PATCH 3/6] Fix due to the coderabbtiai review. --- .github/workflows/assets/lib.sh | 2 +- .github/workflows/start-translation.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/assets/lib.sh b/.github/workflows/assets/lib.sh index 7cfd083..fb81b76 100644 --- a/.github/workflows/assets/lib.sh +++ b/.github/workflows/assets/lib.sh @@ -264,7 +264,7 @@ require_lang_codes() { # Exit 1 if a named variable is unset or empty. _require_nonempty() { local var_name="$1" err_msg="$2" - # shellcheck disable=SC2154 + # :- keeps indirect expansion safe under set -u when the named var is unset. [[ -n "${!var_name:-}" ]] || { echo "$err_msg" >&2; exit 1; } } diff --git a/.github/workflows/start-translation.yml b/.github/workflows/start-translation.yml index b04d9f0..0d56b8b 100644 --- a/.github/workflows/start-translation.yml +++ b/.github/workflows/start-translation.yml @@ -90,9 +90,9 @@ jobs: source "$GITHUB_WORKSPACE/.github/workflows/assets/env.sh" # shellcheck source=assets/lib.sh source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" + validate_secrets weblate # shellcheck source=assets/translation.sh source "$GITHUB_WORKSPACE/.github/workflows/assets/translation.sh" - validate_secrets weblate # LIBS_REF: workflow env # shellcheck disable=SC2153 @@ -106,7 +106,7 @@ jobs: # POST to Weblate add-or-update (async: server returns 202 + task_id quickly). # Payload: {organization, add_or_update: {lang_code: [subs...]}, version, extensions} trigger_weblate() { - local api_base_url="$1" api_token="$2" libs_ref="$3" exts_json="$4" + local weblate_url="$1" weblate_token="$2" libs_ref="$3" exts_json="$4" # Build add_or_update JSON object from associative array. local add_or_update_json="{}" @@ -139,11 +139,11 @@ jobs: local resp http_code curl_exit=0 resp=$(mktemp) http_code=$(curl -sS -o "$resp" -w "%{http_code}" --max-time 120 -X POST \ - -H "Authorization: Token $api_token" \ + -H "Authorization: Token $weblate_token" \ -H "Content-Type: application/json" \ -H "User-Agent: BoostDocsSync/1.0" \ -d "$payload" \ - "${api_base_url%/}/boost-endpoint/add-or-update/" \ + "${weblate_url%/}/boost-endpoint/add-or-update/" \ ) || curl_exit=$? if [[ $curl_exit -ne 0 ]]; then From f7bde7fb241ce4f26af853d8dc41b3c9140d6a3e Mon Sep 17 00:00:00 2001 From: AuraMindNest Date: Thu, 18 Jun 2026 14:34:04 -0600 Subject: [PATCH 4/6] Fix lint fail. --- .github/workflows/start-translation.yml | 7 +- scripts/lint.sh | 96 +++++++++++++++---------- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/.github/workflows/start-translation.yml b/.github/workflows/start-translation.yml index 0d56b8b..97462b2 100644 --- a/.github/workflows/start-translation.yml +++ b/.github/workflows/start-translation.yml @@ -106,7 +106,8 @@ jobs: # POST to Weblate add-or-update (async: server returns 202 + task_id quickly). # Payload: {organization, add_or_update: {lang_code: [subs...]}, version, extensions} trigger_weblate() { - local weblate_url="$1" weblate_token="$2" libs_ref="$3" exts_json="$4" + # Locals differ from WEBLATE_* env names to avoid actionlint SC2153 misspelling hints. + local api_base_url="$1" api_token="$2" libs_ref="$3" exts_json="$4" # Build add_or_update JSON object from associative array. local add_or_update_json="{}" @@ -139,11 +140,11 @@ jobs: local resp http_code curl_exit=0 resp=$(mktemp) http_code=$(curl -sS -o "$resp" -w "%{http_code}" --max-time 120 -X POST \ - -H "Authorization: Token $weblate_token" \ + -H "Authorization: Token $api_token" \ -H "Content-Type: application/json" \ -H "User-Agent: BoostDocsSync/1.0" \ -d "$payload" \ - "${weblate_url%/}/boost-endpoint/add-or-update/" \ + "${api_base_url%/}/boost-endpoint/add-or-update/" \ ) || curl_exit=$? if [[ $curl_exit -ne 0 ]]; then diff --git a/scripts/lint.sh b/scripts/lint.sh index c6307ce..eb1da33 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -1,19 +1,19 @@ #!/usr/bin/env bash # Run ShellCheck and actionlint (same checks as CI lint job). +# Versions below are pinned; binaries are always taken from .cache/ so local matches CI. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" -ensure_shellcheck() { - if command -v shellcheck >/dev/null 2>&1; then - SHELLCHECK_BIN="$(command -v shellcheck)" - return - fi +SHELLCHECK_VERSION="v0.11.0" +ACTIONLINT_VERSION="1.7.7" - local version="v0.11.0" +ensure_shellcheck() { + local version="$SHELLCHECK_VERSION" local cache_dir="$ROOT/.cache/shellcheck" - local bin="$cache_dir/shellcheck" + local extract_dir="$cache_dir/shellcheck-${version}" + local bin="$cache_dir/shellcheck-bin-${version}" mkdir -p "$cache_dir" if [[ -x "$bin" ]]; then @@ -37,7 +37,6 @@ ensure_shellcheck() { ;; *) echo "lint: unsupported Linux architecture for shellcheck download: $arch" >&2 - echo "lint: install shellcheck manually (e.g. apt install shellcheck)." >&2 exit 1 ;; esac @@ -59,8 +58,7 @@ ensure_shellcheck() { esac ;; *) - echo "lint: shellcheck not found and auto-download unsupported on $os." >&2 - echo "lint: install shellcheck manually (e.g. apt install shellcheck)." >&2 + echo "lint: shellcheck auto-download unsupported on $os." >&2 exit 1 ;; esac @@ -70,7 +68,7 @@ ensure_shellcheck() { echo "lint: downloading shellcheck ${version}..." >&2 curl -fsSL -o "$cache_dir/$tarball" "$url" fi - if [[ ! -d "$cache_dir/shellcheck-${version}" ]]; then + if [[ ! -d "$extract_dir" ]]; then if [[ "$os" == "Linux" ]]; then echo "${expected_sha256} $cache_dir/$tarball" | sha256sum -c - else @@ -81,37 +79,34 @@ ensure_shellcheck() { exit 1 fi fi - cp "$cache_dir/shellcheck-${version}/shellcheck" "$bin" + cp "$extract_dir/shellcheck" "$bin" chmod +x "$bin" SHELLCHECK_BIN="$bin" } -ensure_shellcheck - -"$SHELLCHECK_BIN" -x \ - .github/workflows/assets/env.sh \ - .github/workflows/assets/lib.sh \ - .github/workflows/assets/translation.sh \ - scripts/*.sh \ - tests/helpers/*.bash +ensure_actionlint() { + local version="$ACTIONLINT_VERSION" + local cache_dir="$ROOT/.cache/actionlint" + local bin="$cache_dir/actionlint-bin-${version}" + mkdir -p "$cache_dir" -ACTIONLINT_VERSION="1.7.7" -CACHE_DIR="$ROOT/.cache/actionlint" -ACTIONLINT_BIN="$CACHE_DIR/actionlint" -mkdir -p "$CACHE_DIR" + if [[ -x "$bin" ]]; then + ACTIONLINT_BIN="$bin" + return + fi -if [[ ! -x "$ACTIONLINT_BIN" ]]; then + local os arch tarball expected_sha256 os="$(uname -s)" arch="$(uname -m)" case "$os" in Linux) case "$arch" in x86_64) - tarball="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" + tarball="actionlint_${version}_linux_amd64.tar.gz" expected_sha256="023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757" ;; aarch64|arm64) - tarball="actionlint_${ACTIONLINT_VERSION}_linux_arm64.tar.gz" + tarball="actionlint_${version}_linux_arm64.tar.gz" expected_sha256="401942f9c24ed71e4fe71b76c7d638f66d8633575c4016efd2977ce7c28317d0" ;; *) @@ -123,11 +118,11 @@ if [[ ! -x "$ACTIONLINT_BIN" ]]; then Darwin) case "$arch" in x86_64) - tarball="actionlint_${ACTIONLINT_VERSION}_darwin_amd64.tar.gz" + tarball="actionlint_${version}_darwin_amd64.tar.gz" expected_sha256="28e5de5a05fc558474f638323d736d822fff183d2d492f0aecb2b73cc44584f5" ;; arm64) - tarball="actionlint_${ACTIONLINT_VERSION}_darwin_arm64.tar.gz" + tarball="actionlint_${version}_darwin_arm64.tar.gz" expected_sha256="2693315b9093aeacb4ebd91a993fea54fc215057bf0da2659056b4bc033873db" ;; *) @@ -137,18 +132,43 @@ if [[ ! -x "$ACTIONLINT_BIN" ]]; then esac ;; *) - echo "lint: unsupported OS for actionlint download: $os" >&2 + echo "lint: actionlint auto-download unsupported on $os." >&2 exit 1 ;; esac - curl -fsSL -o "$CACHE_DIR/$tarball" \ - "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/${tarball}" - if [[ "$os" == "Linux" ]]; then - echo "${expected_sha256} $CACHE_DIR/$tarball" | sha256sum -c - - else - echo "${expected_sha256} $CACHE_DIR/$tarball" | shasum -a 256 -c - + if [[ ! -f "$cache_dir/$tarball" ]]; then + echo "lint: downloading actionlint ${version}..." >&2 + curl -fsSL -o "$cache_dir/$tarball" \ + "https://github.com/rhysd/actionlint/releases/download/v${version}/${tarball}" fi - tar -xzf "$CACHE_DIR/$tarball" -C "$CACHE_DIR" -fi + if [[ ! -x "$cache_dir/actionlint" ]]; then + if [[ "$os" == "Linux" ]]; then + echo "${expected_sha256} $cache_dir/$tarball" | sha256sum -c - + else + echo "${expected_sha256} $cache_dir/$tarball" | shasum -a 256 -c - + fi + tar -xzf "$cache_dir/$tarball" -C "$cache_dir" + fi + cp "$cache_dir/actionlint" "$bin" + chmod +x "$bin" + ACTIONLINT_BIN="$bin" +} + +ensure_shellcheck +ensure_actionlint + +# actionlint shells out to shellcheck for workflow run: scripts; use our pinned binary. +_shellcheck_dir="$(dirname "$SHELLCHECK_BIN")" +export PATH="${_shellcheck_dir}:${PATH}" + +echo "lint: shellcheck ${SHELLCHECK_VERSION} ($("$SHELLCHECK_BIN" --version | head -1))" >&2 +echo "lint: actionlint ${ACTIONLINT_VERSION} ($("$ACTIONLINT_BIN" -version | head -1))" >&2 + +"$SHELLCHECK_BIN" -x \ + .github/workflows/assets/env.sh \ + .github/workflows/assets/lib.sh \ + .github/workflows/assets/translation.sh \ + scripts/*.sh \ + tests/helpers/*.bash "$ACTIONLINT_BIN" -color From ff83593010fa89028ce9904a9ae9be50cf4d7848 Mon Sep 17 00:00:00 2001 From: AuraMindNest Date: Fri, 19 Jun 2026 09:37:23 -0600 Subject: [PATCH 5/6] Fix due to the first reviewer. --- .github/workflows/add-submodules.yml | 12 ++--- .github/workflows/assets/lib.sh | 2 +- .github/workflows/start-translation.yml | 16 +++--- tests/test_lib.bats | 67 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/.github/workflows/add-submodules.yml b/.github/workflows/add-submodules.yml index b82b99b..83355fc 100644 --- a/.github/workflows/add-submodules.yml +++ b/.github/workflows/add-submodules.yml @@ -60,6 +60,12 @@ jobs: NO_DOC_PATHS=() REPO_EXISTS_SKIP=() + # shellcheck source=assets/env.sh + source "$GITHUB_WORKSPACE/.github/workflows/assets/env.sh" + # shellcheck source=assets/lib.sh + source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" + validate_secrets + WORK_DIR=$(mktemp -d) trap 'rm -rf "$WORK_DIR"' EXIT BOOST_WORK="$WORK_DIR/boost" @@ -70,12 +76,6 @@ jobs: # without embedding tokens in remote URLs. gh auth setup-git - # shellcheck source=assets/env.sh - source "$GITHUB_WORKSPACE/.github/workflows/assets/env.sh" - # shellcheck source=assets/lib.sh - source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" - validate_secrets - # LIBS_REF: workflow env # shellcheck disable=SC2153 libs_ref="${LIBS_REF:?}" diff --git a/.github/workflows/assets/lib.sh b/.github/workflows/assets/lib.sh index fb81b76..9c2b8aa 100644 --- a/.github/workflows/assets/lib.sh +++ b/.github/workflows/assets/lib.sh @@ -255,7 +255,7 @@ validate_lang_codes() { # Exit 1 if LANG_CODES workflow env is unset or empty. require_lang_codes() { - [[ -z "${LANG_CODES:-}" ]] && { + [[ -n "${LANG_CODES:-}" ]] || { echo "Error: lang_codes not set in client_payload or vars.LANG_CODES." >&2 exit 1 } diff --git a/.github/workflows/start-translation.yml b/.github/workflows/start-translation.yml index 97462b2..e24b418 100644 --- a/.github/workflows/start-translation.yml +++ b/.github/workflows/start-translation.yml @@ -76,6 +76,14 @@ jobs: NO_DOC_PATHS=() ORG_REPO_MISSING=() + # shellcheck source=assets/env.sh + source "$GITHUB_WORKSPACE/.github/workflows/assets/env.sh" + # shellcheck source=assets/lib.sh + source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" + validate_secrets weblate + # shellcheck source=assets/translation.sh + source "$GITHUB_WORKSPACE/.github/workflows/assets/translation.sh" + WORK_DIR=$(mktemp -d) trap 'rm -rf "$WORK_DIR"' EXIT BOOST_WORK="$WORK_DIR/boost" @@ -86,14 +94,6 @@ jobs: # without embedding tokens in remote URLs. gh auth setup-git - # shellcheck source=assets/env.sh - source "$GITHUB_WORKSPACE/.github/workflows/assets/env.sh" - # shellcheck source=assets/lib.sh - source "$GITHUB_WORKSPACE/.github/workflows/assets/lib.sh" - validate_secrets weblate - # shellcheck source=assets/translation.sh - source "$GITHUB_WORKSPACE/.github/workflows/assets/translation.sh" - # LIBS_REF: workflow env # shellcheck disable=SC2153 libs_ref="${LIBS_REF:?}" diff --git a/tests/test_lib.bats b/tests/test_lib.bats index f0d7de4..39369df 100644 --- a/tests/test_lib.bats +++ b/tests/test_lib.bats @@ -139,3 +139,70 @@ setup() { cleanup_git_fixture_root } + +@test "require_lang_codes: succeeds when LANG_CODES is set" { + export LANG_CODES="en,zh_Hans" + run require_lang_codes + [ "$status" -eq 0 ] +} + +@test "require_lang_codes: fails when LANG_CODES is unset" { + unset LANG_CODES + run require_lang_codes + [ "$status" -eq 1 ] + [[ "$output" == *"lang_codes not set"* ]] +} + +@test "require_lang_codes: fails when LANG_CODES is empty" { + export LANG_CODES="" + run require_lang_codes + [ "$status" -eq 1 ] + [[ "$output" == *"lang_codes not set"* ]] +} + +@test "validate_secrets: succeeds when required workflow env is set" { + load_env + export GITHUB_TOKEN="test-token" + export LANG_CODES="en" + run validate_secrets + [ "$status" -eq 0 ] +} + +@test "validate_secrets: fails when GITHUB_TOKEN is unset" { + load_env + export LANG_CODES="en" + unset GITHUB_TOKEN + run validate_secrets + [ "$status" -eq 1 ] + [[ "$output" == *"SYNC_TOKEN secret is not set"* ]] +} + +@test "validate_secrets: fails when LANG_CODES is unset" { + load_env + export GITHUB_TOKEN="test-token" + unset LANG_CODES + run validate_secrets + [ "$status" -eq 1 ] + [[ "$output" == *"lang_codes not set"* ]] +} + +@test "validate_secrets weblate: succeeds when Weblate secrets are set" { + load_env + export GITHUB_TOKEN="test-token" + export LANG_CODES="en" + export WEBLATE_URL="https://weblate.example.org" + export WEBLATE_TOKEN="weblate-token" + run validate_secrets weblate + [ "$status" -eq 0 ] +} + +@test "validate_secrets weblate: fails when WEBLATE_URL is unset" { + load_env + export GITHUB_TOKEN="test-token" + export LANG_CODES="en" + export WEBLATE_TOKEN="weblate-token" + unset WEBLATE_URL + run validate_secrets weblate + [ "$status" -eq 1 ] + [[ "$output" == *"WEBLATE_URL secret is not set"* ]] +} From e07aa0fe58069931fb4144e9493d3aad64cf82a8 Mon Sep 17 00:00:00 2001 From: AuraMindNest Date: Fri, 19 Jun 2026 09:48:34 -0600 Subject: [PATCH 6/6] Fix due to second coderabbitai review. --- .github/workflows/start-translation.yml | 2 +- scripts/lint.sh | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/start-translation.yml b/.github/workflows/start-translation.yml index e24b418..9a46e4e 100644 --- a/.github/workflows/start-translation.yml +++ b/.github/workflows/start-translation.yml @@ -106,7 +106,7 @@ jobs: # POST to Weblate add-or-update (async: server returns 202 + task_id quickly). # Payload: {organization, add_or_update: {lang_code: [subs...]}, version, extensions} trigger_weblate() { - # Locals differ from WEBLATE_* env names to avoid actionlint SC2153 misspelling hints. + # Locals differ from WEBLATE_* env names to avoid ShellCheck SC2153 misspelling hints. local api_base_url="$1" api_token="$2" libs_ref="$3" exts_json="$4" # Build add_or_update JSON object from associative array. diff --git a/scripts/lint.sh b/scripts/lint.sh index eb1da33..0938cad 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -87,6 +87,7 @@ ensure_shellcheck() { ensure_actionlint() { local version="$ACTIONLINT_VERSION" local cache_dir="$ROOT/.cache/actionlint" + local extract_dir="$cache_dir/actionlint-${version}" local bin="$cache_dir/actionlint-bin-${version}" mkdir -p "$cache_dir" @@ -141,15 +142,16 @@ ensure_actionlint() { curl -fsSL -o "$cache_dir/$tarball" \ "https://github.com/rhysd/actionlint/releases/download/v${version}/${tarball}" fi - if [[ ! -x "$cache_dir/actionlint" ]]; then + if [[ ! -d "$extract_dir" ]]; then if [[ "$os" == "Linux" ]]; then echo "${expected_sha256} $cache_dir/$tarball" | sha256sum -c - else echo "${expected_sha256} $cache_dir/$tarball" | shasum -a 256 -c - fi - tar -xzf "$cache_dir/$tarball" -C "$cache_dir" + mkdir -p "$extract_dir" + tar -xzf "$cache_dir/$tarball" -C "$extract_dir" fi - cp "$cache_dir/actionlint" "$bin" + cp "$extract_dir/actionlint" "$bin" chmod +x "$bin" ACTIONLINT_BIN="$bin" } @@ -158,7 +160,7 @@ ensure_shellcheck ensure_actionlint # actionlint shells out to shellcheck for workflow run: scripts; use our pinned binary. -_shellcheck_dir="$(dirname "$SHELLCHECK_BIN")" +_shellcheck_dir="$ROOT/.cache/shellcheck/shellcheck-${SHELLCHECK_VERSION}" export PATH="${_shellcheck_dir}:${PATH}" echo "lint: shellcheck ${SHELLCHECK_VERSION} ($("$SHELLCHECK_BIN" --version | head -1))" >&2