11# yaml-language-server: $schema=https://www.schemastore.org/github-workflow.json
22#
33# CI workflow for tests repository
4- # Integration tests require external dependencies (FoundationDB, etc.) and are
5- # run locally or in dedicated test environments, not in GitHub Actions CI.
6- # This workflow provides a consistent CI Success job for branch protection rules.
4+ # Runs E2E integration tests against Docker Compose stack with Ledger, Engine, and Control.
75
86name : CI
97
1210 branches : [main]
1311 pull_request :
1412 branches : [main]
13+ # Allow manual trigger for testing
14+ workflow_dispatch :
1515
1616# Cancel in-progress runs when new commits are pushed
1717concurrency :
@@ -21,32 +21,157 @@ concurrency:
2121permissions :
2222 contents : read
2323
24+ env :
25+ CARGO_TERM_COLOR : always
26+ RUST_BACKTRACE : 1
27+
2428jobs :
25- # Placeholder job - integration tests require external dependencies
26- # Tests are run locally via: make integration-test (uses docker-compose)
27- external-dependencies :
28- name : External Dependencies Required
29+ # ==========================================================================
30+ # Build: Compile tests (fast feedback on syntax errors)
31+ # ==========================================================================
32+ build :
33+ name : Build Tests
2934 runs-on : ubuntu-latest
3035 steps :
3136 - name : Harden the runner (Audit all outbound calls)
3237 uses : step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
3338 with :
3439 egress-policy : audit
3540
36- - name : Skip CI tests
41+ - name : Checkout tests repository
42+ uses : actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
43+
44+ - name : Install Rust toolchain
45+ uses : dtolnay/rust-action@7ac8906b4da87dbf44ef2c5cc52b4e736c91b7f6 # master
46+ with :
47+ toolchain : " 1.85"
48+ components : clippy
49+
50+ - name : Cache Rust dependencies
51+ uses : Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
52+ with :
53+ shared-key : " tests-build"
54+
55+ - name : Check formatting
56+ run : cargo fmt --check
57+
58+ - name : Run clippy
59+ run : cargo clippy --all-targets -- -D warnings
60+
61+ - name : Build tests
62+ run : cargo test --no-run
63+
64+ # ==========================================================================
65+ # E2E Integration Tests: Full stack with Ledger + Engine + Control
66+ # ==========================================================================
67+ e2e-integration-tests :
68+ name : E2E Integration Tests
69+ runs-on : ubuntu-latest
70+ needs : [build]
71+ timeout-minutes : 30
72+ steps :
73+ - name : Harden the runner (Audit all outbound calls)
74+ uses : step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
75+ with :
76+ egress-policy : audit
77+
78+ - name : Checkout meta-repository
79+ uses : actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
80+ with :
81+ repository : inferadb/inferadb
82+ submodules : recursive
83+ path : inferadb
84+
85+ - name : Set up Docker Buildx
86+ uses : docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
87+
88+ - name : Build and start E2E stack
89+ working-directory : inferadb
3790 run : |
38- echo "This repository contains integration tests that require external dependencies."
91+ echo "Building Docker images..."
92+ docker compose -f docker-compose.e2e.yml build
93+
94+ echo "Starting services..."
95+ docker compose -f docker-compose.e2e.yml up -d
96+
97+ - name : Wait for services to be healthy
98+ working-directory : inferadb
99+ run : |
100+ echo "Waiting for services to become healthy..."
101+
102+ TIMEOUT=180
103+ ELAPSED=0
104+
105+ while [[ $ELAPSED -lt $TIMEOUT ]]; do
106+ LEDGER_HEALTHY=$(docker inspect --format='{{.State.Health.Status}}' inferadb-e2e-ledger 2>/dev/null || echo "unknown")
107+ CONTROL_HEALTHY=$(docker inspect --format='{{.State.Health.Status}}' inferadb-e2e-control 2>/dev/null || echo "unknown")
108+ ENGINE_HEALTHY=$(docker inspect --format='{{.State.Health.Status}}' inferadb-e2e-engine 2>/dev/null || echo "unknown")
109+
110+ echo " Ledger: $LEDGER_HEALTHY | Control: $CONTROL_HEALTHY | Engine: $ENGINE_HEALTHY (${ELAPSED}s)"
111+
112+ if [[ "$LEDGER_HEALTHY" == "healthy" ]] && \
113+ [[ "$CONTROL_HEALTHY" == "healthy" ]] && \
114+ [[ "$ENGINE_HEALTHY" == "healthy" ]]; then
115+ echo "All services are healthy!"
116+ exit 0
117+ fi
118+
119+ sleep 5
120+ ELAPSED=$((ELAPSED + 5))
121+ done
122+
123+ echo "ERROR: Services did not become healthy within ${TIMEOUT}s"
39124 echo ""
40- echo "To run tests locally:"
41- echo " make integration-test"
125+ echo "Container logs:"
126+ docker compose -f docker-compose.e2e.yml logs
127+ exit 1
128+
129+ - name : Install Rust toolchain
130+ uses : dtolnay/rust-action@7ac8906b4da87dbf44ef2c5cc52b4e736c91b7f6 # master
131+ with :
132+ toolchain : " 1.85"
133+
134+ - name : Cache Rust dependencies
135+ uses : Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
136+ with :
137+ shared-key : " tests-build"
138+ workspaces : " inferadb/tests"
139+
140+ - name : Run E2E integration tests
141+ working-directory : inferadb/tests
142+ env :
143+ INFERADB_API_URL : " http://localhost:9090"
144+ ENGINE_URL : " http://localhost:8080"
145+ ENGINE_GRPC_URL : " http://localhost:8081"
146+ ENGINE_MESH_URL : " http://localhost:8082"
147+ CONTROL_URL : " http://localhost:9090"
148+ RUST_LOG : " debug"
149+ run : |
150+ cargo test --test integration -- --test-threads=1 --nocapture
151+
152+ - name : Collect logs on failure
153+ if : failure()
154+ working-directory : inferadb
155+ run : |
156+ echo "=== Docker Compose Logs ==="
157+ docker compose -f docker-compose.e2e.yml logs --tail=500
158+
42159 echo ""
43- echo "This uses docker-compose to spin up required services."
44- echo "See README.md for more details."
160+ echo "=== Container Status ==="
161+ docker compose -f docker-compose.e2e.yml ps
162+
163+ - name : Stop E2E stack
164+ if : always()
165+ working-directory : inferadb
166+ run : |
167+ docker compose -f docker-compose.e2e.yml down -v --remove-orphans
45168
169+ # ==========================================================================
46170 # Overall status check - required for branch protection
171+ # ==========================================================================
47172 ci-success :
48173 name : CI Success
49- needs : [external-dependencies ]
174+ needs : [build, e2e-integration-tests ]
50175 runs-on : ubuntu-latest
51176 if : always()
52177 permissions :
@@ -59,22 +184,38 @@ jobs:
59184
60185 - name : Check CI results
61186 env :
62- EXTERNAL_DEPS_RESULT : ${{ needs.external-dependencies.result }}
187+ BUILD_RESULT : ${{ needs.build.result }}
188+ E2E_RESULT : ${{ needs.e2e-integration-tests.result }}
63189 run : |
64190 echo "## CI Results"
65191 echo ""
66192 echo "| Check | Status |"
67193 echo "|-------|--------|"
68- echo "| External Dependencies | $EXTERNAL_DEPS_RESULT (tests skipped) |"
69- echo ""
70- echo "Integration tests require external dependencies and are run locally."
71- echo "See docker-compose.integration.yml for the test environment setup."
194+ echo "| Build | $BUILD_RESULT |"
195+ echo "| E2E Integration Tests | $E2E_RESULT |"
72196 echo ""
73197
74- # Fail if the placeholder job failed (shouldn't happen)
75- if [[ "$EXTERNAL_DEPS_RESULT" != "success" && "$EXTERNAL_DEPS_RESULT" != "skipped" ]]; then
76- echo "Unexpected failure in CI workflow"
198+ # Function to validate result
199+ validate_result() {
200+ local name="$1"
201+ local result="$2"
202+ if [[ "$result" != "success" && "$result" != "skipped" ]]; then
203+ echo "FAILED: $name ($result)"
204+ return 1
205+ fi
206+ return 0
207+ }
208+
209+ # Check all results
210+ FAILED=0
211+ validate_result "Build" "$BUILD_RESULT" || FAILED=1
212+ validate_result "E2E Integration Tests" "$E2E_RESULT" || FAILED=1
213+
214+ if [[ $FAILED -eq 1 ]]; then
215+ echo ""
216+ echo "Some CI checks failed!"
77217 exit 1
78218 fi
79219
80- echo "CI checks passed!"
220+ echo ""
221+ echo "All CI checks passed!"
0 commit comments