├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── servercore_container_build.yaml ├── .gitignore ├── Dockerfile ├── Dockerfile-example ├── LICENSE ├── README.md └── entrypoint.ps1 /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/servercore_container_build.yaml: -------------------------------------------------------------------------------- 1 | name: Servercore Container Build and Push 2 | 3 | on: 4 | push: 5 | tags: 6 | - v1.* 7 | 8 | jobs: 9 | build-and-deploy: 10 | runs-on: windows-2019 11 | env: 12 | RUNNER_VERSION: 2.291.1 13 | 14 | steps: 15 | - name: Checkout source code 16 | uses: actions/checkout@v2 17 | 18 | - name: Login to GitHub Container Registry 19 | uses: docker/login-action@v2 20 | with: 21 | registry: ghcr.io 22 | username: ${{ github.actor }} 23 | password: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | - name: Build the Dockerfile 26 | run: docker build -t ghcr.io/antgrutta/winrunner:${{ github.ref_name }} --build-arg RUNNER_VERSION=${{env.RUNNER_VERSION}} . 27 | 28 | - name: Push to GitHub Container Registry 29 | run: docker push ghcr.io/antgrutta/winrunner:${{ github.ref_name }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gitignore 2 | scratch.txt 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/windows/servercore:ltsc2019 2 | 3 | LABEL org.opencontainers.image.authors Anthony Grutta 4 | LABEL org.opencontainers.image.title Windows Runner Container 5 | LABEL org.opencontainers.image.description This image is a base image for the GitHub Self-Hosted runner for the Windows platform. 6 | LABEL org.opencontainers.image.source https://github.com/antgrutta/windows-runner-container 7 | LABEL org.opencontainers.image.documentation https://github.com/antgrutta/windows-runner-container/README.md 8 | 9 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"] 10 | 11 | ARG RUNNER_VERSION=VERSION 12 | 13 | # Install latest PowerShell 14 | RUN Invoke-WebRequest -Uri 'https://aka.ms/install-powershell.ps1' -OutFile install-powershell.ps1; ./install-powershell.ps1 -AddToPath 15 | 16 | # Install GitHub Runner 17 | RUN Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v$env:RUNNER_VERSION/actions-runner-win-x64-$env:RUNNER_VERSION.zip -OutFile runner.zip 18 | RUN Expand-Archive -Path $pwd/runner.zip -DestinationPath C:/actions-runner 19 | 20 | ADD entrypoint.ps1 entrypoint.ps1 21 | 22 | CMD [ "pwsh", ".\\entrypoint.ps1"] 23 | -------------------------------------------------------------------------------- /Dockerfile-example: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/antgrutta/winrunner:latest 2 | 3 | LABEL org.opencontainers.image.authors Anthony Grutta 4 | LABEL org.opencontainers.image.title Windows Runner Container 5 | LABEL org.opencontainers.image.description This image uses the base image for the GitHub Self-Hosted runner for the Windows platform and includes extra tools that can be used in Actions. 6 | LABEL org.opencontainers.image.source https://github.com/antgrutta/windows-runner-container 7 | LABEL org.opencontainers.image.documentation https://github.com/antgrutta/windows-runner-container/README.md 8 | 9 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"] 10 | 11 | # Install Scoop 12 | 13 | RUN Invoke-WebRequest -Uri get.scoop.sh -OutFile 'install-scoop.ps1'; .\install-scoop.ps1 -RunAsAdmin 14 | 15 | # Install various packages and utilities 16 | 17 | RUN scoop install git 18 | 19 | ## Workaround for https://github.com/ScoopInstaller/Scoop/issues/4917 20 | 21 | RUN scoop bucket rm main 22 | RUN scoop bucket add main 23 | RUN scoop install azure-cli 24 | 25 | # Install MS Build Tools 26 | 27 | RUN Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_buildtools.exe -OutFile vs_buildtools.exe 28 | 29 | ## Install Build Tools with the Microsoft.VisualStudio.Workload.AzureBuildTools workload, excluding workloads and components with known issues. 30 | 31 | RUN ./vs_buildtools.exe --quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.AzureBuildTools --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 --remove Microsoft.VisualStudio.Component.Windows81SDK 32 | 33 | ## Cleanup 34 | 35 | RUN Remove-Item vs_buildtools.exe 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Anthony Grutta 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub Self-Hosted Runner Windows Container 2 | 3 | This project aims to create a self-hosted runner for GitHub Actions using Windows containers that is compatible with the [actions-runner-controller](https://github.com/actions-runner-controller/actions-runner-controller). 4 | 5 | ## Getting Started 6 | 7 | I used [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/) for developing this solution. While I am sure all this can be done with other flavors of Kubernetes, this documentation will be AKS focused. 8 | 9 | ### Prerequisites 10 | 11 | - A Kubernetes cluster with a Windows node pool using `conatinerd`, [AKS and containerd](https://docs.microsoft.com/en-us/azure-stack/aks-hci/use-containerd-on-windows-aks). 12 | - A working install of the [actions-runner-controller](https://github.com/actions-runner-controller/actions-runner-controller). 13 | - A container repository for Kubernetes to retrieve the image from ([GitHub Packages](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry), [Azure Container Registry](https://docs.microsoft.com/en-us/azure/container-registry/), [Docker Hub](https://hub.docker.com/)). 14 | 15 | ### Building Locally 16 | 17 | Ensure you have [Docker Desktop installed](https://docs.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment?tabs=Windows-10-and-11) on your Windows machine. 18 | 19 | Using the included `Dockerfile`, include the `RUNNER_VERSION` in the `docker build` command. 20 | 21 | ``` 22 | docker build -t winrunner --build-arg RUNNER_VERSION= . 23 | ``` 24 | 25 | ## Using the Image with the Runner Controller 26 | 27 | An example `RunnerDeployment` using the image, given this is a Windows-based container you may need to add whatever tolerations and or labels you are using to select your Kubernetes Windows node pool: 28 | 29 | ``` 30 | apiVersion: actions.summerwind.dev/v1alpha1 31 | kind: RunnerDeployment 32 | metadata: 33 | name: example-org-win-runner 34 | spec: 35 | replicas: 2 36 | template: 37 | spec: 38 | image: ghcr.io/antgrutta/winrunner:latest 39 | dockerdWithinRunnerContainer: true 40 | organization: antgrutta 41 | ``` 42 | 43 | ### Adding to the container 44 | 45 | The file `Dockerfile-example` is included in the repository to demonstrate how one might add some common tooling to the container to make it more useful. 46 | 47 | ## Contributing 48 | 49 | Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated. 50 | 51 | If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again! 52 | 53 | - Fork the Project 54 | - Create your Feature Branch (git checkout -b feature/AmazingFeature) 55 | - Commit your Changes (git commit -m 'Add some AmazingFeature') 56 | - Push to the Branch (git push origin feature/AmazingFeature) 57 | - Open a Pull Request 58 | 59 | ## Acknowledgements 60 | 61 | This project was inspired by the excellent work of others, this list contains links to the original projects/articles used in creating this project. 62 | 63 | - [actions-runner-controller](https://github.com/actions-runner-controller/actions-runner-controller) 64 | - [docker-github-self-hosted-runner](https://github.com/rajyraman/docker-github-self-hosted-runner) 65 | - [Dockerized self-hosted runner on Windows](https://github.com/shivammathur/setup-php/wiki/Dockerized-self-hosted-runner-on-Windows) 66 | - [GitHub Self-Hosted Runner inside a container](https://dreamingincrm.com/2020/12/02/github-self-hosted-runner-inside-a-container/) 67 | -------------------------------------------------------------------------------- /entrypoint.ps1: -------------------------------------------------------------------------------- 1 | $CONFIG_CMD = "C:\actions-runner\config.cmd" 2 | $CONFIG_OPTIONS = "--unattended --replace --token $env:RUNNER_TOKEN" 3 | 4 | if (-not [Environment]::GetEnvironmentVariable('GITHUB_URL')){ 5 | $GITHUB_URL = "https://github.com/" 6 | }else{ 7 | $GITHUB_URL = [Environment]::GetEnvironmentVariable('GITHUB_URL') 8 | } 9 | 10 | if ([Environment]::GetEnvironmentVariable('RUNNER_ORG') -and [Environment]::GetEnvironmentVariable('RUNNER_REPO') -and [Environment]::GetEnvironmentVariable('RUNNER_ENTERPRISE')){ 11 | $CONFIG_OPTIONS += " --url ${GITHUB_URL}${env:RUNNER_ORG}/$env:RUNNER_REPO" 12 | } elseif ([Environment]::GetEnvironmentVariable('RUNNER_ORG')) { 13 | $CONFIG_OPTIONS += " --url ${GITHUB_URL}${env:RUNNER_ORG}" 14 | } elseif ([Environment]::GetEnvironmentVariable('RUNNER_REPO')) { 15 | $CONFIG_OPTIONS += " --url ${GITHUB_URL}${env:RUNNER_REPO}" 16 | } elseif ([Environment]::GetEnvironmentVariable('RUNNER_ENTERPRISE')) { 17 | $CONFIG_OPTIONS += " --url ${GITHUB_URL}enterprises/$env:RUNNER_ENTERPRISE" 18 | } 19 | 20 | if ([Environment]::GetEnvironmentVariable('RUNNER_NAME')){ 21 | $CONFIG_OPTIONS += " --name $env:RUNNER_NAME" 22 | } else { 23 | $CONFIG_OPTIONS += " --name windows-container-runner" 24 | } 25 | 26 | if (-not [Environment]::GetEnvironmentVariable('RUNNER_GROUP')){ 27 | $CONFIG_OPTIONS += " --runnergroup Default" 28 | } else { 29 | $CONFIG_OPTIONS += " --runnergroup $env:RUNNER_GROUP" 30 | } 31 | 32 | if ([Environment]::GetEnvironmentVariable('RUNNER_EPHEMERAL')){ 33 | $CONFIG_OPTIONS += " --ephemeral" 34 | } 35 | 36 | if ([Environment]::GetEnvironmentVariable('RUNNER_LABELS')){ 37 | $CONFIG_OPTIONS += " --labels '$env:RUNNER_LABELS'" 38 | } 39 | 40 | Invoke-Expression "$CONFIG_CMD $CONFIG_OPTIONS" 41 | 42 | .\actions-runner\run.cmd; 43 | --------------------------------------------------------------------------------