Add maven package manager support to JFrog modules (#414)

Closes #33 
/claim #33 
## Description
Jfrog Modules doesn't support conda package manager, This PR adds
support of that



## Type of Change

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

## Testing & Validation

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

## Related Issues

#33 
## video


https://github.com/user-attachments/assets/61c33963-e1a7-43e2-b1cc-fdb747405cf5
This commit is contained in:
हिमांशु 2025-09-09 11:06:31 +05:30 committed by GitHub
parent 17734c073a
commit f1010ee7a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 236 additions and 8 deletions

View File

@ -16,7 +16,7 @@ Install the JF CLI and authenticate package managers with Artifactory using OAut
module "jfrog" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jfrog-oauth/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io"
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"
@ -27,6 +27,7 @@ module "jfrog" {
pypi = ["pypi", "extra-index-pypi"]
docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"]
conda = ["conda", "conda-local"]
maven = ["maven", "maven-local"]
}
}
```
@ -46,7 +47,7 @@ Configure the Python pip package manager to fetch packages from Artifactory whil
module "jfrog" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jfrog-oauth/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io"
username_field = "email"
@ -75,7 +76,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
module "jfrog" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jfrog-oauth/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io"
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"

View File

@ -150,4 +150,38 @@ EOF`;
'if [ -z "YES" ]; then\n not_configured conda',
);
});
it("generates a maven settings.xml with multiple repos", async () => {
const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl,
package_managers: JSON.stringify({
maven: ["central", "snapshots", "local"],
}),
});
const coderScript = findResourceInstance(state, "coder_script");
expect(coderScript.script).toContain(
'jf mvnc --global --repo-resolve "central"',
);
expect(coderScript.script).toContain("<servers>");
expect(coderScript.script).toContain("<id>central</id>");
expect(coderScript.script).toContain("<id>snapshots</id>");
expect(coderScript.script).toContain("<id>local</id>");
expect(coderScript.script).toContain(
"<url>http://localhost:8081/artifactory/central</url>",
);
expect(coderScript.script).toContain(
"<url>http://localhost:8081/artifactory/snapshots</url>",
);
expect(coderScript.script).toContain(
"<url>http://localhost:8081/artifactory/local</url>",
);
expect(coderScript.script).toContain(
'if [ -z "YES" ]; then\n not_configured maven',
);
});
});

View File

@ -59,6 +59,7 @@ variable "package_managers" {
pypi = optional(list(string), [])
docker = optional(list(string), [])
conda = optional(list(string), [])
maven = optional(list(string), [])
})
description = <<-EOF
A map of package manager names to their respective artifactory repositories. Unused package managers can be omitted.
@ -69,6 +70,7 @@ variable "package_managers" {
pypi = ["YOUR_PYPI_REPO_KEY", "ANOTHER_PYPI_REPO_KEY"]
docker = ["YOUR_DOCKER_REPO_KEY", "ANOTHER_DOCKER_REPO_KEY"]
conda = ["YOUR_CONDA_REPO_KEY", "ANOTHER_CONDA_REPO_KEY"]
maven = ["YOUR_MAVEN_REPO_KEY", "ANOTHER_MAVEN_REPO_KEY"]
}
EOF
}
@ -103,6 +105,9 @@ locals {
conda_conf = templatefile(
"${path.module}/conda.conf.tftpl", merge(local.common_values, { REPOS = var.package_managers.conda })
)
maven_settings = templatefile(
"${path.module}/settings.xml.tftpl", merge(local.common_values, { REPOS = var.package_managers.maven })
)
}
data "coder_workspace" "me" {}
@ -133,6 +138,9 @@ resource "coder_script" "jfrog" {
HAS_CONDA = length(var.package_managers.conda) == 0 ? "" : "YES"
CONDA_CONF = local.conda_conf
REPOSITORY_CONDA = try(element(var.package_managers.conda, 0), "")
HAS_MAVEN = length(var.package_managers.maven) == 0 ? "" : "YES"
MAVEN_SETTINGS = local.maven_settings
REPOSITORY_MAVEN = try(element(var.package_managers.maven, 0), "")
}
))
run_on_start = true

