Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Docker Image Build

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: "0 1 * * *"
workflow_dispatch:
Comment on lines +3 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These triggers are pretty frequent and overlapping.

  • Is a schedule even needed? How about once a week instead of daily?
  • Is pull_request needed? We shouldn't push "latest" images on unreviewed code, but checking that the image builds successfully is useful.


permissions:
contents: read
packages: write
id-token: write

env:
REGISTRY: ghcr.io
IMAGE_NAME: nod-ai/arc-windows-runner

jobs:
build:
runs-on: windows-latest

steps:
- uses: actions/checkout@v4
Comment on lines +22 to +26
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to pin runners and actions to specific versions so they don't change outside of our control

Suggested change
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
build:
runs-on: windows-2022
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember seeing warnings about changes to Windows runners over the past few months on GitHub. I see the job on this PR failed due to lack of disk space. This could be related. I'll try to dig up info after I finish eating.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. Looks like they swapped from 2022 to 2025, and the job was last run months ago. Probably is a good idea to be fixed to the 2022 runner.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

windows-2025 is also fine with me (if it works)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am assuming windows-latest (i.e., 2022) did not run into the disk space error the last time Elias ran this workflow. I see others complaining about disk space with 2025 runners: actions/runner-images#12609

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I didn't see the disc space errors before


- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# BuildX is not supported and should not be installed or configured
# Features such as multistage builds and cache support are not available
- name: Get Versions
id: versions
env:
AUTH: Bearer ${{ github.token }}
REPO_OWNER: ${{ github.event.repository.owner.login }}
REPO_NAME: ${{ github.event.repository.name }}
REPO_ORG: ${{ github.event.organization.login }}
run: |
$repoOwner = $env:REPO_OWNER
$repoName = $env:REPO_NAME
$orgName = $env:REPO_ORG

# The URL is different for personal or organization endpoints, so resolve the correct one
# The org variable should be non-empty and match the owner name if this is an organization.
$packageUrl = ($repoOwner -eq $orgName) ? "https://api.github.com/orgs/$repoOwner/packages/container/$repoName/versions" : "https://api.github.com/users/$repoOwner/packages/container/$repoName/versions"

# PowerShell 7 syntax to avoid raising an exception.
$apiResults = Invoke-WebRequest -Headers @{ "Authorization"=$env:AUTH } -Uri $packageUrl -SkipHttpErrorCheck
if ($apiResults.StatusCode -eq 200) {
$content = $apiResults.Content | ConvertFrom-Json
}
elseif ($apiResults.StatusCode -eq 404) {
$content = @()
}
else {
Write-Host "Status Code: ${apiResults.StatusCode}"
Write-Host "Error: ${apiResults.Content}"
exit $apiResults.StatusCode
}

