Skip to content

Commit 4c1f2fa

Browse files
feat: allow to use dynamic instance type in multiple events
1 parent 6be3726 commit 4c1f2fa

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
@@ -293,12 +293,11 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
293293
const enableOrgLevel = yn(process.env.ENABLE_ORGANIZATION_RUNNERS, { default: true });
294294
const maximumRunners = parseInt(process.env.RUNNERS_MAXIMUM_COUNT || '3');
295295
const runnerLabels = process.env.RUNNER_LABELS || '';
296-
297296
const runnerGroup = process.env.RUNNER_GROUP_NAME || 'Default';
298297
const environment = process.env.ENVIRONMENT;
299298
const ssmTokenPath = process.env.SSM_TOKEN_PATH;
300299
const subnets = process.env.SUBNET_IDS.split(',');
301-
const instanceTypes = process.env.INSTANCE_TYPES.split(',');
300+
let instanceTypes = process.env.INSTANCE_TYPES.split(',');
302301
const instanceTargetCapacityType = process.env.INSTANCE_TARGET_CAPACITY_TYPE;
303302
const ephemeralEnabled = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false });
304303
const dynamicEc2ConfigEnabled = yn(process.env.ENABLE_DYNAMIC_EC2_CONFIG, { default: false });
@@ -341,7 +340,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
341340
const validMessages = new Map<string, MessagesWithClient>();
342341
const rejectedMessageIds = new Set<string>();
343342
for (const payload of payloads) {
344-
const { eventType, messageId, repositoryName, repositoryOwner } = payload;
343+
const { eventType, messageId, repositoryName, repositoryOwner, labels } = payload;
345344
if (ephemeralEnabled && eventType !== 'workflow_job') {
346345
logger.warn(
347346
'Event is not supported in combination with ephemeral runners. Please ensure you have enabled workflow_job events.',
@@ -365,7 +364,19 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
365364
continue;
366365
}
367366

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

370381
let entry = validMessages.get(key);
371382

@@ -405,13 +416,20 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
405416
let scaleUp = 0;
406417
const queuedMessages: ActionRequestMessageSQS[] = [];
407418

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

@@ -702,3 +720,20 @@ async function createJitConfig(
702720

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

0 commit comments

Comments
 (0)