@@ -190,79 +190,6 @@ async def verify_signature(request: Request, body: bytes) -> str | None:
190190 return delivery_id
191191
192192
193- async def _spawn_single_sandbox (job_data : dict ):
194- """Helper to spawn a single sandbox and wait for completion."""
195- job_id = job_data ["job_id" ]
196- jit_config = job_data ["jit_config" ]
197-
198- logger .info (f"Spawning sandbox for job { job_id } " )
199-
200- try :
201- cmd = "cd /actions-runner && export RUNNER_ALLOW_RUNASROOT=1 && ./run.sh --jitconfig $GHA_JIT_CONFIG"
202-
203- sandbox = modal .Sandbox .create (
204- "bash" ,
205- "-c" ,
206- cmd ,
207- image = runner_image ,
208- app = app ,
209- timeout = TIMEOUT_SECONDS ,
210- env = {"GHA_JIT_CONFIG" : jit_config },
211- )
212-
213- sandbox .set_tags ({"job_id" : str (job_id )})
214-
215- # Wait for completion
216- sandbox .wait ()
217-
218- logger .info (f"Sandbox for job { job_id } completed" )
219-
220- except Exception as e :
221- logger .error (f"Failed to spawn sandbox for job { job_id } : { type (e ).__name__ } " )
222- raise
223-
224-
225- @app .function (image = runner_image , secrets = [github_secret ])
226- async def process_job_batch ():
227- """Process jobs from queue with controlled concurrency using asyncio.Semaphore.
228-
229- This function runs continuously, pulling jobs from the queue and spawning
230- sandboxes with max DEFAULT_MAX_PARALLEL concurrent executions.
231- """
232- semaphore = asyncio .Semaphore (DEFAULT_MAX_PARALLEL )
233-
234- logger .info (
235- f"Starting job processor with max { DEFAULT_MAX_PARALLEL } concurrent sandboxes"
236- )
237-
238- while True :
239- try :
240- # Get job from queue (blocks until available)
241- job_data = await job_queue .get .aio ()
242-
243- if job_data is None :
244- # Sentinel value to stop processing
245- break
246-
247- # Acquire semaphore before spawning
248- await semaphore .acquire ()
249-
250- # Spawn sandbox in background task so we can continue to next job
251- asyncio .create_task (_process_with_semaphore (semaphore , job_data ))
252-
253- except Exception as e :
254- logger .error (f"Error in job processor: { type (e ).__name__ } : { e } " )
255- await asyncio .sleep (1 )
256-
257-
258- async def _process_with_semaphore (semaphore : asyncio .Semaphore , job_data : dict ):
259- """Process a job and release semaphore when done."""
260- try :
261- await _spawn_single_sandbox (job_data )
262- finally :
263- semaphore .release ()
264-
265-
266193@app .function (image = runner_image , secrets = [github_secret ])
267194@modal .fastapi_endpoint (method = "POST" )
268195async def github_webhook (request : Request ):
@@ -426,25 +353,27 @@ async def github_webhook(request: Request):
426353 )
427354 raise HTTPException (status_code = 500 , detail = "Internal server error" )
428355
429- logger .info (f"Queueing job { job_id } for processing ..." )
356+ logger .info (f"Spawning sandbox for job { job_id } ..." )
430357
431358 try :
432- # Prepare job data for queue
433- job_data = {
434- "job_id" : job_id ,
435- "repo_url" : repo_url ,
436- "job_labels" : job_labels ,
437- "jit_config" : jit_config ,
438- }
359+ cmd = "cd /actions-runner && export RUNNER_ALLOW_RUNASROOT=1 && ./run.sh --jitconfig $GHA_JIT_CONFIG"
439360
440- # Put job in queue for processor
441- await job_queue .put .aio (job_data )
361+ sandbox = modal .Sandbox .create (
362+ "bash" ,
363+ "-c" ,
364+ cmd ,
365+ image = runner_image ,
366+ app = app ,
367+ timeout = TIMEOUT_SECONDS ,
368+ env = {"GHA_JIT_CONFIG" : jit_config },
369+ )
442370
443- logger .info (f"Successfully queued job { job_id } " )
371+ sandbox .set_tags ({"job_id" : str (job_id )})
372+
373+ logger .info (f"Successfully spawned sandbox for job { job_id } " )
444374
445375 except Exception as e :
446- logger .error (f"Failed to queue job { job_id } : { type (e ).__name__ } " )
447- raise HTTPException (status_code = 500 , detail = "Failed to queue job " )
376+ logger .error (f"Failed to spawn sandbox for job { job_id } : { type (e ).__name__ } " )
377+ raise HTTPException (status_code = 500 , detail = "Failed to spawn runner sandbox " )
448378
449- logger .info (f"Successfully queued runner for job { job_id } " )
450- return {"status" : "queued" , "job_id" : job_id }
379+ return {"status" : "provisioned" , "job_id" : job_id }
0 commit comments