@@ -145011,7 +145011,9 @@ const {
145011145011 RunInstancesCommand,
145012145012 TerminateInstancesCommand,
145013145013 waitUntilInstanceRunning,
145014- CreateFleetCommand
145014+ CreateFleetCommand,
145015+ CreateLaunchTemplateCommand,
145016+ DeleteLaunchTemplateCommand
145015145017} = __nccwpck_require__(3802);
145016145018
145017145019const core = __nccwpck_require__(2186);
@@ -145241,14 +145243,61 @@ async function createEc2InstanceWithFleetParams(imageId, subnetId, securityGroup
145241145243 ...(imageId ? { ImageId: imageId } : {})
145242145244 }));
145243145245
145246+ // Prepare to ensure we have a Launch Template ID (create one if not provided)
145247+ let launchTemplateId = config.input.launchTemplateId;
145248+ let createdTemporaryLt = false;
145249+
145250+ if (!launchTemplateId) {
145251+ core.info('No launch template ID provided. Creating a temporary Launch Template...');
145252+
145253+ const userData = buildUserDataScript(githubRegistrationToken, label);
145254+ core.info('Executing user data script: ' + userData.replace(githubRegistrationToken, '<redacted>'));
145255+
145256+ // Build LaunchTemplateData similar to RunInstances params
145257+ const ltData = {
145258+ SecurityGroupIds: [securityGroupId],
145259+ UserData: Buffer.from(userData).toString('base64'),
145260+ IamInstanceProfile: config.input.iamRoleArns ? { Name: config.input.iamRoleName } : undefined,
145261+ TagSpecifications: config.tagSpecifications
145262+ };
145263+
145264+ // Block device mappings (prefer explicit mappings if provided)
145265+ if (config.input.blockDeviceMappings && config.input.blockDeviceMappings.length > 0) {
145266+ ltData.BlockDeviceMappings = config.input.blockDeviceMappings;
145267+ } else if (config.input.ec2VolumeSize !== '' || config.input.ec2VolumeType !== '') {
145268+ ltData.BlockDeviceMappings = [
145269+ {
145270+ DeviceName: config.input.ec2DeviceName,
145271+ Ebs: {
145272+ ...(config.input.ec2VolumeSize !== '' && { VolumeSize: config.input.ec2VolumeSize }),
145273+ ...(config.input.ec2VolumeType !== '' && { VolumeType: config.input.ec2VolumeType })
145274+ }
145275+ }
145276+ ];
145277+ }
145278+
145279+ const ltName = `ec2-github-runner-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
145280+
145281+ const createLtParams = {
145282+ LaunchTemplateName: ltName,
145283+ LaunchTemplateData: ltData
145284+ };
145285+
145286+ const createLtRes = await ec2.send(new CreateLaunchTemplateCommand(createLtParams));
145287+ launchTemplateId = createLtRes.LaunchTemplate.LaunchTemplateId;
145288+ createdTemporaryLt = true;
145289+ core.info(`Created temporary Launch Template ${launchTemplateId}`);
145290+ }
145291+
145244145292 const isSpot = config.input.marketType === 'spot';
145245145293
145246145294 const fleetParams = {
145247145295 Type: 'instant',
145248145296 LaunchTemplateConfigs: [
145249145297 {
145250145298 LaunchTemplateSpecification: {
145251- LaunchTemplateId: config.input.launchTemplateId
145299+ LaunchTemplateId: launchTemplateId,
145300+ Version: '$Latest'
145252145301 },
145253145302 Overrides: overrides
145254145303 }
@@ -145262,26 +145311,38 @@ async function createEc2InstanceWithFleetParams(imageId, subnetId, securityGroup
145262145311 SpotOptions: isSpot ? { AllocationStrategy: 'capacity-optimized' } : undefined,
145263145312 };
145264145313
145265- const fleetRes = await ec2.send(new CreateFleetCommand(fleetParams));
145266-
145267- // Try to extract instance ID from the response (Type='instant' should return Instances)
145268145314 let ec2InstanceId;
145269- if (Array.isArray(fleetRes.Instances)) {
145270- for (const group of fleetRes.Instances) {
145271- if (Array.isArray(group.InstanceIds) && group.InstanceIds.length > 0) {
145272- ec2InstanceId = group.InstanceIds[0];
145273- break;
145315+ let fleetRes;
145316+ try {
145317+ fleetRes = await ec2.send(new CreateFleetCommand(fleetParams));
145318+
145319+ // Try to extract instance ID from the response (Type='instant' should return Instances)
145320+ if (Array.isArray(fleetRes.Instances)) {
145321+ for (const group of fleetRes.Instances) {
145322+ if (Array.isArray(group.InstanceIds) && group.InstanceIds.length > 0) {
145323+ ec2InstanceId = group.InstanceIds[0];
145324+ break;
145325+ }
145274145326 }
145275145327 }
145276- }
145277145328
145278- if (!ec2InstanceId) {
145279- const errDetails = JSON.stringify({ Errors: fleetRes.Errors }, null, 2);
145280- throw new Error(`EC2 Fleet did not return an instance ID. Details: ${errDetails}`);
145281- }
145329+ if (!ec2InstanceId) {
145330+ const errDetails = JSON.stringify({ Errors: fleetRes.Errors }, null, 2);
145331+ throw new Error(`EC2 Fleet did not return an instance ID. Details: ${errDetails}`);
145332+ }
145282145333
145283- core.info(`Successfully started AWS EC2 instance ${ec2InstanceId} via EC2 Fleet in region ${region}`);
145284- return ec2InstanceId;
145334+ core.info(`Successfully started AWS EC2 instance ${ec2InstanceId} via EC2 Fleet in region ${region}`);
145335+ return ec2InstanceId;
145336+ } finally {
145337+ if (createdTemporaryLt && launchTemplateId) {
145338+ try {
145339+ await ec2.send(new DeleteLaunchTemplateCommand({ LaunchTemplateId: launchTemplateId }));
145340+ core.info(`Deleted temporary Launch Template ${launchTemplateId}`);
145341+ } catch (e) {
145342+ core.warning(`Failed to delete temporary Launch Template ${launchTemplateId}: ${e.message}`);
145343+ }
145344+ }
145345+ }
145285145346}
145286145347
145287145348module.exports = {
@@ -145307,9 +145368,9 @@ class Config {
145307145368 ec2InstanceType: core.getInput('ec2-instance-type'),
145308145369 ec2InstanceTypes: JSON.parse(core.getInput('ec2-instance-types') || '[]'),
145309145370 launchTemplateId: core.getInput('launch-template-id'),
145310- launchTemplateVersion: core.getInput('launch-template-version') || '$Latest',
145311145371 githubToken: core.getInput('github-token'),
145312145372 iamRoleName: core.getInput('iam-role-name'),
145373+ iamRoleArns: core.getInput('iam-role-arns'),
145313145374 label: core.getInput('label'),
145314145375 marketType: core.getInput('market-type'),
145315145376 mode: core.getInput('mode'),
0 commit comments