@@ -272,12 +272,11 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
272272 const enableOrgLevel = yn ( process . env . ENABLE_ORGANIZATION_RUNNERS , { default : true } ) ;
273273 const maximumRunners = parseInt ( process . env . RUNNERS_MAXIMUM_COUNT || '3' ) ;
274274 const runnerLabels = process . env . RUNNER_LABELS || '' ;
275-
276275 const runnerGroup = process . env . RUNNER_GROUP_NAME || 'Default' ;
277276 const environment = process . env . ENVIRONMENT ;
278277 const ssmTokenPath = process . env . SSM_TOKEN_PATH ;
279278 const subnets = process . env . SUBNET_IDS . split ( ',' ) ;
280- const instanceTypes = process . env . INSTANCE_TYPES . split ( ',' ) ;
279+ let instanceTypes = process . env . INSTANCE_TYPES . split ( ',' ) ;
281280 const instanceTargetCapacityType = process . env . INSTANCE_TARGET_CAPACITY_TYPE ;
282281 const ephemeralEnabled = yn ( process . env . ENABLE_EPHEMERAL_RUNNERS , { default : false } ) ;
283282 const dynamicEc2ConfigEnabled = yn ( process . env . ENABLE_DYNAMIC_EC2_CONFIG , { default : false } ) ;
@@ -320,7 +319,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
320319 const validMessages = new Map < string , MessagesWithClient > ( ) ;
321320 const invalidMessages : string [ ] = [ ] ;
322321 for ( const payload of payloads ) {
323- const { eventType, messageId, repositoryName, repositoryOwner } = payload ;
322+ const { eventType, messageId, repositoryName, repositoryOwner, labels } = payload ;
324323 if ( ephemeralEnabled && eventType !== 'workflow_job' ) {
325324 logger . warn (
326325 'Event is not supported in combination with ephemeral runners. Please ensure you have enabled workflow_job events.' ,
@@ -344,7 +343,19 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
344343 continue ;
345344 }
346345
347- const key = enableOrgLevel ? payload . repositoryOwner : `${ payload . repositoryOwner } /${ payload . repositoryName } ` ;
346+ let key = enableOrgLevel ? payload . repositoryOwner : `${ payload . repositoryOwner } /${ payload . repositoryName } ` ;
347+
348+ if ( dynamicEc2ConfigEnabled && labels ?. length ) {
349+ const requestedDynamicEc2Config = labels
350+ . find ( l => l . startsWith ( 'ghr-ec2-' ) )
351+ ?. slice ( 'ghr-ec2-' . length ) ;
352+
353+ if ( requestedDynamicEc2Config ) {
354+ const ec2Hash = ec2LabelsHash ( labels ) ;
355+ key = `${ key } /${ ec2Hash } ` ;
356+ }
357+ }
358+
348359
349360 let entry = validMessages . get ( key ) ;
350361
@@ -383,13 +394,20 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
383394 // Work out how much we want to scale up by.
384395 let scaleUp = 0 ;
385396
397+ if ( messages . length > 0 && dynamicEc2ConfigEnabled ) {
398+ const requestedInstanceType = messages [ 0 ] . labels ?. find ( label => label . startsWith ( 'ghr-ec2-instance-type' ) ) ?. replace ( 'ghr-ec2-instance-type' , '' ) ;
399+ instanceTypes = requestedInstanceType ? [ requestedInstanceType ] : instanceTypes ;
400+ }
401+
402+
386403 for ( const message of messages ) {
387404 const messageLogger = logger . createChild ( {
388405 persistentKeys : {
389406 eventType : message . eventType ,
390407 group,
391408 messageId : message . messageId ,
392409 repository : `${ message . repositoryOwner } /${ message . repositoryName } ` ,
410+ labels : message . labels ,
393411 } ,
394412 } ) ;
395413
@@ -399,7 +417,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
399417 continue ;
400418 }
401419
402- scaleUp ++ ;
420+ scaleUp ++ ;
403421 }
404422
405423 if ( scaleUp === 0 ) {
@@ -622,3 +640,20 @@ async function createJitConfig(githubRunnerConfig: CreateGitHubRunnerConfig, ins
622640 }
623641 }
624642}
643+
644+ function ec2LabelsHash ( labels : string [ ] ) : string {
645+ const prefix = 'ghr-ec2-' ;
646+
647+ const input = labels
648+ . filter ( l => l . startsWith ( prefix ) )
649+ . sort ( ) // ensure deterministic hash
650+ . join ( '|' ) ;
651+
652+ let hash = 0 ;
653+ for ( let i = 0 ; i < input . length ; i ++ ) {
654+ hash = ( hash << 5 ) - hash + input . charCodeAt ( i ) ;
655+ hash |= 0 ; // force 32-bit integer
656+ }
657+
658+ return Math . abs ( hash ) . toString ( 36 ) ;
659+ }
0 commit comments