feat(git-clone): replace depth, recurse_submodules, and clone_jobs with extra_args for flexible git clone options
This commit is contained in:
parent
d0629d2e28
commit
9d2e19de1a
@ -185,12 +185,12 @@ module "git-clone" {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Git shallow clone
|
## Extra `git clone` arguments
|
||||||
|
|
||||||
Limit the clone history to speed-up workspace startup by setting `depth`.
|
Pass any additional flags through `extra_args` (one element per argument).
|
||||||
|
This lets you enable anything `git clone` supports without the module having
|
||||||
When `depth` is greater than `0` the module runs `git clone --depth <depth>`.
|
to expose it explicitly — for example a shallow clone, submodules, parallel
|
||||||
If not defined, the default, `0`, performs a full clone.
|
fetches, or partial clones.
|
||||||
|
|
||||||
```tf
|
```tf
|
||||||
module "git-clone" {
|
module "git-clone" {
|
||||||
@ -199,27 +199,12 @@ module "git-clone" {
|
|||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
url = "https://github.com/coder/coder"
|
url = "https://github.com/coder/coder"
|
||||||
depth = 1
|
extra_args = [
|
||||||
}
|
"--depth=1",
|
||||||
```
|
"--recurse-submodules",
|
||||||
|
"--jobs=8",
|
||||||
## Recurse submodules
|
"--filter=blob:none",
|
||||||
|
]
|
||||||
Set `recurse_submodules = true` to initialize and clone submodules during the
|
|
||||||
clone (equivalent to `git clone --recurse-submodules`).
|
|
||||||
|
|
||||||
Pair it with `clone_jobs` to fetch submodules in parallel (equivalent to
|
|
||||||
`git clone --jobs <n>`) and speed up workspace start.
|
|
||||||
|
|
||||||
```tf
|
|
||||||
module "git-clone" {
|
|
||||||
count = data.coder_workspace.me.start_count
|
|
||||||
source = "registry.coder.com/coder/git-clone/coder"
|
|
||||||
version = "1.4.0"
|
|
||||||
agent_id = coder_agent.example.id
|
|
||||||
url = "https://github.com/coder/coder"
|
|
||||||
recurse_submodules = true
|
|
||||||
clone_jobs = 8
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -316,58 +316,24 @@ describe("git-clone", async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("defaults recurse_submodules to false and clone_jobs to 0", async () => {
|
it("defaults extra_args to empty", async () => {
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
url: "fake-url",
|
url: "fake-url",
|
||||||
});
|
});
|
||||||
const script = findResourceInstance(state, "coder_script").script;
|
const script = findResourceInstance(state, "coder_script").script;
|
||||||
expect(script).toContain('RECURSE_SUBMODULES="false"');
|
expect(script).toContain('EXTRA_ARGS_B64=""');
|
||||||
expect(script).toContain('CLONE_JOBS="0"');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets RECURSE_SUBMODULES=true when recurse_submodules is enabled", async () => {
|
it("passes extra_args to git clone", async () => {
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
url: "fake-url",
|
url: "fake-url",
|
||||||
recurse_submodules: "true",
|
extra_args: '["--recurse-submodules", "--jobs=8"]',
|
||||||
});
|
});
|
||||||
const script = findResourceInstance(state, "coder_script").script;
|
const output = await executeScriptInContainer(state, "alpine/git");
|
||||||
expect(script).toContain('RECURSE_SUBMODULES="true"');
|
expect(output.stdout).toContain(
|
||||||
});
|
"Running: git clone --recurse-submodules --jobs=8 fake-url /root/fake-url",
|
||||||
|
|
||||||
it("sets CLONE_JOBS when clone_jobs > 0", async () => {
|
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
|
||||||
agent_id: "foo",
|
|
||||||
url: "fake-url",
|
|
||||||
recurse_submodules: "true",
|
|
||||||
clone_jobs: "8",
|
|
||||||
});
|
|
||||||
const script = findResourceInstance(state, "coder_script").script;
|
|
||||||
expect(script).toContain('CLONE_JOBS="8"');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("rejects non-positive clone_jobs", async () => {
|
|
||||||
const t = async () => {
|
|
||||||
await runTerraformApply(import.meta.dir, {
|
|
||||||
agent_id: "foo",
|
|
||||||
url: "fake-url",
|
|
||||||
clone_jobs: "-1",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
expect(t).toThrow("clone_jobs must be a positive integer when set.");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("rejects clone_jobs without recurse_submodules", async () => {
|
|
||||||
const t = async () => {
|
|
||||||
await runTerraformApply(import.meta.dir, {
|
|
||||||
agent_id: "foo",
|
|
||||||
url: "fake-url",
|
|
||||||
clone_jobs: "4",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
expect(t).toThrow(
|
|
||||||
"clone_jobs only affects submodule fetching, so it requires recurse_submodules",
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 1.9"
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
required_providers {
|
required_providers {
|
||||||
coder = {
|
coder = {
|
||||||
@ -56,30 +56,10 @@ variable "folder_name" {
|
|||||||
default = ""
|
default = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "depth" {
|
variable "extra_args" {
|
||||||
description = "If > 0, perform a shallow clone using this depth."
|
description = "Extra arguments to pass to `git clone`, one element per argument (e.g. `[\"--recurse-submodules\", \"--jobs=8\", \"--filter=blob:none\"]`)."
|
||||||
type = number
|
type = list(string)
|
||||||
default = 0
|
default = []
|
||||||
}
|
|
||||||
|
|
||||||
variable "recurse_submodules" {
|
|
||||||
description = "If true, clone submodules recursively (equivalent to `git clone --recurse-submodules`)."
|
|
||||||
type = bool
|
|
||||||
default = false
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "clone_jobs" {
|
|
||||||
description = "If set, fetch submodules in parallel using this many jobs (equivalent to `git clone --jobs <n>`). Only takes effect when `recurse_submodules = true`."
|
|
||||||
type = number
|
|
||||||
default = null
|
|
||||||
validation {
|
|
||||||
condition = var.clone_jobs == null || var.clone_jobs > 0
|
|
||||||
error_message = "clone_jobs must be a positive integer when set."
|
|
||||||
}
|
|
||||||
validation {
|
|
||||||
condition = var.clone_jobs == null || var.recurse_submodules
|
|
||||||
error_message = "clone_jobs only affects submodule fetching, so it requires recurse_submodules = true."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "post_clone_script" {
|
variable "post_clone_script" {
|
||||||
@ -117,6 +97,8 @@ locals {
|
|||||||
encoded_post_clone_script = var.post_clone_script != null ? base64encode(var.post_clone_script) : ""
|
encoded_post_clone_script = var.post_clone_script != null ? base64encode(var.post_clone_script) : ""
|
||||||
# Encode the pre_clone_script for passing to the shell script
|
# Encode the pre_clone_script for passing to the shell script
|
||||||
encoded_pre_clone_script = var.pre_clone_script != null ? base64encode(var.pre_clone_script) : ""
|
encoded_pre_clone_script = var.pre_clone_script != null ? base64encode(var.pre_clone_script) : ""
|
||||||
|
# Encode extra clone args (newline-separated) so the shell script can split them into an array safely
|
||||||
|
encoded_extra_args = base64encode(join("\n", var.extra_args))
|
||||||
}
|
}
|
||||||
|
|
||||||
output "repo_dir" {
|
output "repo_dir" {
|
||||||
@ -155,9 +137,7 @@ resource "coder_script" "git_clone" {
|
|||||||
CLONE_PATH = local.clone_path,
|
CLONE_PATH = local.clone_path,
|
||||||
REPO_URL : local.clone_url,
|
REPO_URL : local.clone_url,
|
||||||
BRANCH_NAME : local.branch_name,
|
BRANCH_NAME : local.branch_name,
|
||||||
DEPTH = var.depth,
|
EXTRA_ARGS = local.encoded_extra_args,
|
||||||
RECURSE_SUBMODULES = tostring(var.recurse_submodules),
|
|
||||||
CLONE_JOBS = coalesce(var.clone_jobs, 0),
|
|
||||||
POST_CLONE_SCRIPT : local.encoded_post_clone_script,
|
POST_CLONE_SCRIPT : local.encoded_post_clone_script,
|
||||||
PRE_CLONE_SCRIPT : local.encoded_pre_clone_script,
|
PRE_CLONE_SCRIPT : local.encoded_pre_clone_script,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,9 +7,7 @@ CLONE_PATH="${CLONE_PATH}"
|
|||||||
BRANCH_NAME="${BRANCH_NAME}"
|
BRANCH_NAME="${BRANCH_NAME}"
|
||||||
# Expand home if it's specified!
|
# Expand home if it's specified!
|
||||||
CLONE_PATH="$${CLONE_PATH/#\~/$${HOME}}"
|
CLONE_PATH="$${CLONE_PATH/#\~/$${HOME}}"
|
||||||
DEPTH="${DEPTH}"
|
EXTRA_ARGS_B64="${EXTRA_ARGS}"
|
||||||
RECURSE_SUBMODULES="${RECURSE_SUBMODULES}"
|
|
||||||
CLONE_JOBS="${CLONE_JOBS}"
|
|
||||||
POST_CLONE_SCRIPT="${POST_CLONE_SCRIPT}"
|
POST_CLONE_SCRIPT="${POST_CLONE_SCRIPT}"
|
||||||
PRE_CLONE_SCRIPT="${PRE_CLONE_SCRIPT}"
|
PRE_CLONE_SCRIPT="${PRE_CLONE_SCRIPT}"
|
||||||
|
|
||||||
@ -50,14 +48,10 @@ fi
|
|||||||
|
|
||||||
# Build optional git clone flags
|
# Build optional git clone flags
|
||||||
CLONE_FLAGS=()
|
CLONE_FLAGS=()
|
||||||
if [ "$DEPTH" -gt 0 ]; then
|
if [ -n "$EXTRA_ARGS_B64" ]; then
|
||||||
CLONE_FLAGS+=(--depth "$DEPTH")
|
while IFS= read -r arg || [ -n "$arg" ]; do
|
||||||
fi
|
[ -n "$arg" ] && CLONE_FLAGS+=("$arg")
|
||||||
if [ "$RECURSE_SUBMODULES" = "true" ]; then
|
done < <(echo "$EXTRA_ARGS_B64" | base64 -d)
|
||||||
CLONE_FLAGS+=(--recurse-submodules)
|
|
||||||
fi
|
|
||||||
if [ "$CLONE_JOBS" -gt 0 ]; then
|
|
||||||
CLONE_FLAGS+=(--jobs "$CLONE_JOBS")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if the directory is empty
|
# Check if the directory is empty
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user