[2.x] fix: Write maven-metadata-local.xml during publishM2 for SNAPSHOTs (#8996)

publishM2 never wrote maven-metadata-local.xml, which Maven uses to
distinguish local installs from remote artifacts. Without it, Maven
re-downloads remote SNAPSHOTs even when a local copy exists, making
publishM2 effectively broken for SNAPSHOT workflows.

Fixes #2053

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
BrianHotopp 2026-03-31 01:58:57 -04:00 committed by GitHub
parent 5697f074c1
commit 4f06b90534
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 52 additions and 0 deletions

View File

@ -872,6 +872,35 @@ private[sbt] object LibraryManagement {
writeChecksumsForFile(targetFile, checksumAlgorithms, log)
else log.warn(s"$targetFile already exists, skipping (overwrite=$overwrite)")
if version.endsWith("-SNAPSHOT") then
writeMavenMetadataLocal(versionDir, groupId, artifactId, version, log)
private def writeMavenMetadataLocal(
versionDir: File,
groupId: String,
artifactId: String,
version: String,
log: Logger
): Unit =
val timestamp = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date())
val metadata =
s"""|<?xml version="1.0" encoding="UTF-8"?>
|<metadata modelVersion="1.1.0">
| <groupId>$groupId</groupId>
| <artifactId>$artifactId</artifactId>
| <version>$version</version>
| <versioning>
| <snapshot>
| <localCopy>true</localCopy>
| </snapshot>
| <lastUpdated>$timestamp</lastUpdated>
| </versioning>
|</metadata>
|""".stripMargin
val metadataFile = new File(versionDir, "maven-metadata-local.xml")
IO.write(metadataFile, metadata)
log.info(s"Published $metadataFile")
/**
* Publishes artifacts to a remote Maven repo (HTTP) without using Apache Ivy.
* Same layout as ivylessPublishMavenToFile; uses HTTP PUT with optional Basic auth.

View File

@ -0,0 +1,21 @@
@transient
lazy val checkMetadata = taskKey[Unit]("check maven-metadata-local.xml is written for SNAPSHOT")
lazy val root = (project in file("."))
.settings(
scalaVersion := "2.13.16",
organization := "com.example.test.scripted",
version := "0.1.0-SNAPSHOT",
name := "publishm2-metadata-test",
checkMetadata := {
val m2Dir = new File(
System.getProperty("user.home"),
".m2/repository/com/example/test/scripted/publishm2-metadata-test_2.13/0.1.0-SNAPSHOT"
)
val metadataFile = new File(m2Dir, "maven-metadata-local.xml")
assert(metadataFile.exists, s"maven-metadata-local.xml not found at $metadataFile")
val content = IO.read(metadataFile)
assert(content.contains("<localCopy>true</localCopy>"), s"Missing localCopy element in:\n$content")
assert(content.contains("<groupId>com.example.test.scripted</groupId>"), s"Wrong groupId in:\n$content")
},
)

View File

@ -0,0 +1,2 @@
> publishM2
> checkMetadata