Skip to content

Commit 12a42f6

Browse files
ctruedenclaude
andcommitted
Add --settings flag to pass a Maven settings.xml
Thread an optional settings.xml path through to every Maven invocation via -s, exposed as a --settings CLI option on smelt and melt and a [common] settings key in pombast.toml (resolved relative to the config file). This lets callers supply mirrors, credentials, or per-repository update policies without editing their user-wide ~/.m2/settings.xml. The motivating case is stale "cached failure" resolution: a settings.xml setting updatePolicy to interval:120 shrinks the retry window from the 24h default to 2h, so a transiently-missing dependency self-heals on a subsequent run without forcing a full -U re-resolution on every component and without waiting a full 24 hours for the recheck. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 093bc60 commit 12a42f6

7 files changed

Lines changed: 42 additions & 0 deletions

File tree

src/pombast/cli/_app.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ def cli() -> None:
7171
default=None,
7272
help="Path to pombast.toml configuration file.",
7373
)
74+
@click.option(
75+
"--settings",
76+
"settings",
77+
type=click.Path(exists=True, dir_okay=False, path_type=Path),
78+
default=None,
79+
help="Maven settings.xml passed to every build via -s "
80+
"(for mirrors, credentials, or repository update policies).",
81+
)
7482
@click.option(
7583
"--build-dir",
7684
"output_dir",
@@ -130,6 +138,7 @@ def smelt_cmd(
130138
exclude: tuple[str, ...],
131139
repository: tuple[str, ...],
132140
config: Path | None,
141+
settings: Path | None,
133142
output_dir: Path,
134143
prune: bool,
135144
force: bool,
@@ -168,6 +177,7 @@ def smelt_cmd(
168177
includes=list(include),
169178
excludes=list(exclude),
170179
repositories=effective_repositories,
180+
settings=settings or pombast_config.settings,
171181
output_dir=output_dir,
172182
prune=prune,
173183
force=force,
@@ -227,6 +237,14 @@ def smelt_cmd(
227237
default=None,
228238
help="Path to pombast.toml configuration file.",
229239
)
240+
@click.option(
241+
"--settings",
242+
"settings",
243+
type=click.Path(exists=True, dir_okay=False, path_type=Path),
244+
default=None,
245+
help="Maven settings.xml passed to the mega-melt build via -s "
246+
"(for mirrors, credentials, or repository update policies).",
247+
)
230248
@click.option(
231249
"--build-dir",
232250
"output_dir",
@@ -260,6 +278,7 @@ def melt_cmd(
260278
exclude: tuple[str, ...],
261279
repository: tuple[str, ...],
262280
config: Path | None,
281+
settings: Path | None,
263282
output_dir: Path,
264283
force: bool,
265284
java_version: int | None,
@@ -290,6 +309,7 @@ def melt_cmd(
290309
melt_config = MeltConfig(
291310
bom=bom,
292311
repositories=effective_repositories,
312+
settings=settings or pombast_config.settings,
293313
output_dir=output_dir,
294314
force=force,
295315
includes=list(include),

src/pombast/config/_settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class PombastConfig:
114114
filter: FilterConfig = field(default_factory=FilterConfig)
115115
default_java: int | None = None
116116
repositories: dict[str, str] = field(default_factory=dict)
117+
settings: Path | None = None # Maven settings.xml passed to every build (-s)
117118
smelt_output: Path | None = None # where `smelt` writes its JSON report
118119
skip_tests: list[str] = field(default_factory=list)
119120
remove_tests: dict[str, list[str]] = field(default_factory=dict)
@@ -197,6 +198,7 @@ def resolve(section: dict, key: str) -> Path | None:
197198
filter=filter_config,
198199
default_java=int(default_java) if default_java is not None else None,
199200
repositories=parse_repo_specs(common_data.get("repositories", [])),
201+
settings=resolve(common_data, "settings"),
200202
smelt_output=resolve(smelt_data, "output"),
201203
skip_tests=smelt_data.get("skip-tests", []),
202204
remove_tests=data.get("remove-tests", {}),
@@ -234,6 +236,7 @@ class PipelineConfig:
234236
includes: list[str] = field(default_factory=list)
235237
excludes: list[str] = field(default_factory=list)
236238
repositories: dict[str, str] = field(default_factory=dict)
239+
settings: Path | None = None
237240
output_dir: Path = field(default_factory=lambda: Path("target") / "pombast")
238241
success_cache_dir: Path | None = None
239242
prune: bool = False
@@ -251,6 +254,7 @@ class MeltConfig:
251254

252255
bom: str
253256
repositories: dict[str, str] = field(default_factory=dict)
257+
settings: Path | None = None
254258
output_dir: Path = field(default_factory=lambda: Path("target") / "pombast")
255259
force: bool = False
256260
includes: list[str] = field(default_factory=list)

src/pombast/core/_melt_pipeline.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def run(self) -> MeltResult:
7171
mega_melt_dir,
7272
java_home=java_home,
7373
extra_properties=maven_properties or None,
74+
settings=self.config.settings,
7475
)
7576
except Exception as e:
7677
_log.error("Mega-melt failed: %s", e)

src/pombast/core/_pipeline.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ def run(self) -> ValidationReport:
151151
**self.config.maven_properties,
152152
},
153153
test_binary=self.config.test_binary,
154+
settings=self.config.settings,
154155
)
155156

156157
# Precompute changed G:A set once for prune filtering.

src/pombast/maven/_builder.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,14 @@ def __init__(
5858
success_cache: SuccessCache | None = None,
5959
extra_properties: dict[str, str] | None = None,
6060
test_binary: bool = True,
61+
settings: Path | None = None,
6162
) -> None:
6263
self.output_dir = output_dir
6364
self.ctx = ctx
6465
self.success_cache = success_cache or SuccessCache()
6566
self.extra_properties = extra_properties or {}
6667
self.test_binary = test_binary
68+
self.settings = settings
6769

6870
def build_and_test(
6971
self,
@@ -123,6 +125,7 @@ def build_and_test(
123125
extra_properties=merged,
124126
log_path=source_log_path,
125127
color=True,
128+
settings=self.settings,
126129
)
127130
duration = time.monotonic() - start
128131

@@ -219,6 +222,7 @@ def _test_binary(
219222
},
220223
log_path=log_path,
221224
color=True,
225+
settings=self.settings,
222226
)
223227

224228
if test_result.returncode == 0:
@@ -247,6 +251,8 @@ def _write_smelt_script(
247251
component = source.component
248252

249253
mvn_args = ["--color", "always", "-Denforcer.skip"]
254+
if self.settings is not None:
255+
mvn_args += ["-s", str(self.settings)]
250256
for key, value in merged.items():
251257
mvn_args.append(f"-D{key}={value}")
252258
args_str = " ".join(shlex.quote(a) for a in mvn_args)

src/pombast/maven/_mega_melt.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ def run_mega_melt_validation(
206206
mega_melt_dir: Path,
207207
java_home: Path | None = None,
208208
extra_properties: dict[str, str] | None = None,
209+
settings: Path | None = None,
209210
) -> tuple[bool, Path, Path]:
210211
"""Run mega-melt validation.
211212
@@ -226,6 +227,7 @@ def run_mega_melt_validation(
226227
extra_properties=extra_properties,
227228
log_path=tree_log,
228229
skip_enforcer=False,
230+
settings=settings,
229231
)
230232
if tree_result.returncode != 0:
231233
_log.warning("Mega-melt dependency:tree FAILED — see %s", tree_log)
@@ -239,6 +241,7 @@ def run_mega_melt_validation(
239241
extra_properties=extra_properties,
240242
log_path=build_log,
241243
skip_enforcer=False,
244+
settings=settings,
242245
)
243246
success = build_result.returncode == 0
244247
level = _log.info if success else _log.warning

src/pombast/util/_process.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def run_maven(
4444
timeout: int | None = None,
4545
skip_enforcer: bool = True,
4646
color: bool = False,
47+
settings: Path | None = None,
4748
) -> subprocess.CompletedProcess:
4849
"""Run a Maven command.
4950
@@ -57,12 +58,18 @@ def run_maven(
5758
skip_enforcer: If True (default), pass -Denforcer.skip to suppress
5859
enforcer rules. Set False for mega-melt validation where the
5960
enforcer is the point.
61+
settings: If provided, a Maven settings.xml passed via ``-s``. Lets the
62+
caller supply mirrors, credentials, or per-repository update
63+
policies without touching their user-wide ``~/.m2/settings.xml``.
6064
6165
Returns:
6266
CompletedProcess with stdout/stderr.
6367
"""
6468
cmd = [_resolve_mvn()]
6569

70+
if settings is not None:
71+
cmd.extend(["-s", str(settings)])
72+
6673
if color:
6774
cmd.extend(["--color", "always"])
6875

0 commit comments

Comments
 (0)