Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/windows support #1476

Merged
merged 76 commits into from
Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
736a854
fix(scale): Refactor Runner Type and Owner (#871)
mcaulifn Jun 15, 2021
6e35845
feat: support multiple instance types (#898)
mcaulifn Jun 16, 2021
a768687
docs: fix lambda_security_group_ids incorrect description #738 (#902)
npalm Jun 17, 2021
5b5ee3b
fix: scale down runners (#905)
npalm Jun 17, 2021
8746249
chore: group upgrade lambda dependencies (#906)
npalm Jun 17, 2021
95a3ab6
chore: Bump aws-sdk (#752) (#909)
dependabot[bot] Jun 18, 2021
c1e7bf3
chore: Bump aws-sdk (#752) (#908)
dependabot[bot] Jun 18, 2021
b860437
chore: Bump aws-sdk (#752) (#887)
dependabot[bot] Jun 18, 2021
cd88e3d
chore: Bump aws-sdk (#752) (#885)
dependabot[bot] Jun 18, 2021
fae4839
chore: Bump aws-sdk (#752) (#889)
dependabot[bot] Jun 18, 2021
b62b63e
chore: Bump aws-sdk (#752) (#892)
dependabot[bot] Jun 18, 2021
5ae4a4d
chore: Bump aws-sdk (#752) (#907)
dependabot[bot] Jun 18, 2021
744d977
chore: Bump aws-sdk (#752) (#864)
dependabot[bot] Jun 18, 2021
118c5d3
feat: support windows binary in cache lambda
RichiCoder1 Apr 10, 2021
ecff591
add variable to control runner os
RichiCoder1 Apr 13, 2021
40f334c
update docs
RichiCoder1 Apr 16, 2021
6a41c42
feat: add windows instance support
npalm Jun 20, 2021
f39dcfd
docs
RichiCoder1 Apr 16, 2021
e21476a
update docs
npalm Jun 20, 2021
0a1f706
fix zip name to include correct os name
RichiCoder1 Apr 18, 2021
8d46612
add powershell closing tag for userdata
RichiCoder1 Apr 18, 2021
8a061b1
add transcript
RichiCoder1 Apr 18, 2021
210b251
fix alias and add more verbose logging
RichiCoder1 Apr 18, 2021
50112c3
tweak install cmdlets
RichiCoder1 Apr 18, 2021
822eacc
add some robustness to userdata
RichiCoder1 Apr 18, 2021
890e26c
fix a number of typos and bugs and restart
RichiCoder1 Apr 19, 2021
f632dd3
try and make run better in weird environment
RichiCoder1 Apr 19, 2021
289d90e
use containers image and kill docker install
RichiCoder1 Apr 19, 2021
7697b00
fix cloudagent log paths
RichiCoder1 Apr 19, 2021
47644c3
update default
RichiCoder1 Apr 19, 2021
83a1c42
give windows runners more time to spin up
RichiCoder1 Apr 19, 2021
9d528e9
fix trigger syntax
RichiCoder1 Apr 19, 2021
df38f3b
move restart before transcript stop
RichiCoder1 Apr 19, 2021
b740451
skip restart
RichiCoder1 Apr 19, 2021
20dbe40
fix container ami filter
RichiCoder1 Apr 19, 2021
dce7292
address pr feedback, add example, and fix ami_filter
npalm Jun 20, 2021
98e8324
fix issue with cloudwatch
RichiCoder1 Apr 28, 2021
e8d889e
remove syntax error highlights in template
RichiCoder1 Apr 28, 2021
093d620
fix win log path
RichiCoder1 May 4, 2021
5d3912b
run as administrator
npalm May 21, 2021
0f49f9b
Merge branch 'develop' into feat/windows-support
ScottGuymer Dec 1, 2021
e47e726
Get the example working OOTB
ScottGuymer Dec 1, 2021
d9ebb4c
Fixes from the merge
ScottGuymer Dec 2, 2021
713b902
Fix readme
ScottGuymer Dec 2, 2021
2a54b31
Fixes to align with develop
ScottGuymer Dec 2, 2021
6b01760
Make the example work for testing
ScottGuymer Dec 2, 2021
a6342ab
Fix the passthrough of the boot time to the runner module
ScottGuymer Dec 2, 2021
323efc9
Extend the boot time so a machine has time to boot.
ScottGuymer Dec 2, 2021
b1d6981
Remove the default AMI from the main module.
ScottGuymer Dec 2, 2021
61f0caf
Added more documentation to the windows example
ScottGuymer Dec 2, 2021
9a7b10a
Format typescript
ScottGuymer Dec 2, 2021
fb61a51
Fix formatting
ScottGuymer Dec 2, 2021
febcad9
Reset default example
ScottGuymer Dec 2, 2021
33ea24b
Improve readability
ScottGuymer Dec 2, 2021
0c5cdb9
Add some validation for the runner_os variable
ScottGuymer Dec 2, 2021
5872b09
Merge branch 'develop' into feat/windows-support
ScottGuymer Dec 3, 2021
ae61125
Added logging change
ScottGuymer Dec 3, 2021
0a77a00
Some further refactoring
ScottGuymer Dec 6, 2021
64b348a
Add a windows start-runner.ps1
ScottGuymer Dec 6, 2021
5a68873
Add more validation
ScottGuymer Dec 6, 2021
a165182
Upgrade the provider
ScottGuymer Dec 6, 2021
add16c2
Add time since boot to script
ScottGuymer Dec 6, 2021
6a5e083
Merge remote-tracking branch 'upstream/develop' into feat/windows-sup…
ScottGuymer Dec 7, 2021
84042c6
Refactoring to use tag/parameter based config
ScottGuymer Dec 7, 2021
648131d
Tweaks from testing
ScottGuymer Dec 7, 2021
72c1a09
Runners only have PS5 where get-uptime might not be available
ScottGuymer Dec 8, 2021
8cd699a
Some more small refactoring.
ScottGuymer Dec 8, 2021
d930490
Fix config access and remove packages that are no longer needed.
ScottGuymer Dec 8, 2021
1078dfc
Set the value of runner_log_files as null so it can be defaulted.
ScottGuymer Dec 8, 2021
86767e7
Merge remote-tracking branch 'upstream/develop' into feat/windows-sup…
ScottGuymer Dec 8, 2021
582ee83
Fix failing tests
ScottGuymer Dec 8, 2021
177bf53
Update modules/runners/variables.tf
ScottGuymer Dec 9, 2021
d6e2926
Updates the github secrets to use hex values rather than strings.
ScottGuymer Dec 9, 2021
37b3984
Merge remote-tracking branch 'origin/feat/windows-support' into feat/…
ScottGuymer Dec 9, 2021
923b681
Updates based on PR feedback
ScottGuymer Dec 9, 2021
1f698f2
Updated byte length to 20
ScottGuymer Dec 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ idle_config = [{
}]
```

_**Note**_: When using Windows runners it's recommended to keep a few runners warmed up due to the minutes-long cold start time.

#### Supported config <!-- omit in toc -->

Cron expressions are parsed by [cron-parser](https://github.com/harrisiirak/cron-parser#readme). The supported syntax.
Expand All @@ -289,6 +291,8 @@ Examples are located in the [examples](./examples) directory. The following exam

- _[Default](examples/default/README.md)_: The default example of the module
- _[Permissions boundary](examples/permissions-boundary/README.md)_: Example usages of permissions boundaries.
- _[Ubuntu](examples/ubuntu/README.md)_: Example usage of creating a runner using Ubuntu AMIs.
- _[Windows](examples/windows/README.md)_: Example usage of creating a runner using Windows as the OS.

## Sub modules

Expand Down
39 changes: 39 additions & 0 deletions examples/windows/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions examples/windows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Action runners deployment windows example

This module shows how to create GitHub action runners using an Windows Runners. Lambda release will be downloaded from GitHub.

## Usages

Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md). First, download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, for which there is a build script available at `<root>/.ci/build.sh`. In the `main.tf` you can remove the location of the lambda zip files, the default location will work in this case.
ScottGuymer marked this conversation as resolved.
Show resolved Hide resolved

> Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see <https://github.com/philips-labs/terraform-aws-github-runner/releases>


```pwsh
cd lambdas-download
terraform init
terraform apply
cd ..
```

Before running Terraform, ensure the GitHub app is configured.

```bash
terraform init
terraform apply
```

_**Note**_: It can take upwards of ten minutes for a runner to start processing jobs, and about as long for logs to start showing up. It's recommend that scale the runners via a warm-up job and then keep them idled.
25 changes: 25 additions & 0 deletions examples/windows/lambdas-download/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
locals {
version = "<REPLACE_BY_GITHUB_RELEASE_VERSION>"
}

module "lambdas" {
source = "../../../modules/download-lambda"
lambdas = [
{
name = "webhook"
tag = local.version
},
{
name = "runners"
tag = local.version
},
{
name = "runner-binaries-syncer"
tag = local.version
}
]
}

output "files" {
value = module.lambdas.files
}
47 changes: 47 additions & 0 deletions examples/windows/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
locals {
environment = "windows"
aws_region = "eu-west-1"
}

resource "random_password" "random" {
length = 28
}

module "runners" {
source = "../../"

aws_region = local.aws_region
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
environment = local.environment

github_app = {
key_base64 = var.github_app_key_base64
id = var.github_app_id
webhook_secret = random_password.random.result
}

# Grab the lambda packages from local directory. Must run /.ci/build.sh first
webhook_lambda_zip = "../../lambda_output/webhook.zip"
runner_binaries_syncer_lambda_zip = "../../lambda_output/runner-binaries-syncer.zip"
runners_lambda_zip = "../../lambda_output/runners.zip"

enable_organization_runners = true
runner_extra_labels = "default,example"

# Set the OS to Windows
runner_os = "win"
# no need to add extra windows tag here as it is automatically added by GitHub
runner_boot_time_in_minutes = 20

# enable access to the runners via SSM
enable_ssm_on_runners = true

instance_types = ["m5.large", "c5.large"]

# override delay of events in seconds for testing
delay_webhook_event = 5

# override scaling down for testing
scale_down_schedule_expression = "cron(* * * * ? *)"
}
15 changes: 15 additions & 0 deletions examples/windows/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "runners" {
value = {
lambda_syncer_name = module.runners.binaries_syncer.lambda.function_name
}
}

output "webhook_endpoint" {
value = module.runners.webhook.endpoint
}

output "webhook_secret" {
sensitive = true
value = random_password.random.result
}

3 changes: 3 additions & 0 deletions examples/windows/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "aws" {
region = local.aws_region
}
4 changes: 4 additions & 0 deletions examples/windows/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

variable "github_app_key_base64" {}

variable "github_app_id" {}
7 changes: 7 additions & 0 deletions examples/windows/vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module "vpc" {
source = "git::https://github.com/philips-software/terraform-aws-vpc.git?ref=2.2.0"

environment = local.environment
aws_region = local.aws_region
create_private_hosted_zone = false
}
8 changes: 4 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ locals {

s3_action_runner_url = "s3://${module.runner_binaries.bucket.id}/${module.runner_binaries.runner_distribution_object_key}"
runner_architecture = substr(var.instance_type, 0, 2) == "a1" || substr(var.instance_type, 1, 2) == "6g" ? "arm64" : "x64"

ami_filter = length(var.ami_filter) > 0 ? var.ami_filter : local.runner_architecture == "arm64" ? { name = ["amzn2-ami-hvm-2*-arm64-gp2"] } : { name = ["amzn2-ami-hvm-2.*-x86_64-ebs"] }
ScottGuymer marked this conversation as resolved.
Show resolved Hide resolved

github_app_parameters = {
id = module.ssm.parameters.github_app_id
key_base64 = module.ssm.parameters.github_app_key_base64
Expand Down Expand Up @@ -81,20 +78,22 @@ module "runners" {
s3_bucket_runner_binaries = module.runner_binaries.bucket
s3_location_runner_binaries = local.s3_action_runner_url

runner_os = var.runner_os
instance_type = var.instance_type
instance_types = var.instance_types
market_options = var.market_options
block_device_mappings = var.block_device_mappings

runner_architecture = local.runner_architecture
ami_filter = local.ami_filter
ami_filter = var.ami_filter
ami_owners = var.ami_owners

sqs_build_queue = aws_sqs_queue.queued_builds
github_app_parameters = local.github_app_parameters
enable_organization_runners = var.enable_organization_runners
scale_down_schedule_expression = var.scale_down_schedule_expression
minimum_running_time_in_minutes = var.minimum_running_time_in_minutes
runner_boot_time_in_minutes = var.runner_boot_time_in_minutes
runner_extra_labels = var.runner_extra_labels
runner_as_root = var.runner_as_root
runners_maximum_count = var.runners_maximum_count
Expand Down Expand Up @@ -153,6 +152,7 @@ module "runner_binaries" {

distribution_bucket_name = "${var.environment}-dist-${random_string.random.result}"

runner_os = var.runner_os
runner_architecture = local.runner_architecture
runner_allow_prerelease_binaries = var.runner_allow_prerelease_binaries

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,23 @@ describe('Synchronize action distribution for arm64.', () => {
await expect(handle()).rejects.toThrow(errorMessage);
});
});

describe('Synchronize action distribution for windows.', () => {
const errorMessage = 'Cannot find GitHub release asset.';
beforeEach(() => {
process.env.S3_BUCKET_NAME = bucketName;
process.env.S3_OBJECT_KEY = bucketObjectKey;
process.env.GITHUB_RUNNER_OS = 'win';
});

it('No win asset.', async () => {
mockOctokit.repos.listReleases.mockImplementation(() => ({
data: listReleases.map((release) => ({
...release,
assets: release.assets.filter((asset) => !asset.name.includes('win')),
})),
}));

await expect(handle()).rejects.toThrow(errorMessage);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ interface ReleaseAsset {
downloadUrl: string;
}

async function getLinuxReleaseAsset(
async function getReleaseAsset(
runnerOs = 'linux',
runnerArch = 'x64',
fetchPrereleaseBinaries = false,
): Promise<ReleaseAsset | undefined> {
Expand All @@ -58,11 +59,11 @@ async function getLinuxReleaseAsset(
} else {
return undefined;
}
const linuxAssets = asset.assets?.filter((a) => a.name?.includes(`actions-runner-linux-${runnerArch}-`));
const assets = asset.assets?.filter((a: { name?: string }) =>
a.name?.includes(`actions-runner-${runnerOs}-${runnerArch}-`),
);

return linuxAssets?.length === 1
? { name: linuxAssets[0].name, downloadUrl: linuxAssets[0].browser_download_url }
: undefined;
return assets?.length === 1 ? { name: assets[0].name, downloadUrl: assets[0].browser_download_url } : undefined;
}

async function uploadToS3(s3: S3, cacheObject: CacheObject, actionRunnerReleaseAsset: ReleaseAsset): Promise<void> {
Expand Down Expand Up @@ -106,6 +107,7 @@ async function uploadToS3(s3: S3, cacheObject: CacheObject, actionRunnerReleaseA
export const handle = async (): Promise<void> => {
const s3 = new AWS.S3();

const runnerOs = process.env.GITHUB_RUNNER_OS || 'linux';
const runnerArch = process.env.GITHUB_RUNNER_ARCHITECTURE || 'x64';
const fetchPrereleaseBinaries = JSON.parse(process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES || 'false');

Expand All @@ -116,16 +118,15 @@ export const handle = async (): Promise<void> => {
if (!cacheObject.bucket || !cacheObject.key) {
throw Error('Please check all mandatory variables are set.');
}

const actionRunnerReleaseAsset = await getLinuxReleaseAsset(runnerArch, fetchPrereleaseBinaries);
if (actionRunnerReleaseAsset === undefined) {
const runnerAsset = await getReleaseAsset(runnerOs, runnerArch, fetchPrereleaseBinaries);
if (runnerAsset === undefined) {
throw Error('Cannot find GitHub release asset.');
}

const currentVersion = await getCachedVersion(s3, cacheObject);
logger.debug('latest: ' + currentVersion);
if (currentVersion === undefined || currentVersion != actionRunnerReleaseAsset.name) {
uploadToS3(s3, cacheObject, actionRunnerReleaseAsset);
if (currentVersion === undefined || currentVersion != runnerAsset.name) {
uploadToS3(s3, cacheObject, runnerAsset);
} else {
logger.debug('Distribution is up-to-date, no action.');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3352,6 +3352,7 @@ tr46@^2.1.0:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"

tr46@~0.0.3:
Expand Down
2 changes: 1 addition & 1 deletion modules/runner-binaries-syncer/main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
locals {
action_runner_distribution_object_key = "actions-runner-linux.tar.gz"
action_runner_distribution_object_key = "actions-runner-${var.runner_os}.${var.runner_os == "linux" ? "tar.gz" : "zip"}"
}

resource "aws_s3_bucket" "action_dist" {
Expand Down
3 changes: 2 additions & 1 deletion modules/runner-binaries-syncer/runner-binaries-syncer.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ resource "aws_lambda_function" "syncer" {

environment {
variables = {
GITHUB_RUNNER_ARCHITECTURE = var.runner_architecture
GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = var.runner_allow_prerelease_binaries
GITHUB_RUNNER_ARCHITECTURE = var.runner_architecture
GITHUB_RUNNER_OS = var.runner_os
LOG_LEVEL = var.log_level
LOG_TYPE = var.log_type
S3_BUCKET_NAME = aws_s3_bucket.action_dist.id
Expand Down
6 changes: 6 additions & 0 deletions modules/runner-binaries-syncer/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ variable "role_path" {
default = null
}

variable "runner_os" {
description = "The operating system for the runner instance (linux, win), defaults to 'linux'"
type = string
default = "linux"
}

variable "runner_architecture" {
description = "The platform architecture for the runner instance (x64, arm64), defaults to 'x64'"
type = string
Expand Down
26 changes: 25 additions & 1 deletion modules/runners/logging.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
locals {
logfiles = var.enable_cloudwatch_agent ? [for l in var.runner_log_files : {
runner_log_files = (
var.runner_log_files != null
? var.runner_log_files
: [
{
"prefix_log_group" : true,
"file_path" : "/var/log/messages",
"log_group_name" : "messages",
"log_stream_name" : "{instance_id}"
},
{
"log_group_name" : "user_data",
"prefix_log_group" : true,
"file_path" : var.runner_os == "win" ? "C:/UserData.log" : "/var/log/user-data.log",
"log_stream_name" : "{instance_id}"
},
{
"log_group_name" : "runner",
"prefix_log_group" : true,
"file_path" : var.runner_os == "win" ? "C:/actions-runner/_diag/Runner_*.log" : "/home/runners/actions-runner/_diag/Runner_**.log",
"log_stream_name" : "{instance_id}"
}
]
)
logfiles = var.enable_cloudwatch_agent ? [for l in local.runner_log_files : {
"log_group_name" : l.prefix_log_group ? "/github-self-hosted-runners/${var.environment}/${l.log_group_name}" : "/${l.log_group_name}"
"log_stream_name" : l.log_stream_name
"file_path" : l.file_path
Expand Down
Loading