083b1f36a8
Gitea Actions Compatibility Suite / aggregate (push) Successful in 0s
Gitea Actions Compatibility Suite / c8 (push) Successful in 2s
Gitea Actions Compatibility Suite / c9 (push) Successful in 58s
Gitea Actions Compatibility Suite / c10 (push) Successful in 0s
Gitea Actions Compatibility Suite / probe (push) Successful in 0s
Gitea Actions Compatibility Suite / c1 (push) Successful in 7s
Gitea Actions Compatibility Suite / c2 (push) Successful in 4s
Gitea Actions Compatibility Suite / c3 (push) Successful in 1m24s
Gitea Actions Compatibility Suite / c4 (push) Successful in 12s
Gitea Actions Compatibility Suite / c5 (push) Successful in 0s
Gitea Actions Compatibility Suite / c6 (push) Successful in 1s
Gitea Actions Compatibility Suite / c7 (push) Successful in 44s
A self-validating test suite that proves Gitea's implementations of GitHub-style actions behave like GitHub's. Push to any Gitea instance with a registered runner — on push or manual dispatch, it runs 10 independent test workflows covering checkout, artifacts, caching, language setup, expression contexts, workflow commands, services, composite/reusable workflows, control flow, and known divergences. Components: - lib/assert.sh — self-asserting shell helper library (assert_eq, assert_contains, assert_exists, assert_not_exists, assert_match, sha256_of) with verified negative fail path - 10 reusable workflows (on: workflow_call): 01-checkout, 02-artifacts, 03-cache, 04-setup-runtime, 05-contexts, 06-workflow-commands, 07-services, 08-composite-reusable, 09-control-flow, 10-gitea-divergences - 00-suite-runner.yml — sole entry (on: push + workflow_dispatch): probe gate (Gitea >= 1.22.0) -> c1-c10 parallel callers (c5/c8 forward secrets: inherit for act_runner #125) -> aggregate (if: always, skipped-as-failure) - Fixtures: LFS 5MB binary, git tag v1-test, 4 language lockfiles (npm/go/pip/maven), sparse-cone layout - Makefile: make lint (actionlint static gate) - README: prerequisites, per-test expectations, correction table, manual eyeball checklist for UI-only behaviors
168 lines
6.6 KiB
Bash
168 lines
6.6 KiB
Bash
#!/usr/bin/env bash
|
|
# lib/assert.sh — self-asserting shell helper library (C11 core)
|
|
#
|
|
# Foundation library sourced by every test workflow (T4-T13). Provides uniform
|
|
# [PASS]/[FAIL] logging to stderr and explicit non-zero return on failure.
|
|
#
|
|
# Design contract:
|
|
# * All assert_* functions log [PASS]/[FAIL] to STDERR (never stdout).
|
|
# * On success: print [PASS] to stderr and `return 0` (caller continues).
|
|
# * On failure: print [FAIL] to stderr and `return 1` (caller decides to exit).
|
|
# * sha256_of is the ONLY function that writes to stdout (the bare hash).
|
|
# * The library never sets `set -e`; the caller owns flow control.
|
|
# * Missing arguments always fail loudly — assertions never silently pass.
|
|
#
|
|
# Usage:
|
|
# source lib/assert.sh
|
|
# assert_eq "$got" "$want" "my note"
|
|
# if ! assert_exists "./build/out"; then exit 1; fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Bootstrap: this library relies on bash-specific features (`[[ ]]`, `=~`).
|
|
# Detect bash early; if absent, fail loudly. This guard itself is written in
|
|
# POSIX-compatible syntax so it parses under any shell.
|
|
# ---------------------------------------------------------------------------
|
|
if [ -z "${BASH_VERSION:-}" ]; then
|
|
printf '[FAIL] assert.sh: requires bash, but BASH_VERSION is unset (current shell is not bash)\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Internal logging helpers. Centralised so the [PASS]/[FAIL] format is uniform
|
|
# and grep-friendly across every assert function.
|
|
# $1 - assert function name (e.g. assert_eq)
|
|
# $2 - caller-supplied note
|
|
# $3 - human-readable detail (actual vs expected, etc.)
|
|
# ---------------------------------------------------------------------------
|
|
__assert_pass() {
|
|
printf '[PASS] %s: %s (%s)\n' "$1" "$2" "$3" >&2
|
|
}
|
|
|
|
__assert_fail() {
|
|
printf '[FAIL] %s: %s (%s)\n' "$1" "$2" "$3" >&2
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assert_eq <actual> <expected> <note>
|
|
# Pass when the two strings are byte-identical.
|
|
# ---------------------------------------------------------------------------
|
|
assert_eq() {
|
|
if [ "$#" -lt 3 ]; then
|
|
printf '[FAIL] assert_eq: missing arguments (usage: assert_eq <actual> <expected> <note>; got %d args)\n' "$#" >&2
|
|
return 1
|
|
fi
|
|
local actual="$1" expected="$2" note="$3"
|
|
if [ "$actual" = "$expected" ]; then
|
|
__assert_pass "assert_eq" "$note" "'$actual' == '$expected'"
|
|
return 0
|
|
fi
|
|
__assert_fail "assert_eq" "$note" "got '$actual', expected '$expected'"
|
|
return 1
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assert_contains <haystack> <needle> <note>
|
|
# Pass when <needle> appears as a substring of <haystack>.
|
|
# ---------------------------------------------------------------------------
|
|
assert_contains() {
|
|
if [ "$#" -lt 3 ]; then
|
|
printf '[FAIL] assert_contains: missing arguments (usage: assert_contains <haystack> <needle> <note>; got %d args)\n' "$#" >&2
|
|
return 1
|
|
fi
|
|
local haystack="$1" needle="$2" note="$3"
|
|
if [[ "$haystack" == *"$needle"* ]]; then
|
|
__assert_pass "assert_contains" "$note" "'$needle' found in '$haystack'"
|
|
return 0
|
|
fi
|
|
__assert_fail "assert_contains" "$note" "'$needle' not found in '$haystack'"
|
|
return 1
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assert_exists <path> [note]
|
|
# Pass when <path> exists on the filesystem (any type: file/dir/symlink).
|
|
# ---------------------------------------------------------------------------
|
|
assert_exists() {
|
|
if [ "$#" -lt 1 ] || [ -z "${1:-}" ]; then
|
|
printf '[FAIL] assert_exists: missing arguments (usage: assert_exists <path>; got %d args)\n' "$#" >&2
|
|
return 1
|
|
fi
|
|
local path="$1"
|
|
local note="${2:-$path}"
|
|
if [ -e "$path" ]; then
|
|
__assert_pass "assert_exists" "$note" "'$path' exists"
|
|
return 0
|
|
fi
|
|
__assert_fail "assert_exists" "$note" "'$path' does not exist"
|
|
return 1
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assert_not_exists <path> [note]
|
|
# Pass when <path> does NOT exist on the filesystem.
|
|
# ---------------------------------------------------------------------------
|
|
assert_not_exists() {
|
|
if [ "$#" -lt 1 ] || [ -z "${1:-}" ]; then
|
|
printf '[FAIL] assert_not_exists: missing arguments (usage: assert_not_exists <path>; got %d args)\n' "$#" >&2
|
|
return 1
|
|
fi
|
|
local path="$1"
|
|
local note="${2:-$path}"
|
|
if [ ! -e "$path" ]; then
|
|
__assert_pass "assert_not_exists" "$note" "'$path' absent"
|
|
return 0
|
|
fi
|
|
__assert_fail "assert_not_exists" "$note" "'$path' exists (expected absent)"
|
|
return 1
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assert_match <actual> <regex> <note>
|
|
# Pass when <actual> matches the bash extended regex <regex> via `[[ =~ ]]`.
|
|
# Bash-specific — hence the bootstrap guard at the top of this file.
|
|
# ---------------------------------------------------------------------------
|
|
assert_match() {
|
|
if [ "$#" -lt 3 ]; then
|
|
printf '[FAIL] assert_match: missing arguments (usage: assert_match <actual> <regex> <note>; got %d args)\n' "$#" >&2
|
|
return 1
|
|
fi
|
|
local actual="$1" regex="$2" note="$3"
|
|
if [[ "$actual" =~ $regex ]]; then
|
|
__assert_pass "assert_match" "$note" "'$actual' =~ /$regex/"
|
|
return 0
|
|
fi
|
|
__assert_fail "assert_match" "$note" "'$actual' !~ /$regex/"
|
|
return 1
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# sha256_of <path>
|
|
# Print JUST the sha256 hex digest of <path> to stdout (capturable via
|
|
# `$(sha256_of file)`). Prefers sha256sum, falls back to `shasum -a 256`.
|
|
# This is the only function that writes to stdout; all errors go to stderr.
|
|
# ---------------------------------------------------------------------------
|
|
sha256_of() {
|
|
if [ "$#" -lt 1 ] || [ -z "${1:-}" ]; then
|
|
printf '[FAIL] sha256_of: missing arguments (usage: sha256_of <path>; got %d args)\n' "$#" >&2
|
|
return 1
|
|
fi
|
|
local path="$1"
|
|
if [ ! -f "$path" ]; then
|
|
printf '[FAIL] sha256_of: not a regular file: '%s'\n' "$path" >&2
|
|
return 1
|
|
fi
|
|
local line
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
line=$(sha256sum "$path") || { printf '[FAIL] sha256_of: sha256sum failed for '%s'\n' "$path" >&2; return 1; }
|
|
elif command -v shasum >/dev/null 2>&1; then
|
|
line=$(shasum -a 256 "$path") || { printf '[FAIL] sha256_of: shasum failed for '%s'\n' "$path" >&2; return 1; }
|
|
else
|
|
printf '[FAIL] sha256_of: neither sha256sum nor shasum is available\n' >&2
|
|
return 1
|
|
fi
|
|
# sha256sum/shasum both emit "<hash> <file>"; strip everything from the
|
|
# first space onward to yield the bare digest.
|
|
printf '%s\n' "${line%% *}"
|
|
return 0
|
|
}
|