Files
ci-actions/pipeline/scripts/lib.sh
T
2026-09-25 17:56:38 +00:00

89 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Shared helpers for the DealSage custom-app pipeline scripts. Sourced, not run.
#
# Conventions:
# * Every script is `set -euo pipefail` and sources this file first.
# * DealSage is reached only through DEALSAGE_FUNCTIONS_URL with the app's
# PUBLISH_TOKEN (appId-scoped, minted by DealSage). Nothing here holds a
# Supabase service key or an R2 account key.
# * Output meant for the job log goes through log(); machine-readable state
# is exchanged through $GITHUB_ENV / $GITHUB_OUTPUT like any other action.
log() { printf '::group::%s\n' "$*" >/dev/null; printf '\n== %s\n' "$*"; }
warn() { printf '::warning::%s\n' "$*"; }
die() { printf '::error::%s\n' "$*"; exit 1; }
# now_ms — wall clock in milliseconds (GNU date; falls back to seconds*1000).
now_ms() { date +%s%3N 2>/dev/null || echo $(( $(date +%s) * 1000 )); }
# iso_now — UTC timestamp for API payloads.
iso_now() { date -u +%Y-%m-%dT%H:%M:%SZ; }
# require_env NAME... — fail loudly when a required variable is missing.
require_env() {
local missing=0 v
for v in "$@"; do
if [ -z "${!v:-}" ]; then printf '::error::%s is not set\n' "$v"; missing=1; fi
done
[ "$missing" = 0 ] || exit 1
}
# json_escape STRING — JSON string literal (with quotes) via jq.
json_escape() { jq -Rn --arg s "$1" '$s'; }
# tail_file FILE [LINES] — last LINES lines of FILE (default 80), for log tails.
tail_file() { tail -n "${2:-80}" "$1" 2>/dev/null || true; }
# ds_post PATH JSON — POST JSON to a DealSage function with the publish token.
# Prints the response body; returns non-zero on HTTP failure (body still printed
# to stderr so the job log shows why).
ds_post() {
local path="$1" body="$2" out code
out="$(mktemp)"
code="$(curl -sS -o "$out" -w '%{http_code}' -X POST \
"${DEALSAGE_FUNCTIONS_URL%/}/${path}" \
-H "Authorization: Bearer ${PUBLISH_TOKEN}" \
-H "apikey: ${SUPABASE_ANON_KEY}" \
-H "content-type: application/json" \
--data-binary "$body")" || { cat "$out" >&2; rm -f "$out"; return 1; }
if [ "${code:0:1}" != "2" ]; then
printf 'DealSage %s returned HTTP %s: ' "$path" "$code" >&2; cat "$out" >&2; echo >&2
rm -f "$out"; return 1
fi
cat "$out"; rm -f "$out"
}
# git_context — export the commit/branch/author the pipeline is publishing.
# Gitea Actions provides the GITHUB_* variables; the event payload carries the
# head commit. Falls back to git itself (the checkout has the commit).
git_context() {
local ev="${GITHUB_EVENT_PATH:-}"
COMMIT_SHA="${GITHUB_SHA:-$(git rev-parse HEAD 2>/dev/null || echo unknown)}"
BRANCH="${GITHUB_REF_NAME:-}"
if [ -z "$BRANCH" ]; then
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)"
fi
COMMIT_MESSAGE=""; COMMIT_AUTHOR=""
if [ -n "$ev" ] && [ -f "$ev" ]; then
COMMIT_MESSAGE="$(jq -r '.head_commit.message // .commits[-1].message // empty' "$ev" 2>/dev/null || true)"
COMMIT_AUTHOR="$(jq -r '.head_commit.author.name // .pusher.login // .pusher.username // empty' "$ev" 2>/dev/null || true)"
fi
[ -n "$COMMIT_MESSAGE" ] || COMMIT_MESSAGE="$(git log -1 --pretty=%B 2>/dev/null | head -c 2000 || true)"
[ -n "$COMMIT_AUTHOR" ] || COMMIT_AUTHOR="$(git log -1 --pretty=%an 2>/dev/null || echo "${GITHUB_ACTOR:-}")"
# First line only for the summary field; the full message travels separately.
COMMIT_SUBJECT="$(printf '%s' "$COMMIT_MESSAGE" | head -n 1 | head -c 200)"
export COMMIT_SHA BRANCH COMMIT_MESSAGE COMMIT_AUTHOR COMMIT_SUBJECT
}
# persist_env NAME VALUE — make a value visible to later composite steps.
persist_env() {
if [ -n "${GITHUB_ENV:-}" ]; then
# Heredoc form handles multi-line values safely.
{ printf '%s<<__DS_EOF__\n' "$1"; printf '%s\n' "$2"; printf '__DS_EOF__\n'; } >> "$GITHUB_ENV"
fi
export "$1=$2"
}
# summary MARKDOWN — append to the run's step summary when the runner supports it.
summary() { [ -n "${GITHUB_STEP_SUMMARY:-}" ] && printf '%s\n' "$*" >> "$GITHUB_STEP_SUMMARY" || true; }