@@ -32,8 +32,6 @@ type WorkflowInputs = Partial<Record<KnownInputName, WorkflowInput>>;
3232 * Represents PR check specifications.
3333 */
3434interface Specification extends JobSpecification {
35- /** The display name for the check. */
36- name : string ;
3735 /** Workflow-level input definitions forwarded to `workflow_dispatch`/`workflow_call`. */
3836 inputs ?: Record < string , WorkflowInput > ;
3937 /** CodeQL bundle versions to test against. Defaults to `DEFAULT_TEST_VERSIONS`. */
@@ -50,12 +48,17 @@ interface Specification extends JobSpecification {
5048 /** Service containers for the job. */
5149 services ?: any ;
5250
51+ /** Additional jobs to run after the main PR check job. */
52+ validationJobs ?: Record < string , JobSpecification > ;
53+
5354 /** If set, this check is part of a named collection that gets its own caller workflow. */
5455 collection ?: string ;
5556}
5657
5758/** Represents job specifications. */
5859interface JobSpecification {
60+ /** The display name for the check. */
61+ name : string ;
5962 /** Custom permissions override for the job. */
6063 permissions ?: Record < string , string > ;
6164 /** Extra environment variables for the job. */
@@ -467,6 +470,77 @@ function generateJob(
467470 return { checkJob, workflowInputs } ;
468471}
469472
473+ /** Generates a validation job. */
474+ function generateValidationJob (
475+ specDocument : yaml . Document ,
476+ jobSpecification : JobSpecification ,
477+ checkName : string ,
478+ name : string ,
479+ ) {
480+ // Extract the sequence of steps from the YAML document to persist as much formatting as possible.
481+ const specSteps = specDocument . getIn ( [
482+ "validationJobs" ,
483+ name ,
484+ "steps" ,
485+ ] ) as yaml . YAMLSeq ;
486+
487+ const validationJob : Record < string , any > = {
488+ name : jobSpecification . name ,
489+ if : "github.triggering_actor != 'dependabot[bot]'" ,
490+ needs : [ checkName ] ,
491+ permissions : {
492+ contents : "read" ,
493+ "security-events" : "read" ,
494+ } ,
495+ "timeout-minutes" : 5 ,
496+ "runs-on" : "ubuntu-slim" ,
497+ steps : specSteps ,
498+ } ;
499+
500+ if ( jobSpecification . permissions ) {
501+ validationJob . permissions = jobSpecification . permissions ;
502+ }
503+
504+ for ( const key of [ "env" ] as const ) {
505+ if ( jobSpecification [ key ] !== undefined ) {
506+ validationJob [ key ] = jobSpecification [ key ] ;
507+ }
508+ }
509+
510+ validationJob . env = validationJob . env ?? { } ;
511+ if ( ! ( "CODEQL_ACTION_TEST_MODE" in validationJob . env ) ) {
512+ validationJob . env . CODEQL_ACTION_TEST_MODE = true ;
513+ }
514+
515+ return validationJob ;
516+ }
517+
518+ /** Generates additional jobs that run after the main check job, based on the `validationJobs` property. */
519+ function generateValidationJobs (
520+ specDocument : yaml . Document ,
521+ checkSpecification : Specification ,
522+ checkName : string ,
523+ ) : Record < string , any > {
524+ if ( checkSpecification . validationJobs === undefined ) {
525+ return { } ;
526+ }
527+
528+ const validationJobs : Record < string , any > = { } ;
529+
530+ for ( const [ jobName , validationJob ] of Object . entries (
531+ checkSpecification . validationJobs ,
532+ ) ) {
533+ validationJobs [ jobName ] = generateValidationJob (
534+ specDocument ,
535+ validationJob ,
536+ checkName ,
537+ jobName ,
538+ ) ;
539+ }
540+
541+ return validationJobs ;
542+ }
543+
470544/**
471545 * Main entry point for the sync script.
472546 */
@@ -517,6 +591,12 @@ function main(): void {
517591 } ) ;
518592 }
519593
594+ const validationJobs = generateValidationJobs (
595+ specDocument ,
596+ checkSpecification ,
597+ checkName ,
598+ ) ;
599+
520600 let extraGroupName = "" ;
521601 for ( const inputName of Object . keys ( workflowInputs ) ) {
522602 extraGroupName += "-${{inputs." + inputName + "}}" ;
@@ -561,6 +641,7 @@ function main(): void {
561641 } ,
562642 jobs : {
563643 [ checkName ] : checkJob ,
644+ ...validationJobs ,
564645 } ,
565646 } ;
566647
0 commit comments