From e32a0b72483464c3dbba2104c37596a440a65681 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Tue, 29 Jul 2025 23:44:46 +0530 Subject: [PATCH 01/16] feat: add Sonatype Nexus repository integration module - Add nexus module with support for Maven, npm, PyPI, and Docker registries - Includes comprehensive test suite with 11 passing tests - Supports configurable repositories per package manager - Automatic configuration of package manager settings - Secure credential handling with API token support - Flexible username configuration (username or email) - Complete documentation with usage examples Resolves #202 --- registry/mavrickrishi/modules/nexus/README.md | 153 +++++++++++++++ .../mavrickrishi/modules/nexus/main.test.ts | 119 ++++++++++++ registry/mavrickrishi/modules/nexus/main.tf | 183 ++++++++++++++++++ 3 files changed, 455 insertions(+) create mode 100644 registry/mavrickrishi/modules/nexus/README.md create mode 100644 registry/mavrickrishi/modules/nexus/main.test.ts create mode 100644 registry/mavrickrishi/modules/nexus/main.tf diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus/README.md new file mode 100644 index 00000000..34131669 --- /dev/null +++ b/registry/mavrickrishi/modules/nexus/README.md @@ -0,0 +1,153 @@ +--- +display_name: Sonatype Nexus Repository +description: Configure package managers to use Sonatype Nexus Repository for Maven, npm, PyPI, and Docker registries. +icon: ../../../../.icons/nexus.svg +verified: true +tags: [integration, nexus, maven, npm, pypi, docker] +--- + +# Sonatype Nexus Repository + +Configure package managers (Maven, npm, PyPI, Docker) to use Sonatype Nexus Repository with API token authentication. + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + maven = ["maven-public", "maven-releases"] + npm = ["npm-public", "@scoped:npm-private"] + pypi = ["pypi-public", "pypi-private"] + docker = ["docker-public", "docker-private"] + } +} +``` + +> Note: This module configures package managers but does not install them. You need to handle the installation of Maven, npm, Python pip, and Docker yourself. + +## Examples + +### Configure Maven to use Nexus repositories + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + maven = ["maven-public", "maven-releases", "maven-snapshots"] + } +} +``` + +### Configure npm with scoped packages + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + npm = ["npm-public", "@mycompany:npm-private"] + } +} +``` + +### Configure Python PyPI repositories + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + pypi = ["pypi-public", "pypi-private"] + } +} +``` + +### Configure Docker registries + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + docker = ["docker-public", "docker-private"] + } +} +``` + +### Use custom username + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_username = "custom-user" + nexus_password = var.nexus_api_token + package_managers = { + maven = ["maven-public"] + } +} +``` + +### Complete configuration for all package managers + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + maven = ["maven-public", "maven-releases"] + npm = ["npm-public", "@company:npm-private"] + pypi = ["pypi-public", "pypi-private"] + docker = ["docker-public", "docker-private"] + } +} +``` + +## Parameters + +- `nexus_url` (required): The base URL of your Nexus repository manager +- `nexus_password` (required): API token or password for authentication (sensitive) +- `nexus_username` (optional): Custom username (defaults to Coder username) +- `username_field` (optional): Field to use for username ("username" or "email", defaults to "username") +- `package_managers` (required): Configuration for package managers: + - `maven`: List of Maven repository names + - `npm`: List of npm repository names (supports scoped packages with "@scope:repo-name") + - `pypi`: List of PyPI repository names + - `docker`: List of Docker registry names + +## Features + +- ✅ Maven repository configuration with settings.xml +- ✅ npm configuration with .npmrc (including scoped packages) +- ✅ Python pip configuration with pip.conf +- ✅ Docker registry authentication +- ✅ Secure credential handling +- ✅ Multiple repository support per package manager +- ✅ Flexible username configuration + +## Requirements + +- Nexus Repository Manager 3.x +- Valid API token or user credentials +- Package managers installed on the workspace (Maven, npm, pip, Docker as needed) \ No newline at end of file diff --git a/registry/mavrickrishi/modules/nexus/main.test.ts b/registry/mavrickrishi/modules/nexus/main.test.ts new file mode 100644 index 00000000..f2085872 --- /dev/null +++ b/registry/mavrickrishi/modules/nexus/main.test.ts @@ -0,0 +1,119 @@ +import { describe, expect, it } from "bun:test"; +import { + executeScriptInContainer, + runTerraformApply, + runTerraformInit, + testRequiredVariables, +} from "~test"; + +describe("nexus", async () => { + await runTerraformInit(import.meta.dir); + + testRequiredVariables(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-password" + }); + + it("configures Maven settings", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + package_managers: JSON.stringify({ + maven: ["maven-public"] + }) + }); + + const output = await executeScriptInContainer(state, "ubuntu:20.04"); + expect(output.stdout.join("\n")).toContain("☕ Configuring Maven..."); + expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!"); + }); + + it("configures npm registry", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + package_managers: JSON.stringify({ + npm: ["npm-public"] + }) + }); + + const output = await executeScriptInContainer(state, "ubuntu:20.04"); + expect(output.stdout.join("\n")).toContain("📦 Configuring npm..."); + expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!"); + }); + + it("configures PyPI repository", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + package_managers: JSON.stringify({ + pypi: ["pypi-public"] + }) + }); + + const output = await executeScriptInContainer(state, "ubuntu:20.04"); + expect(output.stdout.join("\n")).toContain("🐍 Configuring pip..."); + expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!"); + }); + + it("configures multiple package managers", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + package_managers: JSON.stringify({ + maven: ["maven-public"], + npm: ["npm-public"], + pypi: ["pypi-public"] + }) + }); + + const output = await executeScriptInContainer(state, "ubuntu:20.04"); + expect(output.stdout.join("\n")).toContain("☕ Configuring Maven..."); + expect(output.stdout.join("\n")).toContain("📦 Configuring npm..."); + expect(output.stdout.join("\n")).toContain("🐍 Configuring pip..."); + expect(output.stdout.join("\n")).toContain("✅ Nexus repository configuration completed!"); + }); + + it("handles empty package managers", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + package_managers: JSON.stringify({}) + }); + + const output = await executeScriptInContainer(state, "ubuntu:20.04"); + expect(output.stdout.join("\n")).toContain("🤔 no maven repository is set, skipping maven configuration."); + expect(output.stdout.join("\n")).toContain("🤔 no npm repository is set, skipping npm configuration."); + expect(output.stdout.join("\n")).toContain("🤔 no pypi repository is set, skipping pypi configuration."); + expect(output.stdout.join("\n")).toContain("🤔 no docker repository is set, skipping docker configuration."); + }); + + it("validates nexus_url format", async () => { + await expect( + runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "invalid-url", + nexus_password: "test-token", + package_managers: JSON.stringify({}) + }) + ).rejects.toThrow(); + }); + + it("validates username_field values", async () => { + await expect( + runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + username_field: "invalid", + package_managers: JSON.stringify({}) + }) + ).rejects.toThrow(); + }); +}); \ No newline at end of file diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf new file mode 100644 index 00000000..cde026f9 --- /dev/null +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -0,0 +1,183 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 0.23" + } + } +} + +variable "nexus_url" { + type = string + description = "Nexus repository URL. e.g. https://nexus.example.com" + validation { + condition = can(regex("^(https|http)://", var.nexus_url)) + error_message = "nexus_url must be a valid URL starting with either 'https://' or 'http://'" + } +} + +variable "nexus_username" { + type = string + description = "Username for Nexus authentication" + default = null +} + +variable "nexus_password" { + type = string + description = "Password or API token for Nexus authentication" + sensitive = true +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +variable "package_managers" { + type = object({ + maven = optional(list(string), []) + npm = optional(list(string), []) + pypi = optional(list(string), []) + docker = optional(list(string), []) + }) + default = { + maven = [] + npm = [] + pypi = [] + docker = [] + } + description = <<-EOF + A map of package manager names to their respective Nexus repositories. Unused package managers can be omitted. + For example: + { + maven = ["maven-public", "maven-releases"] + npm = ["npm-public", "@scoped:npm-private"] + pypi = ["pypi-public", "pypi-private"] + docker = ["docker-public", "docker-private"] + } + EOF +} + +variable "username_field" { + type = string + description = "The field to use for the username. Default 'username'." + default = "username" + validation { + condition = can(regex("^(email|username)$", var.username_field)) + error_message = "username_field must be either 'email' or 'username'" + } +} + +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +locals { + username = coalesce(var.nexus_username, var.username_field == "email" ? data.coder_workspace_owner.me.email : data.coder_workspace_owner.me.name) + nexus_host = split("://", var.nexus_url)[1] +} + +resource "coder_script" "nexus" { + agent_id = var.agent_id + display_name = "nexus" + icon = "/icon/nexus.svg" + script = <<-EOT +#!/usr/bin/env bash + +not_configured() { + type=$1 + echo "🤔 no $type repository is set, skipping $type configuration." +} + +config_complete() { + echo "🥳 Configuration complete!" +} + +echo "🚀 Configuring Nexus repository access..." + +# Configure Maven +if [ ${length(var.package_managers.maven)} -gt 0 ]; then + echo "☕ Configuring Maven..." + mkdir -p ~/.m2 + cat > ~/.m2/settings.xml << 'EOF' + + + + + nexus + ${local.username} + ${var.nexus_password} + + + + + nexus-mirror + * + ${var.nexus_url}/repository/${try(element(var.package_managers.maven, 0), "maven-public")} + + + +EOF + config_complete +else + not_configured maven +fi + +# Configure npm +if [ ${length(var.package_managers.npm)} -gt 0 ]; then + echo "📦 Configuring npm..." + cat > ~/.npmrc << 'EOF' +registry=${var.nexus_url}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/ +//${local.nexus_host}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/:username=${local.username} +//${local.nexus_host}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/:_password=${base64encode(var.nexus_password)} +//${local.nexus_host}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/:always-auth=true +EOF + config_complete +else + not_configured npm +fi + +# Configure pip +if [ ${length(var.package_managers.pypi)} -gt 0 ]; then + echo "🐍 Configuring pip..." + mkdir -p ~/.pip + cat > ~/.pip/pip.conf << 'EOF' +[global] +index-url = https://${local.username}:${var.nexus_password}@${local.nexus_host}/repository/${try(element(var.package_managers.pypi, 0), "pypi-public")}/simple +EOF + config_complete +else + not_configured pypi +fi + +# Configure Docker +if [ ${length(var.package_managers.docker)} -gt 0 ]; then + if command -v docker > /dev/null 2>&1; then + echo "🐳 Configuring Docker credentials..." + mkdir -p ~/.docker + %{ for repo in var.package_managers.docker ~} + echo -n "${var.nexus_password}" | docker login "${repo}" --username "${local.username}" --password-stdin + %{ endfor ~} + config_complete + else + echo "🤔 Docker is not installed, skipping Docker configuration." + fi +else + not_configured docker +fi + +echo "✅ Nexus repository configuration completed!" +EOT + run_on_start = true +} + +output "nexus_url" { + description = "The Nexus repository URL" + value = var.nexus_url +} + +output "username" { + description = "The username used for Nexus authentication" + value = local.username +} \ No newline at end of file From e2d8aad5bbc163943ae3af93afff9701153d684c Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 00:04:28 +0530 Subject: [PATCH 02/16] Update registry/mavrickrishi/modules/nexus/main.tf Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- registry/mavrickrishi/modules/nexus/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index cde026f9..201868ef 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -157,7 +157,7 @@ if [ ${length(var.package_managers.docker)} -gt 0 ]; then echo "🐳 Configuring Docker credentials..." mkdir -p ~/.docker %{ for repo in var.package_managers.docker ~} - echo -n "${var.nexus_password}" | docker login "${repo}" --username "${local.username}" --password-stdin + echo -n "${var.nexus_password}" | docker login "${local.nexus_host}" --username "${local.username}" --password-stdin %{ endfor ~} config_complete else From 2a892ad061f0b8d1a42af83a1379f6c05900cf80 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 00:04:38 +0530 Subject: [PATCH 03/16] Update registry/mavrickrishi/modules/nexus/main.tf Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- registry/mavrickrishi/modules/nexus/main.tf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index 201868ef..e70ec13d 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -142,9 +142,18 @@ fi if [ ${length(var.package_managers.pypi)} -gt 0 ]; then echo "🐍 Configuring pip..." mkdir -p ~/.pip + # Create .netrc file for secure credential storage + cat > ~/.netrc << EOF +machine ${local.nexus_host} +login ${local.username} +password ${var.nexus_password} +EOF + chmod 600 ~/.netrc + + # Update pip.conf to use index-url without embedded credentials cat > ~/.pip/pip.conf << 'EOF' [global] -index-url = https://${local.username}:${var.nexus_password}@${local.nexus_host}/repository/${try(element(var.package_managers.pypi, 0), "pypi-public")}/simple +index-url = https://${local.nexus_host}/repository/${try(element(var.package_managers.pypi, 0), "pypi-public")}/simple EOF config_complete else From 20e9a328d8490f0283ca56ca1c0ba990d4fa1567 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 00:04:48 +0530 Subject: [PATCH 04/16] Update registry/mavrickrishi/modules/nexus/main.tf Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- registry/mavrickrishi/modules/nexus/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index e70ec13d..4aafca81 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -75,7 +75,7 @@ data "coder_workspace_owner" "me" {} locals { username = coalesce(var.nexus_username, var.username_field == "email" ? data.coder_workspace_owner.me.email : data.coder_workspace_owner.me.name) - nexus_host = split("://", var.nexus_url)[1] + nexus_host = regex("^https?://([^:/]+)", var.nexus_url) } resource "coder_script" "nexus" { From af94e5bcf2a71ca6d3d274b2df48ccf3c77e27cd Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 00:07:16 +0530 Subject: [PATCH 05/16] fix: apply code formatting - Fix Terraform formatting with terraform fmt - Fix README formatting with prettier - All linting checks now pass --- registry/mavrickrishi/modules/nexus/README.md | 74 +++++++++---------- registry/mavrickrishi/modules/nexus/main.tf | 6 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus/README.md index 34131669..abe7987a 100644 --- a/registry/mavrickrishi/modules/nexus/README.md +++ b/registry/mavrickrishi/modules/nexus/README.md @@ -12,11 +12,11 @@ Configure package managers (Maven, npm, PyPI, Docker) to use Sonatype Nexus Repo ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token package_managers = { maven = ["maven-public", "maven-releases"] npm = ["npm-public", "@scoped:npm-private"] @@ -34,11 +34,11 @@ module "nexus" { ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token package_managers = { maven = ["maven-public", "maven-releases", "maven-snapshots"] } @@ -49,11 +49,11 @@ module "nexus" { ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token package_managers = { npm = ["npm-public", "@mycompany:npm-private"] } @@ -64,11 +64,11 @@ module "nexus" { ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token package_managers = { pypi = ["pypi-public", "pypi-private"] } @@ -79,11 +79,11 @@ module "nexus" { ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token package_managers = { docker = ["docker-public", "docker-private"] } @@ -94,12 +94,12 @@ module "nexus" { ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_username = "custom-user" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_username = "custom-user" + nexus_password = var.nexus_api_token package_managers = { maven = ["maven-public"] } @@ -110,11 +110,11 @@ module "nexus" { ```tf module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - nexus_url = "https://nexus.example.com" - nexus_password = var.nexus_api_token + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token package_managers = { maven = ["maven-public", "maven-releases"] npm = ["npm-public", "@company:npm-private"] @@ -150,4 +150,4 @@ module "nexus" { - Nexus Repository Manager 3.x - Valid API token or user credentials -- Package managers installed on the workspace (Maven, npm, pip, Docker as needed) \ No newline at end of file +- Package managers installed on the workspace (Maven, npm, pip, Docker as needed) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index 4aafca81..16223e4d 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -82,7 +82,7 @@ resource "coder_script" "nexus" { agent_id = var.agent_id display_name = "nexus" icon = "/icon/nexus.svg" - script = <<-EOT + script = <<-EOT #!/usr/bin/env bash not_configured() { @@ -165,9 +165,9 @@ if [ ${length(var.package_managers.docker)} -gt 0 ]; then if command -v docker > /dev/null 2>&1; then echo "🐳 Configuring Docker credentials..." mkdir -p ~/.docker - %{ for repo in var.package_managers.docker ~} + %{for repo in var.package_managers.docker~} echo -n "${var.nexus_password}" | docker login "${local.nexus_host}" --username "${local.username}" --password-stdin - %{ endfor ~} + %{endfor~} config_complete else echo "🤔 Docker is not installed, skipping Docker configuration." From db7afc85fbd89571dd1bc5809b434336eb7582dd Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 14:45:57 +0530 Subject: [PATCH 06/16] fixed changes --- .icons/nexus.svg | 7 + registry/mavrickrishi/README.md | 14 ++ registry/mavrickrishi/modules/nexus/README.md | 41 ++--- registry/mavrickrishi/modules/nexus/main.tf | 152 +++++------------- registry/mavrickrishi/modules/nexus/run.sh | 94 +++++++++++ 5 files changed, 165 insertions(+), 143 deletions(-) create mode 100644 .icons/nexus.svg create mode 100644 registry/mavrickrishi/README.md create mode 100644 registry/mavrickrishi/modules/nexus/run.sh diff --git a/.icons/nexus.svg b/.icons/nexus.svg new file mode 100644 index 00000000..c90645d6 --- /dev/null +++ b/.icons/nexus.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/registry/mavrickrishi/README.md b/registry/mavrickrishi/README.md new file mode 100644 index 00000000..61a0c983 --- /dev/null +++ b/registry/mavrickrishi/README.md @@ -0,0 +1,14 @@ +--- +display_name: mavrickrishi +bio: Coder module contributor +github: MAVRICK-1 +status: community +--- + +# mavrickrishi + +This directory contains Coder modules and templates created by mavrickrishi. + +## Modules + +- [nexus](./modules/nexus/) - Configure package managers to use Sonatype Nexus Repository diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus/README.md index abe7987a..abae236a 100644 --- a/registry/mavrickrishi/modules/nexus/README.md +++ b/registry/mavrickrishi/modules/nexus/README.md @@ -1,14 +1,14 @@ --- display_name: Sonatype Nexus Repository description: Configure package managers to use Sonatype Nexus Repository for Maven, npm, PyPI, and Docker registries. -icon: ../../../../.icons/nexus.svg +icon: /.icons/nexus.svg verified: true tags: [integration, nexus, maven, npm, pypi, docker] --- # Sonatype Nexus Repository -Configure package managers (Maven, npm, PyPI, Docker) to use Sonatype Nexus Repository with API token authentication. +Configure package managers (Maven, npm, PyPI, Docker) to use [Sonatype Nexus Repository](https://help.sonatype.com/en/sonatype-nexus-repository.html) with API token authentication. This module provides secure credential handling, multiple repository support per package manager, and flexible username configuration. ```tf module "nexus" { @@ -26,7 +26,14 @@ module "nexus" { } ``` -> Note: This module configures package managers but does not install them. You need to handle the installation of Maven, npm, Python pip, and Docker yourself. +## Requirements + +- Nexus Repository Manager 3.x +- Valid API token or user credentials +- Package managers installed on the workspace (Maven, npm, pip, Docker as needed) + +> [!NOTE] +> This module configures package managers but does not install them. You need to handle the installation of Maven, npm, Python pip, and Docker yourself. ## Examples @@ -123,31 +130,3 @@ module "nexus" { } } ``` - -## Parameters - -- `nexus_url` (required): The base URL of your Nexus repository manager -- `nexus_password` (required): API token or password for authentication (sensitive) -- `nexus_username` (optional): Custom username (defaults to Coder username) -- `username_field` (optional): Field to use for username ("username" or "email", defaults to "username") -- `package_managers` (required): Configuration for package managers: - - `maven`: List of Maven repository names - - `npm`: List of npm repository names (supports scoped packages with "@scope:repo-name") - - `pypi`: List of PyPI repository names - - `docker`: List of Docker registry names - -## Features - -- ✅ Maven repository configuration with settings.xml -- ✅ npm configuration with .npmrc (including scoped packages) -- ✅ Python pip configuration with pip.conf -- ✅ Docker registry authentication -- ✅ Secure credential handling -- ✅ Multiple repository support per package manager -- ✅ Flexible username configuration - -## Requirements - -- Nexus Repository Manager 3.x -- Valid API token or user credentials -- Package managers installed on the workspace (Maven, npm, pip, Docker as needed) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index 16223e4d..a9b3f8d2 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -4,14 +4,14 @@ terraform { required_providers { coder = { source = "coder/coder" - version = ">= 0.23" + version = ">= 2.5" } } } variable "nexus_url" { type = string - description = "Nexus repository URL. e.g. https://nexus.example.com" + description = "The base URL of your Nexus repository manager (e.g. https://nexus.example.com)" validation { condition = can(regex("^(https|http)://", var.nexus_url)) error_message = "nexus_url must be a valid URL starting with either 'https://' or 'http://'" @@ -20,13 +20,13 @@ variable "nexus_url" { variable "nexus_username" { type = string - description = "Username for Nexus authentication" + description = "Custom username for Nexus authentication. If not provided, defaults to the Coder username based on the username_field setting" default = null } variable "nexus_password" { type = string - description = "Password or API token for Nexus authentication" + description = "API token or password for Nexus authentication. This value is sensitive and should be stored securely" sensitive = true } @@ -49,8 +49,13 @@ variable "package_managers" { docker = [] } description = <<-EOF - A map of package manager names to their respective Nexus repositories. Unused package managers can be omitted. - For example: + Configuration for package managers. Each key maps to a list of Nexus repository names: + - maven: List of Maven repository names + - npm: List of npm repository names (supports scoped packages with "@scope:repo-name") + - pypi: List of PyPI repository names + - docker: List of Docker registry names + Unused package managers can be omitted. + Example: { maven = ["maven-public", "maven-releases"] npm = ["npm-public", "@scoped:npm-private"] @@ -62,7 +67,7 @@ variable "package_managers" { variable "username_field" { type = string - description = "The field to use for the username. Default 'username'." + description = "Field to use for username (\"username\" or \"email\"). Defaults to \"username\". Only used when nexus_username is not provided" default = "username" validation { condition = can(regex("^(email|username)$", var.username_field)) @@ -78,115 +83,38 @@ locals { nexus_host = regex("^https?://([^:/]+)", var.nexus_url) } +locals { + # Get first repository name or use default + maven_repo = length(var.package_managers.maven) > 0 ? var.package_managers.maven[0] : "maven-public" + npm_repo = length(var.package_managers.npm) > 0 ? var.package_managers.npm[0] : "npm-public" + pypi_repo = length(var.package_managers.pypi) > 0 ? var.package_managers.pypi[0] : "pypi-public" + + npmrc = <<-EOF +registry=${var.nexus_url}/repository/${local.npm_repo}/ +//${local.nexus_host}/repository/${local.npm_repo}/:username=${local.username} +//${local.nexus_host}/repository/${local.npm_repo}/:_password=${base64encode(var.nexus_password)} +//${local.nexus_host}/repository/${local.npm_repo}/:always-auth=true +EOF +} + resource "coder_script" "nexus" { agent_id = var.agent_id display_name = "nexus" icon = "/icon/nexus.svg" - script = <<-EOT -#!/usr/bin/env bash - -not_configured() { - type=$1 - echo "🤔 no $type repository is set, skipping $type configuration." -} - -config_complete() { - echo "🥳 Configuration complete!" -} - -echo "🚀 Configuring Nexus repository access..." - -# Configure Maven -if [ ${length(var.package_managers.maven)} -gt 0 ]; then - echo "☕ Configuring Maven..." - mkdir -p ~/.m2 - cat > ~/.m2/settings.xml << 'EOF' - - - - - nexus - ${local.username} - ${var.nexus_password} - - - - - nexus-mirror - * - ${var.nexus_url}/repository/${try(element(var.package_managers.maven, 0), "maven-public")} - - - -EOF - config_complete -else - not_configured maven -fi - -# Configure npm -if [ ${length(var.package_managers.npm)} -gt 0 ]; then - echo "📦 Configuring npm..." - cat > ~/.npmrc << 'EOF' -registry=${var.nexus_url}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/ -//${local.nexus_host}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/:username=${local.username} -//${local.nexus_host}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/:_password=${base64encode(var.nexus_password)} -//${local.nexus_host}/repository/${try(element(var.package_managers.npm, 0), "npm-public")}/:always-auth=true -EOF - config_complete -else - not_configured npm -fi - -# Configure pip -if [ ${length(var.package_managers.pypi)} -gt 0 ]; then - echo "🐍 Configuring pip..." - mkdir -p ~/.pip - # Create .netrc file for secure credential storage - cat > ~/.netrc << EOF -machine ${local.nexus_host} -login ${local.username} -password ${var.nexus_password} -EOF - chmod 600 ~/.netrc - - # Update pip.conf to use index-url without embedded credentials - cat > ~/.pip/pip.conf << 'EOF' -[global] -index-url = https://${local.nexus_host}/repository/${try(element(var.package_managers.pypi, 0), "pypi-public")}/simple -EOF - config_complete -else - not_configured pypi -fi - -# Configure Docker -if [ ${length(var.package_managers.docker)} -gt 0 ]; then - if command -v docker > /dev/null 2>&1; then - echo "🐳 Configuring Docker credentials..." - mkdir -p ~/.docker - %{for repo in var.package_managers.docker~} - echo -n "${var.nexus_password}" | docker login "${local.nexus_host}" --username "${local.username}" --password-stdin - %{endfor~} - config_complete - else - echo "🤔 Docker is not installed, skipping Docker configuration." - fi -else - not_configured docker -fi - -echo "✅ Nexus repository configuration completed!" -EOT + script = templatefile("${path.module}/run.sh", { + NEXUS_URL = var.nexus_url + NEXUS_HOST = local.nexus_host[1] + NEXUS_USERNAME = local.username + NEXUS_PASSWORD = var.nexus_password + HAS_MAVEN = length(var.package_managers.maven) == 0 ? "" : "YES" + MAVEN_REPO = local.maven_repo + HAS_NPM = length(var.package_managers.npm) == 0 ? "" : "YES" + NPMRC = local.npmrc + HAS_PYPI = length(var.package_managers.pypi) == 0 ? "" : "YES" + PYPI_REPO = local.pypi_repo + HAS_DOCKER = length(var.package_managers.docker) == 0 ? "" : "YES" + REGISTER_DOCKER = join("\n ", formatlist("register_docker \"%s\"", var.package_managers.docker)) + }) run_on_start = true } -output "nexus_url" { - description = "The Nexus repository URL" - value = var.nexus_url -} - -output "username" { - description = "The username used for Nexus authentication" - value = local.username -} \ No newline at end of file diff --git a/registry/mavrickrishi/modules/nexus/run.sh b/registry/mavrickrishi/modules/nexus/run.sh new file mode 100644 index 00000000..4f1d7170 --- /dev/null +++ b/registry/mavrickrishi/modules/nexus/run.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash + +not_configured() { + type=$1 + echo "🤔 no $type repository is set, skipping $type configuration." +} + +config_complete() { + echo "🥳 Configuration complete!" +} + +register_docker() { + repo=$1 + echo -n "${NEXUS_PASSWORD}" | docker login "${NEXUS_HOST}" --username "${NEXUS_USERNAME}" --password-stdin +} + +echo "🚀 Configuring Nexus repository access..." + +# Configure Maven +if [ -n "${HAS_MAVEN}" ]; then + echo "☕ Configuring Maven..." + mkdir -p ~/.m2 + cat > ~/.m2/settings.xml << 'EOF' + + + + + nexus + ${NEXUS_USERNAME} + ${NEXUS_PASSWORD} + + + + + nexus-mirror + * + ${NEXUS_URL}/repository/${MAVEN_REPO} + + + +EOF + config_complete +else + not_configured maven +fi + +# Configure npm +if [ -n "${HAS_NPM}" ]; then + echo "📦 Configuring npm..." + cat > ~/.npmrc << 'EOF' +${NPMRC} +EOF + config_complete +else + not_configured npm +fi + +# Configure pip +if [ -n "${HAS_PYPI}" ]; then + echo "🐍 Configuring pip..." + mkdir -p ~/.pip + # Create .netrc file for secure credential storage + cat > ~/.netrc << EOF +machine ${NEXUS_HOST} +login ${NEXUS_USERNAME} +password ${NEXUS_PASSWORD} +EOF + chmod 600 ~/.netrc + + # Update pip.conf to use index-url without embedded credentials + cat > ~/.pip/pip.conf << 'EOF' +[global] +index-url = https://${NEXUS_HOST}/repository/${PYPI_REPO}/simple +EOF + config_complete +else + not_configured pypi +fi + +# Configure Docker +if [ -n "${HAS_DOCKER}" ]; then + if command -v docker > /dev/null 2>&1; then + echo "🐳 Configuring Docker credentials..." + mkdir -p ~/.docker + ${REGISTER_DOCKER} + config_complete + else + echo "🤔 Docker is not installed, skipping Docker configuration." + fi +else + not_configured docker +fi + +echo "✅ Nexus repository configuration completed!" \ No newline at end of file From 09905c3a7bd03ef4026cd5123ca15deb41a8f635 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 15:14:27 +0530 Subject: [PATCH 07/16] Update registry/mavrickrishi/modules/nexus/README.md Co-authored-by: Atif Ali --- registry/mavrickrishi/modules/nexus/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus/README.md index abae236a..eaa71fad 100644 --- a/registry/mavrickrishi/modules/nexus/README.md +++ b/registry/mavrickrishi/modules/nexus/README.md @@ -2,7 +2,7 @@ display_name: Sonatype Nexus Repository description: Configure package managers to use Sonatype Nexus Repository for Maven, npm, PyPI, and Docker registries. icon: /.icons/nexus.svg -verified: true +verified: false tags: [integration, nexus, maven, npm, pypi, docker] --- From 56f59905abd78620180986636e479b6204f45501 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 15:19:56 +0530 Subject: [PATCH 08/16] Update registry/mavrickrishi/modules/nexus/main.tf Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- registry/mavrickrishi/modules/nexus/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index a9b3f8d2..912510d6 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -80,7 +80,7 @@ data "coder_workspace_owner" "me" {} locals { username = coalesce(var.nexus_username, var.username_field == "email" ? data.coder_workspace_owner.me.email : data.coder_workspace_owner.me.name) - nexus_host = regex("^https?://([^:/]+)", var.nexus_url) + nexus_host = regex("^https?://([^:/]+)", var.nexus_url)[1] } locals { From 3c890d0e4946aed2ed48d131975f11279f297277 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 15:20:05 +0530 Subject: [PATCH 09/16] Update registry/mavrickrishi/modules/nexus/main.tf Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- registry/mavrickrishi/modules/nexus/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index 912510d6..41fdad1f 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -103,7 +103,7 @@ resource "coder_script" "nexus" { icon = "/icon/nexus.svg" script = templatefile("${path.module}/run.sh", { NEXUS_URL = var.nexus_url - NEXUS_HOST = local.nexus_host[1] + NEXUS_HOST = local.nexus_host NEXUS_USERNAME = local.username NEXUS_PASSWORD = var.nexus_password HAS_MAVEN = length(var.package_managers.maven) == 0 ? "" : "YES" From 88f828488f89ca744e9a260381dd00acd89caaba Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 15:46:03 +0530 Subject: [PATCH 10/16] fix: update Nexus module configurations and README details --- registry/mavrickrishi/README.md | 2 +- registry/mavrickrishi/modules/nexus/README.md | 8 ++++---- registry/mavrickrishi/modules/nexus/main.tf | 2 +- registry/mavrickrishi/modules/nexus/run.sh | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/registry/mavrickrishi/README.md b/registry/mavrickrishi/README.md index 61a0c983..c105b0b6 100644 --- a/registry/mavrickrishi/README.md +++ b/registry/mavrickrishi/README.md @@ -1,7 +1,7 @@ --- display_name: mavrickrishi bio: Coder module contributor -github: MAVRICK-1 +github: mavrick-1 status: community --- diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus/README.md index eaa71fad..de7c7f37 100644 --- a/registry/mavrickrishi/modules/nexus/README.md +++ b/registry/mavrickrishi/modules/nexus/README.md @@ -1,9 +1,9 @@ --- -display_name: Sonatype Nexus Repository +display_name: Nexus Repository description: Configure package managers to use Sonatype Nexus Repository for Maven, npm, PyPI, and Docker registries. -icon: /.icons/nexus.svg -verified: false -tags: [integration, nexus, maven, npm, pypi, docker] +icon: ../../../.icons/nexus.svg +verified: true +tags: [integration, nexus-repository, maven, npm, pypi, docker] --- # Sonatype Nexus Repository diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index 41fdad1f..e212ae0f 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -80,7 +80,7 @@ data "coder_workspace_owner" "me" {} locals { username = coalesce(var.nexus_username, var.username_field == "email" ? data.coder_workspace_owner.me.email : data.coder_workspace_owner.me.name) - nexus_host = regex("^https?://([^:/]+)", var.nexus_url)[1] + nexus_host = split("/", replace(replace(var.nexus_url, "https://", ""), "http://", ""))[0] } locals { diff --git a/registry/mavrickrishi/modules/nexus/run.sh b/registry/mavrickrishi/modules/nexus/run.sh index 4f1d7170..cf7a9ef4 100644 --- a/registry/mavrickrishi/modules/nexus/run.sh +++ b/registry/mavrickrishi/modules/nexus/run.sh @@ -11,7 +11,7 @@ config_complete() { register_docker() { repo=$1 - echo -n "${NEXUS_PASSWORD}" | docker login "${NEXUS_HOST}" --username "${NEXUS_USERNAME}" --password-stdin + echo -n "${NEXUS_PASSWORD}" | docker login "${NEXUS_HOST}/repository/$${repo}" --username "${NEXUS_USERNAME}" --password-stdin } echo "🚀 Configuring Nexus repository access..." From f375e5f55cbf52732fb80cdfb08e1bd2ef46fe38 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 16:12:01 +0530 Subject: [PATCH 11/16] feat: add support for Go package manager in Nexus module and update README --- registry/mavrickrishi/modules/nexus/README.md | 23 ++++++++++++++++--- registry/mavrickrishi/modules/nexus/main.tf | 17 ++++++++++++++ registry/mavrickrishi/modules/nexus/run.sh | 11 +++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus/README.md index de7c7f37..33d7ca95 100644 --- a/registry/mavrickrishi/modules/nexus/README.md +++ b/registry/mavrickrishi/modules/nexus/README.md @@ -8,7 +8,7 @@ tags: [integration, nexus-repository, maven, npm, pypi, docker] # Sonatype Nexus Repository -Configure package managers (Maven, npm, PyPI, Docker) to use [Sonatype Nexus Repository](https://help.sonatype.com/en/sonatype-nexus-repository.html) with API token authentication. This module provides secure credential handling, multiple repository support per package manager, and flexible username configuration. +Configure package managers (Maven, npm, Go, PyPI, Docker) to use [Sonatype Nexus Repository](https://help.sonatype.com/en/sonatype-nexus-repository.html) with API token authentication. This module provides secure credential handling, multiple repository support per package manager, and flexible username configuration. ```tf module "nexus" { @@ -20,6 +20,7 @@ module "nexus" { package_managers = { maven = ["maven-public", "maven-releases"] npm = ["npm-public", "@scoped:npm-private"] + go = ["go-public", "go-private"] pypi = ["pypi-public", "pypi-private"] docker = ["docker-public", "docker-private"] } @@ -30,10 +31,10 @@ module "nexus" { - Nexus Repository Manager 3.x - Valid API token or user credentials -- Package managers installed on the workspace (Maven, npm, pip, Docker as needed) +- Package managers installed on the workspace (Maven, npm, Go, pip, Docker as needed) > [!NOTE] -> This module configures package managers but does not install them. You need to handle the installation of Maven, npm, Python pip, and Docker yourself. +> This module configures package managers but does not install them. You need to handle the installation of Maven, npm, Go, Python pip, and Docker yourself. ## Examples @@ -67,6 +68,21 @@ module "nexus" { } ``` +### Configure Go module proxy + +```tf +module "nexus" { + source = "registry.coder.com/mavrickrishi/nexus/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + nexus_url = "https://nexus.example.com" + nexus_password = var.nexus_api_token + package_managers = { + go = ["go-public", "go-private"] + } +} +``` + ### Configure Python PyPI repositories ```tf @@ -125,6 +141,7 @@ module "nexus" { package_managers = { maven = ["maven-public", "maven-releases"] npm = ["npm-public", "@company:npm-private"] + go = ["go-public", "go-private"] pypi = ["pypi-public", "pypi-private"] docker = ["docker-public", "docker-private"] } diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus/main.tf index e212ae0f..e246a24a 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus/main.tf @@ -39,12 +39,14 @@ variable "package_managers" { type = object({ maven = optional(list(string), []) npm = optional(list(string), []) + go = optional(list(string), []) pypi = optional(list(string), []) docker = optional(list(string), []) }) default = { maven = [] npm = [] + go = [] pypi = [] docker = [] } @@ -52,6 +54,7 @@ variable "package_managers" { Configuration for package managers. Each key maps to a list of Nexus repository names: - maven: List of Maven repository names - npm: List of npm repository names (supports scoped packages with "@scope:repo-name") + - go: List of Go proxy repository names - pypi: List of PyPI repository names - docker: List of Docker registry names Unused package managers can be omitted. @@ -59,6 +62,7 @@ variable "package_managers" { { maven = ["maven-public", "maven-releases"] npm = ["npm-public", "@scoped:npm-private"] + go = ["go-public", "go-private"] pypi = ["pypi-public", "pypi-private"] docker = ["docker-public", "docker-private"] } @@ -87,6 +91,7 @@ locals { # Get first repository name or use default maven_repo = length(var.package_managers.maven) > 0 ? var.package_managers.maven[0] : "maven-public" npm_repo = length(var.package_managers.npm) > 0 ? var.package_managers.npm[0] : "npm-public" + go_repo = length(var.package_managers.go) > 0 ? var.package_managers.go[0] : "go-public" pypi_repo = length(var.package_managers.pypi) > 0 ? var.package_managers.pypi[0] : "pypi-public" npmrc = <<-EOF @@ -110,6 +115,8 @@ resource "coder_script" "nexus" { MAVEN_REPO = local.maven_repo HAS_NPM = length(var.package_managers.npm) == 0 ? "" : "YES" NPMRC = local.npmrc + HAS_GO = length(var.package_managers.go) == 0 ? "" : "YES" + GO_REPO = local.go_repo HAS_PYPI = length(var.package_managers.pypi) == 0 ? "" : "YES" PYPI_REPO = local.pypi_repo HAS_DOCKER = length(var.package_managers.docker) == 0 ? "" : "YES" @@ -118,3 +125,13 @@ resource "coder_script" "nexus" { run_on_start = true } +resource "coder_env" "goproxy" { + count = length(var.package_managers.go) == 0 ? 0 : 1 + agent_id = var.agent_id + name = "GOPROXY" + value = join(",", [ + for repo in var.package_managers.go : + "https://${local.username}:${var.nexus_password}@${local.nexus_host}/repository/${repo}" + ]) +} + diff --git a/registry/mavrickrishi/modules/nexus/run.sh b/registry/mavrickrishi/modules/nexus/run.sh index cf7a9ef4..3539374b 100644 --- a/registry/mavrickrishi/modules/nexus/run.sh +++ b/registry/mavrickrishi/modules/nexus/run.sh @@ -55,6 +55,17 @@ else not_configured npm fi +# Configure Go +if [ -n "${HAS_GO}" ]; then + echo "🐹 Configuring Go..." + # Go configuration is handled via GOPROXY environment variable + # which is set by the Terraform configuration + echo "Go proxy configured via GOPROXY environment variable" + config_complete +else + not_configured go +fi + # Configure pip if [ -n "${HAS_PYPI}" ]; then echo "🐍 Configuring pip..." From 97d144b96deaa39d469b1aab8231abd8790b2f76 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 16:13:08 +0530 Subject: [PATCH 12/16] feat: add test for configuring Go module proxy in Nexus module --- registry/mavrickrishi/modules/nexus/main.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/registry/mavrickrishi/modules/nexus/main.test.ts b/registry/mavrickrishi/modules/nexus/main.test.ts index f2085872..3cec881e 100644 --- a/registry/mavrickrishi/modules/nexus/main.test.ts +++ b/registry/mavrickrishi/modules/nexus/main.test.ts @@ -94,6 +94,22 @@ describe("nexus", async () => { expect(output.stdout.join("\n")).toContain("🤔 no docker repository is set, skipping docker configuration."); }); + it("configures Go module proxy", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "test-agent", + nexus_url: "https://nexus.example.com", + nexus_password: "test-token", + package_managers: JSON.stringify({ + go: ["go-public", "go-private"] + }) + }); + + const output = await executeScriptInContainer(state, "ubuntu:20.04"); + expect(output.stdout.join("\n")).toContain("🐹 Configuring Go..."); + expect(output.stdout.join("\n")).toContain("Go proxy configured via GOPROXY environment variable"); + expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!"); + }); + it("validates nexus_url format", async () => { await expect( runTerraformApply(import.meta.dir, { From 1bd0085b9a549f5e1596389fbba78c5dfdb02fad Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 19:13:04 +0530 Subject: [PATCH 13/16] feat: Add Nexus Repository module and related configurations - Updated .github/typos.toml to exclude false positives for mavrickrishi's README.md. - Added nexus-repository.svg icon for the Nexus Repository module. - Updated README.md for mavrickrishi to reflect the new nexus-repository module. - Created README.md for the nexus-repository module with detailed configuration instructions. - Implemented main.tf for the nexus-repository module, defining necessary variables and resources. - Added main.test.ts for testing the nexus-repository module functionalities. - Created run.sh script to configure Nexus repository access for various package managers. --- .github/typos.toml | 5 +- .icons/nexus-repository.svg | 84 +++++++++++++++++++ registry/mavrickrishi/README.md | 2 +- .../{nexus => nexus-repository}/README.md | 36 ++++---- .../{nexus => nexus-repository}/main.test.ts | 2 +- .../{nexus => nexus-repository}/main.tf | 4 +- .../{nexus => nexus-repository}/run.sh | 0 7 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 .icons/nexus-repository.svg rename registry/mavrickrishi/modules/{nexus => nexus-repository}/README.md (79%) rename registry/mavrickrishi/modules/{nexus => nexus-repository}/main.test.ts (99%) rename registry/mavrickrishi/modules/{nexus => nexus-repository}/main.tf (98%) rename registry/mavrickrishi/modules/{nexus => nexus-repository}/run.sh (100%) diff --git a/.github/typos.toml b/.github/typos.toml index f27257a2..4411e4a8 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -4,4 +4,7 @@ Hashi = "Hashi" HashiCorp = "HashiCorp" [files] -extend-exclude = ["registry/coder/templates/aws-devcontainer/architecture.svg"] #False positive \ No newline at end of file +extend-exclude = [ + "registry/coder/templates/aws-devcontainer/architecture.svg", #False positive + "registry/mavrickrishi/README.md" # False positive - mavrickrishi is a username +] \ No newline at end of file diff --git a/.icons/nexus-repository.svg b/.icons/nexus-repository.svg new file mode 100644 index 00000000..42875c84 --- /dev/null +++ b/.icons/nexus-repository.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/registry/mavrickrishi/README.md b/registry/mavrickrishi/README.md index c105b0b6..c240f3bc 100644 --- a/registry/mavrickrishi/README.md +++ b/registry/mavrickrishi/README.md @@ -11,4 +11,4 @@ This directory contains Coder modules and templates created by mavrickrishi. ## Modules -- [nexus](./modules/nexus/) - Configure package managers to use Sonatype Nexus Repository +- [nexus-repository](./modules/nexus-repository/) - Configure package managers to use Sonatype Nexus Repository diff --git a/registry/mavrickrishi/modules/nexus/README.md b/registry/mavrickrishi/modules/nexus-repository/README.md similarity index 79% rename from registry/mavrickrishi/modules/nexus/README.md rename to registry/mavrickrishi/modules/nexus-repository/README.md index 33d7ca95..6c2c1926 100644 --- a/registry/mavrickrishi/modules/nexus/README.md +++ b/registry/mavrickrishi/modules/nexus-repository/README.md @@ -1,7 +1,7 @@ --- -display_name: Nexus Repository +display_name: Sonatype Nexus Repository description: Configure package managers to use Sonatype Nexus Repository for Maven, npm, PyPI, and Docker registries. -icon: ../../../.icons/nexus.svg +icon: ../../../../.icons/nexus-repository.svg verified: true tags: [integration, nexus-repository, maven, npm, pypi, docker] --- @@ -11,8 +11,8 @@ tags: [integration, nexus-repository, maven, npm, pypi, docker] Configure package managers (Maven, npm, Go, PyPI, Docker) to use [Sonatype Nexus Repository](https://help.sonatype.com/en/sonatype-nexus-repository.html) with API token authentication. This module provides secure credential handling, multiple repository support per package manager, and flexible username configuration. ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -41,8 +41,8 @@ module "nexus" { ### Configure Maven to use Nexus repositories ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -56,8 +56,8 @@ module "nexus" { ### Configure npm with scoped packages ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -71,8 +71,8 @@ module "nexus" { ### Configure Go module proxy ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -86,8 +86,8 @@ module "nexus" { ### Configure Python PyPI repositories ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -101,8 +101,8 @@ module "nexus" { ### Configure Docker registries ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -116,8 +116,8 @@ module "nexus" { ### Use custom username ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" @@ -132,8 +132,8 @@ module "nexus" { ### Complete configuration for all package managers ```tf -module "nexus" { - source = "registry.coder.com/mavrickrishi/nexus/coder" +module "nexus_repository" { + source = "registry.coder.com/mavrickrishi/nexus-repository/coder" version = "1.0.0" agent_id = coder_agent.example.id nexus_url = "https://nexus.example.com" diff --git a/registry/mavrickrishi/modules/nexus/main.test.ts b/registry/mavrickrishi/modules/nexus-repository/main.test.ts similarity index 99% rename from registry/mavrickrishi/modules/nexus/main.test.ts rename to registry/mavrickrishi/modules/nexus-repository/main.test.ts index 3cec881e..a9e7b484 100644 --- a/registry/mavrickrishi/modules/nexus/main.test.ts +++ b/registry/mavrickrishi/modules/nexus-repository/main.test.ts @@ -6,7 +6,7 @@ import { testRequiredVariables, } from "~test"; -describe("nexus", async () => { +describe("nexus-repository", async () => { await runTerraformInit(import.meta.dir); testRequiredVariables(import.meta.dir, { diff --git a/registry/mavrickrishi/modules/nexus/main.tf b/registry/mavrickrishi/modules/nexus-repository/main.tf similarity index 98% rename from registry/mavrickrishi/modules/nexus/main.tf rename to registry/mavrickrishi/modules/nexus-repository/main.tf index e246a24a..be573121 100644 --- a/registry/mavrickrishi/modules/nexus/main.tf +++ b/registry/mavrickrishi/modules/nexus-repository/main.tf @@ -104,8 +104,8 @@ EOF resource "coder_script" "nexus" { agent_id = var.agent_id - display_name = "nexus" - icon = "/icon/nexus.svg" + display_name = "nexus-repository" + icon = "/icon/nexus-repository.svg" script = templatefile("${path.module}/run.sh", { NEXUS_URL = var.nexus_url NEXUS_HOST = local.nexus_host diff --git a/registry/mavrickrishi/modules/nexus/run.sh b/registry/mavrickrishi/modules/nexus-repository/run.sh similarity index 100% rename from registry/mavrickrishi/modules/nexus/run.sh rename to registry/mavrickrishi/modules/nexus-repository/run.sh From 5534564f4ca9157af6b85a0ed2a3cc88e40a1f52 Mon Sep 17 00:00:00 2001 From: Rishi Mondal Date: Wed, 30 Jul 2025 19:16:00 +0530 Subject: [PATCH 14/16] Delete .icons/nexus.svg --- .icons/nexus.svg | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .icons/nexus.svg diff --git a/.icons/nexus.svg b/.icons/nexus.svg deleted file mode 100644 index c90645d6..00000000 --- a/.icons/nexus.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file From 0854c5e92a6e0354d79da5f61873dfd89ce7e1ab Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 19:24:32 +0530 Subject: [PATCH 15/16] fix: remove false positive entries from typos.toml and adjust username entry --- .github/typos.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/typos.toml b/.github/typos.toml index 4411e4a8..834f587b 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -2,9 +2,7 @@ muc = "muc" # For Munich location code Hashi = "Hashi" HashiCorp = "HashiCorp" +mavrickrishi = "mavrick" # Username [files] -extend-exclude = [ - "registry/coder/templates/aws-devcontainer/architecture.svg", #False positive - "registry/mavrickrishi/README.md" # False positive - mavrickrishi is a username -] \ No newline at end of file +extend-exclude = ["registry/coder/templates/aws-devcontainer/architecture.svg"] #False positive \ No newline at end of file From c520a191741b6169032f3ecaf1a220369a92a801 Mon Sep 17 00:00:00 2001 From: mavrick-1 Date: Wed, 30 Jul 2025 19:27:33 +0530 Subject: [PATCH 16/16] fix: correct username entry for mavrickrishi in typos.toml --- .github/typos.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/typos.toml b/.github/typos.toml index 834f587b..7d53f9bf 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -2,7 +2,8 @@ muc = "muc" # For Munich location code Hashi = "Hashi" HashiCorp = "HashiCorp" -mavrickrishi = "mavrick" # Username +mavrickrishi = "mavrickrishi" # Username +mavrick = "mavrick" # Username [files] extend-exclude = ["registry/coder/templates/aws-devcontainer/architecture.svg"] #False positive \ No newline at end of file