Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for docker-in-docker cross platform builds #266

Merged
merged 3 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ inputs:
docker-options:
description: Additional Docker run options, for passing environment variables and etc.
required: false
host-home-mount:
description: Host folder where the runner's home folder is mounted to. Used for building using Docker-in-Docker runners
required: false
target:
description: The --target option for cargo
required: false
Expand Down
73 changes: 52 additions & 21 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11743,7 +11743,7 @@ function getBeforeScript() {
}
return '';
}
async function dockerBuild(container, maturinRelease, args) {
async function dockerBuild(container, maturinRelease, hostHomeMount, args) {
var _a;
const target = getRustTarget(args);
const rustToolchain = (await getRustToolchain(args)) || 'stable';
Expand Down Expand Up @@ -11817,35 +11817,51 @@ async function dockerBuild(container, maturinRelease, args) {
const components = rustupComponents.split(/\s+/).join(' ');
commands.push('echo "::group::Install Extra Rust components"', `rustup component add ${components}`, 'echo "::endgroup::"');
}
if (sccache) {
commands.push('echo "::group::Install sccache"', 'python3 -m pip install "sccache>=0.4.0"', 'sccache --version', 'echo "::endgroup::"');
setupSccacheEnv();
}
const beforeScript = getBeforeScript();
if (beforeScript.length > 0) {
commands.push('echo "::group::Run before script"', ...beforeScript.split('\n'), 'echo "::endgroup::"');
}
if (sccache) {
commands.push('echo "::group::Install sccache"', 'python3 -m pip install "sccache>=0.4.0"', 'sccache --version', 'echo "::endgroup::"');
setupSccacheEnv();
}
commands.push(`maturin ${args.join(' ')}`);
if (sccache) {
commands.push('echo "::group::sccache stats"', 'sccache --show-stats', 'echo "::endgroup::"');
}
const workspace = process.env.GITHUB_WORKSPACE;
const scriptPath = path.join(os.tmpdir(), 'run-maturin-action.sh');
const scriptPath = path.join(process.env.RUNNER_TEMP, 'run-maturin-action.sh');
(0, fs_1.writeFileSync)(scriptPath, commands.join('\n'));
await fs_1.promises.chmod(scriptPath, 0o755);
const hostWorkspace = path.join(hostHomeMount, workspace);
const hostScriptPath = path.join(hostHomeMount, scriptPath);
const targetDir = await getCargoTargetDir(args);
core.startGroup('Cleanup build scripts artifact directory');
const debugBuildDir = path.join(targetDir, 'debug', 'build');
if ((0, fs_1.existsSync)(debugBuildDir)) {
await exec.exec('sudo', ['rm', '-rf', debugBuildDir], {
ignoreReturnCode: true
});
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('rm', ['-rf', debugBuildDir], {
ignoreReturnCode: true
});
}
else {
await exec.exec('sudo', ['rm', '-rf', debugBuildDir], {
ignoreReturnCode: true
});
}
}
const releaseBuildDir = path.join(targetDir, 'release', 'build');
if ((0, fs_1.existsSync)(debugBuildDir)) {
await exec.exec('sudo', ['rm', '-rf', releaseBuildDir], {
ignoreReturnCode: true
});
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('rm', ['-rf', releaseBuildDir], {
ignoreReturnCode: true
});
}
else {
await exec.exec('sudo', ['rm', '-rf', releaseBuildDir], {
ignoreReturnCode: true
});
}
}
core.endGroup();
const dockerEnvs = [];
Expand Down Expand Up @@ -11885,9 +11901,9 @@ async function dockerBuild(container, maturinRelease, args) {
'_PYTHON_SYSCONFIGDATA_NAME',
...dockerEnvs,
'-v',
`${scriptPath}:${scriptPath}`,
`${hostScriptPath}:${scriptPath}`,
'-v',
`${workspace}:${workspace}`,
`${hostWorkspace}:${workspace}`,
...dockerVolumes,
...dockerArgs,
image,
Expand All @@ -11898,15 +11914,29 @@ async function dockerBuild(container, maturinRelease, args) {
core.info(`Fixing file permissions for target directory: ${targetDir}`);
const uid = process.getuid();
const gid = process.getgid();
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', targetDir], {
ignoreReturnCode: true
});
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('chown', [`${uid}:${gid}`, '-R', targetDir], {
ignoreReturnCode: true
});
}
else {
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', targetDir], {
ignoreReturnCode: true
});
}
const outDir = getCliValue(args, '--out') || getCliValue(args, '-o');
if (outDir && (0, fs_1.existsSync)(outDir)) {
core.info(`Fixing file permissions for output directory: ${outDir}`);
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', outDir], {
ignoreReturnCode: true
});
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('chown', [`${uid}:${gid}`, '-R', outDir], {
ignoreReturnCode: true
});
}
else {
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', outDir], {
ignoreReturnCode: true
});
}
}
core.endGroup();
}
Expand Down Expand Up @@ -12079,6 +12109,7 @@ async function innerMain() {
const args = (0, string_argv_1.default)(inputArgs);
const command = core.getInput('command');
const target = getRustTarget(args);
const hostHomeMount = core.getInput('host-home-mount');
let container = core.getInput('container');
if (process.env.CARGO_INCREMENTAL === undefined) {
core.exportVariable('CARGO_INCREMENTAL', '0');
Expand Down Expand Up @@ -12133,7 +12164,7 @@ async function innerMain() {
if (useDocker) {
const dockerContainer = await getDockerContainer(target, manylinux, container);
if (dockerContainer) {
exitCode = await dockerBuild(dockerContainer, maturinRelease, args);
exitCode = await dockerBuild(dockerContainer, maturinRelease, hostHomeMount, args);
}
else {
core.info('No Docker container found, fallback to build on host');
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@
"@vercel/ncc": "^0.36.0",
"eslint": "^8.26.0",
"eslint-plugin-github": "^4.4.0",
"prettier": "^2.6.0"
"prettier": "^2.8.8"
}
}
}
71 changes: 55 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ function getBeforeScript(): string {
async function dockerBuild(
container: string,
maturinRelease: string,
hostHomeMount: string,
args: string[]
): Promise<number> {
const target = getRustTarget(args)
Expand Down Expand Up @@ -621,24 +622,43 @@ async function dockerBuild(

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const workspace = process.env.GITHUB_WORKSPACE!
const scriptPath = path.join(os.tmpdir(), 'run-maturin-action.sh')
const scriptPath = path.join(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
process.env.RUNNER_TEMP!,
'run-maturin-action.sh'
)
writeFileSync(scriptPath, commands.join('\n'))
await fs.chmod(scriptPath, 0o755)

const hostWorkspace = path.join(hostHomeMount, workspace)
const hostScriptPath = path.join(hostHomeMount, scriptPath)

const targetDir = await getCargoTargetDir(args)

core.startGroup('Cleanup build scripts artifact directory')
const debugBuildDir = path.join(targetDir, 'debug', 'build')
if (existsSync(debugBuildDir)) {
await exec.exec('sudo', ['rm', '-rf', debugBuildDir], {
ignoreReturnCode: true
})
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('rm', ['-rf', debugBuildDir], {
ignoreReturnCode: true
})
} else {
await exec.exec('sudo', ['rm', '-rf', debugBuildDir], {
ignoreReturnCode: true
})
}
}
const releaseBuildDir = path.join(targetDir, 'release', 'build')
if (existsSync(debugBuildDir)) {
await exec.exec('sudo', ['rm', '-rf', releaseBuildDir], {
ignoreReturnCode: true
})
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('rm', ['-rf', releaseBuildDir], {
ignoreReturnCode: true
})
} else {
await exec.exec('sudo', ['rm', '-rf', releaseBuildDir], {
ignoreReturnCode: true
})
}
}
core.endGroup()

Expand Down Expand Up @@ -686,10 +706,10 @@ async function dockerBuild(
'_PYTHON_SYSCONFIGDATA_NAME',
...dockerEnvs,
'-v',
`${scriptPath}:${scriptPath}`,
`${hostScriptPath}:${scriptPath}`,
// Mount $GITHUB_WORKSPACE at the same path
'-v',
`${workspace}:${workspace}`,
`${hostWorkspace}:${workspace}`,
...dockerVolumes,
...dockerArgs,
image,
Expand All @@ -701,15 +721,28 @@ async function dockerBuild(
core.info(`Fixing file permissions for target directory: ${targetDir}`)
const uid = process.getuid()
const gid = process.getgid()
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', targetDir], {
ignoreReturnCode: true
})
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('chown', [`${uid}:${gid}`, '-R', targetDir], {
ignoreReturnCode: true
})
} else {
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', targetDir], {
ignoreReturnCode: true
})
}

