feat: add maven settings.xml support for java private registries (#7940)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-02-13 17:57:30 +01:00
committed by GitHub
parent ade94f965b
commit c9bfca4826
8 changed files with 64 additions and 10 deletions

View File

@@ -10,7 +10,7 @@ use monitor::{
load_base_url, load_otel, reload_critical_alerts_on_db_oversize,
reload_delete_logs_periodically_setting, reload_indexer_config,
reload_instance_python_version_setting, reload_maven_repos_setting,
reload_no_default_maven_setting, reload_nuget_config_setting,
reload_maven_settings_xml_setting, reload_no_default_maven_setting, reload_nuget_config_setting,
reload_powershell_repo_pat_setting, reload_powershell_repo_url_setting,
reload_ruby_repos_setting, reload_timeout_wait_result_setting,
send_current_log_file_to_object_store, send_logs_to_object_store, WORKERS_NAMES,
@@ -44,7 +44,7 @@ use windmill_common::{
JOB_ISOLATION_SETTING, HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INDEXER_SETTING,
INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING, JWT_SECRET_SETTING,
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING,
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NO_DEFAULT_MAVEN_SETTING,
MAVEN_SETTINGS_XML_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NO_DEFAULT_MAVEN_SETTING,
NPM_CONFIG_REGISTRY_SETTING, NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING,
OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, UV_INDEX_STRATEGY_SETTING,
POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
@@ -1582,6 +1582,7 @@ async fn process_notify_event(
POWERSHELL_REPO_URL_SETTING => reload_powershell_repo_url_setting(conn).await,
POWERSHELL_REPO_PAT_SETTING => reload_powershell_repo_pat_setting(conn).await,
MAVEN_REPOS_SETTING => reload_maven_repos_setting(conn).await,
MAVEN_SETTINGS_XML_SETTING => reload_maven_settings_xml_setting(conn).await,
NO_DEFAULT_MAVEN_SETTING => reload_no_default_maven_setting(conn).await,
RUBY_REPOS_SETTING => reload_ruby_repos_setting(conn).await,
HUB_API_SECRET_SETTING => reload_hub_api_secret_setting(conn).await,

View File

@@ -88,8 +88,9 @@ use windmill_queue::{cancel_job, get_queued_job_v2, SameWorkerPayload};
use windmill_worker::{
result_processor::handle_job_error, JobCompletedSender, JobIsolationLevel,
OtelTracingProxySettings, SameWorkerSender, BUNFIG_INSTALL_SCOPES, CARGO_REGISTRIES,
INSTANCE_PYTHON_VERSION, JOB_DEFAULT_TIMEOUT, JOB_ISOLATION, KEEP_JOB_DIR, MAVEN_REPOS,
NO_DEFAULT_MAVEN, NPM_CONFIG_REGISTRY, NSJAIL_AVAILABLE, NUGET_CONFIG,
INSTANCE_PYTHON_VERSION, JAVA_HOME_DIR, JOB_DEFAULT_TIMEOUT, JOB_ISOLATION, KEEP_JOB_DIR,
MAVEN_REPOS, MAVEN_SETTINGS_XML, NO_DEFAULT_MAVEN, NPM_CONFIG_REGISTRY, NSJAIL_AVAILABLE,
NUGET_CONFIG,
OTEL_TRACING_PROXY_SETTINGS, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, POWERSHELL_REPO_PAT,
POWERSHELL_REPO_URL, UV_INDEX_STRATEGY,
};
@@ -329,6 +330,7 @@ pub async fn initial_load(
reload_powershell_repo_url_setting(&conn).await;
reload_powershell_repo_pat_setting(&conn).await;
reload_maven_repos_setting(&conn).await;
reload_maven_settings_xml_setting(&conn).await;
reload_no_default_maven_setting(&conn).await;
reload_ruby_repos_setting(&conn).await;
reload_cargo_registries_setting(&conn).await;
@@ -1336,6 +1338,35 @@ pub async fn reload_maven_repos_setting(conn: &Connection) {
.await;
}
pub async fn reload_maven_settings_xml_setting(conn: &Connection) {
reload_option_setting_with_tracing(
conn,
windmill_common::global_settings::MAVEN_SETTINGS_XML_SETTING,
"MAVEN_SETTINGS_XML",
MAVEN_SETTINGS_XML.clone(),
)
.await;
let settings_xml = MAVEN_SETTINGS_XML.read().await.clone();
match settings_xml {
Some(ref content) if !content.trim().is_empty() => {
let m2_dir = format!("{JAVA_HOME_DIR}/.m2");
if let Err(e) = tokio::fs::create_dir_all(&m2_dir).await {
tracing::error!("Failed to create .m2 directory: {e:#}");
return;
}
let settings_path = format!("{m2_dir}/settings.xml");
if let Err(e) = tokio::fs::write(&settings_path, content).await {
tracing::error!("Failed to write Maven settings.xml: {e:#}");
}
}
_ => {
let settings_path = format!("{JAVA_HOME_DIR}/.m2/settings.xml");
let _ = tokio::fs::remove_file(&settings_path).await;
}
}
}
pub async fn reload_no_default_maven_setting(conn: &Connection) {
let value = load_value_from_global_settings_with_conn(
conn,

View File

@@ -14,6 +14,7 @@ pub const NUGET_CONFIG_SETTING: &str = "nuget_config";
pub const POWERSHELL_REPO_URL_SETTING: &str = "powershell_repo_url";
pub const POWERSHELL_REPO_PAT_SETTING: &str = "powershell_repo_pat";
pub const MAVEN_REPOS_SETTING: &str = "maven_repos";
pub const MAVEN_SETTINGS_XML_SETTING: &str = "maven_settings_xml";
pub const NO_DEFAULT_MAVEN_SETTING: &str = "no_default_maven";
pub const RUBY_REPOS_SETTING: &str = "ruby_repos";
pub const CARGO_REGISTRIES_SETTING: &str = "cargo_registries";

View File

@@ -83,7 +83,9 @@ pub async fn generate_nuget_lockfile(
check_executor_binary_exists("dotnet", DOTNET_PATH.as_str(), "C#")?;
if let Some(nuget_config) = NUGET_CONFIG.read().await.clone() {
write_file(job_dir, "nuget.config", &nuget_config)?;
if !nuget_config.trim().is_empty() {
write_file(job_dir, "nuget.config", &nuget_config)?;
}
}
let (reqs, lines_to_remove) = parse_csharp_reqs(code);
@@ -335,7 +337,9 @@ async fn build_cs_proj(
occupancy_metrics: &mut OccupancyMetrics,
) -> error::Result<String> {
if let Some(nuget_config) = NUGET_CONFIG.read().await.clone() {
write_file(job_dir, "nuget.config", &nuget_config)?;
if !nuget_config.trim().is_empty() {
write_file(job_dir, "nuget.config", &nuget_config)?;
}
}
let mut build_cs_cmd = Command::new(DOTNET_PATH.as_str());

View File

@@ -232,9 +232,11 @@ pub fn __WINDMILL_RUN__(_args: __WINDMILL_ARGS__) -> Result<String, Box<dyn std:
async fn write_cargo_config(job_dir: &str) -> anyhow::Result<()> {
if let Some(cargo_registries) = CARGO_REGISTRIES.read().await.clone() {
let cargo_dir = format!("{job_dir}/.cargo");
create_dir_all(&cargo_dir).await?;
write_file(&cargo_dir, "config.toml", &cargo_registries)?;
if !cargo_registries.trim().is_empty() {
let cargo_dir = format!("{job_dir}/.cargo");
create_dir_all(&cargo_dir).await?;
write_file(&cargo_dir, "config.toml", &cargo_registries)?;
}
}
Ok(())
}

View File

@@ -579,6 +579,7 @@ lazy_static::lazy_static! {
pub static ref POWERSHELL_REPO_URL: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
pub static ref POWERSHELL_REPO_PAT: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
pub static ref MAVEN_REPOS: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
pub static ref MAVEN_SETTINGS_XML: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
pub static ref NO_DEFAULT_MAVEN: AtomicBool = AtomicBool::new(std::env::var("NO_DEFAULT_MAVEN")
.ok()
.and_then(|x| x.parse::<bool>().ok())

View File

@@ -353,9 +353,13 @@
.map(async (x) => {
if (x.key === 'license_key') licenseKeySet = true
if (x.requiresReloadOnChange) shouldReloadPage = true
let value = $values?.[x.key]
if (x.fieldType === 'codearea' && typeof value === 'string' && value.trim() === '') {
value = undefined
}
return await SettingService.setGlobal({
key: x.key,
requestBody: { value: $values?.[x.key] }
requestBody: { value }
})
})
)

View File

@@ -442,6 +442,16 @@ export const settings: Record<string, Setting[]> = {
storage: 'setting',
ee_only: ''
},
{
label: 'Maven settings.xml',
description:
'Write a Maven settings.xml file for custom repositories, mirrors, and credentials',
key: 'maven_settings_xml',
fieldType: 'codearea',
codeAreaLang: 'xml',
storage: 'setting',
ee_only: ''
},
{
label: 'Disable default Maven repository',
description: 'Do not use default Maven repository',