Skip to content
Open
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
10 changes: 8 additions & 2 deletions packages/adapters/src/runtime/build-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export async function runBuildPipeline(
await exec(
gitShellCommand(
gitInvocation,
`clone --progress --depth 50 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(env.projectDir)}`,
`clone --progress --depth 50 --recurse-submodules --shallow-submodules --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(env.projectDir)}`,
),
);
const commitPresent = await exec(
Expand All @@ -343,11 +343,17 @@ export async function runBuildPipeline(
`-c advice.detachedHead=false checkout ${sq(config.commitSha)}`,
)}`,
);
await exec(
`cd ${sq(env.projectDir)} && ${gitShellCommand(
gitInvocation,
"submodule update --init --recursive",
)}`,
);
} else {
await exec(
gitShellCommand(
gitInvocation,
`clone --progress --depth 1 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(env.projectDir)}`,
`clone --progress --depth 1 --recurse-submodules --shallow-submodules --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(env.projectDir)}`,
),
);
}
Expand Down
6 changes: 3 additions & 3 deletions packages/adapters/src/runtime/cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1502,18 +1502,18 @@ export class CloudRuntime implements MultiServiceRuntimeAdapter {
// See fetchCommand above for env-var rationale; --progress keeps
// the clone visible in the streamed log even though stdout/stderr
// are pipes, not a tty.
`GIT_TERMINAL_PROMPT=0 GIT_ASKPASS=/bin/echo git -c credential.helper= clone --progress ${depthArgs}--branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(cloneTarget)}`,
`GIT_TERMINAL_PROMPT=0 GIT_ASKPASS=/bin/echo git -c credential.helper= clone --progress ${depthArgs}--recurse-submodules --shallow-submodules --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(cloneTarget)}`,
].join("\n");
const checkoutCommand = config.commitSha
? `cd ${sq(cloneTarget)} && git -c credential.helper= -c advice.detachedHead=false checkout ${sq(config.commitSha)}`
? `cd ${sq(cloneTarget)} && git -c credential.helper= -c advice.detachedHead=false checkout ${sq(config.commitSha)} && GIT_TERMINAL_PROMPT=0 GIT_ASKPASS=/bin/echo git -c credential.helper= submodule update --init --recursive`
: "";
// No name-based pruning: a fresh clone already contains only git-tracked
// files (gitignored output was never committed), so pruning by name here
// would only risk deleting tracked source (e.g. a top-level `data/` dir).
// A tracked `.dockerignore` still applies at `docker build` on the worker.
const prepareCommand = [
"set -e",
`rm -rf ${sq(joinWorkspacePath(cloneTarget, ".git"))}`,
`find ${sq(cloneTarget)} -name .git -prune -exec rm -rf {} +`,
...prepareContextCommands,
'echo "Dockerfile context prepared."',
].join("\n");
Expand Down
26 changes: 21 additions & 5 deletions packages/adapters/src/runtime/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,16 @@ export class DockerRuntime implements RuntimeAdapter {
destDir: remoteContextDir,
onLog: (entry) => log.log(entry.message, parseLogLevel(entry.message)),
});
// Check for submodules. If present, the tarball is missing submodule contents.
const hasSubmodules = await executor
.exec(`test -f ${sq(`${remoteContextDir}/.gitmodules`)}`)
.then(
() => true,
() => false,
);
if (hasSubmodules) {
throw new Error("Repository contains submodules; tarball download is insufficient");
}
// A tarball has no .git, but strip defensively in case a repo tracks one.
await executor.exec(`rm -rf ${sq(`${remoteContextDir}/.git`)}`).catch(() => {});
return;
Expand Down Expand Up @@ -1791,7 +1801,7 @@ export class DockerRuntime implements RuntimeAdapter {
log.log(`Cloning ${config.repoUrl} on the server → ${remoteContextDir} (${authLabel})...\n`);
await executor.exec(`rm -rf ${dir} && mkdir -p ${dir}`);

const run = async (operation: "clone" | "fetch" | "checkout", cmd: string) => {
const run = async (operation: "clone" | "fetch" | "checkout" | "submodule", cmd: string) => {
const { code } = await executor.streamExec(cmd, (entry) =>
log.log(entry.message, parseLogLevel(entry.message)),
);
Expand All @@ -1808,7 +1818,7 @@ export class DockerRuntime implements RuntimeAdapter {
"clone",
gitShellCommand(
gitInvocation,
`clone --progress --depth 50 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${dir}`,
`clone --progress --depth 50 --recurse-submodules --shallow-submodules --branch ${sq(config.branch)} ${sq(cloneUrl)} ${dir}`,
),
);
const commitPresent = await executor
Expand All @@ -1834,17 +1844,23 @@ export class DockerRuntime implements RuntimeAdapter {
`-c advice.detachedHead=false checkout ${sq(config.commitSha)}`,
)}`,
);
await run(
"submodule",
`cd ${dir} && ${gitShellCommand(gitInvocation, "submodule update --init --recursive")}`,
);
} else {
await run(
"clone",
gitShellCommand(
gitInvocation,
`clone --progress --depth 1 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${dir}`,
`clone --progress --depth 1 --recurse-submodules --shallow-submodules --branch ${sq(config.branch)} ${sq(cloneUrl)} ${dir}`,
),
);
}
// Never ship .git into the build image.
await executor.exec(`rm -rf ${sq(`${remoteContextDir}/.git`)}`).catch(() => {});
// Never ship .git into the build image. Submodules may create .git files/dirs within the tree.
await executor
.exec(`find ${sq(remoteContextDir)} -name .git -prune -exec rm -rf {} +`)
.catch(() => {});
} finally {
await sshMaterial?.cleanup();
}
Expand Down