const outDir = getCliValue(args, '--out') || getCliValue(args, '-o')
if (outDir && existsSync(outDir)) {
core.info(`Fixing file permissions for output directory: ${outDir}`)
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', outDir], {
ignoreReturnCode: true
})
if (process.env.RUNNER_ALLOW_RUNASROOT === '1') {
await exec.exec('chown', [`${uid}:${gid}`, '-R', outDir], {
ignoreReturnCode: true
})
} else {
await exec.exec('sudo', ['chown', `${uid}:${gid}`, '-R', outDir], {
ignoreReturnCode: true
})
}
}
core.endGroup()
}
Expand Down Expand Up @@ -924,6 +957,7 @@ async function innerMain(): Promise<void> {
const args = stringArgv(inputArgs)
const command = core.getInput('command')
const target = getRustTarget(args)
const hostHomeMount = core.getInput('host-home-mount')
let container = core.getInput('container')

if (process.env.CARGO_INCREMENTAL === undefined) {
Expand Down Expand Up @@ -995,7 +1029,12 @@ async function innerMain(): Promise<void> {
container
)
if (dockerContainer) {
exitCode = await dockerBuild(dockerContainer, maturinRelease, args)
exitCode = await dockerBuild(
dockerContainer,
maturinRelease,
hostHomeMount,
args
)
} else {
core.info('No Docker container found, fallback to build on host')
exitCode = await hostBuild(maturinRelease, args)
Expand Down
Loading