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}