How to publish Maven packages to a single GitHub repository
Tags: maven, github, githubactions, java
Published: 2021-02-08 14:50:06

![image](https://dev-to-uploads.s3.amazonaws.com/i/k0rbvc42u8lghhpdmyny.png)

A working example of this setup can be found in vlingo XOOM repositories: https://github.com/vlingo/xoom-platform/packages 

# Publishing to the current repository

Before we look at publishing to an external repository, let's review how straight forward it is to publish to the current one:

```yaml
name: Build

on:
  release:
    types: [created]

jobs:
  publish:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Deploy to GitHub
        run: mvn --batch-mode -DuseGitHubPackages=true deploy
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

GitHub packages repository will be automatically configured for us in Maven by the `actions/setup-java` action. All's left to do is to pass the `GITHUB_TOKEN` secret as an environment variable to the `mvn deploy` command.

**Note**: `GITHUB_TOKEN` secret is available on all GitHub action builds out of the box. The token's scope is limited to the current repository.

In the above example we also enabled the `useGitHubPackages` flag in order to load the Maven profile that configures distribution mangement:

```xml
<!-- pom.xml -->
<project ...>
  <!-- ... -->

  <profiles>
    <profile>
      <id>github</id>
      <activation>
        <property>
          <name>useGitHubPackages</name>
          <value>true</value>
        </property>
      </activation>
      <distributionManagement>
        <repository>
          <id>github</id>
          <name>GitHub Packages</name>
          <url>https://maven.pkg.github.com/vlingo/xoom-common</url>
        </repository>
      </distributionManagement>
    </profile>
  </profiles>
</project>
```

The above example works for publishing `vlingo/xoom-common` from within the same repository.

# Publishing to a shared repository

The setup from previous section works great if we only have a single repository to publish from. Once we start publishing from multiple GitHub repositories, we'll end up with one Maven repository per GitHub repository. 

This is not always desired, especially if we develop a set of libraries that are usually installed together. In such a scenario, our clients would be forced to include in their `pom.xml` one Maven repository per library we provide.

The solution is to choose a dedicated repository for publishing our Maven packages and use it in distribution management for all the other repositories.

## Maven configuration

For example, having libraries like *xoom-common*, *xoom-actors*, *xoom-http*, we could choose to publish all of them to a single repository *xoom-platform*:

```xml
<!-- pom.xml -->
<project ...>
  <!-- ... -->

  <profiles>
    <profile>
      <id>github</id>
      <activation>
        <property>
          <name>useGitHubPackages</name>
          <value>true</value>
        </property>
      </activation>
      <distributionManagement>
        <repository>
          <id>github</id>
          <name>GitHub Packages</name>
          <url>https://maven.pkg.github.com/vlingo/xoom-platform</url>
        </repository>
      </distributionManagement>
    </profile>
  </profiles>
</project>
```

## GitHub action

The GitHub action will remain very similar to the one we looked at in the beggining with one notable difference - the `GITHUB_TOKEN`:


```yaml
name: Build

on:
  release:
    types: [created]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Deploy to GitHub
        run: mvn --batch-mode -DuseGitHubPackages=true deploy
        env:
          GITHUB_TOKEN: ${{ secrets.DEPLOY_GITHUB_TOKEN }}
```

We can no longer use the token provided by default as its scope is limited to the current repository. 

Instead, we'll need to create a Personal Access Token and pass it to the action as a secret (`DEPLOY_GITHUB_TOKEN` in the example above).

## Creating a GitHub Personal Access Token

To make it work across repositories we'll need to define a new Personal Access Token in:

* Settings > Developer Settings > [Personal Access Tokens](https://github.com/settings/tokens).

Select the `write:packages` scope and all the `repo` scopes should be automatically selected for us.

![image](https://dev-to-uploads.s3.amazonaws.com/i/4n9jnhfp207ug65dbja5.png)

## Defining a secret

Next, the token needs to be defined as a secret in our organisation or each of the repositories we need to publish packages from.

Give it a name (i.e. `DEPLOY_GITHUB_TOKEN`) and set its value to the Personal Access Token created in the previous step.

![image](https://dev-to-uploads.s3.amazonaws.com/i/h5c0a1tvdwrf6zkbdcah.png)

Repository secrets are defined in repository `Settings` > `Secrets`. There's a similar section for the organisation secrets.