Skip to content

Commit b09683e

Browse files
anth-volkclaude
andcommitted
Use ci_call.py script for Modal invocations instead of python -c
The inline python -c snippets may have had quoting/indentation issues preventing modal.enable_output() from working. Replace with a proper ci_call.py script that: - Takes function name, app name, and args via argparse - Wraps all calls in modal.enable_output() for log streaming - Runs with PYTHONUNBUFFERED=1 to prevent output buffering Also adds actions/checkout to all matrix jobs since ci_call.py lives in the repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8543284 commit b09683e

2 files changed

Lines changed: 103 additions & 75 deletions

File tree

.github/workflows/push.yaml

Lines changed: 47 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,20 @@ jobs:
4646
env:
4747
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
4848
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
49+
PYTHONUNBUFFERED: "1"
4950
steps:
51+
- uses: actions/checkout@v4
5052
- uses: actions/setup-python@v5
5153
with:
5254
python-version: "3.13"
5355
- name: Install Modal CLI
5456
run: pip install modal
5557
- name: Download prerequisites on Modal
5658
run: |
57-
python -c "
58-
import modal
59-
with modal.enable_output():
60-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_single_script')
61-
result = fn.remote(
62-
script_name='download_prerequisites',
63-
branch='${{ github.ref_name }}',
64-
)
65-
print(result)
66-
"
59+
python modal_app/ci_call.py run_single_script \
60+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
61+
--script-name=download_prerequisites \
62+
--branch=${{ github.ref_name }}
6763
6864
# ── Phase 1: Independent datasets (parallel) ───────────────
6965
phase1:
@@ -76,25 +72,21 @@ jobs:
7672
env:
7773
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
7874
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
75+
PYTHONUNBUFFERED: "1"
7976
steps:
77+
- uses: actions/checkout@v4
8078
- uses: actions/setup-python@v5
8179
with:
8280
python-version: "3.13"
8381
- name: Install Modal CLI
8482
run: pip install modal
8583
- name: "Build + test: ${{ matrix.dataset }}"
8684
run: |
87-
python -c "
88-
import modal
89-
with modal.enable_output():
90-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_single_script')
91-
result = fn.remote(
92-
script_name='${{ matrix.dataset }}',
93-
branch='${{ github.ref_name }}',
94-
run_tests=True,
95-
)
96-
print(result)
97-
"
85+
python modal_app/ci_call.py run_single_script \
86+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
87+
--script-name=${{ matrix.dataset }} \
88+
--branch=${{ github.ref_name }} \
89+
--run-tests
9890
9991
# ── Phase 2: CPS + PUF (depend on Phase 1) ─────────────────
10092
phase2:
@@ -107,25 +99,21 @@ jobs:
10799
env:
108100
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
109101
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
102+
PYTHONUNBUFFERED: "1"
110103
steps:
104+
- uses: actions/checkout@v4
111105
- uses: actions/setup-python@v5
112106
with:
113107
python-version: "3.13"
114108
- name: Install Modal CLI
115109
run: pip install modal
116110
- name: "Build + test: ${{ matrix.dataset }}"
117111
run: |
118-
python -c "
119-
import modal
120-
with modal.enable_output():
121-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_single_script')
122-
result = fn.remote(
123-
script_name='${{ matrix.dataset }}',
124-
branch='${{ github.ref_name }}',
125-
run_tests=True,
126-
)
127-
print(result)
128-
"
112+
python modal_app/ci_call.py run_single_script \
113+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
114+
--script-name=${{ matrix.dataset }} \
115+
--branch=${{ github.ref_name }} \
116+
--run-tests
129117
130118
# ── Phase 3: Extended CPS (depends on Phase 2) ─────────────
131119
phase3:
@@ -134,25 +122,21 @@ jobs:
134122
env:
135123
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
136124
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
125+
PYTHONUNBUFFERED: "1"
137126
steps:
127+
- uses: actions/checkout@v4
138128
- uses: actions/setup-python@v5
139129
with:
140130
python-version: "3.13"
141131
- name: Install Modal CLI
142132
run: pip install modal
143133
- name: "Build + test: extended_cps"
144134
run: |
145-
python -c "
146-
import modal
147-
with modal.enable_output():
148-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_single_script')
149-
result = fn.remote(
150-
script_name='extended_cps',
151-
branch='${{ github.ref_name }}',
152-
run_tests=True,
153-
)
154-
print(result)
155-
"
135+
python modal_app/ci_call.py run_single_script \
136+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
137+
--script-name=extended_cps \
138+
--branch=${{ github.ref_name }} \
139+
--run-tests
156140
157141
# ── Phase 4: Enhanced + Stratified CPS (depend on Phase 3) ─
158142
phase4:
@@ -165,25 +149,21 @@ jobs:
165149
env:
166150
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
167151
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
152+
PYTHONUNBUFFERED: "1"
168153
steps:
154+
- uses: actions/checkout@v4
169155
- uses: actions/setup-python@v5
170156
with:
171157
python-version: "3.13"
172158
- name: Install Modal CLI
173159
run: pip install modal
174160
- name: "Build + test: ${{ matrix.dataset }}"
175161
run: |
176-
python -c "
177-
import modal
178-
with modal.enable_output():
179-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_single_script')
180-
result = fn.remote(
181-
script_name='${{ matrix.dataset }}',
182-
branch='${{ github.ref_name }}',
183-
run_tests=True,
184-
)
185-
print(result)
186-
"
162+
python modal_app/ci_call.py run_single_script \
163+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
164+
--script-name=${{ matrix.dataset }} \
165+
--branch=${{ github.ref_name }} \
166+
--run-tests
187167
188168
# ── Phase 5: Source imputed + Small enhanced (depend on 4) ──
189169
phase5:
@@ -196,25 +176,21 @@ jobs:
196176
env:
197177
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
198178
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
179+
PYTHONUNBUFFERED: "1"
199180
steps:
181+
- uses: actions/checkout@v4
200182
- uses: actions/setup-python@v5
201183
with:
202184
python-version: "3.13"
203185
- name: Install Modal CLI
204186
run: pip install modal
205187
- name: "Build + test: ${{ matrix.dataset }}"
206188
run: |
207-
python -c "
208-
import modal
209-
with modal.enable_output():
210-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_single_script')
211-
result = fn.remote(
212-
script_name='${{ matrix.dataset }}',
213-
branch='${{ github.ref_name }}',
214-
run_tests=True,
215-
)
216-
print(result)
217-
"
189+
python modal_app/ci_call.py run_single_script \
190+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
191+
--script-name=${{ matrix.dataset }} \
192+
--branch=${{ github.ref_name }} \
193+
--run-tests
218194
219195
# ── Remaining integration tests (depend on Phase 4) ─────────
220196
remaining-tests:
@@ -229,24 +205,20 @@ jobs:
229205
env:
230206
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
231207
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
208+
PYTHONUNBUFFERED: "1"
232209
steps:
210+
- uses: actions/checkout@v4
233211
- uses: actions/setup-python@v5
234212
with:
235213
python-version: "3.13"
236214
- name: Install Modal CLI
237215
run: pip install modal
238216
- name: "Test: ${{ matrix.test }}"
239217
run: |
240-
python -c "
241-
import modal
242-
with modal.enable_output():
243-
fn = modal.Function.from_name('${{ needs.deploy-modal.outputs.app-name }}', 'run_integration_test')
244-
result = fn.remote(
245-
test_path='${{ matrix.test }}',
246-
branch='${{ github.ref_name }}',
247-
)
248-
print(result)
249-
"
218+
python modal_app/ci_call.py run_integration_test \
219+
--app-name=${{ needs.deploy-modal.outputs.app-name }} \
220+
--test-path=${{ matrix.test }} \
221+
--branch=${{ github.ref_name }}
250222
251223
# ── Cleanup Modal deployment ────────────────────────────────
252224
cleanup-modal:

