loading...
Cover image for Create Your First Github Package

Create Your First Github Package

dalenguyen profile image Dale Nguyen Originally published at dalenguyen.me Updated on ・3 min read

Github introduced their Github Package Registry since May 2019 - a package management service, just like NPM packages. That means you can manage private or public packages next to your source code.

At the moment when I write this article, you still have to Sign up for the beta in order to try this new service.

Here are the steps that you can follow to create your first Github Package.

Step 1: create a Personal Access Tokens

Login to your Github account > Settings > Developer settings

Alt Text

Step 2: log in to npm.pkg.github.com

dnguyen:~ dalenguyen$ npm login --registry=https://npm.pkg.github.com
Username: GitHub-username
Password: your-personal-access-token
Email: (this IS public) your-email@example.com
Logged in as dalenguyen on https://npm.pkg.github.com/.

Step 3: prepare your source code

I already created a TypeScript Package Starter. You can clone it from Github.

git clone https://github.com/dalenguyen/typescript-package-starter.git

Here is the project structure:

dist 
--index.js
src
--index.ts
test
--index.spec.ts

This package has only one simple function: helloWorld

export const helloWorld = () => 'Howdy!'

In order to publish your package to Github Package Registery, you need to add publishConfig. Otherwise, it will publish the package to the NPM Package Registry.

{
  "name": "typescript-package-starter",
  "version": "1.0.0",
  "description": "TypeScript boilerplate for NPM or Github Packages",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "test": "mocha --timeout 60000 --exit -r ts-node/register test/**/*.spec.ts",
    "build": "tsc",
    "deploy": "npm publish"
  },
  "author": "Dale Nguyen",
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/dalenguyen/typescript-package-starter.git"
  },
  .........................
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/@dalenguyen"
  }
}

This will end up creating a package name: @dalenguyen /typescript-package-starter. You need to replace the username in the package.json when you work with your own package.

And thanks to Alex — my coworker — by adding the repository, you have the ability to publish multiple packages to the same GitHub repository.

Step 4: push your project to Github repo

After you have your code ready. Push it to your github repo. You have to create your repo from Github.com.

git init
git add .
git commit -m "Create first github package"
git push origin master

Step 6: publish your first Github package

Run the test, make sure that everything works

npm test

Deploy your first Github package

npm run build && npm deploy

and Voilà

Alt Text

Step 7: Try to install your first Github package

Before that, you need to create a .npmrc file

// .npmrc
@your-username:registry=https://npm.pkg.github.com

Then install your package:

dalenguyen$ npm i @dalenguyen/typescript-package-starter

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN github-packages@1.0.0 No repository field.
+ typescript-package-starter@1.0.0 (as @dalenguyen/typescript-package-starter)
added 1 package from 1 contributor and removed 6 packages in 2.375s

Step 8: Test your new created package

// index.js
const starter = require('@dalenguyen/typescript-package-starter')
console.log(starter.helloWorld())

Run the index.js file

dalenguyen$ node index.js
Howdy!

Now you know how to create and publish your first Github package. In the next post, I will try to add CI/CD in order to publish the package automatically with Github Actions.

Discussion

pic
Editor guide
Collapse
demonkart profile image
Alan P. C. Silva

Hi! Great article :)

I am facing some issues when trying to fetch a specific version of my published package using Yarn.
I have created a repo based on your template: and I am adding this project as a dependency on another.
It works just fine after configuring the registry on .npmrc file. However, when I publish a new version of the package, it does not get updated when I run yarn on their dependent projects.

So, I tried to update the version manually in the package.json file with
"@demonkart/shared-deps-poc": "1.0.1", even though my package is at v1.0.2 right now.

If I run npm install then it works. If I run yarn it fails with the following error:

An unexpected error occurred: "https://npm.pkg.github.com/download/@demonkart/shared-deps-poc/1.0.1/3e9396a9012235c5bced735c282dc2ffcd11c9e7ce1889ace5b8703bb1c9ae48: Request failed \"401 Unauthorized\""

I have logged into github npm registry and this project is public... Any idea of what might be happening? 'x)

Thanks

Collapse
dalenguyen profile image
Dale Nguyen Author

Can you try 'yarn cache clean' and update it again?

Collapse
demonkart profile image
Alan P. C. Silva

Hi there. I tried it and still not working with yarn

Thread Thread
dalenguyen profile image
Dale Nguyen Author

I don't know what happens yet. You can use npm for now. Or create a public repo so people can help to debug it.

Thread Thread
demonkart profile image
Alan P. C. Silva

Hi there. I found a way searching through github yarn repo issues. It is not well documented yet and seems a little hacky, but it works.

I have added a section in the repo mentioned on how to make it work with yarn

github.com/DemonKart/shared-deps-p...

I hope it helps others like you helped me :)

Collapse
davestewart profile image
Dave Stewart

Hey Dale,

Thanks so much for this tutorial! It's certainly got me the closest to publishing and installing a private package.

However, when I try this, my package – and your package – is installed unscoped.

It installs under node_modules/typescript-package-starter not node_modules/@dalenguyen/typescript-package-starter and you need to descope the require as well:

const starter = require('typescript-package-starter')
console.log(starter.helloWorld())

This is the same experience I have had with my own package.

When add the @org-name/ in the package.json name as per normal NPM packages...

{
  "name": "@dalenguyen/typescript-package-starter",
  ...
}

...the install command under GitHub packages ends up including the scope twice, so for your package would be:

npm install @dalenguyen/@dalenguyen/typescript-package-starter@1.0.0

I guess in theory the de-scoping I am experiencing should not be a problem – because the code works – but it's strange considering it could potentially clash with an unscoped package of the same name.

Any ideas?

P.S. You can color-code your codeblocks by appending the language name to codeblock backticks, i.e. '''js

Collapse
dalenguyen profile image
Dale Nguyen Author

Thank Dave for the question. I just tried my package. It installs under node_modules/@dalenguyen

Can you fork my project, modify and deploy to your Github package?

dev-to-uploads.s3.amazonaws.com/i/...

Collapse
davestewart profile image
Dave Stewart

Good plan. Let me try that

Thread Thread
dalenguyen profile image
Dale Nguyen Author

Let me know if it works. And can you help to remove the .npmrc file? The token is invalid, but it is better to remove it though. Thanks,

Collapse
omgdadps profile image
OMGdaDPS

Hey so I get to the point where I have to run the "git push origin master" command, but after entering my credentials and token, I get this:
remote: Permission to dalenguyen/typescript-package-starter.git denied to OMGdaDPS.
fatal: unable to access 'github.com/dalenguyen/typescript-p... The requested URL returned error: 403

Collapse
dalenguyen profile image
Dale Nguyen Author

Hi @omgdadps , you need to create your own git repo, and replace my username with yours. Otherwise, it will push to my repo which you don't have permission to.