Skip to content

Commit df6ca1e

Browse files
committed
Support SNAPSHOT Maven artifact versions in integration tests installation logic
- Refactor artifact installation to detect and handle timestamped SNAPSHOT JARs and POMs from local Maven repositories - Improve logging to help diagnosing missing or mismatched artifacts in custom local repositories.
1 parent c2d0c87 commit df6ca1e

File tree

1 file changed

+66
-58
lines changed

1 file changed

+66
-58
lines changed

integration-tests/test_maven_plugin.py

Lines changed: 66 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import os
4141
import pathlib
4242
import re
43+
import glob
4344
import shutil
4445
import sys
4546
import textwrap
@@ -53,6 +54,62 @@
5354
VENV_UPTODATE = "Virtual environment is up to date with lock file, skipping install"
5455

5556
class MavenPluginTest(util.BuildToolTestBase):
57+
@classmethod
58+
def _install_artifact_from_local_repo(cls, base_path, custom_repo, artifact_id, log):
59+
jar_dir = os.path.join(
60+
base_path,
61+
cls.archetypeGroupId.replace(".", os.path.sep),
62+
artifact_id,
63+
util.graalvmVersion,
64+
)
65+
# For SNAPSHOT versions, search for timestamped jars using the base version (without '-SNAPSHOT')
66+
is_snapshot = util.graalvmVersion.endswith("-SNAPSHOT")
67+
base_version = util.graalvmVersion[:-9] if is_snapshot else util.graalvmVersion
68+
69+
if is_snapshot:
70+
# Only match timestamped SNAPSHOT artifacts without classifiers (e.g., exclude '-sources', '-javadoc', etc.)
71+
# Expected JAR basename: {artifactId}-{baseVersion}-{yyyyMMdd}.{HHmmss}-{buildNumber}.jar
72+
# Example: graalpy-archetype-polyglot-app-25.1.0-20251201.162741-1.jar
73+
jar_glob = os.path.join(jar_dir, f"{artifact_id}-{base_version}-*.jar")
74+
all_candidates = glob.glob(jar_glob)
75+
pattern = re.compile(rf"^{re.escape(artifact_id)}-{re.escape(base_version)}(?P<suffix>-\d{{8}}\.\d{{6}}-\d+)\.jar$")
76+
jar_candidates = [p for p in all_candidates if pattern.match(os.path.basename(p))]
77+
if not jar_candidates:
78+
log.append(f"'{custom_repo}': no timestamped SNAPSHOT jars matching pattern {pattern.pattern} in: {jar_glob}")
79+
return False
80+
jar = max(jar_candidates, key=os.path.getmtime)
81+
82+
jar_base = os.path.basename(jar)
83+
m = pattern.match(jar_base)
84+
suffix = m.group("suffix") if m else ""
85+
pom = os.path.join(jar_dir, f"{artifact_id}-{base_version}{suffix}.pom")
86+
else:
87+
jar = os.path.join(jar_dir, f"{artifact_id}-{util.graalvmVersion}.jar")
88+
if not os.path.exists(jar):
89+
log.append(f"'{custom_repo}': could not find: {jar}")
90+
return False
91+
pom = os.path.join(jar_dir, f"{artifact_id}-{util.graalvmVersion}.pom")
92+
jar_base = os.path.basename(jar)
93+
94+
if not os.path.exists(pom):
95+
log.append(f"'{custom_repo}': POM with matching suffix not found for jar {jar_base}")
96+
return False
97+
98+
cmd = [
99+
"mvn",
100+
"install:install-file",
101+
f"-Dfile={jar}",
102+
f"-DgroupId={cls.archetypeGroupId}",
103+
f"-DartifactId={artifact_id}",
104+
f"-Dversion={util.graalvmVersion}",
105+
"-Dpackaging=jar",
106+
f"-DpomFile={pom}",
107+
"-DcreateChecksum=true",
108+
]
109+
out, return_code = util.run_cmd(cmd, env=cls.env)
110+
assert return_code == 0, out
111+
return True
112+
56113
@classmethod
57114
def setUpClass(cls):
58115
super().setUpClass()
@@ -62,80 +119,31 @@ def setUpClass(cls):
62119
cls.extraRemoteRepo = None
63120

