Skip to content

Commit f8a12be

Browse files
feat: allow to use dynamic instance type in multiple events
1 parent c637bb0 commit f8a12be

1 file changed

Lines changed: 39 additions & 4 deletions

File tree

  • lambdas/functions/control-plane/src/scale-runners

lambdas/functions/control-plane/src/scale-runners/scale-up.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,11 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
295295
const enableOrgLevel = yn(process.env.ENABLE_ORGANIZATION_RUNNERS, { default: true });
296296
const maximumRunners = parseInt(process.env.RUNNERS_MAXIMUM_COUNT || '3');
297297
const runnerLabels = process.env.RUNNER_LABELS || '';
298-
299298
const runnerGroup = process.env.RUNNER_GROUP_NAME || 'Default';
300299
const environment = process.env.ENVIRONMENT;
301300
const ssmTokenPath = process.env.SSM_TOKEN_PATH;
302301
const subnets = process.env.SUBNET_IDS.split(',');
303-
const instanceTypes = process.env.INSTANCE_TYPES.split(',');
302+
let instanceTypes = process.env.INSTANCE_TYPES.split(',');
304303
const instanceTargetCapacityType = process.env.INSTANCE_TARGET_CAPACITY_TYPE;
305304
const ephemeralEnabled = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false });
306305
const dynamicEc2ConfigEnabled = yn(process.env.ENABLE_DYNAMIC_EC2_CONFIG, { default: false });
@@ -343,7 +342,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
343342
const validMessages = new Map<string, MessagesWithClient>();
344343
const rejectedMessageIds = new Set<string>();
345344
for (const payload of payloads) {
346-
const { eventType, messageId, repositoryName, repositoryOwner } = payload;
345+
const { eventType, messageId, repositoryName, repositoryOwner, labels } = payload;
347346
if (ephemeralEnabled && eventType !== 'workflow_job') {
348347
logger.warn(
349348
'Event is not supported in combination with ephemeral runners. Please ensure you have enabled workflow_job events.',
@@ -367,7 +366,19 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
367366
continue;
368367
}
369368

370-
const key = enableOrgLevel ? payload.repositoryOwner : `${payload.repositoryOwner}/${payload.repositoryName}`;
369+
let key = enableOrgLevel ? payload.repositoryOwner : `${payload.repositoryOwner}/${payload.repositoryName}`;
370+
371+
if (dynamicEc2ConfigEnabled && labels?.length) {
372+
const requestedDynamicEc2Config = labels
373+
.find(l => l.startsWith('ghr-ec2-'))
374+
?.slice('ghr-ec2-'.length);
375+
376+
if (requestedDynamicEc2Config) {
377+
const ec2Hash = ec2LabelsHash(labels);
378+
key = `${key}/${ec2Hash}`;
379+
}
380+
}
381+
371382

372383
let entry = validMessages.get(key);
373384

@@ -407,13 +418,20 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
407418
let scaleUp = 0;
408419
const queuedMessages: ActionRequestMessageSQS[] = [];
409420

421+
if (messages.length > 0 && dynamicEc2ConfigEnabled) {
422+
const requestedInstanceType = messages[0].labels?.find(label => label.startsWith('ghr-ec2-instance-type'))?.replace('ghr-ec2-instance-type', '');
423+
instanceTypes = requestedInstanceType ? [requestedInstanceType] : instanceTypes;
424+
}
425+
426+
410427
for (const message of messages) {
411428
const messageLogger = logger.createChild({
412429
persistentKeys: {
413430
eventType: message.eventType,
414431
group,
415432
messageId: message.messageId,
416433
repository: `${message.repositoryOwner}/${message.repositoryName}`,
434+
labels: message.labels,
417435
},
418436
});
419437

@@ -704,3 +722,20 @@ async function createJitConfig(
704722

705723
return failedInstances;
706724
}
725+
726+
function ec2LabelsHash(labels: string[]): string {
727+
const prefix = 'ghr-ec2-';
728+
729+
const input = labels
730+
.filter(l => l.startsWith(prefix))
731+
.sort() // ensure deterministic hash
732+
.join('|');
733+
734+
let hash = 0;
735+
for (let i = 0; i < input.length; i++) {
736+
hash = (hash << 5) - hash + input.charCodeAt(i);
737+
hash |= 0; // force 32-bit integer
738+
}
739+
740+
return Math.abs(hash).toString(36);
741+
}

0 commit comments

Comments
 (0)