From 1e6bbb038c66523865b6d09958d3133d94218aa0 Mon Sep 17 00:00:00 2001 From: Kirill Nikolaev Date: Tue, 13 Feb 2024 00:13:17 +0100 Subject: [PATCH] Create cache destination manually. We have to do it with sudo (to create dirs in root) and make sure that the resulting dirs are owned by the runner user. In order to do that, implement `mkdir -p` manually. --- dist/index/index.js | 26 +++++++++++++++++++++++--- src/index.ts | 5 ++--- src/utils.ts | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/dist/index/index.js b/dist/index/index.js index c67b43c..cf7febd 100644 --- a/dist/index/index.js +++ b/dist/index/index.js @@ -27147,6 +27147,27 @@ function resolveHome(filepath) { } return filepath; } +async function sudoMkdirP(path, userColonGroup) { + const anc = ancestors(path); + for (const p of anc) { + if (external_fs_.existsSync(p)) + continue; + await lib_exec.exec("sudo", ["mkdir", p]); + await lib_exec.exec("sudo", ["chown", userColonGroup, p]); + } +} +function ancestors(filepath) { + const res = []; + let norm = external_path_.normalize(filepath); + while (norm !== "." && norm !== "/") { + res.unshift(norm); + const next = external_path_.dirname(norm); + if (next === norm) + break; + norm = next; + } + return res; +} async function getCacheUtil(cachePath) { const { stdout } = await exec.getExecOutput(`/bin/sh -c "du -sb ${cachePath} | cut -f1"`, [], { silent: true, @@ -27245,9 +27266,8 @@ async function restoreLocalCache(cachePaths) { } const expandedFilePath = resolveHome(p.mountTarget); await io.mkdirP(p.pathInCache); - // Sudo to be able to create dirs in root (e.g. /nix). - // Use `install` instead of `mkdir -p` to easily set owners. - await lib_exec.exec(`sudo install -d -o runner -g docker ${expandedFilePath}`); + // Sudo to be able to create dirs in root (e.g. /nix), but set the runner as owner. + await sudoMkdirP(expandedFilePath, "runner:docker"); await lib_exec.exec(`sudo mount --bind ${p.pathInCache} ${expandedFilePath}`); } return cacheMisses; diff --git a/src/index.ts b/src/index.ts index 92c47b0..fde4dc2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -87,9 +87,8 @@ export async function restoreLocalCache( const expandedFilePath = utils.resolveHome(p.mountTarget); await io.mkdirP(p.pathInCache); - // Sudo to be able to create dirs in root (e.g. /nix). - // Use `install` instead of `mkdir -p` to easily set owners. - await exec.exec(`sudo install -d -o runner -g docker ${expandedFilePath}`); + // Sudo to be able to create dirs in root (e.g. /nix), but set the runner as owner. + await utils.sudoMkdirP(expandedFilePath, "runner:docker"); await exec.exec(`sudo mount --bind ${p.pathInCache} ${expandedFilePath}`); } diff --git a/src/utils.ts b/src/utils.ts index b869376..377e832 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -25,6 +25,27 @@ export function resolveHome(filepath: string): string { return filepath; } +export async function sudoMkdirP(path: string, userColonGroup: string) { + const anc = ancestors(path); + for (const p of anc) { + if (fs.existsSync(p)) continue; + await exec.exec("sudo", ["mkdir", p]); + await exec.exec("sudo", ["chown", userColonGroup, p]); + } +} + +function ancestors(filepath: string) { + const res: string[] = []; + let norm = path.normalize(filepath); + while (norm !== "." && norm !== "/") { + res.unshift(norm); + const next = path.dirname(norm); + if (next === norm) break; + norm = next; + } + return res; +} + export async function getCacheUtil(cachePath: string): Promise { const { stdout } = await exec.getExecOutput( `/bin/sh -c "du -sb ${cachePath} | cut -f1"`,