Using the GitHub Package Registry
This repo exists in order to test out various things with the GitHub Package Registry. Play around to your heart's content!
Learnings about the processes
Here are some things I've learned while experimenting. I've tried to keep this specific to Planning Center's workflow as much as possible.
Setting up a package project to use GPR
Here are some simple steps to take to publish the package to GPR.
Configure the package to use GPR
Add a publishConfig
key to the package.json
file. The namespace
should be the same namespace that the package will be published under
(e.g. @planningcenter
or @ministrycentered
).
"publishConfig": {
"@ministrycentered:registry": "https://npm.pkg.github.com"
}
Publish a new release when a GitHub release is drafted
Add a GitHub workflow to publish the package when a release is cut within GitHub. Note that this action will fail if a version with the same number is already in the registry. So...
Make sure to bump the version number before cutting a release.
Put the following (or something like it) in
.github/workflows/release-package.yml
. The current version in this
repo may have more features or implement things learned after writing
this introductory README. You can check it out
here.
name: Release package
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 12
- run: npm ci
- run: npm test
publish-gpr:
# Make sure the package builds and tests pass before cutting the release
needs: build
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 12
registry-url: https://npm.pkg.github.com/
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Publishing prereleases
There are going to be times in which we need to test a package within our apps and therefore cut a release without actually wanting to release something. I've played around a bit with how best to do this and haven't found an answer yet that is satisfying to me.
But here's what I've got for now.
Tagging the prerelease
In npm-land, the tag latest
has special meaning. Anyone not
specifying a hyper-specific version in their package.json
file will
get the package release tagged as latest
. Furthermore, unless a
specific tag is used when publishing the package, npm will tag it as
latest
automatically. We therefore don't want to tag a prerelease as
latest
and force it to have a tag of our choosing. So what should we
tag it?
I've been toying with the idea of tagging the prereleases with the
branch name involved. For example, a prerelease based off of version
1.2.3 whose work is being done in a branch named gl/fix-bugs
would
be released and tagged as something like v1.2.4-gl--fix-bugs.0
(tags
can't have slashes so I've converted the slash to a double dash). A
subsequent prerelease would be v1.2.4-gl--fix-bugs.1
. These names
are valid according to the semver
spec (which I really want to
adhere to).
This tagging is a manual process at the moment, so in the package's directory, you would run this code:
npm version prerelease --preid=gl--fix-bugs
This will bump the version numbers where required in the package and
create a git commit with the changes along with a git tag with the
version name. If you'd like to skip the git commit and tagging (like
if you want to group the version bump with other changes), pass the
--git-tag-version=false
flag to the command above. Push up that
commit (or commits) in your branch. The actual release is done via
GitHub's UI.
Configuring our workflow to package the prerelease
In the workflow definition, break up the release packaging to two
separate steps guarded by if statements: one for the prerelease and
one for the release. Since we don't specify a tag for a full release,
it defaults to latest
. If it is a prerelease, it'll use the branch
name the release targets with slashes replaced by double dashes1
(e.g. gl--fix-bugs
for branch gl/fix-bugs
) (see the next section).
# other required stuff in the workflow definition
steps:
# other required steps
- name: Publish prerelease
if: ${{ github.event.release.prerelease }}
run: npm publish --tag=${TAG_NAME}
env:
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
TAG_NAME: ${{ github.event.release.target_commitish }}
- name: Publish release
if: ${{ github.event.ref_name == github.event.repository.default_branch }}
run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
Releasing via GitHub's UI
Now that we have the package versioned with a prerelease version name
(e.g. v1.2.4-gl--fix-bugs.1
) and the release workflow configured to
handle releases and prereleases separately, it's time to cut a
prerelease on GitHub.
-
Head to the "Releases" page in the GitHub repo.
-
Hit the "Draft a new release" button.
-
Create a new tag for your release (it would be
v0.0.2-gl--branch-tags.5
in the screenshot below). Be sure to target your branch. Name the release the same as your tag. -
Be sure to hit the "This is a prerelease" checkbox!
-
Publish the release!
-
After the action/workflow creates the package, check to see that it is in the Packages section.
-
Make sure that the "Latest version" tag is not on your prerelease.
-
You can verify it was tagged correctly by checking the dist-tags on the command line. Note that I have to specify the GitHub registry on this command (it doesn't seem to honor our
publishConfig
setting inpackage.json
).npm dist-tag --registry=https://npm.pkg.github.com @ministrycentered/packages-test
-
Use the prerelease in an app. You can do this either by specifying the release version or the release tag. The difference is a tag can point to various versions throughout its life while a version can never be changed.
yarn add @ministrycentered/packages-test@0.0.2-gl--branch-tags.4
or for the most recently tagged version of the
gl--branch-tags
tag:yarn add @ministrycentered/packages-test@gl--branch-tags
Using a published package in an app
We need to give the yarn
and/or npm
commands on your machine
access to our private packages on GitHub in order to install them in
apps or update them in any way. To do that, first generate a Personal
Access Token in GitHub at . The
permissions need to at least be
repo
write:packages
delete:packages
Name it something memorable, give it a reasonable expiration, and create it.
Copy the token it shows you—we'll be using it in the next step.
Your configuration for packages is in the file ~/.npmrc. Add the following line that that file.
//npm.pkg.github.com/:_authToken=THE_TOKEN_THAT_YOU_COPIED_FROM_THE_PREVIOUS_STEP
This will allow yarn
and npm
to have access to the packages hosted
in GPR.
Since using GitHub's Package Repository is not the default for package
management, we need to configure our app to look for packages there
instead of npmjs.org. To do so, we must specify that for a certain
scope of package name, look in GPR instead of npmjs. I'm still not
sure what happens during the transitional period where we have
packages scoped as @planningcenter
in both npmjs and GPR. Thus, I've
scoped my test packages to @ministrycentered
.
Regardless of scope, configure your app by adding a .npmrc file in
the app repo's root directory. It needs to have the following line
added for each scope name. For example, this file scopes all
@ministrycentered
package names to look in GPR instead of the
default of npmjs.
@ministrycentered:registry=https://npm.pkg.github.com
Now that all that is configured correctly, you can finally install your package as required. For example, in ~/Code/people:
yarn add @ministrycentered/packages-test@gl--branch-tags
Some good resources
-
While it seems possible to tag a package with text containing a slash, trying to install that tag fails with the tool trying to use the tag name as a repo on GitHub. For example, running
yarn add @ministrycentered/packages-test@gl/branch-tags
will fail because it tries to load the package from github.com/gl/branch-tags.↩