1{ autoPatchelfHook 2, autoSignDarwinBinariesHook 3, coreutils 4, curl 5, dotnetCorePackages 6, dotnetPackages 7, fetchFromGitHub 8, fetchurl 9, git 10, icu 11, libkrb5 12, lib 13, linkFarmFromDrvs 14, lttng-ust 15, makeWrapper 16, nodejs-16_x 17, openssl 18, stdenv 19, zlib 20, writeShellApplication 21, nuget-to-nix 22}: 23let 24 fetchNuGet = { pname, version, sha256 }: fetchurl { 25 name = "${pname}.${version}.nupkg"; 26 url = "https://www.nuget.org/api/v2/package/${pname}/${version}"; 27 inherit sha256; 28 }; 29 30 sdkSource = linkFarmFromDrvs "nuget-sdk-packages" ( 31 dotnetSdk.passthru.packages { inherit fetchNuGet; } 32 ); 33 34 nugetSource = linkFarmFromDrvs "nuget-packages" ( 35 import ./deps.nix { inherit fetchNuGet; } 36 ); 37 38 dotnetSdk = dotnetCorePackages.sdk_6_0; 39 # Map Nix systems to .NET runtime ids 40 runtimeIds = { 41 "x86_64-linux" = "linux-x64"; 42 "aarch64-linux" = "linux-arm64"; 43 "x86_64-darwin" = "osx-x64"; 44 "aarch64-darwin" = "osx-arm64"; 45 }; 46 runtimeId = runtimeIds.${stdenv.system}; 47 fakeSha1 = "0000000000000000000000000000000000000000"; 48in 49stdenv.mkDerivation rec { 50 pname = "github-runner"; 51 version = "2.299.1"; 52 53 inherit sdkSource; 54 55 src = fetchFromGitHub { 56 owner = "actions"; 57 repo = "runner"; 58 rev = "v${version}"; 59 hash = "sha256-o6N7GDfSEWX6QaEga5hQpbpDcBh7Alcy9mK3QlODTbs="; 60 }; 61 62 nativeBuildInputs = [ 63 dotnetSdk 64 dotnetPackages.Nuget 65 makeWrapper 66 ] ++ lib.optionals stdenv.isLinux [ 67 autoPatchelfHook 68 ] ++ lib.optionals (stdenv.isDarwin && stdenv.isAarch64) [ 69 autoSignDarwinBinariesHook 70 ]; 71 72 buildInputs = [ 73 curl # libcurl.so.4 74 libkrb5 # libgssapi_krb5.so.2 75 stdenv.cc.cc.lib # libstdc++.so.6 76 zlib # libz.so.1 77 icu 78 ] ++ lib.optionals stdenv.isLinux [ 79 lttng-ust # liblttng-ust.so.0 80 ]; 81 82 patches = [ 83 # Don't run Git, no restore on build/test 84 ./patches/dir-proj.patch 85 # Replace some paths that originally point to Nix's read-only store 86 ./patches/host-context-dirs.patch 87 # Use GetDirectory() to obtain "diag" dir 88 ./patches/use-get-directory-for-diag.patch 89 # Don't try to install systemd service 90 ./patches/dont-install-systemd-service.patch 91 ]; 92 93 postPatch = '' 94 # Relax the version requirement 95 substituteInPlace src/global.json \ 96 --replace '6.0.300' '${dotnetSdk.version}' 97 98 # Disable specific tests 99 substituteInPlace src/dir.proj \ 100 --replace 'dotnet test Test/Test.csproj' \ 101 "dotnet test Test/Test.csproj --filter '${lib.concatStringsSep "&" (map (x: "FullyQualifiedName!=${x}") disabledTests)}'" 102 103 # We don't use a Git checkout 104 substituteInPlace src/dir.proj \ 105 --replace 'git update-index --assume-unchanged ./Runner.Sdk/BuildConstants.cs' \ 106 'echo Patched out.' 107 108 # Fix FHS path 109 substituteInPlace src/Test/L0/Util/IOUtilL0.cs \ 110 --replace '/bin/ln' '${coreutils}/bin/ln' 111 ''; 112 113 DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = stdenv.isDarwin; 114 115 configurePhase = '' 116 runHook preConfigure 117 118 export HOME=$(mktemp -d) 119 120 # Never use nuget.org 121 nuget sources Disable -Name "nuget.org" 122 123 # Restore the dependencies 124 dotnet restore src/ActionsRunner.sln \ 125 --runtime "${runtimeId}" \ 126 --source "${sdkSource}" \ 127 --source "${nugetSource}" 128 129 runHook postConfigure 130 ''; 131 132 buildPhase = '' 133 runHook preBuild 134 135 dotnet msbuild \ 136 -t:Build \ 137 -p:PackageRuntime="${runtimeId}" \ 138 -p:BUILDCONFIG="Release" \ 139 -p:RunnerVersion="${version}" \ 140 -p:GitInfoCommitHash="${fakeSha1}" \ 141 src/dir.proj 142 143 runHook postBuild 144 ''; 145 146 doCheck = true; 147 148 __darwinAllowLocalNetworking = true; 149 150 # Fully qualified name of disabled tests 151 disabledTests = 152 [ "GitHub.Runner.Common.Tests.Listener.SelfUpdaterL0.TestSelfUpdateAsync" ] 153 ++ map (x: "GitHub.Runner.Common.Tests.Listener.SelfUpdaterL0.TestSelfUpdateAsync_${x}") [ 154 "Cancel_CloneHashTask_WhenNotNeeded" 155 "CloneHash_RuntimeAndExternals" 156 "DownloadRetry" 157 "FallbackToFullPackage" 158 "NoUpdateOnOldVersion" 159 "NotUseExternalsRuntimeTrimmedPackageOnHashMismatch" 160 "UseExternalsRuntimeTrimmedPackage" 161 "UseExternalsTrimmedPackage" 162 "ValidateHash" 163 ] 164 ++ map (x: "GitHub.Runner.Common.Tests.Worker.ActionManagerL0.PrepareActions_${x}") [ 165 "CompositeActionWithActionfile_CompositeContainerNested" 166 "CompositeActionWithActionfile_CompositePrestepNested" 167 "CompositeActionWithActionfile_MaxLimit" 168 "CompositeActionWithActionfile_Node" 169 "DownloadActionFromGraph" 170 "DownloadActionFromGraph_Legacy" 171 "NotPullOrBuildImagesMultipleTimes" 172 "NotPullOrBuildImagesMultipleTimes_Legacy" 173 "RepositoryActionWithActionYamlFile_DockerHubImage" 174 "RepositoryActionWithActionYamlFile_DockerHubImage_Legacy" 175 "RepositoryActionWithActionfileAndDockerfile" 176 "RepositoryActionWithActionfileAndDockerfile_Legacy" 177 "RepositoryActionWithActionfile_DockerHubImage" 178 "RepositoryActionWithActionfile_DockerHubImage_Legacy" 179 "RepositoryActionWithActionfile_Dockerfile" 180 "RepositoryActionWithActionfile_Dockerfile_Legacy" 181 "RepositoryActionWithActionfile_DockerfileRelativePath" 182 "RepositoryActionWithActionfile_DockerfileRelativePath_Legacy" 183 "RepositoryActionWithActionfile_Node" 184 "RepositoryActionWithActionfile_Node_Legacy" 185 "RepositoryActionWithDockerfile" 186 "RepositoryActionWithDockerfile_Legacy" 187 "RepositoryActionWithDockerfileInRelativePath" 188 "RepositoryActionWithDockerfileInRelativePath_Legacy" 189 "RepositoryActionWithDockerfilePrepareActions_Repository" 190 "RepositoryActionWithInvalidWrapperActionfile_Node" 191 "RepositoryActionWithInvalidWrapperActionfile_Node_Legacy" 192 "RepositoryActionWithWrapperActionfile_PreSteps" 193 "RepositoryActionWithWrapperActionfile_PreSteps_Legacy" 194 ] 195 ++ map (x: "GitHub.Runner.Common.Tests.DotnetsdkDownloadScriptL0.${x}") [ 196 "EnsureDotnetsdkBashDownloadScriptUpToDate" 197 "EnsureDotnetsdkPowershellDownloadScriptUpToDate" 198 ] 199 ++ [ "GitHub.Runner.Common.Tests.Listener.RunnerL0.TestRunOnceHandleUpdateMessage" ] 200 # Tests for trimmed runner packages which aim at reducing the update size. Not relevant for Nix. 201 ++ map (x: "GitHub.Runner.Common.Tests.PackagesTrimL0.${x}") [ 202 "RunnerLayoutParts_CheckExternalsHash" 203 "RunnerLayoutParts_CheckDotnetRuntimeHash" 204 ] 205 ++ lib.optionals (stdenv.hostPlatform.system == "aarch64-linux") [ 206 # "JavaScript Actions in Alpine containers are only supported on x64 Linux runners. Detected Linux Arm64" 207 "GitHub.Runner.Common.Tests.Worker.StepHostL0.DetermineNodeRuntimeVersionInAlpineContainerAsync" 208 ] 209 ++ lib.optionals DOTNET_SYSTEM_GLOBALIZATION_INVARIANT [ 210 "GitHub.Runner.Common.Tests.ProcessExtensionL0.SuccessReadProcessEnv" 211 "GitHub.Runner.Common.Tests.Util.StringUtilL0.FormatUsesInvariantCulture" 212 "GitHub.Runner.Common.Tests.Worker.VariablesL0.Constructor_SetsOrdinalIgnoreCaseComparer" 213 "GitHub.Runner.Common.Tests.Worker.WorkerL0.DispatchCancellation" 214 "GitHub.Runner.Common.Tests.Worker.WorkerL0.DispatchRunNewJob" 215 ]; 216 checkInputs = [ git ]; 217 218 checkPhase = '' 219 runHook preCheck 220 221 mkdir -p _layout/externals 222 ln -s ${nodejs-16_x} _layout/externals/node16 223 224 printf 'Disabled tests:\n%s\n' '${lib.concatMapStringsSep "\n" (x: " - ${x}") disabledTests}' 225 226 # BUILDCONFIG needs to be "Debug" 227 dotnet msbuild \ 228 -t:test \ 229 -p:PackageRuntime="${runtimeId}" \ 230 -p:BUILDCONFIG="Debug" \ 231 -p:RunnerVersion="${version}" \ 232 -p:GitInfoCommitHash="${fakeSha1}" \ 233 src/dir.proj 234 235 runHook postCheck 236 ''; 237 238 installPhase = '' 239 runHook preInstall 240 241 # Copy the built binaries to lib/ instead of bin/ as they 242 # have to be wrapped in the fixup phase to work 243 mkdir -p $out/lib 244 cp -r _layout/bin/. $out/lib/ 245 246 # Delete debugging files 247 find "$out/lib" -type f -name '*.pdb' -delete 248 249 # Install the helper scripts to bin/ to resemble the upstream package 250 mkdir -p $out/bin 251 install -m755 src/Misc/layoutbin/runsvc.sh $out/bin/ 252 install -m755 src/Misc/layoutbin/RunnerService.js $out/lib/ 253 install -m755 src/Misc/layoutroot/run.sh $out/lib/ 254 install -m755 src/Misc/layoutroot/run-helper.sh.template $out/lib/run-helper.sh 255 install -m755 src/Misc/layoutroot/config.sh $out/lib/ 256 install -m755 src/Misc/layoutroot/env.sh $out/lib/ 257 258 # Rewrite reference in helper scripts from bin/ to lib/ 259 substituteInPlace $out/lib/run.sh --replace '"$DIR"/bin' '"$DIR"/lib' 260 substituteInPlace $out/lib/config.sh --replace './bin' $out'/lib' \ 261 --replace 'source ./env.sh' $out/bin/env.sh 262 263 # Remove uneeded copy for run-helper template 264 substituteInPlace $out/lib/run.sh --replace 'cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh' ' ' 265 substituteInPlace $out/lib/run-helper.sh --replace '"$DIR"/bin/' '"$DIR"/' 266 267 # Make paths absolute 268 substituteInPlace $out/bin/runsvc.sh \ 269 --replace './externals' "$out/externals" \ 270 --replace './bin' "$out/lib" 271 272 # The upstream package includes Node {12,16} and expects it at the path 273 # externals/node{12,16}. As opposed to the official releases, we don't 274 # link the Alpine Node flavors. 275 mkdir -p $out/externals 276 ln -s ${nodejs-16_x} $out/externals/node16 277 278 # Install Nodejs scripts called from workflows 279 install -D src/Misc/layoutbin/hashFiles/index.js $out/lib/hashFiles/index.js 280 mkdir -p $out/lib/checkScripts 281 install src/Misc/layoutbin/checkScripts/* $out/lib/checkScripts/ 282 283 runHook postInstall 284 ''; 285 286 # Stripping breaks the binaries 287 dontStrip = true; 288 289 preFixup = lib.optionalString stdenv.isLinux '' 290 patchelf --replace-needed liblttng-ust.so.0 liblttng-ust.so $out/lib/libcoreclrtraceptprovider.so 291 ''; 292 293 postFixup = '' 294 fix_rpath() { 295 patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out/lib/$1 296 } 297 wrap() { 298 makeWrapper $out/lib/$1 $out/bin/$1 \ 299 --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath (buildInputs ++ [ openssl ])} \ 300 "''${@:2}" 301 } 302 '' + lib.optionalString stdenv.isLinux '' 303 fix_rpath Runner.Listener 304 fix_rpath Runner.PluginHost 305 fix_rpath Runner.Worker 306 '' + '' 307 wrap Runner.Listener 308 wrap Runner.PluginHost 309 wrap Runner.Worker 310 wrap run.sh --run 'export RUNNER_ROOT=''${RUNNER_ROOT:-$HOME/.github-runner}' 311 wrap env.sh --run 'cd $RUNNER_ROOT' 312 313 wrap config.sh --run 'export RUNNER_ROOT=''${RUNNER_ROOT:-$HOME/.github-runner}' \ 314 --run 'mkdir -p $RUNNER_ROOT' \ 315 --prefix PATH : ${lib.makeBinPath [ stdenv.cc ]} \ 316 --chdir $out 317 ''; 318 319 # Script to create deps.nix file for dotnet dependencies. Run it with 320 # $(nix-build -A github-runner.passthru.createDepsFile)/bin/create-deps-file 321 # 322 # Default output path is /tmp/${pname}-deps.nix, but can be overriden with cli argument. 323 # 324 # Inspired by passthru.fetch-deps in pkgs/build-support/build-dotnet-module/default.nix 325 passthru.createDepsFile = writeShellApplication { 326 name = "create-deps-file"; 327 runtimeInputs = [ coreutils dotnetSdk (nuget-to-nix.override { dotnet-sdk = dotnetSdk; }) ]; 328 text = '' 329 # Disable telemetry data 330 export DOTNET_CLI_TELEMETRY_OPTOUT=1 331 332 deps_file="$(realpath "''${1:-$(mktemp -t "${pname}-deps-XXXXXX.nix")}")" 333 334 printf "\n* Setup workdir\n" 335 workdir="$(mktemp -d /tmp/${pname}.XXX)" 336 cp -rT "${src}" "$workdir" 337 chmod -R +w "$workdir" 338 trap 'rm -rf "$workdir"' EXIT 339 340 pushd "$workdir" 341 342 mkdir nuget_pkgs 343 344 ${lib.concatMapStrings (rid: '' 345 printf "\n* Restore ${pname} (${rid}) dotnet project\n" 346 dotnet restore src/ActionsRunner.sln --packages nuget_pkgs --no-cache --force --runtime "${rid}" 347 '') (lib.attrValues runtimeIds)} 348 349 printf "\n* Make %s file\n" "$(basename "$deps_file")" 350 nuget-to-nix "$workdir/nuget_pkgs" "${sdkSource}" > "$deps_file" 351 printf "\n* Dependency file writen to %s" "$deps_file" 352 ''; 353 }; 354 355 meta = with lib; { 356 description = "Self-hosted runner for GitHub Actions"; 357 homepage = "https://github.com/actions/runner"; 358 license = licenses.mit; 359 maintainers = with maintainers; [ veehaitch newam kfollesdal aanderse ]; 360 platforms = attrNames runtimeIds; 361 }; 362}