modal_app/ci_call.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""Invoke a deployed Modal function with log streaming.
2+
3+
Used by push.yaml to call deployed functions without rebuilding
4+
the Modal image. Streams container stdout/stderr to the caller.
5+
6+
Usage:
7+
python modal_app/ci_call.py run_single_script \\
8+
--app-name policyengine-us-data-ci-12345 \\
9+
--script-name cps \\
10+
--branch main \\
11+
--run-tests
12+
13+
python modal_app/ci_call.py run_integration_test \\
14+
--app-name policyengine-us-data-ci-12345 \\
15+
--test-path policyengine_us_data/tests/integration/test_cps.py \\
16+
--branch main
17+
"""
18+
19+
import argparse
20+
import sys
21+
22+
import modal
23+
24+
25+
def main():
26+
parser = argparse.ArgumentParser()
27+
parser.add_argument(
28+
"function", choices=["run_single_script", "run_integration_test"]
29+
)
30+
parser.add_argument("--app-name", required=True)
31+
parser.add_argument("--script-name", default="")
32+
parser.add_argument("--branch", default="main")
33+
parser.add_argument("--run-tests", action="store_true")
34+
parser.add_argument("--test-path", default="")
35+
args = parser.parse_args()
36+
37+
with modal.enable_output():
38+
fn = modal.Function.from_name(args.app_name, args.function)
39+
40+
if args.function == "run_single_script":
41+
result = fn.remote(
42+
script_name=args.script_name,
43+
branch=args.branch,
44+
run_tests=args.run_tests,
45+
)
46+
elif args.function == "run_integration_test":
47+
result = fn.remote(
48+
test_path=args.test_path,
49+
branch=args.branch,
50+
)
51+
52+
print(result)
53+
54+
55+
if __name__ == "__main__":
56+
main()

0 commit comments

Comments
 (0)