Skip to content

Commit eedbb18

Browse files
committed
Include Helios in container and run test that involves Helios
1 parent 2bb03a2 commit eedbb18

File tree

5 files changed

+125
-13
lines changed

5 files changed

+125
-13
lines changed

.github/workflows/build_test.yaml

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ jobs:
5555
sudo rm -rf /opt/ghc
5656
sudo rm -rf /usr/local/share/boost
5757
58+
# Add deploy key and clone Helios repository.
59+
- name: Start ssh-agent and add key
60+
uses: webfactory/[email protected]
61+
with:
62+
ssh-private-key: ${{ secrets.DEPLOY_KEY_FOR_HELIOS_CLONE }}
63+
- name: Clone helios and update requirements-extra.txt.
64+
run: |
65+
mkdir docker_build
66+
git clone -b favyen/20250903-fix-beaker-req [email protected]:allenai/helios.git docker_build/helios
67+
echo "helios @ /opt/rslearn_projects/docker_build/helios/" >> requirements-extra.txt
68+
5869
- name: Build and push Docker image
5970
id: build-push
6071
uses: docker/build-push-action@v6
@@ -76,14 +87,12 @@ jobs:
7687
echo "ghcr.io Docker image name is ${GHCR_IMAGE}"
7788
echo "ghcr_image_name=\"${GHCR_IMAGE}\"" >> $GITHUB_OUTPUT
7889
79-
8090
test:
91+
needs: build
8192
runs-on: ubuntu-latest-m
8293
steps:
8394
- name: Checkout repository
8495
uses: actions/checkout@v4
85-
with:
86-
fetch-depth: '0' # checkout all branches, so we know which tests to run
8796

8897
- name: Log in to the Container registry
8998
uses: docker/login-action@v3
@@ -100,27 +109,29 @@ jobs:
100109
sudo rm -rf /opt/ghc
101110
sudo rm -rf /usr/local/share/boost
102111
103-
- name: Build docker images
112+
- name: Pull the latest image
104113
run: |
105-
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f docker-compose.yaml build
114+
docker pull ${{ needs.build.outputs.ghcr_docker_image }}
106115
107116
- name: Authenticate into gcp
108117
uses: "google-github-actions/auth@v2"
109118
with:
110119
credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }}
111120

112-
- name: Run unit tests with Docker Compose
121+
- name: Run unit tests
113122
run: |
114123
echo "Executing unit tests"
115-
docker compose -f docker-compose.yaml run \
124+
docker run --rm \
116125
-e CI="true" \
117-
test pytest tests/unit
126+
${{ needs.build.outputs.ghcr_docker_image }} \
127+
pytest -n auto tests/unit -vv
118128
119-
- name: Run tests with Docker Compose
129+
- name: Run integration tests
120130
run: |
121131
echo "Executing integration tests"
122-
docker compose -f docker-compose.yaml run \
132+
docker run --rm \
123133
-e CI="true" \
134+
${{ needs.build.outputs.ghcr_docker_image }} \
124135
-e AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" \
125136
-e AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}" \
126137
-e BEAKER_TOKEN="${BEAKER_TOKEN}" \
@@ -136,7 +147,7 @@ jobs:
136147
-e TEST_PUBSUB_TOPIC=rslearn_projects_test_topic \
137148
-e TEST_PUBSUB_SUBSCRIPTION=rslearn_projects_test_subscription \
138149
-e TEST_QUEUE_NAME=favyen/rslearn-projects-test-queue \
139-
test pytest tests/integration -vv
150+
pytest -n auto tests/integration -vv
140151
env:
141152
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
142153
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -145,7 +156,7 @@ jobs:
145156
- name: Clean up
146157
if: always()
147158
run: |
148-
docker compose -f docker-compose.yaml down
159+
docker image prune -f
149160
150161
# test-slow:
151162
# runs-on: GPU-Enabled-Runner

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
interrogate>=1.7
22
pre-commit
33
pytest>=8.2
4+
pytest-xdist
45
ruff>=0.7

requirements-helios.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
helios
1+
helios @ git+https://github.com/allenai/helios.git@main

tests/integration/common/test_worker.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
import time
66
from collections.abc import Callable
77

8+
import pytest
9+
810
from rslp.common.worker import worker_pipeline, write_jobs
911

1012
IDLE_TIMEOUT = 2
1113

1214

