@@ -130,16 +130,23 @@ jobs:
130130 select(.key | test("tipgapioutput"; "i")) |
131131 .value' | head -1)
132132
133+ INGESTOR_API_URL=$(cat stack_outputs.json | jq -r '
134+ to_entries[] |
135+ select(.key | test("ingestorapioutput"; "i")) |
136+ .value' | head -1)
137+
133138 echo "Extracted URLs:"
134139 echo "STAC_API_URL: $STAC_API_URL"
135140 echo "TITILER_PGSTAC_API_URL: $TITILER_PGSTAC_API_URL"
136141 echo "TIPG_API_URL: $TIPG_API_URL"
142+ echo "INGESTOR_API_URL: $INGESTOR_API_URL"
137143
138144 # Array of API URLs to check
139145 declare -a API_HEALTH_ENDPOINTS=(
140146 "STAC_API_URL:${STAC_API_URL}_mgmt/health"
141147 "TITILER_PGSTAC_API_URL:${TITILER_PGSTAC_API_URL}healthz"
142148 "TIPG_API_URL:${TIPG_API_URL}healthz"
149+ "INGESTOR_API_URL:${INGESTOR_API_URL}ingestions"
143150 )
144151
145152 # Check each API
@@ -166,6 +173,127 @@ jobs:
166173 fi
167174 done
168175
176+ echo "=== Ingestor Integration Test ==="
177+
178+ if [ -n "$INGESTOR_API_URL" ] && [ "$INGESTOR_API_URL" != "null" ]; then
179+ COLLECTION_ID="integration-test-collection"
180+ ITEM_ID="integration-test-item-001"
181+
182+ # Use a public URL that responds to HEAD requests for asset validation
183+ PUBLIC_ASSET_URL="https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0/examples/simple-item.json"
184+
185+ # No JWKS_URL configured, so identity is provided via ?provided_by query param
186+ INGESTOR_USER="ci-test"
187+
188+ echo "--- Posting collection $COLLECTION_ID ---"
189+ COLLECTION_STATUS=$(curl -s -o /tmp/collection_response.json -w "%{http_code}" \
190+ --max-time 30 \
191+ -X POST "${INGESTOR_API_URL}collections?provided_by=${INGESTOR_USER}" \
192+ -H "Content-Type: application/json" \
193+ -d "{
194+ \"id\": \"$COLLECTION_ID\",
195+ \"type\": \"Collection\",
196+ \"stac_version\": \"1.0.0\",
197+ \"description\": \"Integration test collection\",
198+ \"title\": \"Integration Test Collection\",
199+ \"license\": \"proprietary\",
200+ \"item_assets\": {
201+ \"data\": {\"type\": \"application/json\", \"roles\": [\"data\"]}
202+ },
203+ \"extent\": {
204+ \"spatial\": {\"bbox\": [[-180, -90, 180, 90]]},
205+ \"temporal\": {\"interval\": [[\"2020-01-01T00:00:00Z\", null]]}
206+ },
207+ \"links\": [],
208+ \"stac_extensions\": []
209+ }")
210+
211+ echo "Collection POST status: $COLLECTION_STATUS"
212+ cat /tmp/collection_response.json
213+
214+ if [ "$COLLECTION_STATUS" != "201" ]; then
215+ echo "❌ Failed to post collection (status $COLLECTION_STATUS)"
216+ exit 1
217+ fi
218+ echo "✅ Collection posted successfully"
219+
220+ echo "--- Posting item $ITEM_ID ---"
221+ ITEM_STATUS=$(curl -s -o /tmp/item_response.json -w "%{http_code}" \
222+ --max-time 30 \
223+ -X POST "${INGESTOR_API_URL}ingestions?provided_by=${INGESTOR_USER}" \
224+ -H "Content-Type: application/json" \
225+ -d "{
226+ \"stac_version\": \"1.0.0\",
227+ \"stac_extensions\": [],
228+ \"type\": \"Feature\",
229+ \"id\": \"$ITEM_ID\",
230+ \"collection\": \"$COLLECTION_ID\",
231+ \"bbox\": [-180, -90, 180, 90],
232+ \"geometry\": {
233+ \"type\": \"Polygon\",
234+ \"coordinates\": [[[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]]]
235+ },
236+ \"properties\": {\"datetime\": \"2020-01-01T00:00:00Z\"},
237+ \"assets\": {
238+ \"data\": {
239+ \"href\": \"$PUBLIC_ASSET_URL\",
240+ \"type\": \"application/json\",
241+ \"roles\": [\"data\"]
242+ }
243+ },
244+ \"links\": []
245+ }")
246+
247+ echo "Item POST status: $ITEM_STATUS"
248+ cat /tmp/item_response.json
249+
250+ if [ "$ITEM_STATUS" != "201" ]; then
251+ echo "❌ Failed to post item (status $ITEM_STATUS)"
252+ exit 1
253+ fi
254+ echo "✅ Item queued for ingestion"
255+
256+ echo "--- Polling ingestion status for $ITEM_ID ---"
257+ INGESTION_STATUS="queued"
258+ POLL_ATTEMPTS=0
259+ MAX_POLL_ATTEMPTS=20
260+
261+ while [ "$INGESTION_STATUS" = "queued" ] || [ "$INGESTION_STATUS" = "started" ]; do
262+ if [ "$POLL_ATTEMPTS" -ge "$MAX_POLL_ATTEMPTS" ]; then
263+ echo "❌ Timed out waiting for ingestion of $ITEM_ID (status: $INGESTION_STATUS)"
264+ exit 1
265+ fi
266+
267+ sleep 15
268+ POLL_ATTEMPTS=$((POLL_ATTEMPTS + 1))
269+
270+ INGESTION_RESPONSE=$(curl -s --max-time 30 "${INGESTOR_API_URL}ingestions/${ITEM_ID}?provided_by=${INGESTOR_USER}")
271+ INGESTION_STATUS=$(echo "$INGESTION_RESPONSE" | jq -r '.status // "unknown"')
272+ echo "Attempt $POLL_ATTEMPTS: ingestion status = $INGESTION_STATUS"
273+ done
274+
275+ if [ "$INGESTION_STATUS" != "succeeded" ]; then
276+ echo "❌ Ingestion failed with status: $INGESTION_STATUS"
277+ echo "$INGESTION_RESPONSE" | jq .
278+ exit 1
279+ fi
280+ echo "✅ Item ingested successfully"
281+
282+ echo "--- Verifying item in STAC API ---"
283+ STAC_ITEM_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
284+ --max-time 30 \
285+ "${STAC_API_URL}collections/$COLLECTION_ID/items/$ITEM_ID")
286+
287+ if [ "$STAC_ITEM_STATUS" = "200" ]; then
288+ echo "✅ Item $ITEM_ID is accessible in STAC API"
289+ else
290+ echo "❌ Item $ITEM_ID not found in STAC API (status $STAC_ITEM_STATUS)"
291+ exit 1
292+ fi
293+ else
294+ echo "⚠️ INGESTOR_API_URL not found in stack outputs, skipping ingestor test"
295+ fi
296+
169297 echo "=== Operational Checks Complete ==="
170298 cd -
171299
0 commit comments