20
20
required : false
21
21
description : Repo to deploy the runner to. Only needed if runner_scope is set to "repo-level" (defaults to current repository)
22
22
deallocate_immediately :
23
- type : string
23
+ type : choice
24
+ options :
25
+ - false
26
+ - true
24
27
required : true
25
28
description : Deallocate the runner immediately after creating it (useful for spinning up runners preemptively)
26
29
default : " false"
30
+ ephemeral :
31
+ type : choice
32
+ options :
33
+ - false
34
+ - true
35
+ required : true
36
+ description : Start the runner in ephemeral mode (i.e. unregister after running one job)
37
+ default : " true"
27
38
28
39
env :
29
40
ACTIONS_RUNNER_SCOPE : ${{ github.event.inputs.runner_scope }}
30
41
ACTIONS_RUNNER_ORG : " ${{ github.event.inputs.runner_org || github.repository_owner }}"
31
42
ACTIONS_RUNNER_REPO : " ${{ github.event.inputs.runner_repo || github.event.repository.name }}"
32
43
DEALLOCATE_IMMEDIATELY : ${{ github.event.inputs.deallocate_immediately }}
33
- # This has to be a public URL that the VM can access after creation
34
- POST_DEPLOYMENT_SCRIPT_URL : https://raw.githubusercontent.com/${{ github.repository }}/${{ github.ref }}/azure-self-hosted-runners/post-deployment-script.ps1
44
+ EPHEMERAL_RUNNER : ${{ github.event.inputs.ephemeral }}
35
45
# Note that you'll need "p" (arm64 processor) and ideally "d" (local temp disk). The number 4 stands for 4 CPU-cores.
36
46
# For a convenient overview of all arm64 VM types, see e.g. https://azureprice.net/?_cpuArchitecture=Arm64
37
47
AZURE_VM_TYPE : Standard_D4plds_v5
41
51
AZURE_VM_REGION : westus2
42
52
AZURE_VM_IMAGE : win11-24h2-ent
43
53
54
+ permissions :
55
+ id-token : write # required for Azure login via OIDC
56
+ contents : read
57
+
44
58
# The following secrets are required for this workflow to run:
45
- # AZURE_CREDENTIALS - Credentials for the Azure CLI. It's recommended to set up a resource
46
- # group specifically for self-hosted Actions Runners.
47
- # az ad sp create-for-rbac --name "{YOUR_DESCRIPTIVE_NAME_HERE}" --role contributor \
48
- # --scopes /subscriptions/{SUBSCRIPTION_ID_HERE}/resourceGroups/{RESOURCE_GROUP_HERE} \
49
- # --sdk-auth
59
+ # AZURE_CLIENT_ID - The Client ID of an Azure Managed Identity. It is recommended to set up a resource
60
+ # group specifically for self-hosted Actions Runners, and to add a federated identity
61
+ # to authenticate as the currently-running GitHub workflow.
62
+ # az identity create --name <managed-identity-name> -g <resource-group>
63
+ # az identity federated-credential create \
64
+ # --identity-name <managed-identity-name> \
65
+ # --resource-group <resource-group> \
66
+ # --name github-workflow \
67
+ # --issuer https://token.actions.githubusercontent.com \
68
+ # --subject repo:git-for-windows/git-for-windows-automation:ref:refs/heads/main \
69
+ # --audiences api://AzureADTokenExchange
70
+ # MSYS_NO_PATHCONV=1 \
71
+ # az role assignment create \
72
+ # --assignee <client-id-of-managed-identity> \
73
+ # --scope '/subscriptions/<subscription-id>/resourceGroups/<resource-group>' \
74
+ # --role 'Contributor'
75
+ # AZURE_TENANT_ID - The Tenant ID of the Azure Managed Identity (i.e. the Azure Active Directory in which
76
+ # the Identity lives)
77
+ # AZURE_SUBSCRIPTION_ID - The Subscription ID with which the Azure Managed Identity is associated
78
+ # (technically, this is not necessary for `az login --service-principal` with a
79
+ # managed identity, but `Azure/login` requires it anyway)
50
80
# AZURE_RESOURCE_GROUP - Resource group to create the runner(s) in
51
81
# AZURE_VM_USERNAME - Username of the VM so you can RDP into it
52
82
# AZURE_VM_PASSWORD - Password of the VM so you can RDP into it
83
+ # GH_APP_ID - The ID of the GitHub App whose credentials are to be used to obtain the runner token
84
+ # GH_APP_PRIVATE_KEY - The private key of the GitHub App whose credentials are to be used to obtain the runner token
53
85
jobs :
54
86
create-runner :
55
87
runs-on : ubuntu-latest
@@ -94,14 +126,21 @@ jobs:
94
126
# https://github.com/actions/runner/issues/475
95
127
- name : Generate Actions Runner token and registration URL
96
128
run : |
129
+ # We need to URL-encode the user name because it usually is a GitHub App, which means that
130
+ # it has the suffix `[bot]`. If un-encoded, this would cause a cURL error "bad range in URL"
131
+ # because it would mistake this for an IPv6 address or something like that.
132
+ user_pwd="$(jq -n \
133
+ --arg user '${{ github.actor }}' \
134
+ --arg pwd '${{ secrets.GITHUB_TOKEN }}' \
135
+ '$user | @uri + ":" + $pwd')"
97
136
case "$ACTIONS_RUNNER_SCOPE" in
98
137
"org-level")
99
- ACTIONS_API_URL="https://api.github.com/repos/$ACTIONS_RUNNER_ORG/actions/runners/registration-token"
100
- ACTIONS_RUNNER_REGISTRATION_URL="https://github.com/$ACTIONS_RUNNER_ORG"
138
+ ACTIONS_API_URL="https://$user_pwd@ api.github.com/repos/$ACTIONS_RUNNER_ORG/actions/runners/registration-token"
139
+ ACTIONS_RUNNER_REGISTRATION_URL="https://$user_pwd@ github.com/$ACTIONS_RUNNER_ORG"
101
140
;;
102
141
"repo-level")
103
- ACTIONS_API_URL="https://api.github.com/repos/$ACTIONS_RUNNER_ORG/$ACTIONS_RUNNER_REPO/actions/runners/registration-token"
104
- ACTIONS_RUNNER_REGISTRATION_URL="https://github.com/$ACTIONS_RUNNER_ORG/$ACTIONS_RUNNER_REPO"
142
+ ACTIONS_API_URL="https://$user_pwd@ api.github.com/repos/$ACTIONS_RUNNER_ORG/$ACTIONS_RUNNER_REPO/actions/runners/registration-token"
143
+ ACTIONS_RUNNER_REGISTRATION_URL="https://$user_pwd@ github.com/$ACTIONS_RUNNER_ORG/$ACTIONS_RUNNER_REPO"
105
144
;;
106
145
*)
107
146
echo "Unsupported runner scope: $ACTIONS_RUNNER_SCOPE"
@@ -127,16 +166,30 @@ jobs:
127
166
ACTIONS_RUNNER_PATH="D:\a"
128
167
fi
129
168
169
+ # Zip up and Base64-encode the post-deployment script; We used to provide a public URL
170
+ # for that script instead, but that does not work in private repositories (and we could
171
+ # not even use the `GITHUB_TOKEN` to access the file because it lacks the necessary
172
+ # scope to read repository contents).
173
+ POST_DEPLOYMENT_SCRIPT_ZIP_BASE64="$(
174
+ cd azure-self-hosted-runners &&
175
+ zip -9 tmp.zip post-deployment-script.ps1 >&2 &&
176
+ base64 -w 0 tmp.zip
177
+ )"
178
+
179
+ PUBLIC_IP_ADDRESS_NAME1="${{ github.repository_visibility != 'private' && format('{0}-ip', steps.generate-vm-name.outputs.vm_name) || '' }}"
180
+
130
181
AZURE_ARM_PARAMETERS=$(tr '\n' ' ' <<-END
131
182
githubActionsRunnerRegistrationUrl="$ACTIONS_RUNNER_REGISTRATION_URL"
132
183
githubActionsRunnerToken="$ACTIONS_RUNNER_TOKEN"
133
- postDeploymentPsScriptUrl="$POST_DEPLOYMENT_SCRIPT_URL"
184
+ postDeploymentScriptZipBase64="$POST_DEPLOYMENT_SCRIPT_ZIP_BASE64"
185
+ postDeploymentScriptFileName="post-deployment-script.ps1"
134
186
virtualMachineImage="$AZURE_VM_IMAGE"
135
187
virtualMachineName="${{ steps.generate-vm-name.outputs.vm_name }}"
136
188
virtualMachineSize="$AZURE_VM_TYPE"
137
- publicIpAddressName1="${{ steps.generate-vm-name.outputs.vm_name }}-ip "
189
+ publicIpAddressName1="$PUBLIC_IP_ADDRESS_NAME1 "
138
190
adminUsername="${{ secrets.AZURE_VM_USERNAME }}"
139
191
adminPassword="${{ secrets.AZURE_VM_PASSWORD }}"
192
+ ephemeral="$EPHEMERAL_RUNNER"
140
193
stopService="$DEALLOCATE_IMMEDIATELY"
141
194
githubActionsRunnerPath="$ACTIONS_RUNNER_PATH"
142
195
location="$AZURE_VM_REGION"
@@ -146,10 +199,12 @@ jobs:
146
199
echo "AZURE_ARM_PARAMETERS=$AZURE_ARM_PARAMETERS" >> $GITHUB_ENV
147
200
148
201
- name : Azure Login
149
- uses : ./.github/workflows/ azure- login
202
+ uses : azure/ login@v2
150
203
with :
151
- credentials : ${{ secrets.AZURE_CREDENTIALS }}
152
-
204
+ client-id : ${{ secrets.AZURE_CLIENT_ID }}
205
+ tenant-id : ${{ secrets.AZURE_TENANT_ID }}
206
+ subscription-id : ${{ secrets.AZURE_SUBSCRIPTION_ID }}
207
+
153
208
- uses : azure/arm-deploy@v2
154
209
id : deploy-arm-template
155
210
with :
@@ -179,7 +234,7 @@ jobs:
179
234
if : always()
180
235
env :
181
236
CUSTOM_SCRIPT_OUTPUT : ${{ steps.deploy-arm-template.outputs.customScriptInstanceView }}
182
- run : echo "$CUSTOM_SCRIPT_OUTPUT" | jq -r '.substatuses[0].message'
237
+ run : echo "$CUSTOM_SCRIPT_OUTPUT" | jq -r '.substatuses[0].message' | sed 's/${{ secrets.GITHUB_TOKEN }}/***/g'
183
238
184
239
- name : Deallocate the VM for later use
185
240
if : env.DEALLOCATE_IMMEDIATELY == 'true'
0 commit comments