@@ -184,26 +184,6 @@ class StepStmt extends Statement instanceof Actions::Step {
184
184
string getId ( ) { result = super .getId ( ) }
185
185
186
186
JobStmt getJobStmt ( ) { result = super .getJob ( ) }
187
-
188
- /**
189
- * Gets a environment variable expression by name in the scope of the current step.
190
- */
191
- Expression getEnvExpr ( string name ) {
192
- exists ( Actions:: StepEnv env |
193
- env .getStep ( ) = this and
194
- env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
195
- )
196
- or
197
- exists ( Actions:: JobEnv env |
198
- env .getJob ( ) = this .getJobStmt ( ) and
199
- env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
200
- )
201
- or
202
- exists ( Actions:: WorkflowEnv env |
203
- env .getWorkflow ( ) = this .getJobStmt ( ) .getWorkflowStmt ( ) and
204
- env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
205
- )
206
- }
207
187
}
208
188
209
189
/**
@@ -238,7 +218,25 @@ class StepUsesExpr extends StepStmt, UsesExpr {
238
218
)
239
219
}
240
220
241
- override Expression getEnvExpr ( string name ) { result = this .( StepStmt ) .getEnvExpr ( name ) }
221
+ /**
222
+ * Gets a environment variable expression by name in the scope of the current step.
223
+ */
224
+ override Expression getEnvExpr ( string name ) {
225
+ exists ( Actions:: StepEnv env |
226
+ env .getStep ( ) = this and
227
+ env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
228
+ )
229
+ or
230
+ exists ( Actions:: JobEnv env |
231
+ env .getJob ( ) = this .getJobStmt ( ) and
232
+ env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
233
+ )
234
+ or
235
+ exists ( Actions:: WorkflowEnv env |
236
+ env .getWorkflow ( ) = this .getJobStmt ( ) .getWorkflowStmt ( ) and
237
+ env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
238
+ )
239
+ }
242
240
}
243
241
244
242
/**
@@ -317,6 +315,26 @@ class RunExpr extends StepStmt, Expression {
317
315
Expression getScriptExpr ( ) { result = scriptExpr }
318
316
319
317
string getScript ( ) { result = scriptExpr .getValue ( ) }
318
+
319
+ /**
320
+ * Gets a environment variable expression by name in the scope of the current node.
321
+ */
322
+ Expression getEnvExpr ( string name ) {
323
+ exists ( Actions:: StepEnv env |
324
+ env .getStep ( ) = this and
325
+ env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
326
+ )
327
+ or
328
+ exists ( Actions:: JobEnv env |
329
+ env .getJob ( ) = this .getJobStmt ( ) and
330
+ env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
331
+ )
332
+ or
333
+ exists ( Actions:: WorkflowEnv env |
334
+ env .getWorkflow ( ) = this .getJobStmt ( ) .getWorkflowStmt ( ) and
335
+ env .( YamlMapping ) .maps ( any ( YamlScalar s | s .getValue ( ) = name ) , result )
336
+ )
337
+ }
320
338
}
321
339
322
340
/**
@@ -330,11 +348,14 @@ class ExprAccessExpr extends Expression instanceof YamlString {
330
348
string getExpression ( ) { result = expr }
331
349
332
350
JobStmt getJobStmt ( ) { result .getAChildNode * ( ) = this }
351
+
352
+ abstract Expression getRefExpr ( ) ;
333
353
}
334
354
335
355
/**
336
- * A ExprAccessExpr where the expression evaluated is a step output read.
337
- * eg: `${{ steps.changed-files.outputs.all_changed_files }}`
356
+ * Holds for an ExprAccessExpr accesing the `steps` context.
357
+ * https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
358
+ * e.g. `${{ steps.changed-files.outputs.all_changed_files }}`
338
359
*/
339
360
class StepOutputAccessExpr extends ExprAccessExpr {
340
361
string stepId ;
@@ -347,17 +368,16 @@ class StepOutputAccessExpr extends ExprAccessExpr {
347
368
this .getExpression ( ) .regexpCapture ( "steps\\.[A-Za-z0-9_-]+\\.outputs\\.([A-Za-z0-9_-]+)" , 1 )
348
369
}
349
370
350
- string getStepId ( ) { result = stepId }
351
-
352
- string getVarName ( ) { result = varName }
353
-
354
- StepStmt getStepStmt ( ) { result .getId ( ) = stepId }
371
+ override Expression getRefExpr ( ) {
372
+ this .getJobStmt ( ) = result .( StepStmt ) .getJobStmt ( ) and
373
+ result .( StepStmt ) .getId ( ) = stepId
374
+ }
355
375
}
356
376
357
377
/**
358
- * A ExprAccessExpr where the expression evaluated is a job output read .
359
- * eg: `${{ needs.job1.outputs.foo}}`
360
- * eg: `${{ jobs.job1.outputs.foo}}` (for reusable workflows)
378
+ * Holds for an ExprAccessExpr accesing the `needs` or ` job` contexts .
379
+ * https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
380
+ * e.g. `${{ needs.job1.outputs.foo}}` or `${{ jobs.job1.outputs.foo}}` (for reusable workflows)
361
381
*/
362
382
class JobOutputAccessExpr extends ExprAccessExpr {
363
383
string jobId ;
@@ -372,9 +392,7 @@ class JobOutputAccessExpr extends ExprAccessExpr {
372
392
.regexpCapture ( "(needs|jobs)\\.[A-Za-z0-9_-]+\\.outputs\\.([A-Za-z0-9_-]+)" , 2 )
373
393
}
374
394
375
- string getVarName ( ) { result = varName }
376
-
377
- Expression getOutputExpr ( ) {
395
+ override Expression getRefExpr ( ) {
378
396
exists ( JobStmt job |
379
397
job .getId ( ) = jobId and
380
398
job .getLocation ( ) .getFile ( ) = this .getLocation ( ) .getFile ( ) and
@@ -391,8 +409,9 @@ class JobOutputAccessExpr extends ExprAccessExpr {
391
409
}
392
410
393
411
/**
394
- * A ExprAccessExpr where the expression evaluated is a reusable workflow input read.
395
- * eg: `${{ inputs.foo}}`
412
+ * Holds for an ExprAccessExpr accesing the `inputs` context.
413
+ * https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
414
+ * e.g. `${{ inputs.foo }}`
396
415
*/
397
416
class ReusableWorkflowInputAccessExpr extends ExprAccessExpr {
398
417
string paramName ;
@@ -401,12 +420,29 @@ class ReusableWorkflowInputAccessExpr extends ExprAccessExpr {
401
420
paramName = this .getExpression ( ) .regexpCapture ( "inputs\\.([A-Za-z0-9_-]+)" , 1 )
402
421
}
403
422
404
- string getParamName ( ) { result = paramName }
405
-
406
- Expression getInputExpr ( ) {
423
+ override Expression getRefExpr ( ) {
407
424
exists ( ReusableWorkflowStmt w |
408
425
w .getLocation ( ) .getFile ( ) = this .getLocation ( ) .getFile ( ) and
409
426
w .getInputsStmt ( ) .getInputExpr ( paramName ) = result
410
427
)
411
428
}
412
429
}
430
+
431
+ /**
432
+ * Holds for an ExprAccessExpr accesing the `env` context.
433
+ * https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
434
+ * e.g. `${{ env.foo }}`
435
+ */
436
+ class EnvAccessExpr extends ExprAccessExpr {
437
+ string varName ;
438
+
439
+ EnvAccessExpr ( ) { varName = this .getExpression ( ) .regexpCapture ( "env\\.([A-Za-z0-9_-]+)" , 1 ) }
440
+
441
+ override Expression getRefExpr ( ) {
442
+ exists ( JobUsesExpr s | s .getEnvExpr ( varName ) = result )
443
+ or
444
+ exists ( StepUsesExpr s | s .getEnvExpr ( varName ) = result )
445
+ or
446
+ exists ( RunExpr s | s .getEnvExpr ( varName ) = result )
447
+ }
448
+ }
0 commit comments