From 8988ab72063c21ad5c1e65e3484d51d7b2c23535 Mon Sep 17 00:00:00 2001
From: Dennis Ameling <dennis@dennisameling.com>
Date: Tue, 3 Nov 2020 15:15:46 +0100
Subject: [PATCH] Add support for Windows arm64

---
 .github/workflows/build.yml                    |  8 ++++++--
 .github/workflows/release.yml                  | 18 ++++++++++++++++--
 releaseNote.md                                 | 14 ++++++++++++++
 src/Directory.Build.props                      |  3 +++
 src/Misc/externals.sh                          | 10 ++++++++++
 src/Runner.Common/Runner.Common.csproj         |  2 +-
 src/Runner.Listener/Runner.Listener.csproj     |  2 +-
 src/Runner.PluginHost/Runner.PluginHost.csproj |  2 +-
 src/Runner.Plugins/Runner.Plugins.csproj       |  2 +-
 src/Runner.Sdk/Runner.Sdk.csproj               |  2 +-
 src/Runner.Worker/Runner.Worker.csproj         |  2 +-
 src/Sdk/Sdk.csproj                             |  2 +-
 src/Test/L0/ConstantGenerationL0.cs            |  1 +
 src/Test/Test.csproj                           |  2 +-
 src/dev.sh                                     |  9 ++++++---
 src/dir.proj                                   | 10 +++++-----
 16 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f96185c34ac..d7795e250d4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -18,7 +18,7 @@ jobs:
   build:
     strategy:
       matrix:
-        runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
+        runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64 ]
         include:
         - runtime: linux-x64
           os: ubuntu-latest
@@ -40,6 +40,10 @@ jobs:
           os: windows-latest
           devScript: ./dev
 
+        - runtime: win-arm64
+          os: windows-latest
+          devScript: ./dev
+
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v1
@@ -55,7 +59,7 @@ jobs:
       run: |
         ${{ matrix.devScript }} test
       working-directory: src
-      if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
+      if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'win-arm64'
 
     # Create runner package tar.gz/zip
     - name: Package Release
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 739e1dc59d2..1151e92e8fc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -53,7 +53,7 @@ jobs:
       osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
     strategy:
       matrix:
-        runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
+        runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64 ]
         include:
         - runtime: linux-x64
           os: ubuntu-latest
@@ -75,6 +75,10 @@ jobs:
           os: windows-latest
           devScript: ./dev
 
+        - runtime: win-arm64
+          os: windows-latest
+          devScript: ./dev
+
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v1
@@ -90,7 +94,7 @@ jobs:
       run: |
         ${{ matrix.devScript }} test
       working-directory: src
-      if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
+      if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'win-arm64'
 
     # Create runner package tar.gz/zip
     - name: Package Release
@@ -176,6 +180,16 @@ jobs:
         asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
         asset_content_type: application/octet-stream
 
+    - name: Upload Release Asset (win-arm64)
+      uses: actions/upload-release-asset@v1.0.1
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.createRelease.outputs.upload_url }}
+        asset_path: ${{ github.workspace }}/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
+        asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
+        asset_content_type: application/octet-stream
+
     - name: Upload Release Asset (linux-x64)
       uses: actions/upload-release-asset@v1.0.1
       env:
