Automate monthly incremental catalog updates via GitHub Actions - #24
Conversation
Move stale planning/active files to planning/archive/2026-02-issue-13-url-accessibility/ with outcome README. Clears active/ for issue #23. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
Approved phases: CI-safe pipeline fixes, rtj#184 companion infra, monthly update workflow, post-merge catch-up run. Plan reviewed by Plan agent before baseline (2 blockers + 8 gaps absorbed). Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
- stac_utils.py: STAC_OUTPUT_DIR env override for get_output_dir() - detect_changes.R: exit contract 0/1/2 (no changes/changes/error) via tryCatch; plausibility guard refuses cache update when fresh listing < 90% of cached (truncated-fetch poisoning); no library() calls so missing packages exit 2, not a false "changes detected" - scripts/s3_sync-ci.sh: no-delete sync on default credential chain, item JSONs before collection.json (no dangling links on failure), --dryrun passthrough, trailing-slash bucket normalization - scripts/urls_reconcile.py: one-off cache trim to item-backed URLs so detection re-flags 2,107 never-built URLs (90 parenthesized + post- build refresh remainder) - environment.yml: pystac[validation] (jsonschema for the validate gate) + requests Cold-path rehearsal passed on a stateless workspace (S3-fetched collection.json only): dedupe, validate skip, dry-run sync with zero deletions. Live ngr fetch shows objectstore at 98,039 URLs (+37,900 since Feb) - catch-up run moves to the documented local fallback path; task_plan Phase 4 amended. Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
- .github/workflows/update.yml: monthly cron (3rd, 09:23 UTC) + workflow_dispatch; OIDC via role_gha_stac_dem_bc; detect step maps the 0/1/2 exit contract to outputs; item steps gated on urls_new.txt presence (deletions-only months still commit caches) and on a nonzero created count (an all-invalid batch stays green with a shortfall warning instead of wedging); access check warn-only; sync via s3_sync-ci.sh; caches committed back with rebase-before-push; logs uploaded as artifact (overwrite-safe for re-runs) - DESCRIPTION: R dep manifest for setup-r-dependencies (fs, ngr@519c03b - the locally verified build - readr), water-temp-bc pattern - scripts/README.md: Automation section with failure triage (shortfall remediation, oversized-batch local fallback, 60-day cron auto-disable) - CLAUDE.md: S3 is the only complete catalog copy; local builds use the STAC_OUTPUT_DIR override Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
The sred-2025-2026 repo refs are superseded. Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
|
Reviewed the workflow, One minor edge case worth a look, not blocking:
Everything else — OIDC role usage, |
Relates to #23 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH
|
Reviewed the workflow, R change-detection rewrite, sync script, and reconcile helper. Didn't find correctness or security bugs — the exit-code contract (0/1/2), the plausibility guard, items-before-collection sync order, the zero-created gate, and the A couple of non-blocking observations, both already implicitly acknowledged in the README triage notes:
Both are design tradeoffs rather than bugs, and both have documented remediation paths in |
Summary
.github/workflows/update.yml: monthly incremental catalog update on a GitHub-hosted runner (cron 3rd of month +workflow_dispatch), authenticating via OIDC againstrole_gha_stac_dem_bc(applied in rtj PR #189). Detects objectstore changes, builds/validates STAC items for new URLs only, syncs to S3, and commits refresheddata/caches back to main — a failed run persists nothing and self-heals on the next detection.STAC_OUTPUT_DIRoverride (stac_utils.py),detect_changes.Rexit contract (0/1/2) with a truncated-listing plausibility guard,s3_sync-ci.sh(never--delete; item JSONs beforecollection.json),pystac[validation]+requestsdeps.urls_reconcile.py: one-off cache trim so change detection re-flags the 2,107 URLs that entered the cache without ever producing a catalog item (incl. the 90 parenthesized files).Related Issues
Test plan
collection.jsononly, exact CI dep list via uv/py3.12): item create + dedupe, incremental validate,s3_sync-ci.sh --dryrunwith zero deletions and items-before-collection orderngrfetch verified current listing format matches the cache (98,039 URLs, single-slash scheme uniform) — pinned that ngr SHA in DESCRIPTIONupdate.ymlYAML-parsed (16 steps, all run blocks literal strings), pure ASCIIworkflow_dispatchsteady-state verification → pgstac registration on geoservNotes
urls_fetch.Ris deliberately bypassed in CI:detect_changes.Rfetches the fresh listing itself and maintains the cache, so a separate fetch step would duplicate the ~90 s listing call without adding information.🤖 Generated with Claude Code
https://claude.ai/code/session_01HN1tMTLezPVkv9eT86FLSH