Skip to content

Commit 4b70e92

Browse files
committed
ci: simplify GitHub Actions triggers
Remove workflow_dispatch and tags triggers from build workflow Remove pull_request and workflow_dispatch triggers from test workflow Fix permissions in test workflow (no write access needed for tests)
1 parent 8198ca6 commit 4b70e92

18 files changed

+675
-803
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ on:
44
push:
55
branches:
66
- '**' # Build all branches during rapid iteration
7-
tags:
8-
- 'v*'
9-
workflow_dispatch:
107

118
permissions:
129
contents: read

.github/workflows/test.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@ name: Tests
33
on:
44
push:
55
branches: [ '**' ]
6-
pull_request:
7-
branches: [ main ]
8-
workflow_dispatch:
96

107
permissions:
118
contents: read
12-
packages: write
139

1410
jobs:
1511
test:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ Thumbs.db
6161
# Project-specific
6262
*.zarr
6363
out/
64+
reports/

README.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Transforms Sentinel-1/2 satellite data into web-ready visualizations:
6464
- Argo Workflows (pipeline orchestration)
6565
- RabbitMQ (event-driven automation)
6666
- STAC API & TiTiler (catalog & visualization)
67-
- **Python 3.11+** with `uv` package manager
67+
- **Python 3.13+** with `uv` package manager
6868
- **S3 storage** credentials (OVH de region)
6969
- **Kubeconfig** in `.work/kubeconfig`
7070

@@ -205,10 +205,11 @@ workflows/ # Kubernetes manifests (Kustomize)
205205
└── overlays/ # staging, production configs
206206
207207
docker/Dockerfile # Pipeline image
208-
submit_test_workflow.py # RabbitMQ submission script
209-
notebooks/01_quickstart.ipynb # Interactive example
208+
tools/submit_burst.py # RabbitMQ burst submission tool
210209
```
211210

211+
Tests are available in `tests/` directory (unit and integration tests using pytest).
212+
212213
---
213214

214215
## Deploy
@@ -221,7 +222,7 @@ kubectl apply -k workflows/overlays/staging
221222
kubectl apply -k workflows/overlays/production
222223
```
223224

224-
**Config:** Image version, S3 endpoints, STAC API URLs, RabbitMQ exchanges
225+
**Config:** Image version, S3 endpoints, STAC API URLs, RabbitMQ exchanges configured via kustomize overlays.
225226

226227
---
227228

