@@ -237,12 +237,11 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
237237 const enableOrgLevel = yn ( process . env . ENABLE_ORGANIZATION_RUNNERS , { default : true } ) ;
238238 const maximumRunners = parseInt ( process . env . RUNNERS_MAXIMUM_COUNT || '3' ) ;
239239 const runnerLabels = process . env . RUNNER_LABELS || '' ;
240-
241240 const runnerGroup = process . env . RUNNER_GROUP_NAME || 'Default' ;
242241 const environment = process . env . ENVIRONMENT ;
243242 const ssmTokenPath = process . env . SSM_TOKEN_PATH ;
244243 const subnets = process . env . SUBNET_IDS . split ( ',' ) ;
245- const instanceTypes = process . env . INSTANCE_TYPES . split ( ',' ) ;
244+ let instanceTypes = process . env . INSTANCE_TYPES . split ( ',' ) ;
246245 const instanceTargetCapacityType = process . env . INSTANCE_TARGET_CAPACITY_TYPE ;
247246 const ephemeralEnabled = yn ( process . env . ENABLE_EPHEMERAL_RUNNERS , { default : false } ) ;
248247 const dynamicEc2ConfigEnabled = yn ( process . env . ENABLE_DYNAMIC_EC2_CONFIG , { default : false } ) ;
@@ -281,7 +280,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
281280 const validMessages = new Map < string , MessagesWithClient > ( ) ;
282281 const invalidMessages : string [ ] = [ ] ;
283282 for ( const payload of payloads ) {
284- const { eventType, messageId, repositoryName, repositoryOwner } = payload ;
283+ const { eventType, messageId, repositoryName, repositoryOwner, labels } = payload ;
285284 if ( ephemeralEnabled && eventType !== 'workflow_job' ) {
286285 logger . warn (
287286 'Event is not supported in combination with ephemeral runners. Please ensure you have enabled workflow_job events.' ,
@@ -305,7 +304,19 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
305304 continue ;
306305 }
307306
308- const key = enableOrgLevel ? payload . repositoryOwner : `${ payload . repositoryOwner } /${ payload . repositoryName } ` ;
307+ let key = enableOrgLevel ? payload . repositoryOwner : `${ payload . repositoryOwner } /${ payload . repositoryName } ` ;
308+
309+ if ( dynamicEc2ConfigEnabled && labels ?. length ) {
310+ const requestedDynamicEc2Config = labels
311+ . find ( l => l . startsWith ( 'ghr-ec2-' ) )
312+ ?. slice ( 'ghr-ec2-' . length ) ;
313+
314+ if ( requestedDynamicEc2Config ) {
315+ const ec2Hash = ec2LabelsHash ( labels ) ;
316+ key = `${ key } /${ ec2Hash } ` ;
317+ }
318+ }
319+
309320
310321 let entry = validMessages . get ( key ) ;
311322
@@ -344,13 +355,20 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
344355 // Work out how much we want to scale up by.
345356 let scaleUp = 0 ;
346357
358+ if ( messages . length > 0 && dynamicEc2ConfigEnabled ) {
359+ const requestedInstanceType = messages [ 0 ] . labels ?. find ( label => label . startsWith ( 'ghr-ec2-instance-type' ) ) ?. replace ( 'ghr-ec2-instance-type' , '' ) ;
360+ instanceTypes = requestedInstanceType ? [ requestedInstanceType ] : instanceTypes ;
361+ }
362+
363+
347364 for ( const message of messages ) {
348365 const messageLogger = logger . createChild ( {
349366 persistentKeys : {
350367 eventType : message . eventType ,
351368 group,
352369 messageId : message . messageId ,
353370 repository : `${ message . repositoryOwner } /${ message . repositoryName } ` ,
371+ labels : message . labels ,
354372 } ,
355373 } ) ;
356374
@@ -360,7 +378,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
360378 continue ;
361379 }
362380
363- scaleUp ++ ;
381+ scaleUp ++ ;
364382 }
365383
366384 if ( scaleUp === 0 ) {
@@ -582,3 +600,20 @@ async function createJitConfig(githubRunnerConfig: CreateGitHubRunnerConfig, ins
582600 }
583601 }
584602}
603+
604+ function ec2LabelsHash ( labels : string [ ] ) : string {
605+ const prefix = 'ghr-ec2-' ;
606+
607+ const input = labels
608+ . filter ( l => l . startsWith ( prefix ) )
609+ . sort ( ) // ensure deterministic hash
610+ . join ( '|' ) ;
611+
612+ let hash = 0 ;
613+ for ( let i = 0 ; i < input . length ; i ++ ) {
614+ hash = ( hash << 5 ) - hash + input . charCodeAt ( i ) ;
615+ hash |= 0 ; // force 32-bit integer
616+ }
617+
618+ return Math . abs ( hash ) . toString ( 36 ) ;
619+ }
0 commit comments