View File

@ -94,6 +94,20 @@ EOF
config_complete
fi
# Configure Maven to use the Artifactory "maven" repository.
if [ -z "${HAS_MAVEN}" ]; then
not_configured maven
else
echo "☕ Configuring maven..."
jf mvnc --global --repo-resolve "${REPOSITORY_MAVEN}"
# Create Maven config directory if it doesn't exist
mkdir -p ~/.m2
cat << EOF > ~/.m2/settings.xml
${MAVEN_SETTINGS}
EOF
config_complete
fi
# Install the JFrog vscode extension for code-server.
if [ "${CONFIGURE_CODE_SERVER}" == "true" ]; then
while ! [ -x /tmp/code-server/bin/code-server ]; do

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
%{ for REPO in REPOS ~}
<server>
<id>${REPO}</id>
<username>${ARTIFACTORY_USERNAME}</username>
<password>${ARTIFACTORY_ACCESS_TOKEN}</password>
</server>
%{ endfor ~}
</servers>
<profiles>
<profile>
<id>artifactory</id>
<repositories>
%{ for REPO in REPOS ~}
<repository>
<id>${REPO}</id>
<url>${JFROG_URL}/artifactory/${REPO}</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
%{ endfor ~}
</repositories>
<pluginRepositories>
%{ for REPO in REPOS ~}
<pluginRepository>
<id>${REPO}</id>
<url>${JFROG_URL}/artifactory/${REPO}</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
%{ endfor ~}
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
</settings>

View File

@ -13,7 +13,7 @@ Install the JF CLI and authenticate package managers with Artifactory using Arti
```tf
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token
@ -23,6 +23,7 @@ module "jfrog" {
pypi = ["pypi", "extra-index-pypi"]
docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"]
conda = ["conda", "conda-local"]
maven = ["maven", "maven-local"]
}
}
```
@ -41,7 +42,7 @@ For detailed instructions, please see this [guide](https://coder.com/docs/v2/lat
```tf
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://YYYY.jfrog.io"
artifactory_access_token = var.artifactory_access_token # An admin access token
@ -50,17 +51,19 @@ module "jfrog" {
go = ["go-local"]
pypi = ["pypi-local"]
conda = ["conda-local"]
maven = ["maven-local"]
}
}
```
You should now be able to install packages from Artifactory using both the `jf npm`, `jf go`, `jf pip` and `npm`, `go`, `pip`, `conda` commands.
You should now be able to install packages from Artifactory using both the `jf npm`, `jf go`, `jf pip` and `npm`, `go`, `pip`, `conda`, `maven` commands.
```shell
jf npm install prettier
jf go get github.com/golang/example/hello
jf pip install requests
conda install numpy
mvn clean install
```
```shell
@ -68,6 +71,7 @@ npm install prettier
go get github.com/golang/example/hello
pip install requests
conda install numpy
mvn clean install
```
### Configure code-server with JFrog extension
@ -77,7 +81,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
```tf
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token
@ -97,7 +101,7 @@ data "coder_workspace" "me" {}
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token

View File

@ -187,4 +187,39 @@ EOF`;
'if [ -z "YES" ]; then\n not_configured conda',
);
});
it("generates a maven settings.xml with multiple repos", async () => {
const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl,
artifactory_access_token: "XXXX",
package_managers: JSON.stringify({
maven: ["central", "snapshots", "local"],
}),
});
const coderScript = findResourceInstance(state, "coder_script");
expect(coderScript.script).toContain(
'jf mvnc --global --repo-resolve "central"',
);
expect(coderScript.script).toContain("<servers>");
expect(coderScript.script).toContain("<id>central</id>");
expect(coderScript.script).toContain("<id>snapshots</id>");
expect(coderScript.script).toContain("<id>local</id>");
expect(coderScript.script).toContain(
`<url>${fakeFrogUrl}/artifactory/central</url>`,
);
expect(coderScript.script).toContain(
`<url>${fakeFrogUrl}/artifactory/snapshots</url>`,
);
expect(coderScript.script).toContain(
`<url>${fakeFrogUrl}/artifactory/local</url>`,
);
expect(coderScript.script).toContain(
'if [ -z "YES" ]; then\n not_configured maven',
);
});
});

