Getting Started with GPR

(Github Package Registry)

GitHub Packages

What's the difference with npm?

A new ๐Ÿก home for your packages

with the same experience.

With a great difference:

But that makes them a little more difficult to work with...

Let's create one of our own!

Only stored in GPR (and private)

1. Creating the lib

export const getBlahMessage = () => ({ message: 'blah' })
// src/index.js

1. Creating the lib

Type definitions (TS/JSDocs) for EXTRA POINTS!

2. Installing tools

> npm init
> npm i -D rollup
> npm i -D @babel/core rollup-plugin-babel  
rollup-plugin-terser  rimraf 

3. Configuring Rollup

export default {
  input: 'src/index.js',
  output: {
    file: `dist/blah.mjs`,
    format: 'esm', 
    sourcemap: true,
  },
  plugins: [/*...*/]
}
// rollup.config.js

Outputs 1 file

3. Configuring Rollup

export default [
  {/* ... */},
  {/* ... */},
]
// rollup.config.js

Outputs 2 files

3. Configuring Rollup

import babel from 'rollup-plugin-babel'
import { terser } from 'rollup-plugin-terser'
import pkg from './package.json'

const terserOptions = {
  compress: true,
  mangle: true
}

const createConfig = ({ minify, format, ext = 'js' }) => ({
  input: 'src/index.js',
  output: {
    name: pkg.name,
    file: `dist/index${minify ? '.min' : ''}.${ext}`,
    format,
    sourcemap: true
  },
  plugins: [
    babel({ exclude: 'node_modules/**' }), ...(minify ? [terser(terserOptions)] : [])
  ]
})

export default [
  { minify: false, format: 'esm', ext: 'mjs' },
  { minify: true, format: 'esm', ext: 'mjs' },
  { minify: false, format: 'esm' },
  { minify: true, format: 'esm' }
].map(createConfig)

4. Let's create the bundle!

{
  ...
  "scripts": {
    ...
    "build": "rimraf dist && rollup -c"
  }
  ...
}
> npm run build
// pacakge.json

4. Let's create the bundle!

5. Configure package.json

{
  ...
  "files": [
    "dist"
  ],
    
  "main": "dist/index.js",
    
  "module": "dist/index.mjs"
  ...
}
// pacakge.json

Like .gitignore, but the opposite and for the "artifacts" exposed. If empty, the whole project (src, dist...) will be included (except node_modules)

๐Ÿ‘‰๐Ÿฝ

๐ŸŒŸ

Learn more at Node Resolution Algorithmย docs

or see the npm-pkg-testย (private repo) for guidance

The module one is the one that webpack will use, in case it's present.

6. Creating the repo

(A regular repository... As usual!)

> git init

6. Creating the repo

๐Ÿ˜Ž๐Ÿ‘‰๐Ÿฝ

6. Creating the repo

> git add .
> git commit -m "initial commit :rocket:"
> git branch -M main
> git remote add origin git@...
> git push -u origin main

7. Make it installable

 {
+  "name": "@lovetoknow/npm-pkg-test",
+  "repository": "git://github.com/lovetoknow/npm-pkg-test.git",
+  "publishConfig": {
+    "registry": "https://npm.pkg.github.com/"
+  },
-  "private": true
 }

ย Edit package.json

*

* Name of the organization in github (in lowecase!)

7. Make it installable

registry=https://npm.pkg.github.com/lovetoknow

ย Add a .npmrc file

๐Ÿ‘†๐Ÿฝ Oh, must be lowercase!

8. Publish it!

8. Publish it!

But first, authenticate!

8. Publish it!

You have 2 options:

  1. adding a PAT (Personal Access Token) to the .npmrc file. (Preferred version for CI)
    ย 
  2. logging in via npm CLI

8. Publish it!

Working exampleย (private link)

Option 1

...
      - run: >
      	printf "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > ~/.npmrc
...

This way, a PAT belonging to the CI will be appended to the file, no need to create a "personal" one!

8. Publish it!

> npm publish

Option 2

8. Publish it!

๐Ÿ† Tip! Pre-publish hook, if you publish from the CLI

"prepublish": "npm run build"

Now, let's install it!

9. Installing the lib

9. Installing the lib

> cd ..
> mkdir install-test
> npm init -y

(We set up a test project...)

9. Installing the lib

> npm install @lovetoknow/npm-pkg-test  

9. Installing the lib

Why?

We forgot to tell npm to look for in GPR!

registry=https://npm.pkg.github.com/lovetoknow
// .npmrc

9. Installing the lib

You need to be authenticated to install it!

You have 2 options:

  1. adding a PAT (Personal Access Token) to the .npmrc file.
    ย 
  2. logging in via npm CLI (Preferred option for humans)

๐Ÿ‘‰๐Ÿฝ

9. Installing the lib

PAT Permissions:

  • repo
  • write:packages
  • read:packages
  • delete:packages (optional)
  • read:repo_hook
  • delete_repo

9. Installing the lib

> npm install @lovetoknow/npm-pkg-test  

10. Installing the lib on a CI env

The "robot" ๐Ÿค– needs to be authenticated too. Depending on your needs:

- Via npm CLI

- Via .npmrc with a PAT

//npm.pkg.github.com/:_authToken=PERSONAL_ACCESS_TOKEN
// .npmrc

- Or...

10. Installing the lib on a CI env

Github actions!!

ย 

- GITHUB_TOKEN env var

- registry_url
...
      - uses: actions/setup-node@master
        with:
          registry-url: >
          	https://npm.pkg.github.com/
...
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: >
          	${{ secrets.GITHUB_TOKEN }}

Credit: Daniel Young

11. Updating our library

> git add .

> git commit -m 'change ...'

> git push

> npm version <major | minor | patch>

> npm publish

๐Ÿ‘†๐Ÿฝmanually?

๐Ÿ‘†๐Ÿฝmanually?

11. Updating our library

Alternative workflow:

  • You add as many pushes to master as you want.
  • Once you consider the library should get those changes, you create a git tag
  • npm version manually
  • npm publish automatically on a Github Action.
name: Publish package
on:
  push:
    tags:
      - v.*
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@master
        with:
          node-version: 12.x
          registry-url: >
          	https://npm.pkg.github.com/
      - run: npm install
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: >
          	${{ secrets.GITHUB_TOKEN }}

Credit: Daniel Young

๐Ÿ‘‰๐Ÿฝ

11. Updating our library

> npm version

- Updates package.json and package-lock.json

- Creates git tags

- And a commit

11. Updating our library

npm versioning should follow semver

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards compatible manner, and
  3. PATCH version when you make backwards compatible bug fixes.

12. npm audit

> npm audit

12. npm audit

> npm audit --registry https://registry.npmjs.org/

Credit: Carlo and Josh

13. Good practices

- Tests! (and using the dist files in your tests, not the src)

- npm hooks (pretest, prepublish/postversion)

- semver!

- Publishing a changelog file

Example

Resources

Thank you

Thanks for your help!

Joshua Coady

Carlo D'Ambrosio

Daniel Young
Lluis de Lasaosa

Rakhi Neigi

Credits

Get Started with GPR (Github Package Registry)

By Paul Melero

Get Started with GPR (Github Package Registry)

Short intro to GPR (Github Package Registry) for private npm modules.

  • 1,333