diff --git a/examples/prepare-job.json b/examples/prepare-job.json index cf6f838..f7d03f5 100644 --- a/examples/prepare-job.json +++ b/examples/prepare-job.json @@ -24,37 +24,37 @@ "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work", "targetVolumePath": "/__w", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/externals", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/externals", "targetVolumePath": "/__e", "readOnly": true }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_temp", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_temp", "targetVolumePath": "/__w/_temp", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_actions", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_actions", "targetVolumePath": "/__w/_actions", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_tool", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_tool", "targetVolumePath": "/__w/_tool", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_temp/_github_home", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_temp/_github_home", "targetVolumePath": "/github/home", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_temp/_github_workflow", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_temp/_github_workflow", "targetVolumePath": "/github/workflow", "readOnly": false } diff --git a/examples/run-container-step.json b/examples/run-container-step.json index 7a7cfac..5e13f6e 100644 --- a/examples/run-container-step.json +++ b/examples/run-container-step.json @@ -34,27 +34,27 @@ ], "systemMountVolumes": [ { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work", "targetVolumePath": "/__w", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/externals", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/externals", "targetVolumePath": "/__e", "readOnly": true }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_temp", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_temp", "targetVolumePath": "/__w/_temp", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_actions", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_actions", "targetVolumePath": "/__w/_actions", "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_tool", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_tool", "targetVolumePath": "/__w/_tool", "readOnly": false }, @@ -64,7 +64,7 @@ "readOnly": false }, { - "sourceVolumePath": "//Users/thomas/git/runner/_layout/_work/_temp/_github_workflow", + "sourceVolumePath": "/Users/thomas/git/runner/_layout/_work/_temp/_github_workflow", "targetVolumePath": "/github/workflow", "readOnly": false } diff --git a/packages/k8s/src/k8s/utils.ts b/packages/k8s/src/k8s/utils.ts index 0d8402b..7fc235a 100644 --- a/packages/k8s/src/k8s/utils.ts +++ b/packages/k8s/src/k8s/utils.ts @@ -1,5 +1,6 @@ import * as k8s from '@kubernetes/client-node' import { Mount } from 'hooklib' +import * as path from 'path' import { POD_VOLUME_NAME } from './index' export const DEFAULT_CONTAINER_ENTRY_POINT_ARGS = [`-f`, `/dev/null`] @@ -42,18 +43,23 @@ export function containerVolumes( return mounts } - // TODO: we need to ensure this is a local path under the github workspace or fail/skip - // subpath only accepts a local path under the runner workspace - /* + const workspacePath = process.env.GITHUB_WORKSPACE as string for (const userVolume of userMountVolumes) { - const sourceVolumePath = `${ - path.isAbsolute(userVolume.sourceVolumePath) - ? userVolume.sourceVolumePath - : path.join( - process.env.GITHUB_WORKSPACE as string, - userVolume.sourceVolumePath - ) - }` + let sourceVolumePath = '' + if (path.isAbsolute(userVolume.sourceVolumePath)) { + if (!userVolume.sourceVolumePath.startsWith(workspacePath)) { + throw new Error( + 'Volume mounts outside of the work folder are not supported' + ) + } + // source volume path should be relative path + sourceVolumePath = userVolume.sourceVolumePath.slice( + workspacePath.length + 1 + ) + } else { + sourceVolumePath = userVolume.sourceVolumePath + } + mounts.push({ name: POD_VOLUME_NAME, mountPath: userVolume.targetVolumePath, @@ -61,7 +67,6 @@ export function containerVolumes( readOnly: userVolume.readOnly }) } - */ return mounts } diff --git a/packages/k8s/tests/prepare-job-test.ts b/packages/k8s/tests/prepare-job-test.ts index e53bfc8..1992da1 100644 --- a/packages/k8s/tests/prepare-job-test.ts +++ b/packages/k8s/tests/prepare-job-test.ts @@ -34,11 +34,38 @@ describe('Prepare job', () => { prepareJob(prepareJobData.args, prepareJobOutputFilePath) ).resolves.not.toThrow() }) - /* + it('should generate output file in JSON format', async () => { - await prepareJob(prepareJobData.args, prepareJobOutputFilePath) const content = fs.readFileSync(prepareJobOutputFilePath) expect(() => JSON.parse(content.toString())).not.toThrow() - }) */ + }) + + it('should prepare job with absolute path for userVolumeMount', async () => { + prepareJobData.args.container.userMountVolumes.forEach(v => { + if (!path.isAbsolute(v.sourceVolumePath)) { + v.sourceVolumePath = path.join( + process.env.GITHUB_WORKSPACE as string, + v.sourceVolumePath + ) + } + }) + await expect( + prepareJob(prepareJobData.args, prepareJobOutputFilePath) + ).resolves.not.toThrow() + }) + + it('should throw an exception if the user volume mount is absolute path outside of GITHUB_WORKSPACE', async () => { + prepareJobData.args.container.userMountVolumes.forEach(v => { + if (!path.isAbsolute(v.sourceVolumePath)) { + v.sourceVolumePath = path.join( + '/path/outside/of/github-workspace', + v.sourceVolumePath + ) + } + }) + await expect( + prepareJob(prepareJobData.args, prepareJobOutputFilePath) + ).rejects.toThrow() + }) })