What are GitHub Packages: Code and Packages in One Place

By Sonal Rawalekar

By Sonal Rawalekar

Updated March 9, 2024

GitHub Packages are very effective in providing source code and packages in one place. Read through this detailed study to know what is GitHub packages with step-by-step pictorial representation:

Today, teams are trying to centralize software development in a single place where source code and packages are available. GitHub packages provide this feature along with integrated permissions and billing.

GitHub packages alongside your code can safely publish and consume packages. You can share GitHub packages privately with your team or make them public. They offer various package registries like Maven, Gradle, NPM, RubyGems, Docker, and NuGet.

Understanding GitHub Packages Integration

GitHub Packages

GitHub packages are published using native package formats. For example, with the Maven registry, you would use the pom.xml package format, with the Docker container registry you would use Dockerfile and for NPM it would be package.json. The client’s utility to use these package formats would be ‘mvn’, ‘docker’, ‘npm’.

In this article, we will look at how GitHub packages can be used with Maven, NPM, and Docker Container registry with Jenkins.

GitHub Package Billing

For every account on Github.com, there is a free storage limit and data transfer for private packages. Beyond the free storage limit, there is a cost associated with the feature.

Click here for more information on billing for storage and data transfers for free GitHub, Pro, GHEC, GHES, etc.

Create a Personal Access Token for GitHub Package Authentication

A Personal Access Token is needed to publish the packages. You will need to create a token with certain scopes as shown on the screen.

  • write:packages – To upload and publish packages
  • read:packages – To download packages
  • delete:packages – To delete packages
  • repo – To upload and delete packages
Edit access token

To generate a PAT, click on your Profile -> Settings -> Developer settings -> Personal access tokens -> Generate new token

Select the scope as shown above and save the token safely as it won’t be shown again.

Generate new token

Recommended Reading =>> What Is GitHub

Working With Maven Registry

To start working with the Maven registry, you will need to authenticate the GitHub Packages with Maven with the token generated into your ~/.m2/settings.xml file. If the file does not exist, you can create a settings.xml file.

Working With Maven Registry

Add the below content to the settings.xml file and replace the ones highlighted in BOLD.

<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>central</id>
          <url>https://repo1.maven.org/maven2</url>
        </repository>
        <repository>
          <id>github</id>
          <url>https://maven.pkg.github.com/OWNER/REPOSITORY</url>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </repository>
      </repositories>
    </profile>
  </profiles>

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

Example settings.xml file

Working With Maven Registry Code

Publishing the Package and Jenkins Job

To publish the package, you should include the URL of the repository in the <distributionManagement> element in your pom.xml file and replace the OWNER and REPOSITORY.

<distributionManagement>
   <repository>
     <id>github</id>
     <name>GitHub OWNER Apache Maven Packages</name>
     <url>https://maven.pkg.github.com/OWNER/REPOSITORY</url>
   </repository>
</distributionManagement>

Example pom.xml file used. Also artifactId should match the server id in the settings.xml file.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>HelloWorld-Maven</groupId>
  <artifactId>github</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>HelloWorld-Maven Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
<distributionManagement>
   <repository>
     <id>github</id>
     <name>GitHub OWNER Apache Maven Packages</name>
     <url>https://maven.pkg.github.com/Demo-Org-All/HW-Maven-Repo</url>
   </repository>
</distributionManagement>

  <build>
    <finalName>HelloWorld-Maven</finalName>
  </build>
</project>
artifactId should match server id

Jenkins freestyle job and deploy to Tomcat

Create a Jenkins freestyle job and add the Maven goals as shown. Slave Node is the current machine where my Jenkins is running.

create jenkins freestyle

I am using the Mask password plugin to create a Name/Password pair to store the PAT which will be used later as part of Post Build Actions.

Build Actions
build
Post Build Action

Add a Post Build Action -> Execute Windows batch command since I am using a Windows machine for maven build. The below script will download the WAR file generated and then copy the WAR file to the Tomcat webapps folder to deploy.

curl -O -L https://$PAT@maven.pkg.github.com/Demo-Org-All/HW-Maven-
Repo/HelloWorld-Maven/github/0.0.1-SNAPSHOT/HelloWorld-Maven.war
copy *.war E:\apache-tomcat-7.0.65\apache-tomcat-7.0.65\webapps

Also Read =>> Maven Tutorial for Beginners

Run the Build

Run Build

The artifact is published in GitHub packages, downloaded to the node machine, and also deployed to Tomcat. To view the artifact published to GitHub packages, go to the GitHub Org -> Repo -> Packages section.

Package Section

Working with Container Registry

GitHub packages use the container registry ghcr.io to store and manage Docker images. The Container Registry stores all images within the organization or your personal account and also associates the image with your repository. In this section, we will look at how to use GitHub Packages as Container Registry with a Docker Build and Push example.