@@ -314,13 +315,7 @@ kubectl logs -n devseed-staging -l eventsource-name=rabbitmq-geozarr --tail=50
314315
- [platform-deploy](https://github.com/EOPF-Explorer/platform-deploy) - Infrastructure (Argo, RabbitMQ, STAC, TiTiler)
315316

316317
**Documentation:**
317-
- Interactive notebook: `notebooks/01_quickstart.ipynb`
318-
- Workflow docs: `workflows/README.md`
319-
320-
321-
- Image: `ghcr.io/eopf-explorer/data-pipeline:slim`
322-
- Memory: 6Gi per workflow
323-
- CPU: 500m-2000m (burstable)
324-
- Supports: Sentinel-1 GRD, Sentinel-2 L2A
318+
- Workflow manifests: `workflows/README.md`
319+
- Tests: `tests/` (pytest unit and integration tests)
325320

326-
**License:** Apache 2.0
321+
**License:** MIT

docker/Dockerfile

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,12 @@ WORKDIR /app
1616
# Install uv for fast dependency resolution
1717
RUN pip install -U pip uv
1818

19-
# Use git commit SHA for precise cache control
20-
# Update via: docker build --build-arg DATA_MODEL_COMMIT=$(git ls-remote https://github.com/EOPF-Explorer/data-model.git refs/heads/fix/s1-encoding-conflict | cut -f1)
21-
ARG DATA_MODEL_COMMIT=fix/s1-encoding-conflict
22-
23-
# Install eopf-geozarr from data-model (includes dask[distributed])
24-
RUN uv pip install --system --no-cache \
25-
git+https://github.com/EOPF-Explorer/data-model.git@${DATA_MODEL_COMMIT}
26-
27-
# Copy project files for dependency installation
19+
# Copy project files and install dependencies (includes eopf-geozarr from data-model via git)
2820
COPY pyproject.toml README.md /app/
2921
RUN uv pip install --system --no-cache /app
3022

31-
# Copy scripts (cache invalidated by content changes, not manual ARG)
32-
ARG SCRIPTS_VERSION=auto
33-
3423
# Copy scripts
3524
COPY scripts/ /app/scripts/
36-
RUN chmod +x /app/scripts/*.py
3725

3826
# Copy workflows (example payloads and templates)
3927
COPY workflows/ /app/workflows/

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
requires = ["hatchling"]
33
build-backend = "hatchling.build"
44

5+
[tool.hatch.metadata]
6+
allow-direct-references = true
7+
58
[project]
69
name = "data-pipeline"
710
version = "1.0.0"
@@ -33,6 +36,7 @@ dependencies = [
3336
"requests>=2.31.0",
3437
"morecantile>=5.0.0",
3538
"cf-xarray>=0.9.0",
39+
"eopf-geozarr @ git+https://github.com/EOPF-Explorer/data-model.git@fix/s1-encoding-conflict",
3640
]
3741

3842
[project.optional-dependencies]
@@ -129,7 +133,7 @@ indent-style = "space"
129133
line-ending = "auto"
130134

131135
[tool.mypy]
132-
python_version = "3.11"
136+
python_version = "3.13"
133137
warn_return_any = true
134138
warn_unused_configs = true
135139
disallow_untyped_defs = true

scripts/augment_stac_item.py

100644100755
Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"""STAC item augmentation: add CRS metadata and preview links."""
33

44
import argparse
5+
import logging
56
import os
67
import sys
78
import urllib.parse
@@ -11,6 +12,11 @@
1112
from pystac import Item, Link
1213
from pystac.extensions.projection import ProjectionExtension
1314

15+
logging.basicConfig(
16+
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
17+
)
18+
logger = logging.getLogger(__name__)
19+
1420
EXPLORER_BASE = os.getenv("EXPLORER_BASE_URL", "https://explorer.eopf.copernicus.eu")
1521

1622

@@ -60,8 +66,8 @@ def add_visualization(item: Item, raster_base: str, collection_id: str) -> None:
6066
_add_tile_links(item, base_url, query, "Sentinel-1 GRD VH")
6167

6268
elif coll_lower.startswith(("sentinel-2", "sentinel2")):
63-
# S2: Static quicklook path
64-
var_path = "/quality/l2a_quicklook/r10m:tci"
69+
# S2: Quicklook path (with /0/ for native resolution when using crs-groups)
70+
var_path = "/quality/l2a_quicklook/r10m/0:tci"
6571
query = (
6672
f"variables={urllib.parse.quote(var_path, safe='')}&bidx=1&bidx=2&bidx=3&assets=TCI_10m"
6773
)
@@ -96,10 +102,17 @@ def _add_tile_links(item: Item, base_url: str, query: str, title: str) -> None:
96102
)
97103

98104

99-
def augment(item: Item, *, raster_base: str, collection_id: str, verbose: bool) -> Item:
100-
"""Augment STAC item with extensions and links."""
101-
if verbose:
102-
print(f"[augment] {item.id}")
105+
def augment(item: Item, *, raster_base: str, collection_id: str) -> Item:
106+
"""Augment STAC item with extensions and links.
107+
108+
Args:
109+
item: STAC item to augment
110+
raster_base: TiTiler raster API base URL
111+
collection_id: Collection ID for viewer links
112+
113+
Returns:
114+
Augmented item (modified in place)
115+
"""
103116
add_projection(item)
104117
add_visualization(item, raster_base, collection_id)
105118
return item
@@ -108,45 +121,42 @@ def augment(item: Item, *, raster_base: str, collection_id: str, verbose: bool)
108121
def main(argv: list[str] | None = None) -> int:
109122
"""Main entry point."""
110123
p = argparse.ArgumentParser(description="Augment STAC item")
111-
p.add_argument("--stac", required=True, help="STAC API base")
112-
p.add_argument("--collection", required=True, help="Collection ID")
124+
p.add_argument("--stac-api-url", required=True, help="STAC API base URL")
125+
p.add_argument("--collection-id", required=True, help="Collection ID")
113126
p.add_argument("--item-id", required=True, help="Item ID")
114-
p.add_argument("--bearer", default="", help="Bearer token")
127+
p.add_argument("--bearer", default="", help="Bearer token (optional)")
115128
p.add_argument(
116-
"--raster-base",
129+
"--raster-api-url",
117130
default="https://api.explorer.eopf.copernicus.eu/raster",
118-
help="TiTiler base",
131+
help="TiTiler raster API base URL",
119132
)
120-
p.add_argument("--verbose", action="store_true")
133+
p.add_argument("--verbose", action="store_true", help="Enable verbose logging")
121134
args = p.parse_args(argv)
122135

136+
if args.verbose:
137+
logger.setLevel(logging.DEBUG)
138+
123139
headers = {"Authorization": f"Bearer {args.bearer}"} if args.bearer else {}
124-
item_url = f"{args.stac.rstrip('/')}/collections/{args.collection}/items/{args.item_id}"
140+
item_url = (
141+
f"{args.stac_api_url.rstrip('/')}/collections/{args.collection_id}/items/{args.item_id}"
142+
)
125143

126-
# Fetch item
144+
# Fetch, augment, and update item
127145
try:
128146
with httpx.Client() as client:
147+
# Fetch item
129148
r = client.get(item_url, headers=headers, timeout=30.0)
130149
r.raise_for_status()
131150
item = Item.from_dict(r.json())
132-
except Exception as e:
133-
print(f"ERROR: GET failed: {e}", file=sys.stderr)
134-
return 1
135151

136-
# Augment with CRS + preview links
137-
target_collection = item.collection_id or args.collection
152+
# Augment with CRS + preview links
153+
target_collection = item.collection_id or args.collection_id
154+
augment(item, raster_base=args.raster_api_url, collection_id=target_collection)
138155

139-
augment(
140-
item,
141-
raster_base=args.raster_base,
142-
collection_id=target_collection,
143-
verbose=args.verbose,
144-
)
145-
146-
# Update item via PUT
147-
target_url = f"{args.stac.rstrip('/')}/collections/{target_collection}/items/{item.id}"
148-
try:
149-
with httpx.Client() as client:
156+
# Update item via PUT
157+
target_url = (
158+
f"{args.stac_api_url.rstrip('/')}/collections/{target_collection}/items/{item.id}"
159+
)
150160
r = client.put(
151161
target_url,
152162
json=item.to_dict(),
@@ -155,13 +165,15 @@ def main(argv: list[str] | None = None) -> int:
155165
)
156166
r.raise_for_status()
157167
if args.verbose:
158-
print(f"PUT {target_url}{r.status_code}")
168+
logger.debug(f"PUT {target_url}{r.status_code}")
169+
170+
logger.info(f"✅ Augmented {item.id} in {target_collection}")
171+
return 0
172+
159173
except Exception as e:
160-
print(f"ERROR: PUT failed: {e}", file=sys.stderr)
174+
logger.error(f"Failed to augment {args.item_id}: {e}")
161175
return 1
162176

163-
return 0
164-
165177

166178
if __name__ == "__main__":
167179
sys.exit(main())

0 commit comments

Comments
 (0)