@@ -35,6 +35,7 @@ type Application = {
3535 build_command ?: string ;
3636 instrument_command ?: string ;
3737 project_directory ?: string ;
38+ formula ?: string ; // Optional per-application formula
3839} ;
3940
4041// Track modified files
@@ -74,14 +75,15 @@ function deleteOverlay(overlayPath: string) {
7475 }
7576}
7677
77- function buildMaestroCommand ( app : Application , absOutputJson ?: string , topN ?: string ) : string {
78+ function buildMaestroCommand ( app : Application , absOutputJson ?: string , topN ?: string , globalFormula ?: string , globalBuildCommand ?: string , globalInstrumentCommand ?: string ) : string {
7879 const outputFlag = absOutputJson ? `--output_file ${ absOutputJson } ` : '' ;
7980 const topNFlag = topN ? `--top_n ${ topN } ` : '' ;
80- const buildCommandFlag = app . build_command ? `--build_command "${ app . build_command } "` : '' ;
81- const instrumentCommandFlag = app . instrument_command ? `--instrument_command "${ app . instrument_command } "` : '' ;
81+ const buildCommandFlag = app . build_command || globalBuildCommand ? `--build_command "${ app . build_command || globalBuildCommand } "` : '' ;
82+ const instrumentCommandFlag = app . instrument_command || globalInstrumentCommand ? `--instrument_command "${ app . instrument_command || globalInstrumentCommand } "` : '' ;
8283 const projectDirFlag = app . project_directory ? `--project_directory ${ app . project_directory } ` : '' ;
84+ const formulaFlag = app . formula || globalFormula ? `--formula ${ app . formula || globalFormula } ` : '' ;
8385
84- return `maestro ${ buildCommandFlag } ${ instrumentCommandFlag } ${ projectDirFlag } -vvv ${ outputFlag } ${ topNFlag } -- ${ app . command } ` ;
86+ return `maestro ${ buildCommandFlag } ${ instrumentCommandFlag } ${ projectDirFlag } -vvv ${ outputFlag } ${ topNFlag } ${ formulaFlag } -- ${ app . command } ` ;
8587}
8688
8789function do_cleanup ( workspace : string , dockerImage ?: string ) {
@@ -124,8 +126,8 @@ function do_cleanup(workspace: string, dockerImage?: string) {
124126 }
125127}
126128
127- function run_in_apptainer ( execDir : string , image : string , app : Application , overlay : string , absOutputJson ?: string , topN ?: string , huggingfaceToken ?: string , formula ?: string ) {
128- let maestroCmd = buildMaestroCommand ( app , absOutputJson , topN ) ;
129+ function run_in_apptainer ( execDir : string , image : string , app : Application , overlay : string , absOutputJson ?: string , topN ?: string , huggingfaceToken ?: string , globalFormula ?: string , globalBuildCommand ?: string , globalInstrumentCommand ?: string ) {
130+ let maestroCmd = buildMaestroCommand ( app , absOutputJson , topN , globalFormula , globalBuildCommand , globalInstrumentCommand ) ;
129131
130132 if ( huggingfaceToken ) {
131133 maestroCmd = `huggingface-cli login --token ${ huggingfaceToken } && ${ maestroCmd } ` ;
@@ -143,8 +145,8 @@ function run_in_apptainer(execDir: string, image: string, app: Application, over
143145 execSync ( apptainerCmd , { cwd : execDir , stdio : 'inherit' } ) ;
144146}
145147
146- function run_in_docker ( execDir : string , image : string , app : Application , absOutputJson ?: string , topN ?: string , huggingfaceToken ?: string , formula ?: string ) {
147- let maestroCmd = buildMaestroCommand ( app , absOutputJson , topN ) ;
148+ function run_in_docker ( execDir : string , image : string , app : Application , absOutputJson ?: string , topN ?: string , huggingfaceToken ?: string , globalFormula ?: string , globalBuildCommand ?: string , globalInstrumentCommand ?: string ) {
149+ let maestroCmd = buildMaestroCommand ( app , absOutputJson , topN , globalFormula , globalBuildCommand , globalInstrumentCommand ) ;
148150 const homeDir = process . env . HOME ! ;
149151 const workspace = process . env . GITHUB_WORKSPACE || process . cwd ( ) ;
150152
@@ -153,7 +155,7 @@ function run_in_docker(execDir: string, image: string, app: Application, absOutp
153155 }
154156
155157 // For non-diagnoseOnly formulas, use the workspace directory
156- const workingDir = formula && formula !== "diagnoseOnly" ? workspace : execDir ;
158+ const workingDir = ( app . formula || globalFormula ) && ( app . formula || globalFormula ) !== "diagnoseOnly" ? workspace : execDir ;
157159
158160 const dockerCmd = `docker run \
159161 --rm \
@@ -258,7 +260,9 @@ async function createPullRequest(token: string, modifiedFiles: Set<string>, json
258260
259261async function run ( ) {
260262 try {
261- const formula = core . getInput ( "formula" ) ;
263+ const globalFormula = core . getInput ( "formula" ) ;
264+ const globalBuildCommand = core . getInput ( "build_command" ) ;
265+ const globalInstrumentCommand = core . getInput ( "instrument_command" ) ;
262266 const rawTopN = core . getInput ( "top_n" ) ;
263267 const topN = rawTopN !== '' ? rawTopN : '10' ;
264268 const defaultDockerImage = core . getInput ( "docker_image" ) ;
@@ -268,15 +272,27 @@ async function run() {
268272 const maestroActionsToken = core . getInput ( "maestro_actions_token" ) ;
269273
270274 const validFormulas = [ "diagnoseOnly" , "atomicContention" , "memoryAccess" , "bankConflict" ] ;
271- if ( ! validFormulas . includes ( formula ) ) {
272- core . setFailed ( `Invalid formula: ${ formula } . Allowed formulas are: ${ validFormulas . join ( ", " ) } ` ) ;
275+
276+ // Validate global formula if provided
277+ if ( globalFormula && ! validFormulas . includes ( globalFormula ) ) {
278+ core . setFailed ( `Invalid global formula: ${ globalFormula } . Allowed formulas are: ${ validFormulas . join ( ", " ) } ` ) ;
273279 return ;
274280 }
275281
276282 const appsJson = core . getInput ( "applications" ) ;
277283 const apps : Application [ ] = JSON . parse ( appsJson ) ;
278284
279- core . info ( `Formula: ${ formula } ` ) ;
285+ // Validate per-application formulas if provided
286+ for ( const app of apps ) {
287+ if ( app . formula && ! validFormulas . includes ( app . formula ) ) {
288+ core . setFailed ( `Invalid formula for application ${ app . command } : ${ app . formula } . Allowed formulas are: ${ validFormulas . join ( ", " ) } ` ) ;
289+ return ;
290+ }
291+ }
292+
293+ core . info ( `Global Formula: ${ globalFormula || 'Not specified' } ` ) ;
294+ core . info ( `Global Build Command: ${ globalBuildCommand || 'Not specified' } ` ) ;
295+ core . info ( `Global Instrument Command: ${ globalInstrumentCommand || 'Not specified' } ` ) ;
280296 core . info ( `Top N: ${ topN } ` ) ;
281297 if ( defaultDockerImage ) {
282298 core . info ( `Default Docker Image: ${ defaultDockerImage } ` ) ;
@@ -332,15 +348,15 @@ async function run() {
332348 const overlay = createOverlay ( ) ;
333349
334350 try {
335- run_in_apptainer ( execDir , apptainerAbsImage , app , overlay , absOutputJson , topN , huggingfaceToken , formula ) ;
351+ run_in_apptainer ( execDir , apptainerAbsImage , app , overlay , absOutputJson , topN , huggingfaceToken , globalFormula , globalBuildCommand , globalInstrumentCommand ) ;
336352 // Handle JSON file before tracking changes
337353 lastJsonContent = handleOutputJson ( absOutputJson ) ;
338354 trackModifiedFiles ( workspace ) ;
339355 } finally {
340356 deleteOverlay ( overlay ) ;
341357 }
342358 } else if ( defaultDockerImage ) {
343- run_in_docker ( execDir , defaultDockerImage , app , absOutputJson , topN , huggingfaceToken , formula ) ;
359+ run_in_docker ( execDir , defaultDockerImage , app , absOutputJson , topN , huggingfaceToken , globalFormula , globalBuildCommand , globalInstrumentCommand ) ;
344360 // Handle JSON file before tracking changes
345361 lastJsonContent = handleOutputJson ( absOutputJson ) ;
346362 trackModifiedFiles ( workspace ) ;
0 commit comments