launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #32813
Re: [Merge] ~ruinedyourlife/launchpad-buildd:maven-virtual-remote into launchpad-buildd:master
Left a question below ^^
Diff comments:
> diff --git a/lpbuildd/target/build_craft.py b/lpbuildd/target/build_craft.py
> index 69106a8..524d60f 100644
> --- a/lpbuildd/target/build_craft.py
> +++ b/lpbuildd/target/build_craft.py
> @@ -196,157 +196,144 @@ class BuildCraft(
> name = key[len("CARGO_"):-len("_READ_AUTH")]
> # Extract token from user:token format
> token = value.split(":", 1)[1]
> - cargo_vars[f"CARGO_REGISTRIES_{name}_TOKEN"] = f"Bearer {token}"
> + cargo_vars[f"CARGO_REGISTRIES_{name}_TOKEN"] = (
> + f"Bearer {token}"
> + )
>
> if cargo_vars:
> # Tell Cargo to use token-based authentication from environment
> - cargo_vars["CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS"] = "cargo:token"
> -
> + cargo_vars["CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS"] = (
> + "cargo:token"
> + )
> +
> return cargo_vars
>
> def setup_maven_credentials(self):
> - """Set up Maven credential files if needed.
> -
> + """Set up Maven credential files for Artifactory virtual repository.
> +
> Creates a Maven settings.xml file with:
> - 1. Server configurations for authentication
> - - One for release repository
> - - One for snapshot repository
> - - Uses credentials from MAVEN_*_READ_AUTH variables
> -
> - 2. Profile configurations for each repository
> - - Defines both release and snapshot repositories
> - - Configures plugin repositories
> - - Controls snapshot behavior
> -
> - 3. Mirror configurations
> - - Redirects all repository requests through Artifactory
> - - Ensures dependencies are fetched through our proxy
> -
> - The resulting settings.xml allows Maven to:
> - - Authenticate with private repositories
> - - Use the correct URLs for artifacts
> - - Handle both release and snapshot dependencies
> - - Use plugin repositories with authentication
> -
> - It is up to the user to activate the profile they want to use
> - in the command line (this is done inside sourcecraft.yaml).
> + 1. Server configuration for authentication
> + 2. Profile configuration for the virtual repository
> + 3. Mirror configuration to redirect all requests through Artifactory
> +
> + Note: Multi-tenant Maven setups are complex due to how mirrors work.
> + Instead, we use a single Artifactory virtual repository that shadows
> + Maven Central and other remote repositories as needed.
> """
> env_vars = dict(
> - pair.split("=", maxsplit=1)
> + pair.split("=", maxsplit=1)
> for pair in self.args.environment_variables
> )
> -
> +
> # Extract Maven-specific variables
> - maven_vars = {k: v for k, v in env_vars.items() if k.startswith("MAVEN_")}
> + maven_vars = {
> + k: v for k, v in env_vars.items() if k.startswith("MAVEN_")
> + }
> if not maven_vars:
> + logger.info("No Maven environment variables found")
> return
>
> # Create .m2 directory for Maven configuration
> m2_dir = os.path.join(self.buildd_path, ".m2")
> self.backend.run(["mkdir", "-p", m2_dir])
>
> - # Parse repository URLs and credentials from environment variables
> - repositories = {}
> + # Parse single repository URL and credentials from env vars
> + repository = {}
> for key, value in maven_vars.items():
> if key.endswith("_URL"):
> - repo_name = key[6:-4].lower() # Remove MAVEN_ and _URL
> - repositories.setdefault(repo_name, {})["url"] = value
> + repository["url"] = value
> elif key.endswith("_READ_AUTH"):
> - repo_name = key[6:-10].lower() # Remove MAVEN_ and _READ_AUTH
> user, token = value.split(":")
> - repositories.setdefault(repo_name, {})["username"] = user
> - repositories.setdefault(repo_name, {})["password"] = token
> -
> - # Create settings.xml with server configurations
> - settings_xml = """<?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>
> -"""
> - # Add authentication for both release and snapshot repositories
> - for name, repo in repositories.items():
> - if "username" in repo and "password" in repo:
> - settings_xml += f""" <server>
> - <id>{name}</id>
> - <username>{repo['username']}</username>
> - <password>{repo['password']}</password>
> - </server>
> - <server>
> - <id>{name}-snapshots</id>
> - <username>{repo['username']}</username>
> - <password>{repo['password']}</password>
> - </server>
> -"""
> -
> - # Add profile configurations for repository definitions
> - settings_xml += """ </servers>
> - <profiles>
> -"""
> - for name, repo in repositories.items():
> - if "url" in repo:
> - # Each profile contains both release and snapshot repositories
> - settings_xml += f""" <profile>
> - <id>{name}</id>
> - <repositories>
> - <repository>
> - <id>{name}</id>
> - <name>{name}</name>
> - <url>{repo['url']}</url>
> - <snapshots>
> - <enabled>false</enabled>
> - </snapshots>
> - </repository>
> - <repository>
> - <id>{name}-snapshots</id>
> - <name>{name}</name>
> - <url>{repo['url']}</url>
> - <snapshots>
> - <enabled>true</enabled>
> - </snapshots>
> - </repository>
> - </repositories>
> - <pluginRepositories>
> - <pluginRepository>
> - <id>{name}</id>
> - <name>{name}</name>
> - <url>{repo['url']}</url>
> - <snapshots>
> - <enabled>false</enabled>
> - </snapshots>
> - </pluginRepository>
> - <pluginRepository>
> - <id>{name}-snapshots</id>
> - <name>{name}</name>
> - <url>{repo['url']}</url>
> - <snapshots>
> - <enabled>true</enabled>
> - </snapshots>
> - </pluginRepository>
> - </pluginRepositories>
> - </profile>
> -"""
> -
> - # Add mirror configurations to ensure all requests go through Artifactory
> - settings_xml += """ </profiles>
> - <mirrors>
> -"""
> - for name, repo in repositories.items():
> - if "url" in repo:
> - settings_xml += f""" <mirror>
> - <id>{name}</id>
> - <name>Maven Repository Manager running on {name}</name>
> - <url>{repo['url']}</url>
> - <mirrorOf>*</mirrorOf>
> - </mirror>
> -"""
> -
> - settings_xml += """ </mirrors>
> -</settings>
> -"""
> + repository["username"] = user
> + repository["password"] = token
> +
> + # Get repository name from environment variable
> + # (e.g., MAVEN_ARTIFACTORY_URL -> artifactory)
> + repo_name = None
> + for key in maven_vars.keys():
Do we need another loop over maven_vars.keys()? There is already another loop up above with items() that is also parsing some variables, can't we connect them? Or is it done due to a reason like readability etc?
> + if key.endswith("_URL"):
> + repo_name = key[6:-4].lower() # Remove MAVEN_ and _URL
> + break
> +
> + if not repo_name or not repository.get("url"):
> + return
> +
> + # Generate Maven settings.xml
> + settings_xml = self._generate_maven_settings_xml(repo_name, repository)
> +
> 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):
> + """Generate Maven settings.xml for single virtual repository.
> +
> + :param repo_name: Name/ID of the repository
> + :param repository: Dict with repository configuration
> + :return: XML content as string
> + """
> + # XML header
> + header = (
> + '<?xml version="1.0" encoding="UTF-8"?>\n'
> + '<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"\n'
> + ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n'
> + )
> +
> + schema = (
> + ' xsi:schemaLocation="'
> + "http://maven.apache.org/SETTINGS/1.0.0 "
> + 'http://maven.apache.org/xsd/settings-1.0.0.xsd">\n'
> + )
> +
> + # Servers section for authentication
> + servers = " <servers>\n"
> + if "username" in repository and "password" in repository:
> + servers += (
> + " <server>\n"
> + f" <id>{repo_name}</id>\n"
> + f" <username>{repository['username']}</username>\n"
> + f" <password>{repository['password']}</password>\n"
> + " </server>\n"
> + )
> + servers += " </servers>\n"
> +
> + # Profiles section with virtual repository
> + profiles = " <profiles>\n"
> + profiles += (
> + " <profile>\n"
> + f" <id>{repo_name}</id>\n"
> + " <repositories>\n"
> + " <repository>\n"
> + f" <id>{repo_name}</id>\n"
> + f" <name>Artifactory Virtual Repo</name>\n"
> + f" <url>{repository['url']}</url>\n"
> + " </repository>\n"
> + " </repositories>\n"
> + " <pluginRepositories>\n"
> + " <pluginRepository>\n"
> + f" <id>{repo_name}</id>\n"
> + f" <name>Artifactory Virtual Repo</name>\n"
> + f" <url>{repository['url']}</url>\n"
> + " </pluginRepository>\n"
> + " </pluginRepositories>\n"
> + " </profile>\n"
> + )
> + profiles += " </profiles>\n"
> +
> + # Mirrors section - redirect all requests through Artifactory
> + mirrors = (
> + " <mirrors>\n"
> + " <mirror>\n"
> + f" <id>{repo_name}</id>\n"
> + f" <name>Artifactory Virtual Repo</name>\n"
> + f" <url>{repository['url']}</url>\n"
> + " <mirrorOf>*</mirrorOf>\n"
> + " </mirror>\n"
> + " </mirrors>\n"
> + )
> +
> + # Combine all parts
> + return header + schema + servers + profiles + mirrors + "</settings>"
> +
> def build(self):
> """Running build phase..."""
> # Set up credential files before building
--
https://code.launchpad.net/~ruinedyourlife/launchpad-buildd/+git/launchpad-buildd/+merge/490002
Your team Launchpad code reviewers is requested to review the proposed merge of ~ruinedyourlife/launchpad-buildd:maven-virtual-remote into launchpad-buildd:master.
References