Maven build with two GitHub packages repositories fails

Hi all,

TL;DR : Trying to use artifacts from GitHub packages on multiple accounts does not work with Maven. The easiest solution would be to give each account their own subdomain on maven.pkg.github.com.

I’ve got two GitHub repositories, let’s call them foo and bar, on two different GitHub accounts, let’s call them A and B. Both are Maven projects built with GitHub actions that deploy their JAR artifacts to GitHub Packages.

On B I’ve got a third repository, let’s call it baz, that also contains a Maven project; this one depends on both the foo and bar JAR files produced from the other two projects. To that end, it has two <repository> sections in its POM file, one for foo and one for bar. In order to not have to add the credentials for these repositories to an external settings.xml, they are encoded into the URL, e.g.:

<repositories>
		<repository>
			<id>github-foo</id>
			<name>GitHub Packages - foo</name>
			<url>https://user:PAT_A@maven.pkg.github.com/A/foo</url>
		</repository>
		<repository>
			<id>github-bar</id>
			<name>GitHub Packages - bar</name>
			<url>https://user:PAT_B@maven.pkg.github.com/B/bar</url>
		</repository>
	</repositories>

This build will fail with an error:

Error: Failed to execute goal on project baz: Could not resolve dependencies for project baz:baz:jar:0.0.1-SNAPSHOT: Could not transfer artifact foo:foo:jar:1.0 from/to github-bar (***maven.pkg.github.com/B/bar): Authentication failed for https://maven.pkg.github.com/B/bar/foo/foo/1.0/foo-1.0.jar 401 Unauthorized -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal on project baz: Could not resolve dependencies for project baz:baz:jar:0.0.1-SNAPSHOT: Could not transfer artifact foo:foo:jar:1.0 from/to github-bar (***maven.pkg.github.com/B/bar): Authentication failed for https://maven.pkg.github.com/B/bar/foo/foo/1.0/foo-1.0.jar 401 Unauthorized

I think the error message is a bit confusing because Maven will try fetching all dependencies from all repositories until it gets a hit. So the fact that I have two <repository>s in my POM means that all dependencies will be tried from up to three repos (the two in my POM plus Maven central). So the error message is from an attempt to fetch foo from the bar repository. But I’ve tried it locally, and that just returns a 404 which should signal to Maven to try a different repository.

The problem is that Maven’s HTTP Wagon provider, which handles the communication between Maven and GitHub packages (or any http-based Maven repository, for that matter) keeps a cache of credentials and this cache is basically keyed by host name and authentication realm. These are identical for both of my repositories, because they’re both hosted in GitHub Packages and GitHub packages makes no distinction in the host name based on the account the package is coming from.

So whichever of the two repositories is used first, that’s the credentials that will be cached and used for the other repository as well (and this will then fail).

I’m not sure if the expectation of Maven’s HTTP wagon that credentials are the same across all paths on a particular host is reasonable. But it obviously doesn’t hold for GitHub packages.
Short of solving this on the Maven side, GitHub Packages could introduce a subdomain for each GitHub account (provided the account names are DNS-valid) and that should work around this issue.

I’m going to look if it’s possible to disable the Maven HTTP Wagon’s credentials caching. But otherwise I hope the GitHub team can consider the subdomain suggestion (don’t know if they follow this community?)

Cheers,
Frans

@fransflippo,

You can try to set the authentication like as below in the settings.xml, just use only one token to authenticate.


<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">

  <activeProfiles>
    <activeProfile>github</activeProfile>
  </activeProfiles>

  <profiles>
    <profile>
      <id>github</id>
      <repositories>
        <repository>
          <id>github-foo</id>
          <name>GitHub Packages - foo</name>
          <url>https://maven.pkg.github.com/A/foo</url>
          <releases><enabled>true</enabled></releases>
          <snapshots><enabled>true</enabled></snapshots>
        </repository>
        <repository>
          <id>github-bar</id>
          <name>GitHub Packages - bar</name>
          <url>https://maven.pkg.github.com/B/bar</url>
        </repository>
      </repositories>
    </profile>
  </profiles>

  <servers>
    <server>
      <id>github</id>
      <username>USERNAME</username>
      <password>TOKEN</password>
    </server>
  </servers>
</settings>

To view more details, you can see “Configuring Apache Maven for use with GitHub Packages”.

Hi @fransflippo,

https://user:PAT_A@maven.pkg.github.com/A/foo

I’ve been able to make this work when publishing packages:

But not when restoring them, see:

What you can do is create a separate settings.xml file and implicitly include it using a .mvn/maven.config. See the example repository here for more details:

Note, if your repository is private, your read:packages PAT doesn’t need to be XML encoded (like I’m doing in the example).

I hope that helps!

This won’t work because the <id> of the <repository> doesn’t match the <id> of the <server> (and you can’t have two <repository>s with the same <id>.

Hmm, I really thought PAT in the URL was working. But maybe I had the dependency in my local repo already and Maven didn’t need to download it?

OK, let me strip my project down to the bare minimum and see what happens. I want to get to the bottom of this!

OK so I created a small-ish project with the same two dependencies and completely wiped my local Maven repository. Then I ran mvn clean package and it failed with the “Unauthorized” error.

Then I removed one of the dependencies, wiped my local Maven repository, ran it again, “Unauthorized”.

Then I ran the build again and now it was fine. I removed the dependency I was having issues with before from my local Maven repository and ran the build again, and still fine. At this point I can confirm that putting the PAT in the URL works… sometimes.

But there’s clearly some weirdness going on here. To be continued…

This has broken my brain in the past. I thought it was working and then I convinced myself I was imagining it!

I’ve just looked up an old workflow and sure enough, it looks like it can be made to work!

See the example here:

At this point I can confirm that putting the PAT in the URL works… sometimes.

If you figure out when this works, that would be great! I wonder if it might depend on the version of Java or Maven used?