The first step is to use the Personal Access Token (PAT) to authenticate to the Container Registry ghcr.io.

I am using a Linux VM running Ubuntu.

#1) Save PAT as an environment variable

$ export CR_PAT=ENTER_YOUR_TOKEN

#2) Login to the container registry using the command below:

echo $CR_PAT | docker login ghcr.io -u USERNAME –password-stdin

#3) Sample Dockerfile to create an image.

Sample Dockerfile

#4) Build the Docker image from the Dockerfile

$ docker build -t hello_docker .

Build the Docker image

#5) Tag the image

$ docker tag 75610137a1c9 ghcr.io/package-org/docker-registry/hello-world:latest

Tag the image - github packages

#6) Push the image to GitHub Packages Container Registry

$ docker push ghcr.io/package-org/docker-registry/hello-world:latest

Here package-org is the GitHub Organization and docker-registry is the repository.

Push the image

#7) To view the docker image in the container registry, go to the GitHub ORG -> Repo and Packages section.

Repo and Packages

#8) Make the image Public

By default, the image is Private and accessible to members of the repo. To make the image Public, and to have everyone access it, click on the Image -> Package settings

Package settings - github packages

Scroll down to the Danger Zone and Click on Change Visibility to Public.

Change Visibility

Note: If the image is made public there is no way to make it Private again.

Change Visibility - github packages

#9) Link this package to the repository.

By doing this you can add a README file to the repository and show all the contributors.

Click on the Image -> Connect Repository

Connect Repository

Select the repository and click on Connect Repository

Connect Repository
Connect Repository

Working with NPM Registry

We will look at how to configure npm and also publish the GitHub packages using Jenkins.

Must Read => Integration of Maven with Jenkins

Before we get started, here is my code which was initialized with npm (using npm init) and committed to the GitHub repo.

Github Packages NPM - github packages

The repo contains the package.json file which has references for all npm packages downloaded for the project.

#1) Authenticate using PAT

One can authenticate your GitHub Packages with npm by adding your PAT to the .npmrc file. Include the following line in the file:

//npm.pkg.github.com/:_authToken=TOKEN

Replace TOKEN with your personal access token.

Authenticate using PAT
Authenticate using PAT

#2) package.json setup

The npm packages are stored in your ORG or personal user account. You need to specify the GitHub repository in the name field of the package.json file.

For example, in my setup, the package will be published in the vniranjan1972/npm-repo repository. This defines the scope of the package.

Next, you can use the publishConfig element in the package.json file to specify which registry you want the package published.

In the package.json file for your package, include the publishConfig entry below:

“publishConfig”: {

“registry”:”https://npm.pkg.github.com”

},

The repository field in the package.json file must match the URL of your GitHub repository.

In this example, the value for this field would be https://github.com/vniranjan1972/npm-repo.git

Completed package.json file will be as follows:

{
  "name": "@vniranjan1972/npm-repo",
  "version": "12.0.0",
  "description": "NPM Example",
  "main": "index.js",
  "publishConfig": {
  "registry":"https://npm.pkg.github.com"
   },
  "repository": "https://github.com/vniranjan1972/npm-repo.git",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
}
package.json file

index.js file

var msg = require('./msg.js');
console.log(msg);

msg.js file

module.exports = 'Hello world from GitHub Packages';
Authenticate using PAT

#3) Jenkins job

Create a freestyle job as shown. Add the GitHub repository URL authenticated with a personal access token in the Source Code Management step of the job.

Jenkinsjob

Add a Build step -> Execute Windows batch command

Execute Windows batch command - github packages

Also added a Post-build Actions – Execute scripts. Call the run.sh script.

run.sh script

node index.js

Post-build-Actions

Save the job. Click on Build now.

The package has now been published.

package

Package in the GitHub repository post the publish.

post-the-publish

Conclusion

In this article, we have seen how GitHub Packages can be used as an integrated solution with your source code. We also saw examples of using GitHub Packages such as Maven registry, npm registry, and Container registry using Java Maven, Docker, node.js example.

We have also used JFrog Artifactory as a Binary Repository Manager for similar purposes and do not consider GitHub Packages to be a competitor.

JFrog Artifactory is definitely more robust in terms of additional features such as Advanced Query Language to search for artifacts using different search criteria, Proxy repository caching to cache open-source packages and store them locally as part of remote repositories, support for more package types (25+) as compared to GitHub packages (5).

Further Reading =>> Top GitHub Alternatives with Features

We hope that for teams using GitHub and the various registries currently offered as part of GitHub Packages, this feature can be used for end-to-end delivery as a single integrated solution.

Was this helpful?

Thanks for your feedback!

Leave a Comment