1{ autoPatchelfHook
2, autoSignDarwinBinariesHook
3, buildDotnetModule
4, dotnetCorePackages
5, fetchFromGitHub
6, fetchpatch
7, git
8, glibc
9, glibcLocales
10, lib
11, nixosTests
12, nodejs_16
13, stdenv
14, which
15, buildPackages
16, runtimeShell
17}:
18buildDotnetModule rec {
19 pname = "github-runner";
20 version = "2.304.0";
21
22 src = fetchFromGitHub {
23 owner = "actions";
24 repo = "runner";
25 rev = "v${version}";
26 hash = "sha256-5amc0oVcFCPFrUcX5iITjnN9Mtpzi4wWsJe7Kdm9YxA=";
27 leaveDotGit = true;
28 postFetch = ''
29 git -C $out rev-parse --short HEAD > $out/.git-revision
30 rm -rf $out/.git
31 '';
32 };
33
34 # The git commit is read during the build and some tests depends on a git repo to be present
35 # https://github.com/actions/runner/blob/22d1938ac420a4cb9e3255e47a91c2e43c38db29/src/dir.proj#L5
36 unpackPhase = ''
37 cp -r $src $TMPDIR/src
38 chmod -R +w $TMPDIR/src
39 cd $TMPDIR/src
40 (
41 export PATH=${buildPackages.git}/bin:$PATH
42 git init
43 git config user.email "root@localhost"
44 git config user.name "root"
45 git add .
46 git commit -m "Initial commit"
47 git checkout -b v${version}
48 )
49 mkdir -p $TMPDIR/bin
50 cat > $TMPDIR/bin/git <<EOF
51 #!${runtimeShell}
52 if [ \$# -eq 1 ] && [ "\$1" = "rev-parse" ]; then
53 echo $(cat $TMPDIR/src/.git-revision)
54 exit 0
55 fi
56 exec ${buildPackages.git}/bin/git "\$@"
57 EOF
58 chmod +x $TMPDIR/bin/git
59 export PATH=$TMPDIR/bin:$PATH
60 '';
61
62 patches = [
63 # Replace some paths that originally point to Nix's read-only store
64 ./patches/host-context-dirs.patch
65 # Use GetDirectory() to obtain "diag" dir
66 ./patches/use-get-directory-for-diag.patch
67 # Don't try to install service
68 ./patches/dont-install-service.patch
69 # Access `.env` and `.path` relative to `$RUNNER_ROOT`, if set
70 ./patches/env-sh-use-runner-root.patch
71 # Fix FHS path: https://github.com/actions/runner/pull/2464
72 (fetchpatch {
73 name = "ln-fhs.patch";
74 url = "https://github.com/actions/runner/commit/5ff0ce1.patch";
75 hash = "sha256-2Vg3cKZK3cE/OcPDZkdN2Ro2WgvduYTTwvNGxwCfXas=";
76 })
77 ];
78
79 postPatch = ''
80 # Ignore changes to src/Runner.Sdk/BuildConstants.cs
81 substituteInPlace src/dir.proj \
82 --replace 'git update-index --assume-unchanged ./Runner.Sdk/BuildConstants.cs' \
83 'true'
84 '';
85
86 DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = isNull glibcLocales;
87 LOCALE_ARCHIVE = lib.optionalString (!DOTNET_SYSTEM_GLOBALIZATION_INVARIANT) "${glibcLocales}/lib/locale/locale-archive";
88
89 postConfigure = ''
90 # Generate src/Runner.Sdk/BuildConstants.cs
91 dotnet msbuild \
92 -t:GenerateConstant \
93 -p:ContinuousIntegrationBuild=true \
94 -p:Deterministic=true \
95 -p:PackageRuntime="${dotnetCorePackages.systemToDotnetRid stdenv.hostPlatform.system}" \
96 -p:RunnerVersion="${version}" \
97 src/dir.proj
98 '';
99
100 nativeBuildInputs = [
101 which
102 git
103 ] ++ lib.optionals stdenv.isLinux [
104 autoPatchelfHook
105 ] ++ lib.optionals (stdenv.isDarwin && stdenv.isAarch64) [
106 autoSignDarwinBinariesHook
107 ];
108
109 buildInputs = [ stdenv.cc.cc.lib ];
110
111 dotnet-sdk = dotnetCorePackages.sdk_6_0;
112 dotnet-runtime = dotnetCorePackages.runtime_6_0;
113
114 dotnetFlags = [ "-p:PackageRuntime=${dotnetCorePackages.systemToDotnetRid stdenv.hostPlatform.system}" ];
115
116 # As given here: https://github.com/actions/runner/blob/0befa62/src/dir.proj#L33-L41
117 projectFile = [
118 "src/Sdk/Sdk.csproj"
119 "src/Runner.Common/Runner.Common.csproj"
120 "src/Runner.Listener/Runner.Listener.csproj"
121 "src/Runner.Worker/Runner.Worker.csproj"
122 "src/Runner.PluginHost/Runner.PluginHost.csproj"
123 "src/Runner.Sdk/Runner.Sdk.csproj"
124 "src/Runner.Plugins/Runner.Plugins.csproj"
125 ];
126 nugetDeps = ./deps.nix;
127
128 doCheck = true;
129
130 __darwinAllowLocalNetworking = true;
131
132 # Fully qualified name of disabled tests
133 disabledTests =
134 [ "GitHub.Runner.Common.Tests.Listener.SelfUpdaterL0.TestSelfUpdateAsync" ]
135 ++ map (x: "GitHub.Runner.Common.Tests.Listener.SelfUpdaterL0.TestSelfUpdateAsync_${x}") [
136 "Cancel_CloneHashTask_WhenNotNeeded"
137 "CloneHash_RuntimeAndExternals"
138 "DownloadRetry"
139 "FallbackToFullPackage"
140 "NoUpdateOnOldVersion"
141 "NotUseExternalsRuntimeTrimmedPackageOnHashMismatch"
142 "UseExternalsRuntimeTrimmedPackage"
143 "UseExternalsTrimmedPackage"
144 "ValidateHash"
145 ]
146 ++ map (x: "GitHub.Runner.Common.Tests.Worker.ActionManagerL0.PrepareActions_${x}") [
147 "CompositeActionWithActionfile_CompositeContainerNested"
148 "CompositeActionWithActionfile_CompositePrestepNested"
149 "CompositeActionWithActionfile_MaxLimit"
150 "CompositeActionWithActionfile_Node"
151 "DownloadActionFromGraph"
152 "NotPullOrBuildImagesMultipleTimes"
153 "RepositoryActionWithActionYamlFile_DockerHubImage"
154 "RepositoryActionWithActionfileAndDockerfile"
155 "RepositoryActionWithActionfile_DockerHubImage"
156 "RepositoryActionWithActionfile_Dockerfile"
157 "RepositoryActionWithActionfile_DockerfileRelativePath"
158 "RepositoryActionWithActionfile_Node"
159 "RepositoryActionWithDockerfile"
160 "RepositoryActionWithDockerfileInRelativePath"
161 "RepositoryActionWithDockerfilePrepareActions_Repository"
162 "RepositoryActionWithInvalidWrapperActionfile_Node"
163 "RepositoryActionWithWrapperActionfile_PreSteps"
164 ]
165 ++ map (x: "GitHub.Runner.Common.Tests.DotnetsdkDownloadScriptL0.${x}") [
166 "EnsureDotnetsdkBashDownloadScriptUpToDate"
167 "EnsureDotnetsdkPowershellDownloadScriptUpToDate"
168 ]
169 ++ [ "GitHub.Runner.Common.Tests.Listener.RunnerL0.TestRunOnceHandleUpdateMessage" ]
170 # Tests for trimmed runner packages which aim at reducing the update size. Not relevant for Nix.
171 ++ map (x: "GitHub.Runner.Common.Tests.PackagesTrimL0.${x}") [
172 "RunnerLayoutParts_CheckExternalsHash"
173 "RunnerLayoutParts_CheckDotnetRuntimeHash"
174 ]
175 ++ lib.optionals (stdenv.hostPlatform.system == "aarch64-linux") [
176 # "JavaScript Actions in Alpine containers are only supported on x64 Linux runners. Detected Linux Arm64"
177 "GitHub.Runner.Common.Tests.Worker.StepHostL0.DetermineNodeRuntimeVersionInAlpineContainerAsync"
178 ]
179 ++ lib.optionals DOTNET_SYSTEM_GLOBALIZATION_INVARIANT [
180 "GitHub.Runner.Common.Tests.ProcessExtensionL0.SuccessReadProcessEnv"
181 "GitHub.Runner.Common.Tests.Util.StringUtilL0.FormatUsesInvariantCulture"
182 "GitHub.Runner.Common.Tests.Worker.VariablesL0.Constructor_SetsOrdinalIgnoreCaseComparer"
183 "GitHub.Runner.Common.Tests.Worker.WorkerL0.DispatchCancellation"
184 "GitHub.Runner.Common.Tests.Worker.WorkerL0.DispatchRunNewJob"
185 ];
186
187 testProjectFile = [ "src/Test/Test.csproj" ];
188
189 preCheck = ''
190 mkdir -p _layout/externals
191 ln -s ${nodejs_16} _layout/externals/node16
192 '';
193
194 postInstall = ''
195 mkdir -p $out/bin
196
197 install -m755 src/Misc/layoutbin/runsvc.sh $out/lib/github-runner
198 install -m755 src/Misc/layoutbin/RunnerService.js $out/lib/github-runner
199 install -m755 src/Misc/layoutroot/run.sh $out/lib/github-runner
200 install -m755 src/Misc/layoutroot/run-helper.sh.template $out/lib/github-runner/run-helper.sh
201 install -m755 src/Misc/layoutroot/config.sh $out/lib/github-runner
202 install -m755 src/Misc/layoutroot/env.sh $out/lib/github-runner
203
204 # env.sh is patched to not require any wrapping
205 ln -sr "$out/lib/github-runner/env.sh" "$out/bin/"
206
207 substituteInPlace $out/lib/github-runner/config.sh \
208 --replace './bin/Runner.Listener' "$out/bin/Runner.Listener"
209 '' + lib.optionalString stdenv.isLinux ''
210 substituteInPlace $out/lib/github-runner/config.sh \
211 --replace 'command -v ldd' 'command -v ${glibc.bin}/bin/ldd' \
212 --replace 'ldd ./bin' '${glibc.bin}/bin/ldd ${dotnet-runtime}/shared/Microsoft.NETCore.App/${dotnet-runtime.version}/' \
213 --replace '/sbin/ldconfig' '${glibc.bin}/bin/ldconfig'
214 '' + ''
215 # Remove uneeded copy for run-helper template
216 substituteInPlace $out/lib/github-runner/run.sh --replace 'cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh' ' '
217 substituteInPlace $out/lib/github-runner/run-helper.sh --replace '"$DIR"/bin/' '"$DIR"/'
218
219 # Make paths absolute
220 substituteInPlace $out/lib/github-runner/runsvc.sh \
221 --replace './externals' "$out/lib/externals" \
222 --replace './bin/RunnerService.js' "$out/lib/github-runner/RunnerService.js"
223
224 # The upstream package includes Node 16 and expects it at the path
225 # externals/node16. As opposed to the official releases, we don't
226 # link the Alpine Node flavors.
227 mkdir -p $out/lib/externals
228 ln -s ${nodejs_16} $out/lib/externals/node16
229
230 # Install Nodejs scripts called from workflows
231 install -D src/Misc/layoutbin/hashFiles/index.js $out/lib/github-runner/hashFiles/index.js
232 mkdir -p $out/lib/github-runner/checkScripts
233 install src/Misc/layoutbin/checkScripts/* $out/lib/github-runner/checkScripts/
234 '' + lib.optionalString stdenv.isLinux ''
235 # Wrap explicitly to, e.g., prevent extra entries for LD_LIBRARY_PATH
236 makeWrapperArgs=()
237
238 # We don't wrap with libicu
239 substituteInPlace $out/lib/github-runner/config.sh \
240 --replace '$LDCONFIG_COMMAND -NXv ''${libpath//:/ }' 'echo libicu'
241 '' + ''
242 # XXX: Using the corresponding Nix argument does not work as expected:
243 # https://github.com/NixOS/nixpkgs/issues/218449
244 # Common wrapper args for `executables`
245 makeWrapperArgs+=(
246 --run 'export RUNNER_ROOT="''${RUNNER_ROOT:-"$HOME/.github-runner"}"'
247 --run 'mkdir -p "$RUNNER_ROOT"'
248 --chdir "$out"
249 )
250 '';
251
252 # List of files to wrap
253 executables = [
254 "config.sh"
255 "Runner.Listener"
256 "Runner.PluginHost"
257 "Runner.Worker"
258 "run.sh"
259 "runsvc.sh"
260 ];
261
262 doInstallCheck = true;
263 installCheckPhase = ''
264 runHook preInstallCheck
265
266 export RUNNER_ROOT="$TMPDIR"
267
268 $out/bin/config.sh --help >/dev/null
269 $out/bin/Runner.Listener --help >/dev/null
270
271 version=$($out/bin/Runner.Listener --version)
272 if [[ "$version" != "${version}" ]]; then
273 printf 'Unexpected version %s' "$version"
274 exit 1
275 fi
276
277 commit=$($out/bin/Runner.Listener --commit)
278 if [[ "$commit" != "$(git rev-parse HEAD)" ]]; then
279 printf 'Unexpected commit %s' "$commit"
280 exit 1
281 fi
282
283 runHook postInstallCheck
284 '';
285
286 passthru = {
287 tests.smoke-test = nixosTests.github-runner;
288 updateScript = ./update.sh;
289 };
290
291 meta = with lib; {
292 changelog = "https://github.com/actions/runner/releases/tag/v${version}";
293 description = "Self-hosted runner for GitHub Actions";
294 homepage = "https://github.com/actions/runner";
295 license = licenses.mit;
296 maintainers = with maintainers; [ veehaitch newam kfollesdal aanderse zimbatm ];
297 platforms = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
298 sourceProvenance = with sourceTypes; [ binaryNativeCode ];
299 };
300}