feat: add support for macos runners#4930
feat: add support for macos runners#4930edersonbrilhante wants to merge 35 commits intogithub-aws-runners:mainfrom
Conversation
|
@npalm what do you think? I didn't test yet. I gonna test during this week. |
0c44c3c to
ecd88a0
Compare
|
Sorry had no time yet to dig in. |
41912ad to
e142885
Compare
|
@npalm I think the code is ready for review. |
|
@koendelaat @guicaulada When the time permits can you also take a look? |
08812d4 to
68e4bb9
Compare
There was a problem hiding this comment.
Pull request overview
This PR enables support for macOS runners on EC2 instances by adding "osx" as a valid runner_os option alongside "linux" and "windows". The changes include macOS-specific bootstrap scripts, placement group and license specification configuration for dedicated Mac hosts, and updated documentation.
Changes:
- Added "osx" as a valid value for
runner_osvariables across modules with corresponding validation updates - Introduced macOS-specific user-data and runner installation/startup scripts
- Added
license_specificationsvariable support through the module hierarchy for Mac dedicated host licensing requirements - Created a new example module for provisioning dedicated Mac hosts with resource groups and license configurations
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| variables.tf | Added osx to runner_os validation and updated description |
| modules/runners/variables.tf | Added osx support and license_specifications variable |
| modules/runners/templates/user-data-osx.sh | New macOS bootstrap script template |
| modules/runners/templates/start-runner-osx.sh | New macOS runner startup script |
| modules/runners/templates/install-runner-osx.sh | New macOS runner installation script |
| modules/runners/templates/install-runner.ps1 | Removed trailing newline |
| modules/runners/scale-down.tf | Added osx minimum runtime default of 20 minutes |
| modules/runners/scale-down-state-diagram.md | Updated documentation with OSX timing |
| modules/runners/main.tf | Added osx AMI defaults, templates, and license specification support |
| modules/runners/README.md | Updated documentation with osx references |
| modules/runner-binaries-syncer/variables.tf | Added osx to runner_os validation |
| modules/runner-binaries-syncer/main.tf | Fixed file extension logic to use tar.gz for osx |
| modules/runner-binaries-syncer/README.md | Updated documentation |
| modules/multi-runner/variables.tf | Added license_specifications to runner config |
| modules/multi-runner/runners.tf | Wired license_specifications parameter |
| modules/multi-runner/README.md | Updated documentation |
| main.tf | Wired license_specifications parameter |
| examples/prebuilt/variables.tf | Added osx to description |
| examples/prebuilt/README.md | Updated documentation |
| examples/dedicated-mac-hosts/* | New example for Mac dedicated host provisioning |
| README.md | Updated documentation with osx and license_specifications |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b7c722c to
019e874
Compare
Brend-Smits
left a comment
There was a problem hiding this comment.
This is a very exciting new feature, great work! Appreciate it a lot.
I've spend quite a bit of time testing this and there are a few things that I noticed:
- While there is a module now for setting up the dedicated hosts for macos, I wonder if this really makes sense and is the right approach. Not saying this is bad or anything, just wondering. It's quite a challenge now to set up and organize a macos based runner and requires a lot of manual effort still. Also requiring to input the license and host arn can make this less trivial to use than other parts of the framework.
- I could not get the spawning of instances to work, likely this was caused by the switch on the main branch to using CreateFleet instead of CreateInstance recently. Switching to 'RunInstancesCommand' with a temporary fix like:
async function createInstancesWithRunInstances(
runnerParameters: Runners.RunnerInputParameters,
amiIdOverride: string | undefined,
ec2Client: EC2Client,
): Promise<string[]> {
const tags = [
{ Key: 'ghr:Application', Value: 'github-action-runner' },
{ Key: 'ghr:created_by', Value: runnerParameters.numberOfRunners === 1 ? 'scale-up-lambda' : 'pool-lambda' },
{ Key: 'ghr:Type', Value: runnerParameters.runnerType },
{ Key: 'ghr:Owner', Value: runnerParameters.runnerOwner },
];
if (runnerParameters.tracingEnabled) {
const traceId = tracer.getRootXrayTraceId();
tags.push({ Key: 'ghr:trace_id', Value: traceId! });
}
try {
const instanceType = runnerParameters.ec2instanceCriteria.instanceTypes[0] as _InstanceType;
const runInstancesCommand = new RunInstancesCommand({
LaunchTemplate: {
LaunchTemplateName: runnerParameters.launchTemplateName,
Version: '$Default',
},
InstanceType: instanceType,
MinCount: runnerParameters.numberOfRunners,
MaxCount: runnerParameters.numberOfRunners,
SubnetId: runnerParameters.subnets[0],
...(amiIdOverride ? { ImageId: amiIdOverride } : {}),
TagSpecifications: [
{
ResourceType: 'instance',
Tags: tags,
},
{
ResourceType: 'volume',
Tags: tags,
},
],
});
const result = await ec2Client.send(runInstancesCommand);
const instanceIds = result.Instances?.map((i) => i.InstanceId!).filter(Boolean) || [];
if (instanceIds.length === 0) {
throw new Error('RunInstances returned no instances for dedicated host.');
}
return instanceIds;
} catch (e) {
logger.warn('RunInstances request failed for dedicated host.', { error: e as Error });
throw e;
}
}resolved the issues I had and resulted in machines getting spawned. So in this case you would have something like:
// EC2 Fleet (CreateFleet) does not support launching instances onto dedicated hosts
// for instance types like mac*.metal. Use RunInstances directly instead.
if (runnerParameters.useDedicatedHost) {
logger.info('Using RunInstances for dedicated host placement (CreateFleet does not support dedicated hosts).');
const instances = await createInstancesWithRunInstances(runnerParameters, amiIdOverride, ec2Client);
logger.info(`Created instance(s) via RunInstances: ${instances.join(',')}`);
return instances;
}- In addition to the above, I don't think these instance types support
spotinstance target capacity, meaning it should also not be an option. The example should reflect this as well by using theinstance_target_capacity_type: "on-demand"runner option.
I'm sorry for the delay in testing/providing feedback on this PR. It's been a bit of a challenge getting this set up and with things going on outside of work, I've prioritized other things.
That is restriction on AWS side, in a analogy I see mandatory requirement to use macos, like we have for VPC/subnet, but just for macos types.
I will rebase the code and test again. |
a88f591 to
55ed8d9
Compare
|
@Brend-Smits About your concerns: Host groups require a self-managed license. When using a host group (instead of a specific host), AWS will select one host from the host group. The “manual” step requires creating a host group, a host, and a license. Then you associate the license with the host group, and associate the host group with the host. This can be done via Terraform and only needs to be done once upfront. After that, you just configure the module to use the appropriate placement and license_specifications. This is a caveat when using Mac runners. I think a short doc explaining this should be enough. |
064b1da to
7781acd
Compare
|
@Brend-Smits Thanks for checking. I would suggest we clearly mark in docs as well in variables. Suggestions:
|
There was a problem hiding this comment.
- Can we add here a quick quide for the steps to setup the example.
- Please check the docs dir, new examples needs to be added here as well.
2e6de20 to
17d38a3
Compare
35e341b to
ad532dc
Compare
Summary
This PR adds support for provisioning GitHub Actions runners on macOS EC2 instances by wiring placement group configuration through the multi-runner module and introducing macOS-specific bootstrap scripts.
Motivation
macOS EC2 instances require a dedicated host (host_id), which is managed through placement groups.
This work prepares the module to request mac-based EC2 runners by consuming placement configuration as defined in #4929
This PR closes #2070 #2069
Test Plan:
and license_configuration_arn