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.
Table of Contents:
Understanding GitHub Packages Integration
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
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.
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.
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
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>
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.
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.
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
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.
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.
#4) Build the Docker image from the Dockerfile
$ docker build -t hello_docker .
#5) Tag the image
$ docker tag 75610137a1c9 ghcr.io/package-org/docker-registry/hello-world:latest
#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.
#7) To view the docker image in the container registry, go to the GitHub ORG -> Repo and Packages section.
#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
Scroll down to the Danger Zone and Click on Change Visibility to Public.
Note: If the image is made public there is no way to make it Private again.
#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
Select the repository and click on 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.
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.
#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",
}
index.js file
var msg = require('./msg.js'); console.log(msg);
msg.js file
module.exports = 'Hello world from GitHub Packages';
#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.
Add a Build step -> Execute Windows batch command
Also added a Post-build Actions – Execute scripts. Call the run.sh script.
run.sh script
node index.js
Save the job. Click on Build now.
The package has now been published.
Package in the GitHub repository 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.