This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +1,2 @@
|
||||
migrations/*.sql text eol=crlf
|
||||
*.sh text eol=lf
|
||||
|
||||
@@ -8,6 +8,32 @@ on:
|
||||
jobs:
|
||||
verify:
|
||||
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:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -40,10 +66,13 @@ jobs:
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Run Clippy
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
run: cargo clippy --all-targets --all-features --locked -- -D warnings
|
||||
|
||||
- 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
|
||||
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