From 455dd3d9e098a10d0599c3ed7228d504489674f6 Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Thu, 21 Aug 2025 21:28:29 +0600 Subject: [PATCH 1/5] feat(git-clone module): added post_clone_script. Custom script to run after cloning the repository. Runs always after git clone, even if the repository already exists. --- registry/coder/modules/git-clone/main.tf | 9 +++++++++ registry/coder/modules/git-clone/run.sh | 14 +++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/registry/coder/modules/git-clone/main.tf b/registry/coder/modules/git-clone/main.tf index d03a59d72..2d547ad2b 100644 --- a/registry/coder/modules/git-clone/main.tf +++ b/registry/coder/modules/git-clone/main.tf @@ -62,6 +62,12 @@ variable "depth" { default = 0 } +variable "post_clone_script" { + description = "Custom script to run after cloning the repository. Runs always after git clone, even if the repository already exists." + type = string + default = null +} + locals { # Remove query parameters and fragments from the URL url = replace(replace(var.url, "/\\?.*/", ""), "/#.*/", "") @@ -81,6 +87,8 @@ locals { clone_path = var.base_dir != "" ? join("/", [var.base_dir, local.folder_name]) : join("/", ["~", local.folder_name]) # Construct the web URL web_url = startswith(local.clone_url, "git@") ? replace(replace(local.clone_url, ":", "/"), "git@", "https://") : local.clone_url + # Encode the post_clone_script for passing to the shell script + encoded_post_clone_script = var.post_clone_script != null ? base64encode(var.post_clone_script) : "" } output "repo_dir" { @@ -120,6 +128,7 @@ resource "coder_script" "git_clone" { REPO_URL : local.clone_url, BRANCH_NAME : local.branch_name, DEPTH = var.depth, + POST_CLONE_SCRIPT : local.encoded_post_clone_script, }) display_name = "Git Clone" icon = "/icon/git.svg" diff --git a/registry/coder/modules/git-clone/run.sh b/registry/coder/modules/git-clone/run.sh index 282c667ad..d4391f387 100644 --- a/registry/coder/modules/git-clone/run.sh +++ b/registry/coder/modules/git-clone/run.sh @@ -6,6 +6,7 @@ BRANCH_NAME="${BRANCH_NAME}" # Expand home if it's specified! CLONE_PATH="$${CLONE_PATH/#\~/$${HOME}}" DEPTH="${DEPTH}" +POST_CLONE_SCRIPT="${POST_CLONE_SCRIPT}" # Check if the variable is empty... if [ -z "$REPO_URL" ]; then @@ -52,5 +53,16 @@ if [ -z "$(ls -A "$CLONE_PATH")" ]; then fi else echo "$CLONE_PATH already exists and isn't empty, skipping clone!" - exit 0 fi + +# Run post-clone script if provided +if [ -n "$POST_CLONE_SCRIPT" ]; then + echo "Running post-clone script..." + echo "$POST_CLONE_SCRIPT" | base64 -d > /tmp/post_clone.sh + chmod +x /tmp/post_clone.sh + cd "$CLONE_PATH" + /tmp/post_clone.sh + rm /tmp/post_clone.sh +fi + +exit 0 From b42e4f9b11a8f9865cd81d834c2ea8f346312962 Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Thu, 21 Aug 2025 21:32:39 +0600 Subject: [PATCH 2/5] docs(git-clone module): add docs for post_clone_script --- registry/coder/modules/git-clone/README.md | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/registry/coder/modules/git-clone/README.md b/registry/coder/modules/git-clone/README.md index c12eb5909..45193f9f7 100644 --- a/registry/coder/modules/git-clone/README.md +++ b/registry/coder/modules/git-clone/README.md @@ -198,3 +198,26 @@ module "git-clone" { depth = 1 } ``` + +## Post-clone script + +Run a custom script after cloning the repository by setting the `post_clone_script` variable. +This is useful for running initialization tasks like installing dependencies or setting up the environment. + +```tf +module "git-clone" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/git-clone/coder" + version = "1.2.0" + agent_id = coder_agent.example.id + url = "https://github.com/coder/coder" + post_clone_script = <<-EOT + #!/bin/bash + echo "Repository cloned successfully!" + # Install dependencies + npm install + # Run any other initialization tasks + make setup + EOT +} +``` From 6fbdf40587cd4f8769be393704dc5e0b93f23e89 Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Thu, 21 Aug 2025 21:33:38 +0600 Subject: [PATCH 3/5] docs(git-clone module): add docs for post_clone_script --- registry/coder/modules/git-clone/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/registry/coder/modules/git-clone/README.md b/registry/coder/modules/git-clone/README.md index 45193f9f7..6c81c83a7 100644 --- a/registry/coder/modules/git-clone/README.md +++ b/registry/coder/modules/git-clone/README.md @@ -206,11 +206,11 @@ This is useful for running initialization tasks like installing dependencies or ```tf module "git-clone" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/git-clone/coder" - version = "1.2.0" - agent_id = coder_agent.example.id - url = "https://github.com/coder/coder" + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/git-clone/coder" + version = "1.2.0" + agent_id = coder_agent.example.id + url = "https://github.com/coder/coder" post_clone_script = <<-EOT #!/bin/bash echo "Repository cloned successfully!" From 8cd3b108dfe1d6e406b188c9b9ab4b0ab82e0361 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Wed, 8 Oct 2025 15:28:10 -0500 Subject: [PATCH 4/5] chore: bump git-clone module version to 1.2.0 --- registry/coder/modules/git-clone/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/registry/coder/modules/git-clone/README.md b/registry/coder/modules/git-clone/README.md index 6c81c83a7..03ad3855a 100644 --- a/registry/coder/modules/git-clone/README.md +++ b/registry/coder/modules/git-clone/README.md @@ -14,7 +14,7 @@ This module allows you to automatically clone a repository by URL and skip if it module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.com/coder/coder" } @@ -28,7 +28,7 @@ module "git-clone" { module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.com/coder/coder" base_dir = "~/projects/coder" @@ -43,7 +43,7 @@ To use with [Git Authentication](https://coder.com/docs/v2/latest/admin/git-prov module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.com/coder/coder" } @@ -69,7 +69,7 @@ data "coder_parameter" "git_repo" { module "git_clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = data.coder_parameter.git_repo.value } @@ -103,7 +103,7 @@ Configuring `git-clone` for a self-hosted GitHub Enterprise Server running at `g module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.example.com/coder/coder/tree/feat/example" git_providers = { @@ -122,7 +122,7 @@ To GitLab clone with a specific branch like `feat/example` module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://gitlab.com/coder/coder/-/tree/feat/example" } @@ -134,7 +134,7 @@ Configuring `git-clone` for a self-hosted GitLab running at `gitlab.example.com` module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://gitlab.example.com/coder/coder/-/tree/feat/example" git_providers = { @@ -155,7 +155,7 @@ For example, to clone the `feat/example` branch: module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.com/coder/coder" branch_name = "feat/example" @@ -173,7 +173,7 @@ For example, this will clone into the `~/projects/coder/coder-dev` folder: module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-clone/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.com/coder/coder" folder_name = "coder-dev" @@ -192,7 +192,7 @@ If not defined, the default, `0`, performs a full clone. module "git-clone" { count = data.coder_workspace.me.start_count source = "registry.coder.com/modules/git-clone/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.example.id url = "https://github.com/coder/coder" depth = 1 From 079f5670aeccdfe2535eac5cc981fca9741e2912 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Wed, 8 Oct 2025 15:29:21 -0500 Subject: [PATCH 5/5] feat: add post-clone script test, and update runs with git test since the exit code is no longer output the same way with the run.sh --- registry/coder/modules/git-clone/main.test.ts | 19 ++++++++++++++++++- registry/coder/modules/git-clone/run.sh | 2 -- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/git-clone/main.test.ts b/registry/coder/modules/git-clone/main.test.ts index 1e074fc02..0ae0a8dbf 100644 --- a/registry/coder/modules/git-clone/main.test.ts +++ b/registry/coder/modules/git-clone/main.test.ts @@ -30,11 +30,12 @@ describe("git-clone", async () => { url: "fake-url", }); const output = await executeScriptInContainer(state, "alpine/git"); - expect(output.exitCode).toBe(128); expect(output.stdout).toEqual([ "Creating directory ~/fake-url...", "Cloning fake-url to ~/fake-url...", ]); + expect(output.stderr.join(" ")).toContain("fatal"); + expect(output.stderr.join(" ")).toContain("fake-url"); }); it("repo_dir should match repo name for https", async () => { @@ -244,4 +245,20 @@ describe("git-clone", async () => { "Cloning https://github.com/michaelbrewer/repo-tests.log to ~/repo-tests.log on branch feat/branch...", ]); }); + + it("runs post-clone script", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + url: "fake-url", + post_clone_script: "echo 'Post-clone script executed'", + }); + const output = await executeScriptInContainer( + state, + "alpine/git", + "sh", + "mkdir -p ~/fake-url && echo 'existing' > ~/fake-url/file.txt", + ); + expect(output.stdout).toContain("Running post-clone script..."); + expect(output.stdout).toContain("Post-clone script executed"); + }); }); diff --git a/registry/coder/modules/git-clone/run.sh b/registry/coder/modules/git-clone/run.sh index d4391f387..07c970e9f 100644 --- a/registry/coder/modules/git-clone/run.sh +++ b/registry/coder/modules/git-clone/run.sh @@ -64,5 +64,3 @@ if [ -n "$POST_CLONE_SCRIPT" ]; then /tmp/post_clone.sh rm /tmp/post_clone.sh fi - -exit 0