$publishedImageVersions = $($apiResults.Content | ConvertFrom-Json) | %{ [PSCustomObject]@{ Id=$_.id; Url=$_.url;Tags=$_.metadata.container.tags } } | %{ $_.tags }
$currentRunnerVersion = ((Invoke-WebRequest -Uri https://api.github.com/repos/actions/runner/releases/latest).Content | ConvertFrom-Json).tag_name -replace 'v',''
$currentHooksVersion = ((Invoke-WebRequest -Uri https://api.github.com/repos/actions/runner-container-hooks/releases/latest).Content | ConvertFrom-Json).tag_name -replace 'v',''

# Convert the values to step outputs
echo "PUBLISHED=$($publishedImageVersions -Contains "v${currentRunnerVersion}")" >> ${env:GITHUB_OUTPUT}
echo "RUNNER_VERSION=${currentRunnerVersion}" >> ${env:GITHUB_OUTPUT}
echo "RUNNER_HOOKS_VERSION=${currentHooksVersion}" >> ${env:GITHUB_OUTPUT}

# Output details to the step summary
echo "**Current Runner version :** v${currentRunnerVersion}" >> ${env:GITHUB_STEP_SUMMARY}
echo "**Current Runner hooks version:** v${currentHooksVersion}" >> ${env:GITHUB_STEP_SUMMARY}
echo "**Published New Image:** $($publishedImageVersions -Contains "v${currentRunnerVersion}")" >> ${env:GITHUB_STEP_SUMMARY}
- name: Docker Build
#if: ${{ steps.versions.outputs.PUBLISHED != 'True' }}
env:
RUNNER_VERSION: ${{ steps.versions.outputs.RUNNER_VERSION }}
RUNNER_HOOKS_VERSION: ${{ steps.versions.outputs.RUNNER_HOOKS_VERSION }}
run: |
$currentRunnerVersion = $env:RUNNER_VERSION
$currentHooksVersion = $env:RUNNER_HOOKS_VERSION
docker build --build-arg RUNNER_CONTAINER_HOOKS_VERSION=$currentHooksVersion --build-arg RUNNER_VERSION=$currentRunnerVersion -f windows-arc-runner/Dockerfile -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:"v${currentRunnerVersion}" .
- name: Docker Push
#if: ${{ github.event_name != 'pull_request' && steps.versions.outputs.PUBLISHED != 'True' }}
run: |
docker push -a ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
Comment on lines +90 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uncomment? Pull request triggers should not publish (at least without some label marking them as dev builds and not "latest" / "prod"



115 changes: 115 additions & 0 deletions windows-arc-runner/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# escape=`

FROM mcr.microsoft.com/windows/servercore:ltsc2022
ARG RUNNER_OS=win
ARG RUNNER_ARCH=x64
ARG RUNNER_VERSION
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.6.1

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"]

WORKDIR /home/runner

SHELL ["cmd", "/C"]

RUN setx /M PATH "%PATH%;C:/home/runner"

RUN echo $Env:PATH

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"]

RUN `
###############################################################################################
# Install Actions Runner
# You must always install the runner, and you want the latest version to avoid the restrictions
# applied to out-of-date runners.
# https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/autoscaling-with-self-hosted-runners#:~:text=Warning,-Any%20updates%20released
###############################################################################################
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v${env:RUNNER_VERSION}/actions-runner-${env:RUNNER_OS}-${env:RUNNER_ARCH}-${env:RUNNER_VERSION}.zip -OutFile actions-runner.zip;`
Add-Type -AssemblyName System.IO.Compression.FileSystem;`
[System.IO.Compression.ZipFile]::ExtractToDirectory('actions-runner.zip', $PWD);`
Remove-Item -Path actions-runner.zip -Force;`
###############################################################################################
# Install Runner Container Hooks
# While it is possible to include these hooks, Windows runners can't use these today.
# GitHub documents that you must use Linux runners for Docker container actions, job containers,
# or service containers.
# See also https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idservices
# and https://github.com/actions/runner/issues/904
###############################################################################################
# Invoke-WebRequest -OutFile runner-container-hooks.zip -Uri https://github.com/actions/runner-container-hooks/releases/download/v${env:RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${env:RUNNER_CONTAINER_HOOKS_VERSION}.zip;`
# [System.IO.Compression.ZipFile]::ExtractToDirectory('runner-container-hooks.zip', (Join-Path -Path $PWD -ChildPath 'k8s'));`
# Remove-Item -Path runner-container-hooks.zip -Force;`
###############################################################################################
# Install Git Using Choco
# Runners should have access to the latest version of Git and Git LFS, which we can
# install using Choco. This also makes a Bash shell available on Windows for scripting.
# You may want to include other tools and script engines as well.
###############################################################################################
Set-ExecutionPolicy Bypass -Scope Process -Force;`
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;`
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));`
choco install -y git.install gh powershell-core azure-cli;`
choco feature enable -n allowGlobalConfirmation;`
###############################################################################################
# Install Docker CLI Using Choco
# It's important to know that Windows doesn't support nested containers, so you can't
# use a Docker-in-Docker on Windows. That frequently limits the value of having the
# Docker CLI available on your images.
###############################################################################################
choco install docker-cli docker-compose -force;

# Append Git\bin to $PATH so bash.exe can be used.
RUN setx /M PATH $($Env:PATH + ';C:\Program Files\Git\bin')

RUN New-ItemProperty -Path "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force

# Download vswhere.exe from the official GitHub releases
RUN Invoke-WebRequest -Uri "https://github.com/microsoft/vswhere/releases/download/2.8.4/vswhere.exe" -OutFile "vswhere.exe"

RUN .\vswhere.exe
RUN vswhere
# Set the entrypoint to cmd.exe so you can run vswhere

# Restore the default Windows shell for correct batch processing.
SHELL ["cmd", "/S", "/C"]

RUN `
# Download the Build Tools bootstrapper.
curl -SL --output vs_buildtools.exe https://aka.ms/vs/17/release/vs_buildtools.exe `
`
# Install Build Tools with the Microsoft.VisualStudio.Workload.AzureBuildTools workload, excluding workloads and components with known issues.
&& (start /w vs_buildtools.exe --quiet --wait --norestart --nocache `
--installPath "%ProgramFiles(x86)%\Microsoft Visual Studio\2022\BuildTools" `
--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 `
|| IF "%ERRORLEVEL%"=="3010" EXIT 0) `
`
# Cleanup
&& del /q vs_buildtools.exe

# Define the entry point for the docker container.
# This entry point starts the developer command prompt and launches the PowerShell shell.
RUN choco install cmake --version=3.31.0 -y --no-progress --installargs '"ADD_CMAKE_TO_PATH=System"'
RUN choco install python -y --no-progress
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to pin the Python version here so it doesn't update when the dockerfile is rebuilt

RUN python -m pip install --upgrade certifi
RUN setx SSL_CERT_FILE "C:\Users\ContainerAdministrator\AppData\Local\Programs\Python\Python310\Lib\site-packages\certifi\cacert.pem"
RUN certutil -generateSSTFromWU certs.sst
RUN certutil -addstore -f ROOT certs.sst
RUN del certs.sst
RUN choco install visualstudio2022-workload-vctools "--add Microsoft.VisualStudio.Component.ATL" -y --no-progress
RUN python -m pip install setuptools
RUN choco install visualstudio2022buildtools -y
RUN choco install visualstudio2022community --package-parameters "--add Microsoft.VisualStudio.Workload.CoreEditor --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.DesktopDevelopmentWithC++" -y
RUN choco install visualstudio2022-workload-nativedesktop -y
RUN git clone https://github.com/microsoft/vcpkg.git C:\vcpkg `
&& cd C:\vcpkg `
&& bootstrap-vcpkg.bat `
&& SETX /M PATH "C:\vcpkg;%PATH%" `
&& vcpkg install zlib:x64-windows --clean-after-build `
&& vcpkg remove zlib:x64-windows

ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
38 changes: 38 additions & 0 deletions windows-arc-runner/scripts/Cleanup-Runners.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#This script invokes GitHub-CLI (Pre-installed on container image)
Param (
[Parameter(Mandatory = $false)]
[string]$owner = $env:GH_OWNER,
[Parameter(Mandatory = $false)]
[string]$repo = $env:GH_REPOSITORY,
[Parameter(Mandatory = $false)]
[string]$pat = $env:GH_TOKEN
)

#Use --with-token to pass in a PAT token on standard input. The minimum required scopes for the token are: "repo", "read:org".
#Alternatively, gh will use the authentication token found in environment variables. See gh help environment for more info.
#To use gh in GitHub Actions, add GH_TOKEN: $ to "env". on Docker run: Docker run -e GH_TOKEN='myPatToken'
gh auth login --with-token $pat

#Cleanup#
#Look for any old/stale dockerNode- registrations to clean up
#Windows containers cannot gracefully remove registration via powershell due to issue: https://github.com/moby/moby/issues/25982#
#For this reason we can use this scrip to cleanup old offline instances/registrations
$runnerBaseName = "dockerNode-"
$runnerListJson = gh api -H "Accept: application/vnd.github.v3+json" "/repos/$owner/$repo/actions/runners"
$runnerList = (ConvertFrom-Json -InputObject $runnerListJson).runners

Foreach ($runner in $runnerList) {
try {
If (($runner.name -like "$runnerBaseName*") -and ($runner.status -eq "offline")) {
write-host "Unregsitering old stale runner: $($runner.name)"
gh api --method DELETE -H "Accept: application/vnd.github.v3+json" "/repos/$owner/$repo/actions/runners/$($runner.id)"
}
}
catch {
Write-Error $_.Exception.Message
}
}

#Remove PAT token after cleanup
$pat=$null
$env:GH_TOKEN=$null
13 changes: 13 additions & 0 deletions windows-arc-runner/scripts/Install-Choco.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
$securityProtocolSettingsOriginal = [System.Net.ServicePointManager]::SecurityProtocol
try {
# Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48)
# Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won’t
# exist in .NET 4.0, even though they are addressable if .NET 4.5+ is
# installed (.NET 4.5 is an in-place upgrade).
[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
43 changes: 43 additions & 0 deletions windows-arc-runner/scripts/start.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#This script invokes GitHub-CLI (Already installed on container image)
#To use this entrypoint script run: Docker run -e GH_TOKEN='myPatToken' -e GH_OWNER='orgName' -e GH_REPOSITORY='repoName' -d imageName
Param (
[Parameter(Mandatory = $false)]
[string]$owner = $env:GH_OWNER,
[Parameter(Mandatory = $false)]
[string]$repo = $env:GH_REPOSITORY,
[Parameter(Mandatory = $false)]
[string]$pat = $env:GH_TOKEN
)

#Use --with-token to pass in a PAT token on standard input. The minimum required scopes for the token are: "repo", "read:org".
#Alternatively, gh will use the authentication token found in environment variables. See gh help environment for more info.
#To use gh in GitHub Actions, add GH_TOKEN: $ to "env". on Docker run: Docker run -e GH_TOKEN='myPatToken'
gh auth login

#Get Runner registration Token
$jsonObj = gh api --method POST -H "Accept: application/vnd.github.v3+json" "/repos/$owner/$repo/actions/runners/registration-token"
$regToken = (ConvertFrom-Json -InputObject $jsonObj).token
$runnerBaseName = "dockerNode-"
$runnerName = $runnerBaseName + (((New-Guid).Guid).replace("-", "")).substring(0, 5)

try {
#Register new runner instance
write-host "Registering GitHub Self Hosted Runner on: $owner/$repo"
./config.cmd --unattended --url "https://github.com/$owner/$repo" --token $regToken --name $runnerName

#Remove PAT token after registering new instance
$pat=$null
$env:GH_TOKEN=$null

#Start runner listener for jobs
./run.cmd
}
catch {
Write-Error $_.Exception.Message
}
finally {
# Trap signal with finally - cleanup (When docker container is stopped remove runner registration from GitHub)
# Does not currently work due to issue: https://github.com/moby/moby/issues/25982#
# Perform manual cleanup of stale runners using Cleanup-Runners.ps1
./config.cmd remove --unattended --token $regToken
}
Loading