commit a6741ac1d047bb98d20832191f99cafb2bec37a5 Author: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Thu Sep 28 17:50:43 2023 +0200 First iteration of Windows Runner diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7780464 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.bak +docker-compose.yml \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a8d13c4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM mcr.microsoft.com/windows/servercore:ltsc2022 + +ARG RUNNER_VERSION="2.309.0" + +SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"] + +# Set working directory +WORKDIR /actions-runner + +COPY install-choco.ps1 . +RUN .\install-choco.ps1; Remove-Item .\install-choco.ps1 -Force + +# Install dependencies with Chocolatey +RUN choco install -y \ + git \ + gh \ + powershell-core + +RUN choco install -y visualstudio2022buildtools --package-parameters \" \ + --quiet --norestart \ + --add Microsoft.VisualStudio.Workload.VisualStudioExtensionBuildTools \ + --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools \ + --add Microsoft.NetCore.Component.SDK \ + --add Microsoft.Net.Component.4.6.1.TargetingPack \ + --add Microsoft.Net.Component.4.8.TargetingPack \ + \" + +# Add MSBuild to the path +RUN [Environment]::SetEnvironmentVariable(\"Path\", $env:Path + \";C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\", \"Machine\") + +COPY install-runner.ps1 . +RUN .\install-runner.ps1; Remove-Item .\install-runner.ps1 -Force + +COPY entrypoint.ps1 . + +ENTRYPOINT ["pwsh.exe", ".\\entrypoint.ps1"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9505fed --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Windows Docker GitHub Runner + +This repository is a Windows version of the [myoung34/docker-github-actions-runner](https://github.com/myoung34/docker-github-actions-runner) runner for Linux. Tried has been to keep the usage as close as possible. + +This repository will run the [self-hosted github actions runners](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/hosting-your-own-runners) for Windows with [Visual Studio 2022 buildtools](https://community.chocolatey.org/packages/visualstudio2022buildtools) installed by default. + +## Environment variables + +| Environment Variable | Description | +| -------------------- | ----------- | +| `RUNNER_NAME` | The name of the runner to use. Overrides `RUNNER_NAME_PREFIX` | +| `RUNNER_NAME_PREFIX` | A prefix for runner name. Note: will be overridden by `RUNNER_NAME` if provided. Defaults to `windows-runner` | +| `ACCESS_TOKEN` | A [github PAT](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) to use to generate `RUNNER_TOKEN` dynamically at container start. Not using this requires a valid `RUNNER_TOKEN` | +| `RUNNER_TOKEN` | If not using a PAT for `ACCESS_TOKEN` this will be the runner token provided by the Add Runner UI (a manual process). Note: This token is short lived and will change frequently. `ACCESS_TOKEN` is likely preferred. | +| `RUNNER_SCOPE` | The scope the runner will be registered on. Valid values are `repo`, `org` and `enterprise`. For 'org' and 'enterprise' the `REPO_URL` is unnecessary. If 'org', requires `ORG_NAME`; if 'enterprise', requires `ENTERPRISE_NAME`. Default is 'repo'. | +| `ORG_NAME` | The organization name for the runner to register under. Requires `RUNNER_SCOPE` to be 'org'. No default value. | +| `ENTERPRISE_NAME` | The enterprise name for the runner to register under. Requires `RUNNER_SCOPE` to be 'enterprise'. No default value. | +| `LABELS` | A comma separated string to indicate the labels. Default is 'default' | +| `REPO_URL` | If using a non-organization runner this is the full repository url to register under such as 'https://github.com/tiobe/repo' | +| `RUNNER_GROUP` | Name of the runner group to add this runner to (defaults to the default runner group) | +| `GITHUB_HOST` | Optional URL of the Github Enterprise server e.g github.mycompany.com. Defaults to `github.com`. | +| `DISABLE_AUTO_UPDATE` | Optional environment variable to [disable auto updates](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/). Auto updates are enabled by default to preserve past behavior. Any value is considered truthy and will disable them. | \ No newline at end of file diff --git a/entrypoint.ps1 b/entrypoint.ps1 new file mode 100644 index 0000000..8bfe912 --- /dev/null +++ b/entrypoint.ps1 @@ -0,0 +1,130 @@ + +# Set the runner name +if ($null -ne $env:RUNNER_NAME) { + $RUNNER_NAME = $env:RUNNER_NAME +} else { + if ($null -ne $env:RUNNER_NAME_PREFIX) { + $RUNNER_NAME = $env:RUNNER_NAME_PREFIX + } else { + $RUNNER_NAME = "windows-runner" + } + + $RUNNER_NAME += "-" + (((New-Guid).Guid).replace("-", "")).substring(0, 8) +} + +# Set GitHub host if not set +if ($null -ne $env:GITHUB_HOST) { + $GITHUB_HOST = $env:GITHUB_HOST +} else { + $GITHUB_HOST = 'github.com' +} + +# Set the api url +if ('github.com' -eq $GITHUB_HOST) { + $URI = "https://api.$GITHUB_HOST" +} else { + $URI = "https://$GITHUB_HOST/api/v3" +} + +# Set the api to get the access token from +switch ($env:RUNNER_SCOPE) { + org { + if ($null -eq $env:ORG_NAME) { + Write-Error "ORG_NAME required for organisational runners" + exit 1 + } + Write-Host "Setting up GitHub Self Hosted Runner for organisation: $env:ORG_NAME" + $TOKEN_URL = "$URI/orgs/$env:ORG_NAME/actions/runners/registration-token" + $CONFIG_URL = "https://$GITHUB_HOST/$env:ORG_NAME" + } + + enterprise { + if ($null -eq $env:ENTERPRISE_NAME) { + Write-Error "ENTERPRISE_NAME required for enterprise runners" + exit + } + Write-Host "Setting up GitHub Self Hosted Runner for enterprise: $env:ENTERPRISE_NAME" + $TOKEN_URL = "$URI/enterprises/$env:ENTERPRISE_NAME/actions/runners/registration-token" + $CONFIG_URL = "https://$GITHUB_HOST/enterprises/$env:ENTERPRISE_NAME" + } + + default { + if ($null -eq $env:REPO_URL) { + Write-Error "REPO_URL required for repository runners" + exit + } + if ($null -ne $env:RUNNER_TOKEN) { + $RUNNER_TOKEN = $env:RUNNER_TOKEN + } elseif ($null -ne $env:ACCESS_TOKEN) { + $PATTERN = "https://(?:[^/]+/)?([^/]+)/([^/]+)" + if ($env:REPO_URL -match $PATTERN) { + + $OWNER = $Matches[1] + $REPO = $Matches[2] + + $TOKEN_URL = "$URI/repos/$OWNER/$REPO/actions/runners/registration-token" + } else { + Write-Error "URL format not recognized: $env:REPO_URL" + } + } else { + Write-Error "ACCESS_TOKEN or RUNNER_TOKEN required for repository runners" + exit + } + Write-Host "Setting up GitHub Self Hosted Runner for repository: $env:REPO_URL" + + $CONFIG_URL = $env:REPO_URL + } +} + +if ($null -ne $TOKEN_URL) { + $HEADERS = @{ + 'Accept' = 'application/vnd.github.v3+json'; + 'Authorization' = "token $env:ACCESS_TOKEN"; + 'Content-Length' = '0'; + } + + try { + Write-Host "Obtaining the token for the runner" + $RUNNER_TOKEN = ((Invoke-WebRequest -Uri $TOKEN_URL -Method "POST" -Headers $HEADERS).Content | ConvertFrom-Json).token + } + catch { + Write-Error "Cannot obtain the token => $_.Exception.Message" + exit + } +} + +# Set the labels if given +if ($null -ne $env:LABELS) { + $LABELS = $env:LABELS +} else { + $LABELS = 'default' +} + +# Set the labels if given +if ($null -ne $env:RUNNER_GROUP) { + $RUNNER_GROUP = $env:RUNNER_GROUP +} else { + $RUNNER_GROUP = 'Default' +} + +$EXTRA_ARGS='' + +# Disable auto update if set +if ($null -ne $env:DISABLE_AUTO_UPDATE) { + Write-Host "Auto updating is disabled" + $EXTRA_ARGS += " --disableupdate" +} + +try { + Write-Host "Configuring runner: $RUNNER_NAME" + ./config.cmd --unattended --replace --url $CONFIG_URL --token $RUNNER_TOKEN --name $RUNNER_NAME --labels $LABELS --runnergroup $RUNNER_GROUP $EXTRA_ARGS + + # Remove access token for security reasons + $env:ACCESS_TOKEN=$null + + ./run.cmd +} catch { + Write-Error $_.Exception.Message +} finally { + ./config.cmd remove --unattended --token $RUNNER_TOKEN +} \ No newline at end of file diff --git a/install-choco.ps1 b/install-choco.ps1 new file mode 100644 index 0000000..7e99119 --- /dev/null +++ b/install-choco.ps1 @@ -0,0 +1,9 @@ +$securityProtocolSettingsOriginal = [System.Net.ServicePointManager]::SecurityProtocol +try { + [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48 +} +catch { + Write-Warning "Unable to set PowerShell to use TLS 1.2 and TLS 1.1 check .NET Framework installed. If you see underlying connection closed or trust errors, try the following: (1) upgrade to .NET Framework 4.5 (2) specify internal Chocolatey package location (set $env:chocolateyDownloadUrl prior to install or host the package internally), (3) use the Download + PowerShell method of install. See https://chocolatey.org/install for all install options." +} +Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) +[System.Net.ServicePointManager]::SecurityProtocol = $securityProtocolSettingsOriginal \ No newline at end of file diff --git a/install-runner.ps1 b/install-runner.ps1 new file mode 100644 index 0000000..fa0652a --- /dev/null +++ b/install-runner.ps1 @@ -0,0 +1,3 @@ +# (New-Object System.Net.WebClient).DownloadFile("https://github.com/actions/runner/releases/download/v$env:RUNNER_VERSION/actions-runner-win-x64-$env:RUNNER_VERSION.zip","actions-runner.zip") +Invoke-WebRequest -Uri "https://github.com/actions/runner/releases/download/v$env:RUNNER_VERSION/actions-runner-win-x64-$env:RUNNER_VERSION.zip" -OutFile "actions-runner.zip" +Expand-Archive -Path ".\\actions-runner.zip" -DestinationPath '.' \ No newline at end of file