This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +1,2 @@
|
|||||||
migrations/*.sql text eol=crlf
|
migrations/*.sql text eol=crlf
|
||||||
|
*.sh text eol=lf
|
||||||
|
|||||||
@@ -8,6 +8,32 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
verify:
|
verify:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: codex_test
|
||||||
|
POSTGRES_DB: imageforge_test
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U postgres -d imageforge_test"
|
||||||
|
--health-interval 5s
|
||||||
|
--health-timeout 3s
|
||||||
|
--health-retries 20
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
options: >-
|
||||||
|
--health-cmd "redis-cli ping"
|
||||||
|
--health-interval 5s
|
||||||
|
--health-timeout 3s
|
||||||
|
--health-retries 20
|
||||||
|
env:
|
||||||
|
DATABASE_URL: postgres://postgres:codex_test@postgres:5432/imageforge_test
|
||||||
|
REDIS_URL: redis://redis:6379/
|
||||||
|
IMAGEFORGE_TEST_DATABASE_URL: postgres://postgres:codex_test@postgres:5432/imageforge_test
|
||||||
|
IMAGEFORGE_TEST_REDIS_URL: redis://redis:6379/
|
||||||
|
JWT_SECRET: imageforge-ci-jwt-secret
|
||||||
|
API_KEY_PEPPER: imageforge-ci-api-key-pepper
|
||||||
|
EXPECTED_EXTERNAL_TESTS: '9'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -40,10 +66,13 @@ jobs:
|
|||||||
run: cargo fmt --all -- --check
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
- name: Run Clippy
|
- name: Run Clippy
|
||||||
run: cargo clippy --all-targets -- -D warnings
|
run: cargo clippy --all-targets --all-features --locked -- -D warnings
|
||||||
|
|
||||||
- name: Run Rust tests
|
- name: Run Rust tests
|
||||||
run: cargo test --all-targets
|
run: cargo test --all-targets --locked
|
||||||
|
|
||||||
|
- name: Run external-state tests
|
||||||
|
run: bash scripts/run_external_state_tests.sh
|
||||||
|
|
||||||
- name: Install cargo-audit
|
- name: Install cargo-audit
|
||||||
run: cargo install cargo-audit --locked --version 0.22.2
|
run: cargo install cargo-audit --locked --version 0.22.2
|
||||||
|
|||||||
134
scripts/run_external_state_tests.sh
Normal file
134
scripts/run_external_state_tests.sh
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
EXPECTED_EXTERNAL_TESTS="${EXPECTED_EXTERNAL_TESTS:-9}"
|
||||||
|
WORK_DIR="$(mktemp -d)"
|
||||||
|
POSTGRES_CONTAINER=""
|
||||||
|
REDIS_CONTAINER=""
|
||||||
|
MINIO_PID=""
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local status=$?
|
||||||
|
trap - EXIT INT TERM
|
||||||
|
set +e
|
||||||
|
if [[ -n "$MINIO_PID" ]]; then
|
||||||
|
kill "$MINIO_PID" 2>/dev/null
|
||||||
|
wait "$MINIO_PID" 2>/dev/null
|
||||||
|
fi
|
||||||
|
if [[ -n "$POSTGRES_CONTAINER" ]]; then
|
||||||
|
docker rm -f "$POSTGRES_CONTAINER" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
if [[ -n "$REDIS_CONTAINER" ]]; then
|
||||||
|
docker rm -f "$REDIS_CONTAINER" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
rm -rf "$WORK_DIR"
|
||||||
|
exit "$status"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
wait_for_command() {
|
||||||
|
local description=$1
|
||||||
|
shift
|
||||||
|
for _ in $(seq 1 60); do
|
||||||
|
if "$@" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "Timed out waiting for ${description}" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -z "${IMAGEFORGE_TEST_DATABASE_URL:-}" || -z "${IMAGEFORGE_TEST_REDIS_URL:-}" ]]; then
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
echo "Set IMAGEFORGE_TEST_DATABASE_URL and IMAGEFORGE_TEST_REDIS_URL, or install Docker." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
suffix="$$-${RANDOM}"
|
||||||
|
postgres_port="${IMAGEFORGE_TEST_POSTGRES_PORT:-25432}"
|
||||||
|
redis_port="${IMAGEFORGE_TEST_REDIS_PORT:-26379}"
|
||||||
|
POSTGRES_CONTAINER="imageforge-test-postgres-${suffix}"
|
||||||
|
REDIS_CONTAINER="imageforge-test-redis-${suffix}"
|
||||||
|
|
||||||
|
docker run -d \
|
||||||
|
--label imageforge.external-tests=true \
|
||||||
|
--name "$POSTGRES_CONTAINER" \
|
||||||
|
-e POSTGRES_PASSWORD=codex_test \
|
||||||
|
-e POSTGRES_DB=imageforge_test \
|
||||||
|
-p "127.0.0.1:${postgres_port}:5432" \
|
||||||
|
postgres:16-alpine >/dev/null
|
||||||
|
docker run -d \
|
||||||
|
--label imageforge.external-tests=true \
|
||||||
|
--name "$REDIS_CONTAINER" \
|
||||||
|
-p "127.0.0.1:${redis_port}:6379" \
|
||||||
|
redis:7-alpine >/dev/null
|
||||||
|
|
||||||
|
wait_for_command PostgreSQL docker exec "$POSTGRES_CONTAINER" \
|
||||||
|
pg_isready -U postgres -d imageforge_test
|
||||||
|
wait_for_command Redis docker exec "$REDIS_CONTAINER" redis-cli ping
|
||||||
|
|
||||||
|
export IMAGEFORGE_TEST_DATABASE_URL="postgres://postgres:codex_test@127.0.0.1:${postgres_port}/imageforge_test"
|
||||||
|
export IMAGEFORGE_TEST_REDIS_URL="redis://127.0.0.1:${redis_port}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
arch="$(uname -m)"
|
||||||
|
case "$arch" in
|
||||||
|
x86_64) minio_arch=amd64 ;;
|
||||||
|
aarch64|arm64) minio_arch=arm64 ;;
|
||||||
|
*) echo "Unsupported MinIO architecture: ${arch}" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
MINIO_BIN="${MINIO_BIN:-${WORK_DIR}/minio}"
|
||||||
|
MC_BIN="${MC_BIN:-${WORK_DIR}/mc}"
|
||||||
|
if [[ ! -x "$MINIO_BIN" ]]; then
|
||||||
|
curl --fail --silent --show-error --location --retry 3 \
|
||||||
|
"https://dl.min.io/server/minio/release/linux-${minio_arch}/minio" \
|
||||||
|
--output "$MINIO_BIN"
|
||||||
|
chmod +x "$MINIO_BIN"
|
||||||
|
fi
|
||||||
|
if [[ ! -x "$MC_BIN" ]]; then
|
||||||
|
curl --fail --silent --show-error --location --retry 3 \
|
||||||
|
"https://dl.min.io/client/mc/release/linux-${minio_arch}/mc" \
|
||||||
|
--output "$MC_BIN"
|
||||||
|
chmod +x "$MC_BIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export IMAGEFORGE_TEST_S3_ENDPOINT="${IMAGEFORGE_TEST_S3_ENDPOINT:-http://127.0.0.1:19000}"
|
||||||
|
export IMAGEFORGE_TEST_S3_BUCKET="${IMAGEFORGE_TEST_S3_BUCKET:-imageforge-test}"
|
||||||
|
export IMAGEFORGE_TEST_S3_ACCESS_KEY="${IMAGEFORGE_TEST_S3_ACCESS_KEY:-codexminio}"
|
||||||
|
export IMAGEFORGE_TEST_S3_SECRET_KEY="${IMAGEFORGE_TEST_S3_SECRET_KEY:-codexminio123}"
|
||||||
|
|
||||||
|
if [[ "$IMAGEFORGE_TEST_S3_ENDPOINT" == "http://127.0.0.1:19000" ]]; then
|
||||||
|
MINIO_ROOT_USER="$IMAGEFORGE_TEST_S3_ACCESS_KEY" \
|
||||||
|
MINIO_ROOT_PASSWORD="$IMAGEFORGE_TEST_S3_SECRET_KEY" \
|
||||||
|
"$MINIO_BIN" server "${WORK_DIR}/minio-data" \
|
||||||
|
--address 127.0.0.1:19000 >"${WORK_DIR}/minio.log" 2>&1 &
|
||||||
|
MINIO_PID=$!
|
||||||
|
wait_for_command MinIO curl --fail --silent \
|
||||||
|
"${IMAGEFORGE_TEST_S3_ENDPOINT}/minio/health/ready"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$MC_BIN" alias set imageforge-test \
|
||||||
|
"$IMAGEFORGE_TEST_S3_ENDPOINT" \
|
||||||
|
"$IMAGEFORGE_TEST_S3_ACCESS_KEY" \
|
||||||
|
"$IMAGEFORGE_TEST_S3_SECRET_KEY" >/dev/null
|
||||||
|
"$MC_BIN" mb --ignore-existing \
|
||||||
|
"imageforge-test/${IMAGEFORGE_TEST_S3_BUCKET}" >/dev/null
|
||||||
|
|
||||||
|
export DATABASE_URL="$IMAGEFORGE_TEST_DATABASE_URL"
|
||||||
|
export REDIS_URL="$IMAGEFORGE_TEST_REDIS_URL"
|
||||||
|
export JWT_SECRET="${JWT_SECRET:-imageforge-external-test-jwt-secret}"
|
||||||
|
export API_KEY_PEPPER="${API_KEY_PEPPER:-imageforge-external-test-api-key-pepper}"
|
||||||
|
|
||||||
|
test_log="${WORK_DIR}/external-tests.log"
|
||||||
|
cargo test --all-targets --locked -- \
|
||||||
|
--ignored --test-threads=1 --nocapture 2>&1 | tee "$test_log"
|
||||||
|
|
||||||
|
expected_summary="test result: ok. ${EXPECTED_EXTERNAL_TESTS} passed; 0 failed; 0 ignored;"
|
||||||
|
if ! grep --fixed-strings --quiet "$expected_summary" "$test_log"; then
|
||||||
|
echo "External-state test count mismatch; expected: ${expected_summary}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "External-state gate passed: ${EXPECTED_EXTERNAL_TESTS} passed, 0 failed, 0 ignored."
|
||||||
Reference in New Issue
Block a user