64121
found = False
122+
log = []
65123
for custom_repo in util.extra_maven_repos:
66124
url = urllib.parse.urlparse(custom_repo)
67125
if url.scheme != "file":
126+
log.append(f"'{custom_repo}' was identified as a remote repo and skipped")
68127
if not cls.extraRemoteRepo:
69128
cls.extraRemoteRepo = custom_repo
70129
continue
71130

72-
jar = os.path.join(
73-
urllib.parse.unquote(url.path),
74-
cls.archetypeGroupId.replace(".", os.path.sep),
75-
cls.archetypeArtifactId,
76-
util.graalvmVersion,
77-
f"{cls.archetypeArtifactId}-{util.graalvmVersion}.jar",
78-
)
79-
pom = os.path.join(
80-
urllib.parse.unquote(url.path),
81-
cls.archetypeGroupId.replace(".", os.path.sep),
82-
cls.archetypeArtifactId,
83-
util.graalvmVersion,
84-
f"{cls.archetypeArtifactId}-{util.graalvmVersion}.pom",
85-
)
86-
if not os.path.exists(pom):
131+
base_path = urllib.parse.unquote(url.path)
132+
133+
if not cls._install_artifact_from_local_repo(base_path, custom_repo, cls.archetypeArtifactId, log):
134+
continue
135+
if not cls._install_artifact_from_local_repo(base_path, custom_repo, cls.pluginArtifactId, log):
87136
continue
88-
cmd = [
89-
"mvn",
90-
"install:install-file",
91-
f"-Dfile={jar}",
92-
f"-DgroupId={cls.archetypeGroupId}",
93-
f"-DartifactId={cls.archetypeArtifactId}",
94-
f"-Dversion={util.graalvmVersion}",
95-
"-Dpackaging=jar",
96-
f"-DpomFile={pom}",
97-
"-DcreateChecksum=true",
98-
]
99-
out, return_code = util.run_cmd(cmd, env=cls.env)
100-
assert return_code == 0, out
101137

102-
jar = os.path.join(
103-
urllib.parse.unquote(url.path),
104-
cls.archetypeGroupId.replace(".", os.path.sep),
105-
cls.pluginArtifactId,
106-
util.graalvmVersion,
107-
f"{cls.pluginArtifactId}-{util.graalvmVersion}.jar",
108-
)
109-
110-
pom = os.path.join(
111-
urllib.parse.unquote(url.path),
112-
cls.archetypeGroupId.replace(".", os.path.sep),
113-
cls.pluginArtifactId,
114-
util.graalvmVersion,
115-
f"{cls.pluginArtifactId}-{util.graalvmVersion}.pom",
116-
)
117-
118-
cmd = [
119-
"mvn",
120-
"install:install-file",
121-
f"-Dfile={jar}",
122-
f"-DgroupId={cls.archetypeGroupId}",
123-
f"-DartifactId={cls.pluginArtifactId}",
124-
f"-Dversion={util.graalvmVersion}",
125-
"-Dpackaging=jar",
126-
f"-DpomFile={pom}",
127-
"-DcreateChecksum=true",
128-
]
129-
out, return_code = util.run_cmd(cmd, env=cls.env)
130-
assert return_code == 0, out
131138
found = True
132139
break
133140

134141
if util.extra_maven_repos and not found and not cls.extraRemoteRepo:
135142
print("WARNING: extra Maven repos passed, but could not find GraalPy Maven archetype "
136143
"in any of the local repos and there is no extra remote repo. This is OK only if "
137144
"GraalPy Maven archetype of the required version is available at Mavencentral, "
138-
"otherwise the tests will fail to generate the example application.")
145+
"otherwise the tests will fail to generate the example application. Searched these repositories: \n"
146+
'\n'.join([' ' + x for x in log]))
139147

140148
def generate_app(self, tmpdir, target_dir, target_name, pom_template=None, group_id="archetype.it", package="it.pkg", log=Logger()):
141149
extra_repo = []

0 commit comments

Comments
 (0)