mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-06 16:02:23 +00:00
feat: add min release age instance settings for bun and uv (#8956)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
b2004f357d
commit
1d279e7a1e
+23
-17
@@ -39,14 +39,15 @@ use windmill_common::{
|
||||
agent_workers::AgentConfig,
|
||||
global_settings::{
|
||||
AI_CONFIG_SETTING, APP_WORKSPACED_ROUTE_SETTING, AUDIT_LOG_RETENTION_DAYS_SETTING,
|
||||
BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING, CRITICAL_ALERTS_ON_DB_OVERSIZE_SETTING,
|
||||
CRITICAL_ALERTS_ON_TOKEN_EXPIRY_SETTING, CRITICAL_ALERT_MUTE_UI_SETTING,
|
||||
CRITICAL_ERROR_CHANNELS_SETTING, CUSTOM_TAGS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING,
|
||||
DEFAULT_TAGS_WORKSPACES_SETTING, DISABLE_PASSWORD_LOGIN_SETTING, EMAIL_DOMAIN_SETTING,
|
||||
ENV_SETTINGS, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING,
|
||||
EXTRA_PIP_INDEX_URL_SETTING, FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
|
||||
HTTP_ROUTE_WORKSPACED_ROUTE_SETTING, HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING,
|
||||
INDEXER_SETTING, INSTANCE_EVENTS_WEBHOOK_SETTING, INSTANCE_PYTHON_VERSION_SETTING,
|
||||
BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING, BUN_INSTALL_MIN_RELEASE_AGE_SETTING,
|
||||
CRITICAL_ALERTS_ON_DB_OVERSIZE_SETTING, CRITICAL_ALERTS_ON_TOKEN_EXPIRY_SETTING,
|
||||
CRITICAL_ALERT_MUTE_UI_SETTING, CRITICAL_ERROR_CHANNELS_SETTING, CUSTOM_TAGS_SETTING,
|
||||
DEFAULT_TAGS_PER_WORKSPACE_SETTING, DEFAULT_TAGS_WORKSPACES_SETTING,
|
||||
DISABLE_PASSWORD_LOGIN_SETTING, EMAIL_DOMAIN_SETTING, ENV_SETTINGS,
|
||||
EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING,
|
||||
FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING, HTTP_ROUTE_WORKSPACED_ROUTE_SETTING,
|
||||
HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INDEXER_SETTING,
|
||||
INSTANCE_EVENTS_WEBHOOK_SETTING, INSTANCE_PYTHON_VERSION_SETTING,
|
||||
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING,
|
||||
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING, MAVEN_SETTINGS_XML_SETTING,
|
||||
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NO_DEFAULT_MAVEN_SETTING,
|
||||
@@ -56,7 +57,7 @@ use windmill_common::{
|
||||
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RESTART_COORDINATION_SETTING,
|
||||
RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING, SAML_METADATA_SETTING,
|
||||
SCIM_TOKEN_SETTING, SMTP_SETTING, TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
|
||||
UV_INDEX_STRATEGY_SETTING, WORKSPACE_REGISTRIES_SETTING,
|
||||
UV_EXCLUDE_NEWER_SETTING, UV_INDEX_STRATEGY_SETTING, WORKSPACE_REGISTRIES_SETTING,
|
||||
},
|
||||
scripts::ScriptLang,
|
||||
stats_oss::schedule_stats,
|
||||
@@ -105,15 +106,16 @@ use crate::monitor::{
|
||||
load_require_preexisting_user, load_tag_per_workspace_enabled,
|
||||
load_tag_per_workspace_workspaces, monitor_db, reload_app_workspaced_route_setting,
|
||||
reload_audit_log_retention_days_setting, reload_base_url_setting,
|
||||
reload_bunfig_install_scopes_setting, reload_critical_alert_mute_ui_setting,
|
||||
reload_critical_alerts_on_token_expiry_setting, reload_critical_error_channels_setting,
|
||||
reload_extra_pip_index_url_setting, reload_http_route_workspaced_route_setting,
|
||||
reload_hub_api_secret_setting, reload_hub_base_url_setting,
|
||||
reload_instance_events_webhook_setting, reload_job_default_timeout_setting,
|
||||
reload_job_isolation_setting, reload_jwt_secret_setting, reload_license_key,
|
||||
reload_npm_config_registry_setting, reload_otel_tracing_proxy_setting,
|
||||
reload_bun_install_min_release_age_setting, reload_bunfig_install_scopes_setting,
|
||||
reload_critical_alert_mute_ui_setting, reload_critical_alerts_on_token_expiry_setting,
|
||||
reload_critical_error_channels_setting, reload_extra_pip_index_url_setting,
|
||||
reload_http_route_workspaced_route_setting, reload_hub_api_secret_setting,
|
||||
reload_hub_base_url_setting, reload_instance_events_webhook_setting,
|
||||
reload_job_default_timeout_setting, reload_job_isolation_setting, reload_jwt_secret_setting,
|
||||
reload_license_key, reload_npm_config_registry_setting, reload_otel_tracing_proxy_setting,
|
||||
reload_pip_index_url_setting, reload_retention_period_setting, reload_scim_token_setting,
|
||||
reload_smtp_config, reload_uv_index_strategy_setting, reload_worker_config, MonitorIteration,
|
||||
reload_smtp_config, reload_uv_exclude_newer_setting, reload_uv_index_strategy_setting,
|
||||
reload_worker_config, MonitorIteration,
|
||||
};
|
||||
|
||||
#[cfg(feature = "parquet")]
|
||||
@@ -1742,6 +1744,10 @@ async fn process_notify_event(
|
||||
EXTRA_PIP_INDEX_URL_SETTING => reload_extra_pip_index_url_setting(conn).await,
|
||||
PIP_INDEX_URL_SETTING => reload_pip_index_url_setting(conn).await,
|
||||
UV_INDEX_STRATEGY_SETTING => reload_uv_index_strategy_setting(conn).await,
|
||||
UV_EXCLUDE_NEWER_SETTING => reload_uv_exclude_newer_setting(conn).await,
|
||||
BUN_INSTALL_MIN_RELEASE_AGE_SETTING => {
|
||||
reload_bun_install_min_release_age_setting(conn).await
|
||||
}
|
||||
INSTANCE_PYTHON_VERSION_SETTING => {
|
||||
reload_instance_python_version_setting(conn).await
|
||||
}
|
||||
|
||||
+33
-11
@@ -53,11 +53,11 @@ use windmill_common::{
|
||||
flow_status::{FlowStatus, FlowStatusModule},
|
||||
global_settings::{
|
||||
AUDIT_LOG_RETENTION_DAYS_SETTING, BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING,
|
||||
CRITICAL_ALERTS_ON_DB_OVERSIZE_SETTING, CRITICAL_ALERTS_ON_TOKEN_EXPIRY_SETTING,
|
||||
CRITICAL_ALERT_MUTE_UI_SETTING, CRITICAL_ERROR_CHANNELS_SETTING,
|
||||
DEFAULT_TAGS_PER_WORKSPACE_SETTING, DEFAULT_TAGS_WORKSPACES_SETTING,
|
||||
DISABLE_PASSWORD_LOGIN, DISABLE_PASSWORD_LOGIN_SETTING, EXPOSE_DEBUG_METRICS_SETTING,
|
||||
EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING,
|
||||
BUN_INSTALL_MIN_RELEASE_AGE_SETTING, CRITICAL_ALERTS_ON_DB_OVERSIZE_SETTING,
|
||||
CRITICAL_ALERTS_ON_TOKEN_EXPIRY_SETTING, CRITICAL_ALERT_MUTE_UI_SETTING,
|
||||
CRITICAL_ERROR_CHANNELS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING,
|
||||
DEFAULT_TAGS_WORKSPACES_SETTING, DISABLE_PASSWORD_LOGIN, DISABLE_PASSWORD_LOGIN_SETTING,
|
||||
EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING,
|
||||
FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING, HUB_API_SECRET_SETTING,
|
||||
HUB_BASE_URL_SETTING, INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING,
|
||||
JOB_ISOLATION_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING,
|
||||
@@ -66,7 +66,7 @@ use windmill_common::{
|
||||
POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING,
|
||||
REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING,
|
||||
RETENTION_PERIOD_SECS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING,
|
||||
TIMEOUT_WAIT_RESULT_SETTING, UV_INDEX_STRATEGY_SETTING,
|
||||
TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING, UV_INDEX_STRATEGY_SETTING,
|
||||
},
|
||||
indexer::load_indexer_config,
|
||||
jwt::JWT_SECRET,
|
||||
@@ -103,11 +103,11 @@ use windmill_queue::{cancel_job, get_queued_job_v2, SameWorkerPayload};
|
||||
use windmill_worker::{
|
||||
result_processor::handle_job_error, JobCompletedSender, JobIsolationLevel,
|
||||
OtelTracingProxySettings, SameWorkerSender, WorkspaceRegistryMap, BUNFIG_INSTALL_SCOPES,
|
||||
CARGO_REGISTRIES, INSTANCE_PYTHON_VERSION, JAVA_HOME_DIR, JOB_DEFAULT_TIMEOUT, JOB_ISOLATION,
|
||||
KEEP_JOB_DIR, MAVEN_REPOS, MAVEN_SETTINGS_XML, NO_DEFAULT_MAVEN, NPMRC, NPM_CONFIG_REGISTRY,
|
||||
NSJAIL_AVAILABLE, NUGET_CONFIG, OTEL_TRACING_PROXY_SETTINGS, PIP_EXTRA_INDEX_URL,
|
||||
PIP_INDEX_URL, POWERSHELL_REPO_PAT, POWERSHELL_REPO_URL, UNSHARE_PATH, UV_INDEX_STRATEGY,
|
||||
WORKSPACE_REGISTRIES,
|
||||
BUN_INSTALL_MIN_RELEASE_AGE, CARGO_REGISTRIES, INSTANCE_PYTHON_VERSION, JAVA_HOME_DIR,
|
||||
JOB_DEFAULT_TIMEOUT, JOB_ISOLATION, KEEP_JOB_DIR, MAVEN_REPOS, MAVEN_SETTINGS_XML,
|
||||
NO_DEFAULT_MAVEN, NPMRC, NPM_CONFIG_REGISTRY, NSJAIL_AVAILABLE, NUGET_CONFIG,
|
||||
OTEL_TRACING_PROXY_SETTINGS, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, POWERSHELL_REPO_PAT,
|
||||
POWERSHELL_REPO_URL, UNSHARE_PATH, UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY, WORKSPACE_REGISTRIES,
|
||||
};
|
||||
|
||||
#[cfg(feature = "parquet")]
|
||||
@@ -368,6 +368,8 @@ pub async fn initial_load(
|
||||
reload_extra_pip_index_url_setting(&conn).await;
|
||||
reload_pip_index_url_setting(&conn).await;
|
||||
reload_uv_index_strategy_setting(&conn).await;
|
||||
reload_uv_exclude_newer_setting(&conn).await;
|
||||
reload_bun_install_min_release_age_setting(&conn).await;
|
||||
reload_npm_config_registry_setting(&conn).await;
|
||||
reload_bunfig_install_scopes_setting(&conn).await;
|
||||
reload_npmrc_setting(&conn).await;
|
||||
@@ -1592,6 +1594,26 @@ pub async fn reload_uv_index_strategy_setting(conn: &Connection) {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn reload_uv_exclude_newer_setting(conn: &Connection) {
|
||||
reload_option_setting_with_tracing(
|
||||
conn,
|
||||
UV_EXCLUDE_NEWER_SETTING,
|
||||
"UV_EXCLUDE_NEWER",
|
||||
UV_EXCLUDE_NEWER.clone(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn reload_bun_install_min_release_age_setting(conn: &Connection) {
|
||||
reload_option_setting_with_tracing(
|
||||
conn,
|
||||
BUN_INSTALL_MIN_RELEASE_AGE_SETTING,
|
||||
"BUN_INSTALL_MIN_RELEASE_AGE",
|
||||
BUN_INSTALL_MIN_RELEASE_AGE.clone(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn reload_instance_python_version_setting(conn: &Connection) {
|
||||
reload_option_setting_with_tracing(
|
||||
conn,
|
||||
|
||||
@@ -29,6 +29,8 @@ pub const CARGO_REGISTRIES_SETTING: &str = "cargo_registries";
|
||||
pub const EXTRA_PIP_INDEX_URL_SETTING: &str = "pip_extra_index_url";
|
||||
pub const PIP_INDEX_URL_SETTING: &str = "pip_index_url";
|
||||
pub const UV_INDEX_STRATEGY_SETTING: &str = "uv_index_strategy";
|
||||
pub const UV_EXCLUDE_NEWER_SETTING: &str = "uv_exclude_newer";
|
||||
pub const BUN_INSTALL_MIN_RELEASE_AGE_SETTING: &str = "bun_install_min_release_age";
|
||||
pub const INSTANCE_PYTHON_VERSION_SETTING: &str = "instance_python_version";
|
||||
pub const RUFF_CONFIG_SETTING: &str = "ruff_config";
|
||||
pub const SCIM_TOKEN_SETTING: &str = "scim_token";
|
||||
|
||||
@@ -213,6 +213,10 @@ pub struct GlobalSettings {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub job_default_timeout: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bun_install_min_release_age: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub uv_exclude_newer: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub request_size_limit_mb: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timeout_wait_result: Option<i64>,
|
||||
|
||||
@@ -22,9 +22,9 @@ use crate::{
|
||||
get_proxy_envs_for_lang,
|
||||
handle_child::handle_child,
|
||||
is_sandboxing_enabled, read_ee_registry_with_workspace_override, BUNFIG_INSTALL_SCOPES,
|
||||
BUN_BUNDLE_CACHE_DIR, BUN_CACHE_DIR, BUN_NO_CACHE, BUN_PATH, DISABLE_NUSER, HOME_ENV,
|
||||
NODE_BIN_PATH, NODE_PATH, NPMRC, NPM_CONFIG_REGISTRY, NPM_PATH, NSJAIL_AVAILABLE, NSJAIL_PATH,
|
||||
PATH_ENV, PROXY_ENVS, TRACING_PROXY_CA_CERT_PATH, TZ_ENV,
|
||||
BUN_BUNDLE_CACHE_DIR, BUN_CACHE_DIR, BUN_INSTALL_MIN_RELEASE_AGE, BUN_NO_CACHE, BUN_PATH,
|
||||
DISABLE_NUSER, HOME_ENV, NODE_BIN_PATH, NODE_PATH, NPMRC, NPM_CONFIG_REGISTRY, NPM_PATH,
|
||||
NSJAIL_AVAILABLE, NSJAIL_PATH, PATH_ENV, PROXY_ENVS, TRACING_PROXY_CA_CERT_PATH, TZ_ENV,
|
||||
};
|
||||
use windmill_common::{
|
||||
client::AuthedClient,
|
||||
@@ -3240,6 +3240,12 @@ pub async fn get_common_bun_proc_envs(base_internal_url: Option<&str>) -> HashMa
|
||||
if let Some(ref node_path) = NODE_PATH.as_ref() {
|
||||
bun_envs.insert(String::from("NODE_PATH"), node_path.to_string());
|
||||
}
|
||||
if let Some(secs) = *BUN_INSTALL_MIN_RELEASE_AGE.read().await {
|
||||
bun_envs.insert(
|
||||
String::from("BUN_INSTALL_MINIMUM_RELEASE_AGE"),
|
||||
secs.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
|
||||
@@ -142,7 +142,7 @@ use crate::{
|
||||
worker_utils::ping_job_status,
|
||||
PyV, DISABLE_NUSER, HOME_ENV, NSJAIL_AVAILABLE, NSJAIL_PATH, PATH_ENV, PIP_EXTRA_INDEX_URL,
|
||||
PIP_INDEX_URL, PROXY_ENVS, PY_INSTALL_DIR, TRACING_PROXY_CA_CERT_PATH, TZ_ENV, UV_CACHE_DIR,
|
||||
UV_INDEX_STRATEGY,
|
||||
UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY,
|
||||
};
|
||||
use windmill_common::client::AuthedClient;
|
||||
|
||||
@@ -231,6 +231,7 @@ pub async fn uv_pip_compile(
|
||||
|
||||
let uv_index_strategy = UV_INDEX_STRATEGY.read().await.clone();
|
||||
let uv_index_strategy = uv_index_strategy.as_deref().unwrap_or("unsafe-best-match");
|
||||
let uv_exclude_newer = (*UV_EXCLUDE_NEWER.read().await).map(|secs| format!("{}s", secs));
|
||||
|
||||
let py_version_str = py_version.clone().to_string();
|
||||
// Include python version to requirements.in
|
||||
@@ -242,8 +243,12 @@ pub async fn uv_pip_compile(
|
||||
let requirements = replace_pip_secret(conn, w_id, &requirements, worker_name, job_id).await?;
|
||||
|
||||
let ws_suffix = crate::workspace_registry_cache_suffix(w_id).await;
|
||||
let exclude_newer_suffix = uv_exclude_newer
|
||||
.as_deref()
|
||||
.map(|v| format!("-en{}", v))
|
||||
.unwrap_or_default();
|
||||
let req_hash = format!(
|
||||
"py-{}-{uv_index_strategy}{ws_suffix}",
|
||||
"py-{}-{uv_index_strategy}{exclude_newer_suffix}{ws_suffix}",
|
||||
calculate_hash(&requirements)
|
||||
);
|
||||
|
||||
@@ -333,6 +338,9 @@ pub async fn uv_pip_compile(
|
||||
if *NATIVE_CERT {
|
||||
args.extend(["--native-tls"]);
|
||||
}
|
||||
if let Some(exclude_newer) = uv_exclude_newer.as_deref() {
|
||||
args.extend(["--exclude-newer", exclude_newer]);
|
||||
}
|
||||
tracing::debug!("uv args: {:?}", args);
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -1901,6 +1909,8 @@ async fn spawn_uv_install(
|
||||
let uv_index_strategy = uv_index_strategy_guard
|
||||
.as_deref()
|
||||
.unwrap_or("unsafe-best-match");
|
||||
let uv_exclude_newer = (*UV_EXCLUDE_NEWER.read().await).map(|secs| format!("{}s", secs));
|
||||
let uv_exclude_newer = uv_exclude_newer.as_deref();
|
||||
|
||||
if is_sandboxing_enabled() {
|
||||
tracing::info!(
|
||||
@@ -1936,6 +1946,9 @@ async fn spawn_uv_install(
|
||||
vars.push(("REQ", &req));
|
||||
vars.push(("TARGET", venv_p));
|
||||
vars.push(("UV_INDEX_STRATEGY", uv_index_strategy));
|
||||
if let Some(v) = uv_exclude_newer {
|
||||
vars.push(("UV_EXCLUDE_NEWER", v));
|
||||
}
|
||||
|
||||
std::fs::create_dir_all(venv_p)?;
|
||||
let nsjail_proto = format!("{req}.config.proto");
|
||||
@@ -2007,6 +2020,9 @@ async fn spawn_uv_install(
|
||||
command_args.extend(["--extra-index-url", url]);
|
||||
});
|
||||
}
|
||||
if let Some(v) = uv_exclude_newer {
|
||||
command_args.extend(["--exclude-newer", v]);
|
||||
}
|
||||
|
||||
let mut envs = vec![("PATH", PATH_ENV.as_str())];
|
||||
envs.push(("HOME", HOME_ENV.as_str()));
|
||||
|
||||
@@ -634,6 +634,8 @@ lazy_static::lazy_static! {
|
||||
pub static ref PIP_EXTRA_INDEX_URL: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref PIP_INDEX_URL: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref UV_INDEX_STRATEGY: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref UV_EXCLUDE_NEWER: Arc<RwLock<Option<i64>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref BUN_INSTALL_MIN_RELEASE_AGE: Arc<RwLock<Option<i64>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref INSTANCE_PYTHON_VERSION: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
|
||||
pub static ref JOB_DEFAULT_TIMEOUT: Arc<RwLock<Option<i32>>> = Arc::new(RwLock::new(None));
|
||||
|
||||
|
||||
@@ -509,6 +509,24 @@ export const settings: Record<string, Setting[]> = {
|
||||
ee_only: '',
|
||||
hiddenIfEmpty: true
|
||||
},
|
||||
{
|
||||
label: 'Minimum release age (uv / Python)',
|
||||
description:
|
||||
'Refuse to install Python packages younger than this many seconds. Protects against supply-chain attacks via freshly published versions. Wires to <code>uv pip --exclude-newer</code>.',
|
||||
key: 'uv_exclude_newer',
|
||||
fieldType: 'seconds',
|
||||
placeholder: '604800',
|
||||
storage: 'setting'
|
||||
},
|
||||
{
|
||||
label: 'Minimum release age (bun / npm)',
|
||||
description:
|
||||
'Refuse to install npm packages younger than this many seconds. Protects against supply-chain attacks via freshly published versions. Sets <code>BUN_INSTALL_MINIMUM_RELEASE_AGE</code>.',
|
||||
key: 'bun_install_min_release_age',
|
||||
fieldType: 'seconds',
|
||||
placeholder: '604800',
|
||||
storage: 'setting'
|
||||
},
|
||||
{
|
||||
label: 'Nuget Config',
|
||||
description:
|
||||
|
||||
Reference in New Issue
Block a user