├── .gitignore ├── install-runner.ps1 ├── install-choco.ps1 ├── LICENSE ├── .github └── workflows │ └── publish.yml ├── Dockerfile ├── entrypoint.ps1 └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | docker-compose.yml -------------------------------------------------------------------------------- /install-runner.ps1: -------------------------------------------------------------------------------- 1 | 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" 2 | Expand-Archive -Path ".\\actions-runner.zip" -DestinationPath '.' -------------------------------------------------------------------------------- /install-choco.ps1: -------------------------------------------------------------------------------- 1 | $securityProtocolSettingsOriginal = [System.Net.ServicePointManager]::SecurityProtocol 2 | try { 3 | [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48 4 | } 5 | catch { 6 | 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." 7 | } 8 | Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 9 | [System.Net.ServicePointManager]::SecurityProtocol = $securityProtocolSettingsOriginal -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 TIOBE Software 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | publish: 9 | runs-on: windows-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | - name: Build & push (ltsc2022) 14 | uses: mr-smithers-excellent/docker-build-push@v6 15 | with: 16 | username: ${{ secrets.DOCKERHUB_USERNAME }} 17 | password: ${{ secrets.DOCKERHUB_TOKEN }} 18 | image: tiobesoftware/github-runner-windows 19 | tags: ${{ github.ref_name }}-20H2 20 | registry: docker.io 21 | buildArgs: SERVERCORE_VERSION="ltsc2022",RUNNER_VERSION="${{ github.ref_name }}" 22 | - name: Build & push (20H2) 23 | uses: mr-smithers-excellent/docker-build-push@v6 24 | with: 25 | username: ${{ secrets.DOCKERHUB_USERNAME }} 26 | password: ${{ secrets.DOCKERHUB_TOKEN }} 27 | image: tiobesoftware/github-runner-windows 28 | tags: ${{ github.ref_name }}, latest 29 | registry: docker.io 30 | buildArgs: SERVERCORE_VERSION="20H2",RUNNER_VERSION="${{ github.ref_name }}" 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG SERVERCORE_VERSION="ltsc2022" 2 | ARG RUNNER_VERSION="2.319.1" 3 | 4 | FROM mcr.microsoft.com/windows/servercore:${SERVERCORE_VERSION} 5 | 6 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"] 7 | 8 | # Set working directory 9 | WORKDIR /actions-runner 10 | 11 | COPY install-choco.ps1 . 12 | RUN .\install-choco.ps1; Remove-Item .\install-choco.ps1 -Force 13 | 14 | # Install dependencies with Chocolatey 15 | RUN choco install -y \ 16 | git \ 17 | gh \ 18 | powershell-core \ 19 | docker-cli \ 20 | python 21 | 22 | RUN choco install -y visualstudio2022buildtools --package-parameters \" \ 23 | --quiet --norestart \ 24 | --add Microsoft.VisualStudio.Workload.VisualStudioExtensionBuildTools \ 25 | --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools \ 26 | --add Microsoft.NetCore.Component.SDK \ 27 | --add Microsoft.Net.Component.4.6.1.TargetingPack \ 28 | --add Microsoft.Net.Component.4.8.TargetingPack \ 29 | \" 30 | 31 | # Add MSBuild to the path 32 | RUN [Environment]::SetEnvironmentVariable(\"Path\", $env:Path + \";C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\", \"Machine\") 33 | 34 | COPY install-runner.ps1 . 35 | RUN .\install-runner.ps1; Remove-Item .\install-runner.ps1 -Force 36 | 37 | COPY entrypoint.ps1 . 38 | 39 | ENTRYPOINT ["pwsh.exe", ".\\entrypoint.ps1"] -------------------------------------------------------------------------------- /entrypoint.ps1: -------------------------------------------------------------------------------- 1 | 2 | # Set the runner name 3 | if ($null -ne $env:RUNNER_NAME) { 4 | $RUNNER_NAME = $env:RUNNER_NAME 5 | } else { 6 | if ($null -ne $env:RUNNER_NAME_PREFIX) { 7 | $RUNNER_NAME = $env:RUNNER_NAME_PREFIX 8 | } else { 9 | $RUNNER_NAME = "windows-runner" 10 | } 11 | 12 | $RUNNER_NAME += "-" + (((New-Guid).Guid).replace("-", "")).substring(0, 8) 13 | } 14 | 15 | # Set GitHub host if not set 16 | if ($null -ne $env:GITHUB_HOST) { 17 | $GITHUB_HOST = $env:GITHUB_HOST 18 | } else { 19 | $GITHUB_HOST = 'github.com' 20 | } 21 | 22 | # Set the api url 23 | if ('github.com' -eq $GITHUB_HOST) { 24 | $URI = "https://api.$GITHUB_HOST" 25 | } else { 26 | $URI = "https://$GITHUB_HOST/api/v3" 27 | } 28 | 29 | # Set the api to get the access token from 30 | switch ($env:RUNNER_SCOPE) { 31 | org { 32 | if ($null -eq $env:ORG_NAME) { 33 | Write-Error "ORG_NAME required for organisational runners" 34 | exit 1 35 | } 36 | Write-Host "Setting up GitHub Self Hosted Runner for organisation: $env:ORG_NAME" 37 | $TOKEN_URL = "$URI/orgs/$env:ORG_NAME/actions/runners/registration-token" 38 | $CONFIG_URL = "https://$GITHUB_HOST/$env:ORG_NAME" 39 | } 40 | 41 | enterprise { 42 | if ($null -eq $env:ENTERPRISE_NAME) { 43 | Write-Error "ENTERPRISE_NAME required for enterprise runners" 44 | exit 45 | } 46 | Write-Host "Setting up GitHub Self Hosted Runner for enterprise: $env:ENTERPRISE_NAME" 47 | $TOKEN_URL = "$URI/enterprises/$env:ENTERPRISE_NAME/actions/runners/registration-token" 48 | $CONFIG_URL = "https://$GITHUB_HOST/enterprises/$env:ENTERPRISE_NAME" 49 | } 50 | 51 | default { 52 | if ($null -eq $env:REPO_URL) { 53 | Write-Error "REPO_URL required for repository runners" 54 | exit 55 | } 56 | if ($null -ne $env:RUNNER_TOKEN) { 57 | $RUNNER_TOKEN = $env:RUNNER_TOKEN 58 | } elseif ($null -ne $env:ACCESS_TOKEN) { 59 | $PATTERN = "https://(?:[^/]+/)?([^/]+)/([^/]+)" 60 | if ($env:REPO_URL -match $PATTERN) { 61 | 62 | $OWNER = $Matches[1] 63 | $REPO = $Matches[2] 64 | 65 | $TOKEN_URL = "$URI/repos/$OWNER/$REPO/actions/runners/registration-token" 66 | } else { 67 | Write-Error "URL format not recognized: $env:REPO_URL" 68 | } 69 | } else { 70 | Write-Error "ACCESS_TOKEN or RUNNER_TOKEN required for repository runners" 71 | exit 72 | } 73 | Write-Host "Setting up GitHub Self Hosted Runner for repository: $env:REPO_URL" 74 | 75 | $CONFIG_URL = $env:REPO_URL 76 | } 77 | } 78 | 79 | if ($null -ne $TOKEN_URL) { 80 | $HEADERS = @{ 81 | 'Accept' = 'application/vnd.github.v3+json'; 82 | 'Authorization' = "token $env:ACCESS_TOKEN"; 83 | 'Content-Length' = '0'; 84 | } 85 | 86 | try { 87 | Write-Host "Obtaining the token for the runner" 88 | $RUNNER_TOKEN = ((Invoke-WebRequest -Uri $TOKEN_URL -Method "POST" -Headers $HEADERS).Content | ConvertFrom-Json).token 89 | } 90 | catch { 91 | Write-Error "Cannot obtain the token => $_" 92 | exit 93 | } 94 | } 95 | 96 | # Set the labels if given 97 | if ($null -ne $env:LABELS) { 98 | $LABELS = $env:LABELS 99 | } else { 100 | $LABELS = 'default' 101 | } 102 | 103 | # Set the labels if given 104 | if ($null -ne $env:RUNNER_GROUP) { 105 | $RUNNER_GROUP = $env:RUNNER_GROUP 106 | } else { 107 | $RUNNER_GROUP = 'Default' 108 | } 109 | 110 | $EXTRA_ARGS='' 111 | 112 | # Disable auto update if set 113 | if ($null -ne $env:DISABLE_AUTO_UPDATE) { 114 | Write-Host "Auto updating is disabled" 115 | $EXTRA_ARGS += " --disableupdate" 116 | } 117 | 118 | try { 119 | Write-Host "Configuring runner: $RUNNER_NAME" 120 | ./config.cmd --unattended --replace --url $CONFIG_URL --token $RUNNER_TOKEN --name $RUNNER_NAME --labels $LABELS --runnergroup $RUNNER_GROUP $EXTRA_ARGS 121 | 122 | # Remove access token for security reasons 123 | $env:ACCESS_TOKEN=$null 124 | 125 | ./run.cmd 126 | } catch { 127 | Write-Error $_.Exception.Message 128 | } finally { 129 | ./config.cmd remove --unattended --token $RUNNER_TOKEN 130 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows Docker GitHub Runner 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | The build images can be found on [Docker Hub](https://hub.docker.com/r/tiobesoftware/github-runner-windows). 8 | 9 | ## Environment variables 10 | 11 | | Environment Variable | Description | 12 | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 13 | | `RUNNER_NAME` | The name of the runner to use. Overrides `RUNNER_NAME_PREFIX` | 14 | | `RUNNER_NAME_PREFIX` | A prefix for runner name. Note: will be overridden by `RUNNER_NAME` if provided. Defaults to `windows-runner` | 15 | | `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` | 16 | | `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. | 17 | | `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'. | 18 | | `ORG_NAME` | The organization name for the runner to register under. Requires `RUNNER_SCOPE` to be 'org'. No default value. | 19 | | `ENTERPRISE_NAME` | The enterprise name for the runner to register under. Requires `RUNNER_SCOPE` to be 'enterprise'. No default value. | 20 | | `LABELS` | A comma separated string to indicate the labels. Default is 'default' | 21 | | `REPO_URL` | If using a non-organization runner this is the full repository url to register under such as 'https://github.com/tiobe/repo' | 22 | | `RUNNER_GROUP` | Name of the runner group to add this runner to (defaults to the default runner group) | 23 | | `GITHUB_HOST` | Optional URL of the Github Enterprise server e.g github.mycompany.com. Defaults to `github.com`. | 24 | | `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. | 25 | --------------------------------------------------------------------------------