mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-28 09:34:36 +08:00
Docker Compose resolves these values from the .env file, so the parser no longer rejects or misresolves them. Also copy the expected parser fixtures when parser-snapshot-diff compares with a git ref.
120 lines
5.3 KiB
Bash
Executable File
120 lines
5.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Show how a code change alters the service parser output for every template and the reference fixture.
|
|
#
|
|
# Usage:
|
|
# ./scripts/parser-snapshot-diff save # 1. before you change code: save the current output
|
|
# ./scripts/parser-snapshot-diff baseline # 2. after the change: compare with the saved output
|
|
# ./scripts/parser-snapshot-diff [git-ref] # or compare with a git ref (default: main)
|
|
# ./scripts/parser-snapshot-diff baseline -- --filter='"template appwrite"' # extra Pest arguments
|
|
#
|
|
# Each run parses everything with tests/Feature/ServiceParserReferenceTest.php (about 90 seconds).
|
|
# A git ref is exported with git archive to a temporary directory and parsed with the current test,
|
|
# fixtures and templates, so the diff shows only the effect of the code change.
|
|
# The terminal shows one line per changed case; the full diff is written to storage/framework/testing/.
|
|
set -euo pipefail
|
|
|
|
repo="$(git -C "$(dirname "$0")/.." rev-parse --show-toplevel)"
|
|
mode="${1:-main}"
|
|
shift || true
|
|
[[ "${1:-}" == "--" ]] && shift
|
|
pest_args=("$@")
|
|
|
|
testing="$repo/storage/framework/testing" # gitignored, same file system as the repository
|
|
saved="$testing/parser-snapshots-baseline"
|
|
report="$testing/parser-snapshot-diff.diff"
|
|
work="$(mktemp -d "$testing/parser-snapshot-diff.XXXXXX")"
|
|
trap 'rm -rf "$work"' EXIT
|
|
|
|
# Run the golden test in <dir> with UPDATE_PARSER_SNAPSHOTS=1 and copy its expected files to <target>.
|
|
parse_into() {
|
|
local dir="$1" target="$2" label="$3" expected="$1/tests/Fixtures/parser/expected" backup="$work/expected-backup" status=0
|
|
echo "==> Parsing on $label (about 90 seconds)"
|
|
# The run rewrites the expected files: put the previous ones back afterwards, so the repository is unchanged.
|
|
rm -rf "$backup"
|
|
cp -r "$expected" "$backup"
|
|
rm -rf "$expected/templates"
|
|
(cd "$dir" && UPDATE_PARSER_SNAPSHOTS=1 php -d memory_limit=2G artisan test --compact \
|
|
tests/Feature/ServiceParserReferenceTest.php "${pest_args[@]}" >"$work/run.log" 2>&1) || status=$?
|
|
rm -rf "$target"
|
|
cp -r "$expected" "$target"
|
|
rm -rf "$expected"
|
|
mv "$backup" "$expected"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "Test run on $label failed:" >&2
|
|
tail -30 "$work/run.log" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
case "$mode" in
|
|
save)
|
|
parse_into "$repo" "$saved" "working tree"
|
|
echo "Saved baseline: $saved"
|
|
echo "Change the code, then run: ./scripts/parser-snapshot-diff baseline"
|
|
exit 0
|
|
;;
|
|
baseline)
|
|
[[ -d "$saved" ]] || { echo "No saved baseline. Run ./scripts/parser-snapshot-diff save first." >&2; exit 1; }
|
|
base_label="saved baseline"
|
|
cp -r "$saved" "$work/base-expected"
|
|
;;
|
|
*)
|
|
base_label="$mode"
|
|
base="$work/base"
|
|
mkdir -p "$base"
|
|
echo "==> Exporting $mode ($(git -C "$repo" rev-parse --short "$mode"))"
|
|
git -C "$repo" archive "$mode" | tar -x -C "$base"
|
|
# Hard links: fast and no extra disk space. A symlink would make Composer load the classes of $repo.
|
|
cp -al "$repo/vendor" "$base/vendor"
|
|
[[ -f "$repo/.env" ]] && cp "$repo/.env" "$base/.env"
|
|
rm -rf "$base/templates/compose" "$base/tests/Fixtures/parser"
|
|
cp -r "$repo/templates/compose" "$base/templates/compose"
|
|
mkdir -p "$base/tests/Fixtures/parser"
|
|
cp "$repo"/tests/Fixtures/parser/*.yaml "$base/tests/Fixtures/parser/"
|
|
cp -r "$repo/tests/Fixtures/parser/expected" "$base/tests/Fixtures/parser/expected"
|
|
cp "$repo/tests/Feature/ServiceParserReferenceTest.php" "$base/tests/Feature/"
|
|
parse_into "$base" "$work/base-expected" "$mode"
|
|
;;
|
|
esac
|
|
|
|
parse_into "$repo" "$work/current-expected" "working tree"
|
|
|
|
echo
|
|
if diff -ru "$work/base-expected" "$work/current-expected" | sed -E "s#$work/(base|current)-expected/##g" >"$report"; then
|
|
echo "No differences from $base_label: the parser output of every case is the same."
|
|
exit 0
|
|
fi
|
|
|
|
# Line 2 is the first step (1_deploy): an error there means the case did not parse at all on that side.
|
|
first_step_error() { sed -n 2p "$1" | grep '^ error:' | cut -c10-130 || true; }
|
|
|
|
summary() {
|
|
local file="$1" base_file="$work/base-expected/$1" current_file="$work/current-expected/$1" base_error current_error
|
|
[[ -f "$base_file" ]] || { echo " new case $file"; return; }
|
|
[[ -f "$current_file" ]] || { echo " removed case $file"; return; }
|
|
base_error="$(first_step_error "$base_file")"
|
|
current_error="$(first_step_error "$current_file")"
|
|
if [[ -n "$base_error" && -z "$current_error" ]]; then
|
|
echo " base error $file: $base_error"
|
|
elif [[ -n "$current_error" && -z "$base_error" ]]; then
|
|
echo " CURRENT ERROR $file: $current_error"
|
|
else
|
|
echo " changed $file (+$(diff "$base_file" "$current_file" | grep -c '^>' || true) -$(diff "$base_file" "$current_file" | grep -c '^<' || true))"
|
|
fi
|
|
}
|
|
|
|
changed_cases=()
|
|
while IFS= read -r file; do
|
|
cmp -s "$work/base-expected/$file" "$work/current-expected/$file" || changed_cases+=("$file")
|
|
done < <( (cd "$work/base-expected" && find . -name '*.yaml'; cd "$work/current-expected" && find . -name '*.yaml') | sed 's|^\./||' | sort -u)
|
|
|
|
lines="$(for file in "${changed_cases[@]}"; do summary "$file"; done)"
|
|
echo "${#changed_cases[@]} case(s) differ from $base_label:"
|
|
echo "$lines"
|
|
echo
|
|
echo "Full diff: $report"
|
|
if grep -q '^ base error' <<<"$lines"; then
|
|
echo "Note: 'base error' cases did not parse on $base_label, so there is no base output to compare with."
|
|
fi
|
|
exit 1
|