diff --git a/releaseNote.md b/releaseNote.md
index 3a2ef201184..d1011923084 100644
--- a/releaseNote.md
+++ b/releaseNote.md
@@ -29,6 +29,20 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem ;
 [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
 ```
 
+## Windows arm64 (Pre-release)
+We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
+
+The following snipped needs to be run on `powershell`:
+``` powershell
+# Create a folder under the drive root
+mkdir \actions-runner ; cd \actions-runner
+# Download the latest runner package
+Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-arm64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-arm64-<RUNNER_VERSION>.zip
+# Extract the installer
+Add-Type -AssemblyName System.IO.Compression.FileSystem ; 
+[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-arm64-<RUNNER_VERSION>.zip", "$PWD")
+```
+
 ## OSX
 
 ``` bash
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 71e570e08d7..7ebc436f15a 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -24,6 +24,9 @@
   <PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
     <DefineConstants>$(DefineConstants);X86</DefineConstants>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-arm64'">
+    <DefineConstants>$(DefineConstants);ARM64</DefineConstants>
+  </PropertyGroup>
 
   <PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
     <DefineConstants>$(DefineConstants);X64</DefineConstants>
diff --git a/src/Misc/externals.sh b/src/Misc/externals.sh
index fe7a74b9a0d..1e545d4c002 100755
--- a/src/Misc/externals.sh
+++ b/src/Misc/externals.sh
@@ -134,6 +134,16 @@ if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
     fi
 fi
 
+if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
+    acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
+    acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
+    acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
+    acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
+    if [[ "$PRECACHE" != "" ]]; then
+        acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
+    fi
+fi
+
 # Download the external tools only for OSX.
 if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
     acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
diff --git a/src/Runner.Common/Runner.Common.csproj b/src/Runner.Common/Runner.Common.csproj
index bf55ea845da..62a1352293a 100644
--- a/src/Runner.Common/Runner.Common.csproj
+++ b/src/Runner.Common/Runner.Common.csproj
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Library</OutputType>
-    <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
     <NoWarn>NU1701;NU1603</NoWarn>
     <Version>$(Version)</Version>
diff --git a/src/Runner.Listener/Runner.Listener.csproj b/src/Runner.Listener/Runner.Listener.csproj
index e4266ad8dbd..3efdeb32b58 100644
--- a/src/Runner.Listener/Runner.Listener.csproj
+++ b/src/Runner.Listener/Runner.Listener.csproj
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Exe</OutputType>
-    <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
     <NoWarn>NU1701;NU1603</NoWarn>
     <Version>$(Version)</Version>
diff --git a/src/Runner.PluginHost/Runner.PluginHost.csproj b/src/Runner.PluginHost/Runner.PluginHost.csproj
index e6625dc3ece..33c626579ac 100644
--- a/src/Runner.PluginHost/Runner.PluginHost.csproj
+++ b/src/Runner.PluginHost/Runner.PluginHost.csproj
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Exe</OutputType>
-    <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
     <NoWarn>NU1701;NU1603</NoWarn>
     <Version>$(Version)</Version>
diff --git a/src/Runner.Plugins/Runner.Plugins.csproj b/src/Runner.Plugins/Runner.Plugins.csproj
index daa86f02687..1c02e977203 100644
--- a/src/Runner.Plugins/Runner.Plugins.csproj
+++ b/src/Runner.Plugins/Runner.Plugins.csproj
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Library</OutputType>
-    <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
     <NoWarn>NU1701;NU1603</NoWarn>
     <Version>$(Version)</Version>
diff --git a/src/Runner.Sdk/Runner.Sdk.csproj b/src/Runner.Sdk/Runner.Sdk.csproj
index e0294afc6a3..4a629ae256a 100644
--- a/src/Runner.Sdk/Runner.Sdk.csproj
+++ b/src/Runner.Sdk/Runner.Sdk.csproj
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Library</OutputType>
-    <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
     <NoWarn>NU1701;NU1603</NoWarn>
     <Version>$(Version)</Version>
diff --git a/src/Runner.Worker/Runner.Worker.csproj b/src/Runner.Worker/Runner.Worker.csproj
index adc7c02fd91..45531d5de8e 100644
--- a/src/Runner.Worker/Runner.Worker.csproj
+++ b/src/Runner.Worker/Runner.Worker.csproj
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Exe</OutputType>
-    <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
     <NoWarn>NU1701;NU1603</NoWarn>
     <Version>$(Version)</Version>
diff --git a/src/Sdk/Sdk.csproj b/src/Sdk/Sdk.csproj
index 133f99a419e..3a4bfed695b 100644
--- a/src/Sdk/Sdk.csproj
+++ b/src/Sdk/Sdk.csproj
@@ -3,7 +3,7 @@
     <PropertyGroup>
         <TargetFramework>net6.0</TargetFramework>
         <OutputType>Library</OutputType>
-        <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+        <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
         <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
         <NoWarn>NU1701;NU1603</NoWarn>
         <Version>$(Version)</Version>
diff --git a/src/Test/L0/ConstantGenerationL0.cs b/src/Test/L0/ConstantGenerationL0.cs
index d964ba4743f..9b8f3ae7e78 100644
--- a/src/Test/L0/ConstantGenerationL0.cs
+++ b/src/Test/L0/ConstantGenerationL0.cs
@@ -16,6 +16,7 @@ public void BuildConstantGenerateSucceed()
             {
                 "win-x64",
                 "win-x86",
+                "win-arm64",
                 "linux-x64",
                 "linux-arm",
                 "linux-arm64",
diff --git a/src/Test/Test.csproj b/src/Test/Test.csproj
index 432d482237f..1ad891ca0ec 100644
--- a/src/Test/Test.csproj
+++ b/src/Test/Test.csproj
@@ -1,7 +1,7 @@
 ﻿<Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>net6.0</TargetFramework>
-        <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
+        <RuntimeIdentifiers>win-x64;win-x86;win-arm64;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
         <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
         <NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn>
     </PropertyGroup>
diff --git a/src/dev.sh b/src/dev.sh
index df71896e46c..78c08df85f0 100755
--- a/src/dev.sh
+++ b/src/dev.sh
@@ -38,6 +38,9 @@ if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
     if [[ "$PROCESSOR_ARCHITECTURE" == 'x86' ]]; then
         RUNTIME_ID='win-x86'
     fi
+    if [[ "$PROCESSOR_ARCHITECTURE" == 'ARM64' ]]; then
+        RUNTIME_ID='win-arm64'
+    fi
 elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
     RUNTIME_ID="linux-x64"
     if command -v uname > /dev/null; then
@@ -56,11 +59,11 @@ if [[ -n "$DEV_TARGET_RUNTIME" ]]; then
 fi
 
 # Make sure current platform support publish the dotnet runtime
-# Windows can publish win-x86/x64
+# Windows can publish win-x86/x64/arm64
 # Linux can publish linux-x64/arm/arm64
 # OSX can publish osx-x64
 if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
-    if [[ ("$RUNTIME_ID" != 'win-x86') && ("$RUNTIME_ID" != 'win-x64') ]]; then
+    if [[ ("$RUNTIME_ID" != 'win-x86') && ("$RUNTIME_ID" != 'win-x64') && ("$RUNTIME_ID" != 'win-arm64') ]]; then
         echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2
         exit 1
     fi
@@ -146,7 +149,7 @@ function package ()
         echo "You must build first.  Expecting to find ${LAYOUT_DIR}/bin"
     fi
 
-    # TODO: We are cross-compiling arm on x64 so we cant exec Runner.Listener. Remove after building on native arm host
+    # TODO: We are cross-compiling arm on x64 (Linux + Windows) so we cant exec Runner.Listener. Remove after building on native arm host
     runner_ver=$("${LAYOUT_DIR}/bin/Runner.Listener" --version) || runner_ver=$(cat runnerversion) || failed "version"
     runner_pkg_name="actions-runner-${RUNTIME_ID}-${runner_ver}"
 
diff --git a/src/dir.proj b/src/dir.proj
index cc0b796ebc1..12c9d19f431 100644
--- a/src/dir.proj
+++ b/src/dir.proj
@@ -43,7 +43,7 @@
     <Target Name="Build" DependsOnTargets="GenerateConstant">
         <MSBuild Targets="Restore" Projects="@(ProjectFiles)" StopOnFirstFailure="true" />
         <MSBuild Targets="Publish" Projects="@(ProjectFiles)" BuildInParallel="false" StopOnFirstFailure="true" Properties="Configuration=$(BUILDCONFIG);PackageRuntime=$(PackageRuntime);Version=$(RunnerVersion);RuntimeIdentifier=$(PackageRuntime);PublishDir=$(MSBuildProjectDirectory)/../_layout/bin" />
-        <Exec Command="%22$(DesktopMSBuild)%22 Runner.Service/Windows/RunnerService.csproj /p:Configuration=$(BUILDCONFIG) /p:OutputPath=%22$(MSBuildProjectDirectory)/../_layout/bin%22" ConsoleToMSBuild="true" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86'" />
+        <Exec Command="%22$(DesktopMSBuild)%22 Runner.Service/Windows/RunnerService.csproj /p:Configuration=$(BUILDCONFIG) /p:OutputPath=%22$(MSBuildProjectDirectory)/../_layout/bin%22" ConsoleToMSBuild="true" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86' Or '$(PackageRuntime)' == 'win-arm64'" />
     </Target>
 
     <Target Name="Test" DependsOnTargets="GenerateConstant">
@@ -61,9 +61,9 @@
         <Copy SourceFiles="@(LayoutBinFiles)" DestinationFolder="$(MSBuildProjectDirectory)/../_layout/bin/%(RecursiveDir)"/>
 
         <ItemGroup>
-            <LayoutRootFilesToDelete Include="$(MSBuildProjectDirectory)/../_layout/*.cmd" Condition="'$(PackageRuntime)' != 'win-x64' And '$(PackageRuntime)' != 'win-x86'"/>
-            <LayoutRootFilesToDelete Include="$(MSBuildProjectDirectory)/../_layout/*.sh" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86'"/>
-            <LayoutRootFilesToDelete Include="$(MSBuildProjectDirectory)/../_layout/bin/RunnerService.js" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86'"/>
+            <LayoutRootFilesToDelete Include="$(MSBuildProjectDirectory)/../_layout/*.cmd" Condition="'$(PackageRuntime)' != 'win-x64' And '$(PackageRuntime)' != 'win-x86' And '$(PackageRuntime)' != 'win-arm64'"/>
+            <LayoutRootFilesToDelete Include="$(MSBuildProjectDirectory)/../_layout/*.sh" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86' Or '$(PackageRuntime)' == 'win-arm64'"/>
+            <LayoutRootFilesToDelete Include="$(MSBuildProjectDirectory)/../_layout/bin/RunnerService.js" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86' Or '$(PackageRuntime)' == 'win-arm64'"/>
         </ItemGroup>
 
         <Delete Files="@(LayoutRootFilesToDelete)" />
@@ -86,4 +86,4 @@
         <RemoveDir Directories="Test/bin" />
         <RemoveDir Directories="Test/obj" />
     </Target>
-</Project>
\ No newline at end of file
+</Project>
