launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #32837
[Merge] ~ruinedyourlife/launchpad-buildd:maven-virtual-remote into launchpad-buildd:master
Quentin Debhi has proposed merging ~ruinedyourlife/launchpad-buildd:maven-virtual-remote into launchpad-buildd:master.
Commit message:
Allow maven to pull plugins from AF and disallow external access
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~ruinedyourlife/launchpad-buildd/+git/launchpad-buildd/+merge/490354
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~ruinedyourlife/launchpad-buildd:maven-virtual-remote into launchpad-buildd:master.
diff --git a/lpbuildd/target/build_craft.py b/lpbuildd/target/build_craft.py
index 1e01c97..81cb27f 100644
--- a/lpbuildd/target/build_craft.py
+++ b/lpbuildd/target/build_craft.py
@@ -1,5 +1,6 @@
import logging
import os
+from urllib.parse import urlparse
from lpbuildd.target.backend import check_path_escape
from lpbuildd.target.build_snap import SnapChannelsAction
@@ -122,7 +123,7 @@ class BuildCraft(
"snap",
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
]
)
@@ -208,13 +209,14 @@ class BuildCraft(
return cargo_vars
- def setup_maven_credentials(self):
+ def setup_maven_credentials(self, proxy_env=None):
"""Set up Maven credential files for Artifactory virtual repository.
Creates a Maven settings.xml file with:
1. Server configuration for authentication
2. Profile configuration for the virtual repository
3. Mirror configuration to redirect all requests through Artifactory
+ 4. Proxy configuration for HTTP requests
Note: Multi-tenant Maven setups are complex due to how mirrors work.
Instead, we use a single Artifactory virtual repository that shadows
@@ -234,7 +236,7 @@ class BuildCraft(
return
# Create .m2 directory for Maven configuration
- m2_dir = os.path.join(self.buildd_path, ".m2")
+ m2_dir = os.path.join("/root", ".m2")
self.backend.run(["mkdir", "-p", m2_dir])
# Parse single repository URL, credentials, and name from env vars
@@ -254,17 +256,23 @@ class BuildCraft(
if not repo_name or not repository.get("url"):
return
+ # Extract proxy URL from environment if available
+ proxy_url = None
+ if proxy_env and "http_proxy" in proxy_env:
+ proxy_url = proxy_env["http_proxy"]
+
# Generate Maven settings.xml
- settings_xml = self._generate_maven_settings_xml(repo_name, repository)
+ settings_xml = self._generate_maven_settings_xml(repo_name, repository, proxy_url)
with self.backend.open(os.path.join(m2_dir, "settings.xml"), "w") as f:
f.write(settings_xml)
- def _generate_maven_settings_xml(self, repo_name, repository):
+ def _generate_maven_settings_xml(self, repo_name, repository, proxy_url=None):
"""Generate Maven settings.xml for single virtual repository.
:param repo_name: Name/ID of the repository
:param repository: Dict with repository configuration
+ :param proxy_url: Optional proxy URL for Maven to use
:return: XML content as string
"""
# XML header
@@ -292,6 +300,23 @@ class BuildCraft(
)
servers += " </servers>\n"
+ # Proxies section for HTTP proxy configuration
+ proxies = " <proxies>\n"
+ if proxy_url:
+ # Parse proxy URL to extract host, port, and credentials
+ parsed_proxy = urlparse(proxy_url)
+
+ proxies += (
+ " <proxy>\n"
+ " <id>default</id>\n"
+ " <active>true</active>\n"
+ " <protocol>http</protocol>\n"
+ f" <host>{parsed_proxy.hostname}</host>\n"
+ f" <port>{parsed_proxy.port or 80}</port>\n"
+ " </proxy>\n"
+ )
+ proxies += " </proxies>\n"
+
# Profiles section with virtual repository
profiles = " <profiles>\n"
profiles += (
@@ -328,23 +353,25 @@ class BuildCraft(
)
# Combine all parts
- return header + schema + servers + profiles + mirrors + "</settings>"
+ return header + schema + servers + proxies + profiles + mirrors + "</settings>"
def build(self):
"""Running build phase..."""
+ env = self.build_proxy_environment(
+ proxy_url=self.args.proxy_url,
+ use_fetch_service=self.args.use_fetch_service,
+ )
+
# Set up credential files before building
cargo_env = self.setup_cargo_credentials()
- self.setup_maven_credentials()
+ self.setup_maven_credentials(proxy_env=env)
logger.info("Running build phase...")
build_context_path = os.path.join(
"/home/buildd", self.args.name, self.args.build_path
)
check_path_escape(self.buildd_path, build_context_path)
- env = self.build_proxy_environment(
- proxy_url=self.args.proxy_url,
- use_fetch_service=self.args.use_fetch_service,
- )
+
if cargo_env:
env.update(cargo_env)
if self.args.launchpad_instance:
diff --git a/lpbuildd/target/tests/test_build_craft.py b/lpbuildd/target/tests/test_build_craft.py
index 0e83514..98f2623 100644
--- a/lpbuildd/target/tests/test_build_craft.py
+++ b/lpbuildd/target/tests/test_build_craft.py
@@ -130,7 +130,7 @@ class TestBuildCraft(TestCase):
RanSnap(
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
),
RanCommand(["mkdir", "-p", "/home/buildd"]),
@@ -159,7 +159,7 @@ class TestBuildCraft(TestCase):
RanSnap(
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
),
RanCommand(["mkdir", "-p", "/home/buildd"]),
@@ -216,7 +216,7 @@ class TestBuildCraft(TestCase):
RanSnap(
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
),
RanCommand(["mkdir", "-p", "/home/buildd"]),
@@ -258,7 +258,7 @@ class TestBuildCraft(TestCase):
RanSnap(
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
),
RanCommand(["mkdir", "-p", "/home/buildd"]),
@@ -310,7 +310,7 @@ class TestBuildCraft(TestCase):
RanSnap(
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
),
RanCommand(["rm", "-rf", "/var/lib/apt/lists"]),
@@ -410,7 +410,7 @@ class TestBuildCraft(TestCase):
RanSnap(
"install",
"--classic",
- "--channel=latest/edge/craftctl",
+ "--channel=latest/edge",
"sourcecraft",
),
RanCommand(["rm", "-rf", "/var/lib/apt/lists"]),
@@ -1305,7 +1305,7 @@ class TestBuildCraft(TestCase):
build_craft.build()
# Check that .m2/settings.xml was created correctly
- maven_settings_path = "/home/buildd/test-image/.m2/settings.xml"
+ maven_settings_path = "/root/.m2/settings.xml"
self.assertTrue(build_craft.backend.path_exists(maven_settings_path))
with build_craft.backend.open(maven_settings_path) as f:
settings_content = f.read()
@@ -1359,7 +1359,7 @@ class TestBuildCraft(TestCase):
build_craft.backend.run.calls,
MatchesListwise(
[
- RanCommand(["mkdir", "-p", "/home/buildd/test-image/.m2"]),
+ RanCommand(["mkdir", "-p", "/root/.m2"]),
RanBuildCommand(
["sourcecraft", "pack", "-v", "--destructive-mode"],
cwd="/home/buildd/test-image/.",
@@ -1384,7 +1384,7 @@ class TestBuildCraft(TestCase):
build_craft.build()
# Check that .m2/settings.xml was NOT created
- maven_settings_path = "/home/buildd/test-image/.m2/settings.xml"
+ maven_settings_path = "/root/.m2/settings.xml"
self.assertFalse(build_craft.backend.path_exists(maven_settings_path))
# Verify only the build command was run (no mkdir for .m2)