Skip to content
48 changes: 39 additions & 9 deletions packages/k8s/src/hooks/run-script-step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,51 @@ export async function runScriptStep(
)

const workdir = dirname(process.env.RUNNER_WORKSPACE as string)
const containerTemp = '/__w/_temp'
const runnerTemp = `${workdir}/_temp`
await execCpToPod(state.jobPod, runnerTemp, containerTemp)
const containerTemp = '/__w/_temp'
const containerTempSrc = '/__w/_temp_pre'
// Ensure base and staging dirs exist before copying
await execPodStep(
[
'sh',
'-c',
'mkdir -p /__w && mkdir -p /__w/_temp && mkdir -p /__w/_temp_pre'
],
state.jobPod,
JOB_CONTAINER_NAME
)
await execCpToPod(state.jobPod, runnerTemp, containerTempSrc)

// Copy GitHub directories from temp to /github
const setupCommands = [
'mkdir -p /github',
'cp -r /__w/_temp/_github_home /github/home',
'cp -r /__w/_temp/_github_workflow /github/workflow'
// Merge strategy:
// - Overwrite files in _runner_file_commands
// - Append files not already present elsewhere
const mergeCommands = [
'set -e',
'mkdir -p /__w/_temp /__w/_temp_pre',
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The directories /__w/_temp and /__w/_temp_pre are already created in lines 30-39 before this merge command runs. The mkdir -p on this line is redundant and can be removed to simplify the code.

Suggested change:

'set -e',
'SRC=/__w/_temp_pre',
'DST=/__w/_temp',
Suggested change
'mkdir -p /__w/_temp /__w/_temp_pre',

Copilot uses AI. Check for mistakes.
'SRC=/__w/_temp_pre',
'DST=/__w/_temp',
// Overwrite _runner_file_commands
`find "$SRC" -type f ! -path "*/_runner_file_commands/*" -exec sh -c '
rel="\${1#$2/}"
target="$3/$rel"
mkdir -p "$(dirname "$target")"
cp -a "$1" "$target"
' _ {} "$SRC" "$DST" \\;`,
// Remove _temp_pre after merging
'rm -rf /__w/_temp_pre'
]

try {
await execPodStep(
['sh', '-c', shlex.quote(setupCommands.join(' && '))],
['sh', '-c', mergeCommands.join(' && ')],
state.jobPod,
JOB_CONTAINER_NAME
)
} catch (err) {
core.debug(`Failed to copy GitHub directories: ${JSON.stringify(err)}`)
core.debug(`Failed to merge temp directories: ${JSON.stringify(err)}`)
const message = (err as any)?.response?.body?.message || err
throw new Error(`failed to merge temp dirs: ${message}`)
}

// Execute the entrypoint script
Expand Down Expand Up @@ -69,7 +95,11 @@ export async function runScriptStep(
core.debug(
`Copying from job pod '${state.jobPod}' ${containerTemp} to ${runnerTemp}`
)
await execCpFromPod(state.jobPod, containerTemp, workdir)
await execCpFromPod(
state.jobPod,
`${containerTemp}/_runner_file_commands`,
`${workdir}/_temp`
)
} catch (error) {
core.warning('Failed to copy _temp from pod')
}
Expand Down
2 changes: 1 addition & 1 deletion packages/k8s/src/k8s/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ export async function isPodContainerAlpine(
[
'sh',
'-c',
`'[ $(cat /etc/*release* | grep -i -e "^ID=*alpine*" -c) != 0 ] || exit 1'`
`[ $(cat /etc/*release* | grep -i -e "^ID=*alpine*" -c) != 0 ] || exit 1`
],
podName,
containerName
Expand Down
5 changes: 5 additions & 0 deletions packages/k8s/src/k8s/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ function mergeLists<T>(base?: T[], from?: T[]): T[] {
}

export function fixArgs(args: string[]): string[] {
// Preserve shell command strings passed via `sh -c` without re-tokenizing.
// Retokenizing would split the script into multiple args, breaking `sh -c`.
if (args.length >= 2 && args[0] === 'sh' && args[1] === '-c') {
return args
}
return shlex.split(args.join(' '))
}

Expand Down
8 changes: 2 additions & 6 deletions packages/k8s/tests/prepare-job-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('Prepare job', () => {
process.env.GITHUB_WORKSPACE as string,
'myvolume'
)
fs.mkdirSync(userVolumeMount)
fs.mkdirSync(userVolumeMount, { recursive: true })
fs.writeFileSync(path.join(userVolumeMount, 'file.txt'), 'hello')
prepareJobData.args.container.userMountVolumes = [
{
Expand All @@ -63,11 +63,7 @@ describe('Prepare job', () => {
)

await execPodStep(
[
'sh',
'-c',
'\'[ "$(cat /__w/myvolume/file.txt)" = "hello" ] || exit 5\''
],
['sh', '-c', '[ "$(cat /__w/myvolume/file.txt)" = "hello" ] || exit 5'],
content!.state!.jobPod,
JOB_CONTAINER_NAME
).then(output => {
Expand Down
Loading