15+
# Group together these tests since they use the same Beaker queue.
16+
@pytest.mark.xdist_group(name="worker_test_group")
1317
class TestWorker:
1418
"""Test the rslp.common.worker module."""
1519

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""Test esrun pipeline."""
2+
3+
import shutil
4+
from datetime import UTC, datetime
5+
from pathlib import Path
6+
7+
import numpy as np
8+
import rasterio
9+
import shapely
10+
import yaml
11+
from rslearn.const import WGS84_PROJECTION
12+
from rslearn.utils.feature import Feature
13+
from rslearn.utils.geometry import STGeometry
14+
from rslearn.utils.vector_format import GeojsonVectorFormat
15+
from upath import UPath
16+
17+
from rslp.esrun.esrun import esrun
18+
19+
20+
def test_esrun_solar_farm(tmp_path: Path) -> None:
21+
"""Test ESRun pipeline by applying solar farm on small request geometry."""
22+
# For now this is fixed but we should figure out how to have standardized path for
23+
# each application later, similar to RSLP_PREFIX.
24+
checkpoint_path = "gs://ai2-rslearn-projects-data/projects/2025_06_06_helios_finetuning/v2_satlas_solar_farm_128_ts_helios_per_mod_patchdisc_contrastive_fix_esrun/checkpoints/epoch=9999-step=99999.ckpt"
25+
26+
# Copy the configuration files. We use the tmp_path as the config dir that we will
27+
# initialize from since we will customize the request geometry.
28+
src_dir = Path("esrun_data/satlas/solar_farm_oe/")
29+
config_dir = tmp_path / "config"
30+
config_dir.mkdir(parents=True)
31+
for fname in ["dataset.json", "model.yaml"]:
32+
with (
33+
(src_dir / fname).open("rb") as src,
34+
(config_dir / fname).open("wb") as dst,
35+
):
36+
shutil.copyfileobj(src, dst)
37+
38+
# This request geometry should be at least 10% solar farm (and at most 50%).
39+
# It is centered at a solar farm and we extend beyond the solar farm.
40+
solar_farm_center = (-111.613, 33.267)
41+
request_geometry = STGeometry(
42+
WGS84_PROJECTION,
43+
shapely.box(
44+
solar_farm_center[0] - 0.01,
45+
solar_farm_center[1] - 0.01,
46+
solar_farm_center[0] + 0.01,
47+
solar_farm_center[1] + 0.01,
48+
),
49+
None,
50+
)
51+
feat = Feature(
52+
request_geometry,
53+
{
54+
"es_start_time": datetime(2024, 12, 1, tzinfo=UTC).isoformat(),
55+
"es_end_time": datetime(2025, 7, 1, tzinfo=UTC).isoformat(),
56+
},
57+
)
58+
GeojsonVectorFormat().encode_to_file(
59+
UPath(config_dir / "prediction_request_geometry.geojson"), [feat]
60+
)
61+
62+
# We also customize the esrun.yaml since we want to use a single window.
63+
with (src_dir / "esrun.yaml").open() as f:
64+
esrun_config = yaml.safe_load(f)
65+
esrun_config["partition_strategies"]["partition_request_geometry"] = {
66+
"class_path": "esrun.runner.tools.partitioners.noop_partitioner.NoopPartitioner",
67+
}
68+
esrun_config["partition_strategies"]["prepare_window_geometries"] = {
69+
"class_path": "esrun.runner.tools.partitioners.reprojection_partitioner.ReprojectionPartitioner",
70+
"init_args": {
71+
"output_projection": {
72+
"class_path": "rslearn.utils.geometry.Projection",
73+
"init_args": {
74+
"crs": "EPSG:3857",
75+
"x_resolution": 10,
76+
"y_resolution": -10,
77+
},
78+
},
79+
"use_utm": True,
80+
},
81+
}
82+
with (config_dir / "esrun.yaml").open("w") as f:
83+
yaml.safe_dump(esrun_config, f)
84+
85+
scratch_dir = tmp_path / "scratch"
86+
esrun(
87+
config_path=config_dir,
88+
scratch_path=scratch_dir,
89+
checkpoint_path=checkpoint_path,
90+
)
91+
92+
result_fname = scratch_dir / "results" / "results_raster" / "result_0.tif"
93+
assert result_fname.exists()
94+
with rasterio.open(result_fname) as raster:
95+
array = raster.read()
96+
assert 0.1 < (np.count_nonzero(array == 1) / np.size(array)) < 0.5

0 commit comments

Comments
 (0)