Compare commits

...

3 Commits

Author SHA1 Message Date
ikkz 297b07190f feat(git-clone): add pre_clone_script parameter (#887)
## Summary

Add `pre_clone_script` parameter to the git-clone module, allowing users
to run custom scripts before cloning a repository.

## Use Case

This solves SSH host key verification issues (e.g., "Host key
verification failed") by enabling users to configure SSH settings before
the clone operation, such as adding known hosts or setting
`StrictHostKeyChecking no`.

```tf
module "git-clone" {
  count            = data.coder_workspace.me.start_count
  source           = "registry.coder.com/coder/git-clone/coder"
  version          = "1.3.0"
  agent_id         = coder_agent.example.id
  url              = "git@github.com:org/repo.git"
  pre_clone_script = <<-EOT
    #!/bin/bash
    mkdir -p ~/.ssh
    echo -e "Host github.com\n    StrictHostKeyChecking no\n" > ~/.ssh/config
    chmod 600 ~/.ssh/config
  EOT
}
```

Ref:
https://discord.com/channels/747933592273027093/1447777180695396452/1447777180695396452

## Type of Change

- [ ] New module
- [ ] New template
- [ ] Bug fix
- [x] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Module Information

**Path:** `registry/coder/modules/git-clone`  
**New version:** `v1.3.0`  
**Breaking change:** [ ] Yes [x] No

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally

Co-authored-by: DevCats <christofer@coder.com>
2026-05-09 17:00:43 -05:00
Harsh Singh Panwar bce0897099 Fix(gemini): the Coder MCP server configuration (#882)
## Description

Fixed the Coder MCP server configuration

* Added the full path to the coder binary for Gemini
* Removed unnecessary configuration fields

<img width="1365" height="715" alt="Screenshot 2026-05-04 120727"
src="https://github.com/user-attachments/assets/35cdb18f-c4a5-437d-8ad6-38134104e5e6"
/>
<img width="1365" height="717" alt="Screenshot 2026-05-04 120836"
src="https://github.com/user-attachments/assets/bdce543e-dd7f-4122-b356-896d08e1fd3f"
/>

## Type of Change

- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Module Information

<!-- Delete this section if not applicable -->

**Path:** `registry/coder-labs/modules/gemini`  
**New version:** `v1.0.0`  
**Breaking change:** [ ] Yes [ ] No

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally

## Related Issues

fix: #881
2026-05-06 13:50:20 -05:00
DevCats 6b8d89daba fix(registry/coder-labs/modules/codex): align variable names with claude-code v5 (#885)
Aligns codex module variable names with the claude-code v5 conventions
established in #861 and #879.

- Rename `additional_mcp_servers` to `mcp` to match claude-code's
variable name.
- Change `codex_version` default from `""` to `"latest"` to match
`claude_code_version`.

## Type of Change

- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Module Information

**Path:** `registry/coder-labs/modules/codex`
**Breaking change:** [x] Yes [ ] No

> [!WARNING]
> Breaking change for anyone referencing `additional_mcp_servers` by
name. Since v5.0.0 was released and deleted on the same day (#879), this
should have zero downstream impact.

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally

## Related Issues

- Follow-up to #879
- Filed #886 to track adding `mcp_config_remote_path` support to codex

---
*This PR was authored by Coder Agents.*
2026-05-05 12:31:09 -05:00
11 changed files with 121 additions and 35 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ module "codex" {
preferred_auth_method = "apikey"
EOT
additional_mcp_servers = <<-EOT
mcp = <<-EOT
[mcp_servers.GitHub]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
@@ -246,7 +246,7 @@ describe("codex", async () => {
].join("\n");
const { id, scripts } = await setup({
moduleVariables: {
additional_mcp_servers: additional,
mcp: additional,
},
});
await runScripts(id, scripts);
+6 -6
View File
@@ -50,8 +50,8 @@ variable "install_codex" {
variable "codex_version" {
type = string
description = "The version of Codex to install. Empty string installs the latest available version."
default = ""
description = "The version of Codex to install."
default = "latest"
}
variable "openai_api_key" {
@@ -75,16 +75,16 @@ variable "base_config_toml" {
trust_level = "trusted"
When non-empty, the value is written verbatim as the base of config.toml;
additional_mcp_servers and AI Gateway sections are still appended after it.
mcp and AI Gateway sections are still appended after it.
Note: model_reasoning_effort and workdir trust are only applied in the
default config. Include them in your custom config if needed.
EOT
default = ""
}
variable "additional_mcp_servers" {
variable "mcp" {
type = string
description = "Additional MCP servers configuration in TOML format."
description = "MCP server configurations in TOML format. When set, servers are appended to the Codex config.toml."
default = ""
}
@@ -140,7 +140,7 @@ locals {
ARG_CODEX_VERSION = var.codex_version != "" ? base64encode(var.codex_version) : ""
ARG_WORKDIR = local.workdir != "" ? base64encode(local.workdir) : ""
ARG_BASE_CONFIG_TOML = var.base_config_toml != "" ? base64encode(var.base_config_toml) : ""
ARG_ADDITIONAL_MCP_SERVERS = var.additional_mcp_servers != "" ? base64encode(var.additional_mcp_servers) : ""
ARG_MCP = var.mcp != "" ? base64encode(var.mcp) : ""
ARG_ENABLE_AI_GATEWAY = tostring(var.enable_ai_gateway)
ARG_AIBRIDGE_CONFIG = var.enable_ai_gateway ? base64encode(local.aibridge_config) : ""
ARG_MODEL_REASONING_EFFORT = var.model_reasoning_effort
@@ -12,7 +12,7 @@ ARG_INSTALL='${ARG_INSTALL}'
ARG_CODEX_VERSION=$(echo -n '${ARG_CODEX_VERSION}' | base64 -d)
ARG_WORKDIR=$(echo -n '${ARG_WORKDIR}' | base64 -d)
ARG_BASE_CONFIG_TOML=$(echo -n '${ARG_BASE_CONFIG_TOML}' | base64 -d)
ARG_ADDITIONAL_MCP_SERVERS=$(echo -n '${ARG_ADDITIONAL_MCP_SERVERS}' | base64 -d)
ARG_MCP=$(echo -n '${ARG_MCP}' | base64 -d)
ARG_ENABLE_AI_GATEWAY='${ARG_ENABLE_AI_GATEWAY}'
ARG_AIBRIDGE_CONFIG=$(echo -n '${ARG_AIBRIDGE_CONFIG}' | base64 -d)
ARG_MODEL_REASONING_EFFORT='${ARG_MODEL_REASONING_EFFORT}'
@@ -150,9 +150,9 @@ function populate_config_toml() {
write_minimal_default_config "$${config_path}"
fi
if [ -n "$${ARG_ADDITIONAL_MCP_SERVERS}" ]; then
printf "Adding additional MCP servers\n"
echo "$${ARG_ADDITIONAL_MCP_SERVERS}" >> "$${config_path}"
if [ -n "$${ARG_MCP}" ]; then
printf "Adding MCP servers\n"
echo "$${ARG_MCP}" >> "$${config_path}"
fi
if [ "$${ARG_ENABLE_AI_GATEWAY}" = "true" ] && [ -n "$${ARG_AIBRIDGE_CONFIG}" ]; then
+20 -4
View File
@@ -13,7 +13,7 @@ Run [Gemini CLI](https://github.com/google-gemini/gemini-cli) in your workspace
```tf
module "gemini" {
source = "registry.coder.com/coder-labs/gemini/coder"
version = "3.0.0"
version = "3.0.1"
agent_id = coder_agent.main.id
folder = "/home/coder/project"
}
@@ -46,7 +46,7 @@ variable "gemini_api_key" {
module "gemini" {
source = "registry.coder.com/coder-labs/gemini/coder"
version = "3.0.0"
version = "3.0.1"
agent_id = coder_agent.main.id
gemini_api_key = var.gemini_api_key
folder = "/home/coder/project"
@@ -94,7 +94,7 @@ data "coder_parameter" "ai_prompt" {
module "gemini" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder-labs/gemini/coder"
version = "3.0.0"
version = "3.0.1"
agent_id = coder_agent.main.id
gemini_api_key = var.gemini_api_key
gemini_model = "gemini-2.5-flash"
@@ -105,6 +105,22 @@ module "gemini" {
You are a helpful coding assistant. Always explain your code changes clearly.
YOU MUST REPORT ALL TASKS TO CODER.
EOT
pre_install_script = <<-EOT
#!/bin/bash
set -e
echo "Installing Node.js via NodeSource..."
sudo apt-get update -qq && sudo apt-get install -y curl ca-certificates
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo bash -
sudo apt-get install -y nodejs
echo "Node version: $(node -v)"
echo "npm version: $(npm -v)"
echo "Node install complete."
EOT
}
```
@@ -118,7 +134,7 @@ For enterprise users who prefer Google's Vertex AI platform:
```tf
module "gemini" {
source = "registry.coder.com/coder-labs/gemini/coder"
version = "3.0.0"
version = "3.0.1"
agent_id = coder_agent.main.id
gemini_api_key = var.gemini_api_key
folder = "/home/coder/project"
+2 -8
View File
@@ -148,22 +148,16 @@ locals {
base_extensions = <<-EOT
{
"coder": {
"command": "coder",
"args": [
"exp",
"mcp",
"server"
],
"command": "coder",
"description": "Report ALL tasks and statuses (in progress, done, failed) you are working on.",
"enabled": true,
"env": {
"CODER_MCP_APP_STATUS_SLUG": "${local.app_slug}",
"CODER_MCP_AI_AGENTAPI_URL": "http://localhost:3284"
},
"name": "Coder",
"timeout": 3000,
"type": "stdio",
"trust": true
}
}
}
EOT
@@ -17,6 +17,7 @@ echo "--------------------------------"
printf "gemini_config: %s\n" "$ARG_GEMINI_CONFIG"
printf "install: %s\n" "$ARG_INSTALL"
printf "gemini_version: %s\n" "$ARG_GEMINI_VERSION"
printf "BASE_EXTENSIONS: %s\n" "$BASE_EXTENSIONS"
echo "--------------------------------"
set +o nounset
@@ -140,6 +141,25 @@ function add_system_prompt_if_exists() {
fi
}
function patch_coder_mcp_command() {
CODER_BIN=$(which coder)
SETTINGS_PATH="$HOME/.gemini/settings.json"
if [ -z "$CODER_BIN" ]; then
printf "Warning: could not find coder binary, MCP command path not patched.\n"
return
fi
printf "Patching coder MCP command path to: %s\n" "$CODER_BIN"
TMP_SETTINGS=$(mktemp)
jq --arg bin "$CODER_BIN" \
'.mcpServers.coder.command = $bin' \
"$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH"
printf "Patch complete.\n"
}
function configure_mcp() {
export CODER_MCP_APP_STATUS_SLUG="gemini"
export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284"
@@ -149,4 +169,5 @@ function configure_mcp() {
install_gemini
populate_settings_json
add_system_prompt_if_exists
patch_coder_mcp_command
configure_mcp
+34 -11
View File
@@ -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.2.3"
version = "1.3.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.2.3"
version = "1.3.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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
}
@@ -70,7 +70,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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = data.coder_parameter.git_repo.value
}
@@ -105,7 +105,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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.example.com/coder/coder/tree/feat/example"
git_providers = {
@@ -125,7 +125,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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://gitlab.com/coder/coder/-/tree/feat/example"
}
@@ -137,7 +137,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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://gitlab.example.com/coder/coder/-/tree/feat/example"
git_providers = {
@@ -159,7 +159,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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
branch_name = "feat/example"
@@ -177,7 +177,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.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
folder_name = "coder-dev"
@@ -196,13 +196,36 @@ If not defined, the default, `0`, performs a full clone.
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
depth = 1
}
```
## Pre-clone script
Run a custom script before cloning the repository by setting the `pre_clone_script` variable.
This is useful for preparing the environment or validating prerequisites before cloning.
```tf
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
pre_clone_script = <<-EOT
#!/bin/bash
echo "Preparing to clone repository..."
# Check prerequisites
command -v npm >/dev/null 2>&1 || { echo "npm is required but not installed."; exit 1; }
# Set up environment
export NODE_ENV=development
EOT
}
```
## Post-clone script
Run a custom script after cloning the repository by setting the `post_clone_script` variable.
@@ -212,7 +235,7 @@ This is useful for running initialization tasks like installing dependencies or
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.2.3"
version = "1.3.0"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
post_clone_script = <<-EOT
@@ -261,4 +261,16 @@ describe("git-clone", async () => {
expect(output.stdout).toContain("Running post-clone script...");
expect(output.stdout).toContain("Post-clone script executed");
});
it("runs pre-clone script", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
url: "fake-url",
pre_clone_script: "echo 'Pre-clone script executed'",
});
const output = await executeScriptInContainer(state, "alpine/git");
expect(output.stdout).toContain("Running pre-clone script...");
expect(output.stdout).toContain("Pre-clone script executed");
expect(output.stdout).toContain("Cloning fake-url to ~/fake-url...");
});
});
+9
View File
@@ -68,6 +68,12 @@ variable "post_clone_script" {
default = null
}
variable "pre_clone_script" {
description = "Custom script to run before cloning the repository. Runs before 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, "/\\?.*/", ""), "/#.*/", "")
@@ -89,6 +95,8 @@ locals {
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) : ""
# 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) : ""
}
output "repo_dir" {
@@ -129,6 +137,7 @@ resource "coder_script" "git_clone" {
BRANCH_NAME : local.branch_name,
DEPTH = var.depth,
POST_CLONE_SCRIPT : local.encoded_post_clone_script,
PRE_CLONE_SCRIPT : local.encoded_pre_clone_script,
})
display_name = "Git Clone"
icon = "/icon/git.svg"
+11
View File
@@ -7,6 +7,7 @@ BRANCH_NAME="${BRANCH_NAME}"
CLONE_PATH="$${CLONE_PATH/#\~/$${HOME}}"
DEPTH="${DEPTH}"
POST_CLONE_SCRIPT="${POST_CLONE_SCRIPT}"
PRE_CLONE_SCRIPT="${PRE_CLONE_SCRIPT}"
# Check if the variable is empty...
if [ -z "$REPO_URL" ]; then
@@ -33,6 +34,16 @@ if [ ! -d "$CLONE_PATH" ]; then
mkdir -p "$CLONE_PATH"
fi
# Run pre-clone script if provided
if [ -n "$PRE_CLONE_SCRIPT" ]; then
echo "Running pre-clone script..."
PRE_CLONE_TMP=$(mktemp)
echo "$PRE_CLONE_SCRIPT" | base64 -d > "$PRE_CLONE_TMP"
chmod +x "$PRE_CLONE_TMP"
$PRE_CLONE_TMP
rm "$PRE_CLONE_TMP"
fi
# Check if the directory is empty
# and if it is, clone the repo, otherwise skip cloning
if [ -z "$(ls -A "$CLONE_PATH")" ]; then