Skip to content

Commit 6cfc1d0

Browse files
committed
Add CI pipeline for creating self-hosted runners
Signed-off-by: Dennis Ameling <[email protected]>
1 parent 97791e8 commit 6cfc1d0

File tree

4 files changed

+585
-0
lines changed

4 files changed

+585
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: create-azure-self-hosted-runners
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
amount_of_runners:
7+
description: 'Amount of runners to set up'
8+
required: true
9+
runner_scope:
10+
type: choice
11+
required: true
12+
description: Scope of the runner. On personal accounts, only "repo-level" works
13+
options:
14+
- org-level
15+
- repo-level
16+
runner_org:
17+
type: string
18+
required: true
19+
description: Organization or personal account to deploy the runner to
20+
runner_repo:
21+
type: string
22+
required: false
23+
description: Repo to deploy the runner to. Only needed if runner_scope is set to "repo-level"
24+
25+
env:
26+
ACTIONS_RUNNER_ORG: "${{ github.event.inputs.runner_org }}"
27+
ACTIONS_RUNNER_REPO: "${{ github.event.inputs.runner_repo }}"
28+
# This has to be a public URL that the VM can access after creation
29+
POST_DEPLOYMENT_SCRIPT_URL: https://raw.githubusercontent.com/git-for-windows/git-for-windows-automation/main/azure-self-hosted-runners/post-deployment-script.ps1
30+
31+
# The following secrets are required for this workflow to run:
32+
# GH_API_PAT - PAT to create a runner registration token using GitHub's API
33+
# AZURE_CREDENTIALS - Credentials for the Azure CLI. It's recommended to set up a resource
34+
# group specifically for self-hosted Actions Runners.
35+
# az ad sp create-for-rbac --name "{YOUR_DESCRIPTIVE_NAME_HERE}" --role contributor \
36+
# --scopes /subscriptions/{SUBSCRIPTION_ID_HERE}/resourceGroups/{RESOURCE_GROUP_HERE} \
37+
# --sdk-auth
38+
# AZURE_RESOURCE_GROUP - Resource group to create the runner(s) in
39+
# AZURE_VM_USERNAME - Username of the VM so you can RDP into it
40+
# AZURE_VM_PASSWORD - Password of the VM so you can RDP into it
41+
jobs:
42+
create-matrix:
43+
runs-on: ubuntu-latest
44+
outputs:
45+
matrix: ${{ steps.create-matrix.outputs.matrix }}
46+
steps:
47+
- name: Create matrix for setting up runners in parallel
48+
id: create-matrix
49+
run: |
50+
AMOUNT_OF_RUNNERS="${{ inputs.amount_of_runners }}"
51+
echo "Going to create $AMOUNT_OF_RUNNERS runners"
52+
MATRIX="matrix={\"runner_index\":[$(seq -s "," 1 $AMOUNT_OF_RUNNERS)]}"
53+
echo "Going to use this matrix: $MATRIX"
54+
echo $MATRIX >> $GITHUB_OUTPUT
55+
create-runners:
56+
name: create-runner-${{ matrix.runner_index }}
57+
needs: create-matrix
58+
runs-on: ubuntu-latest
59+
strategy:
60+
matrix: ${{ fromJSON(needs.create-matrix.outputs.matrix) }}
61+
outputs:
62+
vm_name: ${{ steps.generate-vm-name.outputs.vm_name }}
63+
steps:
64+
- name: Generate VM name
65+
id: generate-vm-name
66+
run: |
67+
VM_NAME="actions-runner-$(date +%Y%m%d%H%M%S%N)"
68+
echo "Will be using $VM_NAME as the VM name"
69+
echo "vm_name=$VM_NAME" >> $GITHUB_OUTPUT
70+
71+
# We can't use the octokit/request-action as we can't properly mask the runner token with it
72+
# https://github.com/actions/runner/issues/475
73+
- name: Generate Actions Runner token and registration URL
74+
run: |
75+
case "${{ inputs.runner_scope }}" in
76+
"org-level")
77+
ACTIONS_API_URL="https://api.github.com/repos/${{ env.ACTIONS_RUNNER_ORG }}/actions/runners/registration-token"
78+
echo ACTIONS_RUNNER_REGISTRATION_URL="https://github.com/${{ env.ACTIONS_RUNNER_ORG }}" >> $GITHUB_ENV
79+
;;
80+
"repo-level")
81+
ACTIONS_API_URL="https://api.github.com/repos/${{ env.ACTIONS_RUNNER_ORG }}/${{ env.ACTIONS_RUNNER_REPO }}/actions/runners/registration-token"
82+
echo ACTIONS_RUNNER_REGISTRATION_URL="https://github.com/${{ env.ACTIONS_RUNNER_ORG }}/${{ env.ACTIONS_RUNNER_REPO }}" >> $GITHUB_ENV
83+
;;
84+
*)
85+
echo "Unsupported runner scope: ${{ inputs.runner_scope }}"
86+
exit 1
87+
;;
88+
esac
89+
90+
ACTIONS_RUNNER_TOKEN=$(curl \
91+
-X POST \
92+
-H "Accept: application/vnd.github+json" \
93+
-H "Authorization: Bearer ${{ secrets.GH_API_PAT }}"\
94+
-H "X-GitHub-Api-Version: 2022-11-28" \
95+
$ACTIONS_API_URL \
96+
| jq --raw-output .token)
97+
echo "::add-mask::$ACTIONS_RUNNER_TOKEN"
98+
echo ACTIONS_RUNNER_TOKEN=$ACTIONS_RUNNER_TOKEN >> $GITHUB_ENV
99+
100+
- name: Azure Login
101+
uses: azure/login@v1
102+
with:
103+
creds: ${{ secrets.AZURE_CREDENTIALS }}
104+
105+
# Checkout the repo so that we can access the template files
106+
- uses: actions/checkout@v3
107+
108+
- uses: azure/arm-deploy@v1
109+
with:
110+
resourceGroupName: ${{ secrets.AZURE_RESOURCE_GROUP }}
111+
template: ./azure-self-hosted-runners/azure-arm-template.json
112+
parameters: ./azure-self-hosted-runners/azure-arm-template-example-parameters.json githubActionsRunnerRegistrationUrl="${{ env.ACTIONS_RUNNER_REGISTRATION_URL }}" githubActionsRunnerToken="${{ env.ACTIONS_RUNNER_TOKEN }}" postDeploymentPsScriptUrl="${{ env.POST_DEPLOYMENT_SCRIPT_URL }}" virtualMachineName=${{ steps.generate-vm-name.outputs.vm_name }} virtualMachineSize=Standard_D8pls_v5 publicIpAddressName1=${{ steps.generate-vm-name.outputs.vm_name }}-ip adminUsername=${{ secrets.AZURE_VM_USERNAME }} adminPassword=${{ secrets.AZURE_VM_PASSWORD }}
113+
114+
- name: Deallocate the VM for later use
115+
uses: azure/CLI@v1
116+
with:
117+
azcliversion: 2.43.0
118+
inlineScript: |
119+
az vm deallocate -n ${{ steps.generate-vm-name.outputs.vm_name }} -g ${{ secrets.AZURE_RESOURCE_GROUP }} --verbose
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3+
"contentVersion": "1.0.0.0",
4+
"parameters": {
5+
"location": {
6+
"value": "westeurope"
7+
},
8+
"enableAcceleratedNetworking": {
9+
"value": true
10+
},
11+
"networkSecurityGroupRules": {
12+
"value": [
13+
{
14+
"name": "RDP",
15+
"properties": {
16+
"priority": 300,
17+
"protocol": "TCP",
18+
"access": "Allow",
19+
"direction": "Inbound",
20+
"sourceAddressPrefix": "*",
21+
"sourcePortRange": "*",
22+
"destinationAddressPrefix": "*",
23+
"destinationPortRange": "3389"
24+
}
25+
}
26+
]
27+
},
28+
"subnetName": {
29+
"value": "default"
30+
},
31+
"addressPrefixes": {
32+
"value": [
33+
"10.2.0.0/16"
34+
]
35+
},
36+
"subnets": {
37+
"value": [
38+
{
39+
"name": "default",
40+
"properties": {
41+
"addressPrefix": "10.2.0.0/24"
42+
}
43+
}
44+
]
45+
},
46+
"publicIpAddressType": {
47+
"value": "Static"
48+
},
49+
"publicIpAddressSku": {
50+
"value": "Standard"
51+
},
52+
"pipDeleteOption": {
53+
"value": "Detach"
54+
},
55+
"osDiskType": {
56+
"value": "Premium_LRS"
57+
},
58+
"osDiskDeleteOption": {
59+
"value": "Delete"
60+
},
61+
"nicDeleteOption": {
62+
"value": "Detach"
63+
},
64+
"patchMode": {
65+
"value": "AutomaticByOS"
66+
},
67+
"enableHotpatching": {
68+
"value": false
69+
},
70+
"zone": {
71+
"value": "1"
72+
},
73+
"computerName": {
74+
"value": "actions-runner"
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)