Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 7 additions & 19 deletions .github/workflows/add-submodules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -57,22 +54,18 @@ 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=()
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"
Expand All @@ -83,11 +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"

# LIBS_REF: workflow env
# shellcheck disable=SC2153
libs_ref="${LIBS_REF:?}"
Expand Down
45 changes: 43 additions & 2 deletions .github/workflows/assets/lib.sh
Original file line number Diff line number Diff line change
@@ -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 ──────────────────────────────────────────────────────────

Expand Down Expand Up @@ -249,3 +252,41 @@ validate_lang_codes() {
exit 1
fi
}

# Exit 1 if LANG_CODES workflow env is unset or empty.
require_lang_codes() {
[[ -n "${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"
# :- keeps indirect expansion safe under set -u when the named var is unset.
[[ -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
}
47 changes: 13 additions & 34 deletions .github/workflows/start-translation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -72,33 +69,21 @@ 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.
META_MISSING=()
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"
Expand All @@ -109,13 +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"
# shellcheck source=assets/translation.sh
source "$GITHUB_WORKSPACE/.github/workflows/assets/translation.sh"

# LIBS_REF: workflow env
# shellcheck disable=SC2153
libs_ref="${LIBS_REF:?}"
Expand All @@ -128,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 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.
local add_or_update_json="{}"
Expand Down Expand Up @@ -161,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
Expand Down
98 changes: 60 additions & 38 deletions scripts/lint.sh
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -81,37 +79,35 @@ 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 extract_dir="$cache_dir/actionlint-${version}"
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"
;;
*)
Expand All @@ -123,11 +119,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"
;;
*)
Expand All @@ -137,18 +133,44 @@ 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 [[ ! -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
mkdir -p "$extract_dir"
tar -xzf "$cache_dir/$tarball" -C "$extract_dir"
fi
cp "$extract_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="$ROOT/.cache/shellcheck/shellcheck-${SHELLCHECK_VERSION}"
export PATH="${_shellcheck_dir}:${PATH}"
Comment thread
AuraMindNest marked this conversation as resolved.

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
Loading
Loading