You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/09/01 19:43:53 UTC
(maven) branch fix-13004-consumer-pom-builder-fails-on-profile created (now fc32f54418)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a change to branch fix-13004-consumer-pom-builder-fails-on-profile
in repository https://gitbox.apache.org/repos/asf/maven.git
at fc32f54418 Add tests for GH-13004: consumer POM profile-activated property in artifactId
This branch includes the following new commits:
new fc32f54418 Add tests for GH-13004: consumer POM profile-activated property in artifactId
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(maven) 01/01: Add tests for GH-13004: consumer POM profile-activated property in artifactId
Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch fix-13004-consumer-pom-builder-fails-on-profile
in repository https://gitbox.apache.org/repos/asf/maven.git
commit fc32f544188d9b528b205572f4c0d47d02115829
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue Sep 1 21:43:40 2026 +0200
Add tests for GH-13004: consumer POM profile-activated property in artifactId
Add unit tests and integration test verifying that the consumer POM
builder correctly handles OS-activated profile properties used in
dependency artifactId coordinates. This scenario (from Apache Hop)
is already handled by the CONSUMER_PARENT request type (#11799)
and the MNG-8709 user-property fix, but had no regression test.
Unit tests cover:
- BUILD_CONSUMER resolving parent profile properties in artifactId
- BUILD_CONSUMER after BUILD_PROJECT (cache hit scenario)
- OS-activated profile properties with full reactor simulation
Integration test covers:
- Multi-module project with OS-activated profiles in parent POM
- Dependency management entries inside profiles using ${...} artifactId
- Non-flattened consumer POM preserving parent and profiles
- Flattened consumer POM fully resolving the property
Closes #13004
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
.../maven/impl/model/DefaultModelBuilderTest.java | 164 +++++++++++++++++++++
.../poms/factory/consumer-os-profile-child.xml | 35 +++++
.../poms/factory/consumer-os-profile-parent.xml | 61 ++++++++
.../factory/consumer-profile-artifactid-child.xml | 35 +++++
.../factory/consumer-profile-artifactid-parent.xml | 37 +++++
...nITgh13004ConsumerPomProfileArtifactIdTest.java | 106 +++++++++++++
.../child/pom.xml | 41 ++++++
.../java/org/apache/maven/its/gh13004/Child.java | 3 +
.../lib/pom.xml | 31 ++++
.../java/org/apache/maven/its/gh13004/Lib.java | 3 +
.../pom.xml | 79 ++++++++++
11 files changed, 595 insertions(+)
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
index e88cb09ca5..edb0b06b21 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
@@ -765,6 +765,170 @@ public void testBuildConsumerResolvesParentProfileProperties() {
"Managed dependency version should be interpolated, not ${managed.version}");
}
+ /**
+ * Verifies that BUILD_CONSUMER resolves properties defined in parent POM profiles
+ * when those properties are used in dependency artifactId fields.
+ * This reproduces GH-13004: the effective model coordinate validation rejects
+ * ${swt.artifactId} because profiles are not activated for BUILD_CONSUMER.
+ */
+ @Test
+ public void testBuildConsumerResolvesParentProfilePropertyInArtifactId() {
+ Path parentPom = getPom("consumer-profile-artifactid-parent");
+ Path childPom = getPom("consumer-profile-artifactid-child");
+
+ ModelBuilder.ModelBuilderSession mbs = builder.newSession();
+
+ mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(parentPom))
+ .build());
+
+ ModelBuilderResult consumerResult = assertDoesNotThrow(
+ () -> mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_CONSUMER)
+ .source(Sources.buildSource(childPom))
+ .build()),
+ "BUILD_CONSUMER should not fail when parent profile property is used in dependency artifactId");
+
+ assertNotNull(consumerResult);
+ Model effectiveModel = consumerResult.getEffectiveModel();
+ assertNotNull(effectiveModel);
+
+ // The property from the parent's profile should be inherited and available
+ assertEquals(
+ "org.eclipse.swt.gtk.linux.x86-64",
+ effectiveModel.getProperties().get("swt.artifactId"),
+ "Property from parent's profile should be resolved in BUILD_CONSUMER effective model");
+
+ // The dependency artifactId should be interpolated (not ${swt.artifactId})
+ Dependency dep = effectiveModel.getDependencies().stream()
+ .filter(d -> "org.eclipse.platform".equals(d.getGroupId()))
+ .findFirst()
+ .orElse(null);
+ assertNotNull(dep, "Dependency with org.eclipse.platform groupId should exist");
+ assertEquals(
+ "org.eclipse.swt.gtk.linux.x86-64",
+ dep.getArtifactId(),
+ "Dependency artifactId should be interpolated from parent profile property");
+ }
+
+ /**
+ * Same as above but builds the child as BUILD_PROJECT first (simulating
+ * the full reactor build), then builds BUILD_CONSUMER for the child.
+ * This is closer to what happens in a real Maven build.
+ */
+ @Test
+ public void testBuildConsumerAfterBuildProjectResolvesParentProfilePropertyInArtifactId() {
+ Path parentPom = getPom("consumer-profile-artifactid-parent");
+ Path childPom = getPom("consumer-profile-artifactid-child");
+
+ ModelBuilder.ModelBuilderSession mbs = builder.newSession();
+
+ // Build parent as BUILD_PROJECT
+ mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(parentPom))
+ .build());
+
+ // Build child as BUILD_PROJECT (as in reactor build)
+ mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(childPom))
+ .build());
+
+ // Now build child as BUILD_CONSUMER (as in consumer POM generation)
+ ModelBuilderResult consumerResult = assertDoesNotThrow(
+ () -> mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_CONSUMER)
+ .source(Sources.buildSource(childPom))
+ .build()),
+ "BUILD_CONSUMER should not fail after BUILD_PROJECT when parent profile property is used in artifactId");
+
+ assertNotNull(consumerResult);
+ Model effectiveModel = consumerResult.getEffectiveModel();
+ assertNotNull(effectiveModel);
+
+ assertEquals(
+ "org.eclipse.swt.gtk.linux.x86-64",
+ effectiveModel.getProperties().get("swt.artifactId"),
+ "Property from parent's profile should be resolved in BUILD_CONSUMER effective model");
+
+ Dependency dep = effectiveModel.getDependencies().stream()
+ .filter(d -> "org.eclipse.platform".equals(d.getGroupId()))
+ .findFirst()
+ .orElse(null);
+ assertNotNull(dep, "Dependency with org.eclipse.platform groupId should exist");
+ assertEquals(
+ "org.eclipse.swt.gtk.linux.x86-64",
+ dep.getArtifactId(),
+ "Dependency artifactId should be interpolated from parent profile property");
+ }
+
+ /**
+ * Verifies that BUILD_CONSUMER resolves properties defined in parent POM
+ * OS-activated profiles when those properties are used in dependency artifactId fields.
+ * This is the exact scenario from GH-13004 (Apache Hop).
+ */
+ @Test
+ public void testBuildConsumerResolvesOsActivatedProfilePropertyInArtifactId() {
+ Path parentPom = getPom("consumer-os-profile-parent");
+ Path childPom = getPom("consumer-os-profile-child");
+
+ ModelBuilder.ModelBuilderSession mbs = builder.newSession();
+
+ // Build parent as BUILD_PROJECT first
+ mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(parentPom))
+ .build());
+
+ // Build child as BUILD_PROJECT (reactor build)
+ mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(childPom))
+ .build());
+
+ // Now build child as BUILD_CONSUMER
+ ModelBuilderResult consumerResult = assertDoesNotThrow(
+ () -> mbs.build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_CONSUMER)
+ .source(Sources.buildSource(childPom))
+ .build()),
+ "BUILD_CONSUMER should not fail when parent defines OS-activated profile property used in artifactId");
+
+ assertNotNull(consumerResult);
+ Model effectiveModel = consumerResult.getEffectiveModel();
+ assertNotNull(effectiveModel);
+
+ // The platform.artifactId property should be resolved from one of the OS profiles
+ String platformArtifactId = effectiveModel.getProperties().get("platform.artifactId");
+ assertNotNull(
+ platformArtifactId,
+ "Property from parent's OS profile should be resolved in BUILD_CONSUMER effective model");
+
+ // The dependency artifactId should be interpolated
+ Dependency dep = effectiveModel.getDependencies().stream()
+ .filter(d -> "org.example".equals(d.getGroupId()))
+ .findFirst()
+ .orElse(null);
+ assertNotNull(dep, "Dependency with org.example groupId should exist");
+ assertFalse(
+ dep.getArtifactId().contains("${"),
+ "Dependency artifactId should be interpolated, got: " + dep.getArtifactId());
+ assertEquals(
+ platformArtifactId,
+ dep.getArtifactId(),
+ "Dependency artifactId should match the platform property value");
+ }
+
/**
* Verifies that the versions of sibling reactor modules declared in {@code <dependencyManagement>}
* are inferred, just like they already are for regular dependencies (GH-11147).
diff --git a/impl/maven-impl/src/test/resources/poms/factory/consumer-os-profile-child.xml b/impl/maven-impl/src/test/resources/poms/factory/consumer-os-profile-child.xml
new file mode 100644
index 0000000000..c377507386
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/consumer-os-profile-child.xml
@@ -0,0 +1,35 @@
+<?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">
+ <parent>
+ <groupId>org.apache.maven.tests</groupId>
+ <artifactId>consumer-os-profile-parent</artifactId>
+ <relativePath>consumer-os-profile-parent.xml</relativePath>
+ </parent>
+ <artifactId>consumer-os-profile-child</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.example</groupId>
+ <artifactId>${platform.artifactId}</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/consumer-os-profile-parent.xml b/impl/maven-impl/src/test/resources/poms/factory/consumer-os-profile-parent.xml
new file mode 100644
index 0000000000..7a70c95a3c
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/consumer-os-profile-parent.xml
@@ -0,0 +1,61 @@
+<?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">
+ <groupId>org.apache.maven.tests</groupId>
+ <artifactId>consumer-os-profile-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <!-- OS-activated profile defines a property used in child dependency artifactId.
+ This simulates the Apache Hop scenario (GH-13004). -->
+ <profiles>
+ <profile>
+ <id>platform-linux</id>
+ <activation>
+ <os>
+ <family>unix</family>
+ </os>
+ </activation>
+ <properties>
+ <platform.artifactId>platform-lib-linux</platform.artifactId>
+ </properties>
+ </profile>
+ <profile>
+ <id>platform-windows</id>
+ <activation>
+ <os>
+ <family>windows</family>
+ </os>
+ </activation>
+ <properties>
+ <platform.artifactId>platform-lib-windows</platform.artifactId>
+ </properties>
+ </profile>
+ <profile>
+ <id>platform-mac</id>
+ <activation>
+ <os>
+ <family>mac</family>
+ </os>
+ </activation>
+ <properties>
+ <platform.artifactId>platform-lib-mac</platform.artifactId>
+ </properties>
+ </profile>
+ </profiles>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/consumer-profile-artifactid-child.xml b/impl/maven-impl/src/test/resources/poms/factory/consumer-profile-artifactid-child.xml
new file mode 100644
index 0000000000..89659a8deb
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/consumer-profile-artifactid-child.xml
@@ -0,0 +1,35 @@
+<?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">
+ <parent>
+ <groupId>org.apache.maven.tests</groupId>
+ <artifactId>consumer-profile-artifactid-parent</artifactId>
+ <relativePath>consumer-profile-artifactid-parent.xml</relativePath>
+ </parent>
+ <artifactId>consumer-profile-artifactid-child</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.platform</groupId>
+ <artifactId>${swt.artifactId}</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/consumer-profile-artifactid-parent.xml b/impl/maven-impl/src/test/resources/poms/factory/consumer-profile-artifactid-parent.xml
new file mode 100644
index 0000000000..c0d9c99237
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/consumer-profile-artifactid-parent.xml
@@ -0,0 +1,37 @@
+<?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">
+ <groupId>org.apache.maven.tests</groupId>
+ <artifactId>consumer-profile-artifactid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <profiles>
+ <profile>
+ <id>default-platform</id>
+ <activation>
+ <property>
+ <name>!skipDefaultPlatform</name>
+ </property>
+ </activation>
+ <properties>
+ <swt.artifactId>org.eclipse.swt.gtk.linux.x86-64</swt.artifactId>
+ </properties>
+ </profile>
+ </profiles>
+</project>
diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh13004ConsumerPomProfileArtifactIdTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh13004ConsumerPomProfileArtifactIdTest.java
new file mode 100644
index 0000000000..16150e1a7c
--- /dev/null
+++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh13004ConsumerPomProfileArtifactIdTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.nio.file.Files;
+import java.nio.file.Path;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verify that the consumer POM builder correctly resolves properties from
+ * OS-activated profiles in parent POMs when those properties are used in
+ * child dependency artifactId coordinates.
+ * <p>
+ * This simulates the Apache Hop scenario where the root POM uses OS-activated
+ * profiles to set platform-specific dependency artifactIds (e.g., SWT) and
+ * dependency management entries that reference those properties.
+ * <p>
+ * The consumer POM builder must resolve these properties before coordinate
+ * validation, otherwise it fails with:
+ * <pre>
+ * 'dependencies.dependency.artifactId' ... with value '${swt.artifactId}'
+ * does not match a valid coordinate id pattern.
+ * </pre>
+ *
+ * @see <a href="https://github.com/apache/maven/issues/13004">GH-13004</a>
+ */
+class MavenITgh13004ConsumerPomProfileArtifactIdTest extends AbstractMavenIntegrationTestCase {
+
+ /**
+ * Test that the build succeeds when a parent POM defines OS-activated profiles
+ * with properties used in child dependency artifactIds. The default (non-flattened)
+ * consumer POM preserves the parent reference and profile activation, so consumers
+ * can resolve the property through the parent.
+ */
+ @Test
+ void testConsumerPomResolvesOsProfilePropertyInArtifactId() throws Exception {
+ Path basedir = extractResources("/gh-13004-consumer-pom-profile-artifactid");
+
+ Verifier verifier = newVerifier(basedir);
+ verifier.addCliArgument("install");
+ verifier.execute();
+ verifier.verifyErrorFreeLog();
+
+ // Verify the parent consumer POM preserves the OS-activated profiles
+ Path parentConsumerPom = verifier.getArtifactPath(
+ "org.apache.maven.its.gh13004", "parent", "1.0-SNAPSHOT", "pom");
+ assertTrue(Files.exists(parentConsumerPom), "Parent consumer POM should exist");
+ String parentContent = Files.readString(parentConsumerPom);
+ assertTrue(
+ parentContent.contains("<family>unix</family>") || parentContent.contains("<family>windows</family>"),
+ "Parent consumer POM should preserve OS-activation profiles");
+ assertTrue(
+ parentContent.contains("platform.artifactId"),
+ "Parent consumer POM should preserve the profile property definition");
+ }
+
+ /**
+ * Test that flattened consumer POM generation succeeds and fully resolves the
+ * profile property in the dependency artifactId. With flattening enabled, the
+ * effective (interpolated) model is used, so the consumer POM must contain the
+ * resolved artifactId, not the raw ${platform.artifactId} reference.
+ */
+ @Test
+ void testFlattenedConsumerPomResolvesOsProfilePropertyInArtifactId() throws Exception {
+ Path basedir = extractResources("/gh-13004-consumer-pom-profile-artifactid");
+
+ Verifier verifier = newVerifier(basedir);
+ verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
+ verifier.addCliArgument("install");
+ verifier.execute();
+ verifier.verifyErrorFreeLog();
+
+ // With flattening, the consumer POM uses the effective model:
+ // ${platform.artifactId} must be resolved to "lib"
+ Path childConsumerPom = verifier.getArtifactPath(
+ "org.apache.maven.its.gh13004", "child", "1.0-SNAPSHOT", "pom");
+ assertTrue(Files.exists(childConsumerPom), "Child consumer POM should exist");
+ String childContent = Files.readString(childConsumerPom);
+ assertFalse(
+ childContent.contains("${platform.artifactId}"),
+ "Flattened consumer POM should not contain unresolved ${platform.artifactId}");
+ assertTrue(
+ childContent.contains("<artifactId>lib</artifactId>"),
+ "Flattened consumer POM should contain the resolved artifactId 'lib'");
+ }
+}
diff --git a/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/child/pom.xml b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/child/pom.xml
new file mode 100644
index 0000000000..ff93b09a93
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/child/pom.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.1.0">
+ <modelVersion>4.1.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.its.gh13004</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>child</artifactId>
+ <packaging>jar</packaging>
+
+ <!-- Uses property from OS-activated parent profile in dependency artifactId.
+ The consumer POM builder must resolve this before coordinate validation. -->
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.its.gh13004</groupId>
+ <artifactId>${platform.artifactId}</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/child/src/main/java/org/apache/maven/its/gh13004/Child.java b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/child/src/main/java/org/apache/maven/its/gh13004/Child.java
new file mode 100644
index 0000000000..6fcc99a322
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/child/src/main/java/org/apache/maven/its/gh13004/Child.java
@@ -0,0 +1,3 @@
+package org.apache.maven.its.gh13004;
+
+public class Child {}
diff --git a/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/lib/pom.xml b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/lib/pom.xml
new file mode 100644
index 0000000000..47065c00bc
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/lib/pom.xml
@@ -0,0 +1,31 @@
+<?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">
+ <modelVersion>4.1.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.its.gh13004</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>lib</artifactId>
+ <packaging>jar</packaging>
+</project>
diff --git a/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/lib/src/main/java/org/apache/maven/its/gh13004/Lib.java b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/lib/src/main/java/org/apache/maven/its/gh13004/Lib.java
new file mode 100644
index 0000000000..21d12cbf7b
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/lib/src/main/java/org/apache/maven/its/gh13004/Lib.java
@@ -0,0 +1,3 @@
+package org.apache.maven.its.gh13004;
+
+public class Lib {}
diff --git a/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/pom.xml b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/pom.xml
new file mode 100644
index 0000000000..e6b2239e7b
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/gh-13004-consumer-pom-profile-artifactid/pom.xml
@@ -0,0 +1,79 @@
+<?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">
+ <modelVersion>4.1.0</modelVersion>
+
+ <groupId>org.apache.maven.its.gh13004</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>lib</module>
+ <module>child</module>
+ </modules>
+
+ <!-- OS-activated profiles defining a property used in child dependency artifactId.
+ This simulates the Apache Hop scenario (GH-13004) where the root POM uses
+ OS-activated profiles to select platform-specific dependencies. -->
+ <profiles>
+ <profile>
+ <id>platform-unix</id>
+ <activation>
+ <os>
+ <family>unix</family>
+ </os>
+ </activation>
+ <properties>
+ <platform.artifactId>lib</platform.artifactId>
+ </properties>
+ <!-- Dependency management inside the profile, like Apache Hop's SWT setup -->
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.its.gh13004</groupId>
+ <artifactId>${platform.artifactId}</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ </profile>
+ <profile>
+ <id>platform-windows</id>
+ <activation>
+ <os>
+ <family>windows</family>
+ </os>
+ </activation>
+ <properties>
+ <platform.artifactId>lib</platform.artifactId>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.its.gh13004</groupId>
+ <artifactId>${platform.artifactId}</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ </profile>
+ </profiles>
+</project>