View File

@ -92,6 +92,7 @@ variable "package_managers" {
pypi = optional(list(string), [])
docker = optional(list(string), [])
conda = optional(list(string), [])
maven = optional(list(string), [])
})
description = <<-EOF
A map of package manager names to their respective artifactory repositories. Unused package managers can be omitted.
@ -102,6 +103,7 @@ variable "package_managers" {
pypi = ["YOUR_PYPI_REPO_KEY", "ANOTHER_PYPI_REPO_KEY"]
docker = ["YOUR_DOCKER_REPO_KEY", "ANOTHER_DOCKER_REPO_KEY"]
conda = ["YOUR_CONDA_REPO_KEY", "ANOTHER_CONDA_REPO_KEY"]
maven = ["YOUR_MAVEN_REPO_KEY", "ANOTHER_MAVEN_REPO_KEY"]
}
EOF
}
@ -136,6 +138,9 @@ locals {
conda_conf = templatefile(
"${path.module}/conda.conf.tftpl", merge(local.common_values, { REPOS = var.package_managers.conda })
)
maven_settings = templatefile(
"${path.module}/settings.xml.tftpl", merge(local.common_values, { REPOS = var.package_managers.maven })
)
}
# Configure the Artifactory provider
@ -179,6 +184,9 @@ resource "coder_script" "jfrog" {
HAS_CONDA = length(var.package_managers.conda) == 0 ? "" : "YES"
CONDA_CONF = local.conda_conf
REPOSITORY_CONDA = try(element(var.package_managers.conda, 0), "")
HAS_MAVEN = length(var.package_managers.maven) == 0 ? "" : "YES"
MAVEN_SETTINGS = local.maven_settings
REPOSITORY_MAVEN = try(element(var.package_managers.maven, 0), "")
}
))
run_on_start = true

View File

@ -93,6 +93,20 @@ EOF
config_complete
fi
# Configure Maven to use the Artifactory "maven" repository.
if [ -z "${HAS_MAVEN}" ]; then
not_configured maven
else
echo "☕ Configuring maven..."
jf mvnc --global --repo-resolve "${REPOSITORY_MAVEN}"
# Create Maven config directory if it doesn't exist
mkdir -p ~/.m2
cat << EOF > ~/.m2/settings.xml
${MAVEN_SETTINGS}
EOF
config_complete
fi
# Install the JFrog vscode extension for code-server.
if [ "${CONFIGURE_CODE_SERVER}" == "true" ]; then
while ! [ -x /tmp/code-server/bin/code-server ]; do

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
%{ for REPO in REPOS ~}
<server>
<id>${REPO}</id>
<username>${ARTIFACTORY_USERNAME}</username>
<password>${ARTIFACTORY_ACCESS_TOKEN}</password>
</server>
%{ endfor ~}
</servers>
<profiles>
<profile>
<id>artifactory</id>
<repositories>
%{ for REPO in REPOS ~}
<repository>
<id>${REPO}</id>
<url>${JFROG_URL}/artifactory/${REPO}</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
%{ endfor ~}
</repositories>
<pluginRepositories>
%{ for REPO in REPOS ~}
<pluginRepository>
<id>${REPO}</id>
<url>${JFROG_URL}/artifactory/${REPO}</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
%{ endfor ~}
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
</settings>