This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch backport/maven-4.0.x/pr-11140 in repository https://gitbox.apache.org/repos/asf/maven.git
commit 0e1faeac63e0eb6704e62ec7cac3dc58ed03a518 Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Tue Oct 7 16:54:26 2025 +0200 Allow repository URL interpolation with improved validation (#11140) This commit enables repository URL interpolation in Maven 4 while maintaining backward compatibility and providing early validation of unresolved expressions. Repository URLs can now use expressions like ${env.REPO_URL} and ${project.basedir.uri} which are interpolated during model building. Key changes: 1. DefaultModelBuilder: Add repository URL interpolation during model building - Support for repositories, pluginRepositories, profiles, and distributionManagement - Provide basedir, project.basedir, project.basedir.uri, project.rootDirectory, and project.rootDirectory.uri properties for interpolation - Enable environment variable and project property interpolation in repository URLs 2. DefaultModelValidator: Validate interpolated repository URLs for unresolved expressions - Repository URL expressions are interpolated during model building - After interpolation, any remaining ${...} expressions cause validation errors - Early failure during model validation provides clear error messages 3. CompatibilityFixStrategy: Remove repository disabling logic, replace with informational logging for interpolated URLs 4. Add integration tests for repository URL interpolation: - Test successful interpolation from environment variables and project properties - Test early failure when expressions cannot be resolved during model building The new approach enables legitimate use cases while providing early, clear error messages for unresolved expressions during the validate phase rather than later during repository resolution. (cherry picked from commit 210dbdcb7e77b5bd549d2b6263a92cca4179ec2d) # Conflicts: # impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java # impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java --- .../mvnup/goals/CompatibilityFixStrategy.java | 22 +--- .../maven/impl/model/DefaultModelBuilder.java | 79 +++++++++++++ .../maven/impl/model/DefaultModelValidator.java | 129 ++++++++++++--------- .../impl/model/DefaultModelValidatorTest.java | 19 ++- .../repository-with-unsupported-expression.xml | 41 +++++++ .../it/MavenITgh11140RepoDmUnresolvedTest.java | 48 ++++++++ .../it/MavenITgh11140RepoInterpolationTest.java | 90 ++++++++++++++ .../resources/gh-11140-repo-dm-unresolved/pom.xml | 42 +++++++ .../resources/gh-11140-repo-interpolation/pom.xml | 51 ++++++++ 9 files changed, 444 insertions(+), 77 deletions(-) diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java index 426981a09a..69e09e0a0d 100644 --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java @@ -33,7 +33,6 @@ import org.apache.maven.api.di.Singleton; import org.apache.maven.cling.invoker.mvnup.UpgradeContext; import org.jdom2.Attribute; -import org.jdom2.Comment; import org.jdom2.Content; import org.jdom2.Document; import org.jdom2.Element; @@ -498,25 +497,12 @@ private boolean fixRepositoryExpressions(Element repositoriesElement, Namespace Element urlElement = repository.getChild("url", namespace); if (urlElement != null) { String url = urlElement.getTextTrim(); - if (url.contains("${") - && !url.contains("${project.basedir}") - && !url.contains("${project.rootDirectory}")) { + if (url.contains("${")) { + // Allow repository URL interpolation; do not disable. + // Keep a gentle warning to help users notice unresolved placeholders at build time. String repositoryId = getChildText(repository, "id", namespace); - context.warning("Found unsupported expression in " + elementType + " URL (id: " + repositoryId + context.info("Detected interpolated expression in " + elementType + " URL (id: " + repositoryId + "): " + url); - context.warning( - "Maven 4 only supports ${project.basedir} and ${project.rootDirectory} expressions in repository URLs"); - - // Comment out the problematic repository - Comment comment = - new Comment(" Repository disabled due to unsupported expression in URL: " + url + " "); - Element parent = repository.getParentElement(); - parent.addContent(parent.indexOf(repository), comment); - removeElementWithFormatting(repository); - - context.detail("Fixed: " + "Commented out " + elementType + " with unsupported URL expression (id: " - + repositoryId + ")"); - fixed = true; } } } diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java index 9ab2505871..f773e66659 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java @@ -42,6 +42,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiFunction; import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.stream.Collectors; @@ -63,12 +64,15 @@ import org.apache.maven.api.model.Activation; import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.DeploymentRepository; +import org.apache.maven.api.model.DistributionManagement; import org.apache.maven.api.model.Exclusion; import org.apache.maven.api.model.InputLocation; import org.apache.maven.api.model.InputSource; import org.apache.maven.api.model.Model; import org.apache.maven.api.model.Parent; import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.Repository; import org.apache.maven.api.services.BuilderProblem; import org.apache.maven.api.services.BuilderProblem.Severity; import org.apache.maven.api.services.Interpolator; @@ -1415,6 +1419,29 @@ Model doReadFileModel() throws ModelBuilderException { model.getParent().getVersion())) : null) .build(); + // Interpolate repository URLs + if (model.getProjectDirectory() != null) { + String basedir = model.getProjectDirectory().toString(); + String basedirUri = model.getProjectDirectory().toUri().toString(); + properties.put("basedir", basedir); + properties.put("project.basedir", basedir); + properties.put("project.basedir.uri", basedirUri); + } + try { + String root = request.getSession().getRootDirectory().toString(); + String rootUri = + request.getSession().getRootDirectory().toUri().toString(); + properties.put("project.rootDirectory", root); + properties.put("project.rootDirectory.uri", rootUri); + } catch (IllegalStateException e) { + } + UnaryOperator<String> callback = properties::get; + model = model.with() + .repositories(interpolateRepository(model.getRepositories(), callback)) + .pluginRepositories(interpolateRepository(model.getPluginRepositories(), callback)) + .profiles(map(model.getProfiles(), this::interpolateRepository, callback)) + .distributionManagement(interpolateRepository(model.getDistributionManagement(), callback)) + .build(); // Override model properties with user properties Map<String, String> newProps = merge(model.getProperties(), session.getUserProperties()); if (newProps != null) { @@ -1445,6 +1472,41 @@ Model doReadFileModel() throws ModelBuilderException { return model; } + private DistributionManagement interpolateRepository( + DistributionManagement distributionManagement, UnaryOperator<String> callback) { + return distributionManagement == null + ? null + : distributionManagement + .with() + .repository((DeploymentRepository) + interpolateRepository(distributionManagement.getRepository(), callback)) + .snapshotRepository((DeploymentRepository) + interpolateRepository(distributionManagement.getSnapshotRepository(), callback)) + .build(); + } + + private Profile interpolateRepository(Profile profile, UnaryOperator<String> callback) { + return profile == null + ? null + : profile.with() + .repositories(interpolateRepository(profile.getRepositories(), callback)) + .pluginRepositories(interpolateRepository(profile.getPluginRepositories(), callback)) + .build(); + } + + private List<Repository> interpolateRepository(List<Repository> repositories, UnaryOperator<String> callback) { + return map(repositories, this::interpolateRepository, callback); + } + + private Repository interpolateRepository(Repository repository, UnaryOperator<String> callback) { + return repository == null + ? null + : repository + .with() + .url(interpolator.interpolate(repository.getUrl(), callback)) + .build(); + } + /** * Merges a list of model profiles with user-defined properties. * For each property defined in both the model and user properties, the user property value @@ -2250,4 +2312,21 @@ Set<String> getContexts() { return contexts; } } + + private static <T, A> List<T> map(List<T> resources, BiFunction<T, A, T> mapper, A argument) { + List<T> newResources = null; + if (resources != null) { + for (int i = 0; i < resources.size(); i++) { + T resource = resources.get(i); + T newResource = mapper.apply(resource, argument); + if (newResource != resource) { + if (newResources == null) { + newResources = new ArrayList<>(resources); + } + newResources.set(i, newResource); + } + } + } + return newResources; + } } diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java index 576ef1bf23..18be13c560 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java @@ -494,15 +494,6 @@ public void validateFileModel(Session s, Model m, int validationLevel, ModelProb validationLevel); } - validateRawRepositories(problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel); - - validateRawRepositories( - problems, - m.getPluginRepositories(), - "pluginRepositories.pluginRepository.", - EMPTY, - validationLevel); - Build build = m.getBuild(); if (build != null) { validate20RawPlugins(problems, build.getPlugins(), "build.plugins.plugin.", EMPTY, validationLevel); @@ -556,16 +547,6 @@ public void validateFileModel(Session s, Model m, int validationLevel, ModelProb validationLevel); } - validateRawRepositories( - problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel); - - validateRawRepositories( - problems, - profile.getPluginRepositories(), - prefix, - "pluginRepositories.pluginRepository.", - validationLevel); - BuildBase buildBase = profile.getBuild(); if (buildBase != null) { validate20RawPlugins(problems, buildBase.getPlugins(), prefix, "plugins.plugin.", validationLevel); @@ -635,6 +616,43 @@ public void validateRawModel(Session s, Model m, int validationLevel, ModelProbl parent); } } + + if (validationLevel > VALIDATION_LEVEL_MINIMAL) { + validateRawRepositories(problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel); + + validateRawRepositories( + problems, + m.getPluginRepositories(), + "pluginRepositories.pluginRepository.", + EMPTY, + validationLevel); + + for (Profile profile : m.getProfiles()) { + String prefix = "profiles.profile[" + profile.getId() + "]."; + + validateRawRepositories( + problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel); + + validateRawRepositories( + problems, + profile.getPluginRepositories(), + prefix, + "pluginRepositories.pluginRepository.", + validationLevel); + } + + DistributionManagement distMgmt = m.getDistributionManagement(); + if (distMgmt != null) { + validateRawRepository( + problems, distMgmt.getRepository(), "distributionManagement.repository.", "", true); + validateRawRepository( + problems, + distMgmt.getSnapshotRepository(), + "distributionManagement.snapshotRepository.", + "", + true); + } + } } private void validate30RawProfileActivation(ModelProblemCollector problems, Activation activation, String prefix) { @@ -1444,40 +1462,7 @@ private void validateRawRepositories( Map<String, Repository> index = new HashMap<>(); for (Repository repository : repositories) { - validateStringNotEmpty( - prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository); - - if (validateStringNotEmpty( - prefix, - prefix2, - "[" + repository.getId() + "].url", - problems, - Severity.ERROR, - Version.V20, - repository.getUrl(), - null, - repository)) { - // only allow ${basedir} and ${project.basedir} - Matcher m = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl()); - while (m.find()) { - String expr = m.group(1); - if (!("basedir".equals(expr) - || "project.basedir".equals(expr) - || expr.startsWith("project.basedir.") - || "project.rootDirectory".equals(expr) - || expr.startsWith("project.rootDirectory."))) { - addViolation( - problems, - Severity.ERROR, - Version.V40, - prefix + prefix2 + "[" + repository.getId() + "].url", - null, - "contains an unsupported expression (only expressions starting with 'project.basedir' or 'project.rootDirectory' are supported).", - repository); - break; - } - } - } + validateRawRepository(problems, repository, prefix, prefix2, false); String key = repository.getId(); @@ -1501,6 +1486,44 @@ private void validateRawRepositories( } } + private void validateRawRepository( + ModelProblemCollector problems, + Repository repository, + String prefix, + String prefix2, + boolean allowEmptyUrl) { + if (repository == null) { + return; + } + validateStringNotEmpty( + prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository); + + if (!allowEmptyUrl + && validateStringNotEmpty( + prefix, + prefix2, + "[" + repository.getId() + "].url", + problems, + Severity.ERROR, + Version.V20, + repository.getUrl(), + null, + repository)) { + // Check for uninterpolated expressions - these should have been interpolated by now + Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl()); + if (matcher.find()) { + addViolation( + problems, + Severity.ERROR, + Version.V40, + prefix + prefix2 + "[" + repository.getId() + "].url", + null, + "contains an uninterpolated expression.", + repository); + } + } + } + private void validate20EffectiveRepository( ModelProblemCollector problems, Repository repository, String prefix, int validationLevel) { if (repository != null) { diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java index 6dc7a05851..9948814d4e 100644 --- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java +++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java @@ -336,7 +336,7 @@ void testEmptyPluginVersion() throws Exception { @Test void testMissingRepositoryId() throws Exception { SimpleProblemCollector result = - validateFile("missing-repository-id-pom.xml", ModelValidator.VALIDATION_LEVEL_STRICT); + validateRaw("missing-repository-id-pom.xml", ModelValidator.VALIDATION_LEVEL_STRICT); assertViolations(result, 0, 4, 0); @@ -855,16 +855,23 @@ void testParentVersionRELEASE() throws Exception { @Test void repositoryWithExpression() throws Exception { SimpleProblemCollector result = validateFile("raw-model/repository-with-expression.xml"); - assertViolations(result, 0, 1, 0); - assertEquals( - "'repositories.repository.[repo].url' contains an unsupported expression (only expressions starting with 'project.basedir' or 'project.rootDirectory' are supported).", - result.getErrors().get(0)); + // Interpolation in repository URLs is allowed; unresolved placeholders will fail later during resolution + assertViolations(result, 0, 0, 0); } @Test void repositoryWithBasedirExpression() throws Exception { SimpleProblemCollector result = validateRaw("raw-model/repository-with-basedir-expression.xml"); - assertViolations(result, 0, 0, 0); + // This test runs on raw model without interpolation, so all expressions appear uninterpolated + // In the real flow, supported expressions would be interpolated before validation + assertViolations(result, 0, 3, 0); + } + + @Test + void repositoryWithUnsupportedExpression() throws Exception { + SimpleProblemCollector result = validateRaw("raw-model/repository-with-unsupported-expression.xml"); + // Unsupported expressions should cause validation errors + assertViolations(result, 0, 1, 0); } @Test diff --git a/impl/maven-impl/src/test/resources/poms/validation/raw-model/repository-with-unsupported-expression.xml b/impl/maven-impl/src/test/resources/poms/validation/raw-model/repository-with-unsupported-expression.xml new file mode 100644 index 0000000000..ed61d566aa --- /dev/null +++ b/impl/maven-impl/src/test/resources/poms/validation/raw-model/repository-with-unsupported-expression.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.1.0</modelVersion> + + <groupId>org.apache.maven.its.mng0000</groupId> + <artifactId>test</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>Maven Integration Test :: Test</name> + <description>Test unsupported repository URL expressions that should cause validation errors.</description> + + <repositories> + <repository> + <id>repo-unsupported</id> + <url>${project.baseUri}/sdk/maven/repo</url> + </repository> + </repositories> + +</project> diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11140RepoDmUnresolvedTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11140RepoDmUnresolvedTest.java new file mode 100644 index 0000000000..b3a2929239 --- /dev/null +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11140RepoDmUnresolvedTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.it; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +/** + * IT to assert unresolved placeholders cause failure when used. + */ +class MavenITgh11140RepoDmUnresolvedTest extends AbstractMavenIntegrationTestCase { + + MavenITgh11140RepoDmUnresolvedTest() { + super("(4.0.0-rc-3,)"); + } + + @Test + void testFailsOnUnresolvedPlaceholders() throws Exception { + File testDir = extractResources("/gh-11140-repo-dm-unresolved"); + Verifier verifier = newVerifier(testDir.getAbsolutePath()); + + try { + verifier.addCliArgument("validate"); + verifier.execute(); + } catch (VerificationException expected) { + // Expected to fail due to unresolved placeholders during model validation + } + // We expect error mentioning uninterpolated expression + verifier.verifyTextInLog("contains an uninterpolated expression"); + } +} diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11140RepoInterpolationTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11140RepoInterpolationTest.java new file mode 100644 index 0000000000..d354b33f2e --- /dev/null +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11140RepoInterpolationTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.it; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * ITs for repository/distributionManagement URL interpolation. + */ +class MavenITgh11140RepoInterpolationTest extends AbstractMavenIntegrationTestCase { + + MavenITgh11140RepoInterpolationTest() { + super("(4.0.0-rc-3,)"); + } + + @Test + void testInterpolationFromEnvAndProps() throws Exception { + File testDir = extractResources("/gh-11140-repo-interpolation"); + Verifier verifier = newVerifier(testDir.getAbsolutePath()); + + // Provide env vars consumed by POM via ${env.*} + Path base = testDir.toPath().toAbsolutePath(); + String baseUri = getBaseUri(base); + verifier.setEnvironmentVariable("IT_REPO_BASE", baseUri); + verifier.setEnvironmentVariable("IT_DM_BASE", baseUri); + + // Use a cheap goal that prints effective POM + verifier.addCliArgument("help:effective-pom"); + verifier.execute(); + verifier.verifyErrorFreeLog(); + + List<String> lines = verifier.loadLogLines(); + // Expect resolved file:// URLs, not placeholders + assertTrue(lines.stream().anyMatch(s -> s.contains("<id>envRepo</id>")), "envRepo present"); + assertTrue(lines.stream().anyMatch(s -> s.contains("<url>" + baseUri + "/repo</url>")), "envRepo url resolved"); + assertTrue(lines.stream().anyMatch(s -> s.contains("<id>propRepo</id>")), "propRepo present"); + assertTrue( + lines.stream().anyMatch(s -> s.contains("<url>" + baseUri + "/custom</url>")), + "propRepo url resolved via property"); + assertTrue(lines.stream().anyMatch(s -> s.contains("<id>distRepo</id>")), "distRepo present"); + assertTrue( + lines.stream().anyMatch(s -> s.contains("<url>" + baseUri + "/dist</url>")), "distRepo url resolved"); + } + + private static String getBaseUri(Path base) { + String baseUri = base.toUri().toString(); + if (baseUri.endsWith("/")) { + baseUri = baseUri.substring(0, baseUri.length() - 1); + } + return baseUri; + } + + @Test + void testUnresolvedPlaceholderFailsResolution() throws Exception { + File testDir = extractResources("/gh-11140-repo-interpolation"); + Verifier verifier = newVerifier(testDir.getAbsolutePath()); + + // Do NOT set env vars, so placeholders stay + verifier.addCliArgument("validate"); + try { + verifier.execute(); + } catch (VerificationException expected) { + // Expected to fail due to unresolved placeholders during model validation + } + // We expect error mentioning uninterpolated expression + verifier.verifyTextInLog("contains an uninterpolated expression"); + } +} diff --git a/its/core-it-suite/src/test/resources/gh-11140-repo-dm-unresolved/pom.xml b/its/core-it-suite/src/test/resources/gh-11140-repo-dm-unresolved/pom.xml new file mode 100644 index 0000000000..106bb79dc3 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-11140-repo-dm-unresolved/pom.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> +<project xmlns="http://maven.apache.org/POM/4.1.0" root="true"> + <groupId>org.apache.maven.its.repointerp</groupId> + <artifactId>repo-dm-unresolved</artifactId> + <version>1.0</version> + <packaging>pom</packaging> + + <name>Maven Integration Test :: Unresolved placeholders must fail</name> + <description>Verify that unresolved placeholders in repository/distributionManagement cause failure when used.</description> + + <distributionManagement> + <repository> + <id>badDist</id> + <url>${env.MISSING_VAR}/dist</url> + </repository> + </distributionManagement> + + <repositories> + <repository> + <id>badRepo</id> + <url>${env.MISSING_VAR}/repo</url> + </repository> + </repositories> +</project> diff --git a/its/core-it-suite/src/test/resources/gh-11140-repo-interpolation/pom.xml b/its/core-it-suite/src/test/resources/gh-11140-repo-interpolation/pom.xml new file mode 100644 index 0000000000..5f07980e74 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-11140-repo-interpolation/pom.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> +<project xmlns="http://maven.apache.org/POM/4.1.0" root="true"> + <groupId>org.apache.maven.its.repointerp</groupId> + <artifactId>repo-interpolation</artifactId> + <version>1.0</version> + <packaging>pom</packaging> + + <name>Maven Integration Test :: Repository and DistributionManagement URL interpolation</name> + <description>Verify that repository and distributionManagement URLs are interpolated from env and project properties.</description> + + <distributionManagement> + <repository> + <id>distRepo</id> + <url>${env.IT_DM_BASE}/dist</url> + </repository> + </distributionManagement> + + <properties> + <!-- Property sourced from env via model interpolation in test class --> + <customRepoUrl>${env.IT_REPO_BASE}/custom</customRepoUrl> + </properties> + + <repositories> + <repository> + <id>envRepo</id> + <url>${env.IT_REPO_BASE}/repo</url> + </repository> + <repository> + <id>propRepo</id> + <url>${customRepoUrl}</url> + </repository> + </repositories> +</project>