适用范围

如果你跟我一样,公司/组织使用着github来管理代码,业务累加到一定程度,存在着许多相同或相似的逻辑代码,几个业务项目同时使用到。

出于解耦的理念,这些逻辑代码都应该被封装起来,但因为是公司的机密,并不能开源出去。

这时候packages或许会是一个不错的选择。

那为啥要扯上github action呢?自动化这么帅的事情,又有谁会拒绝呢?,8·〉

鉴于我是个jser,所以,以下用npm来举例说明。

packages

github packages与npmjs.org一样,都是用于node包的发布与获取的地方。

github action

github action是一个基于docker的自动化工作流程。如果你之前用过其他CI应该会不陌生。

发布代码到packages

为了更好的组织代码,我在给包起名的时候都会添加上 @org,已标示该包归属那个组织。

package.json

1
2
3
{
"name": "@org/pkg-name"
}

npm login

通过 npm login,我们登录到 npm.pkg.github.com,那么我们执行 npm publish时,默认就会将包推送 github packages 了。

但这样子并不灵活,后边我们会通过 github action 的任务来完成这个发布过程。

.npmrc

或者通过添加 .npmrc 文件规定 @org 的推送范围,我们需要在项目根目录下添加.npmrc文件,文件内容如下:

1
@org:registry=https://npm.pkg.github.com

但这样子添加会造成 @org 组织下的所有包都会从 npm.pkg.github.com 获取,这存在一些问题。因为如果项目中同时也依赖到该组织下的推送到 registry.npmjs.org 的包,则会安装失败。

当然,我们也可以将这些开源的包也统一同步发布到 npm.pkg.github.com,这样子就解决了问题。事实上,我懒于一个个指定包源,也是这么干的。

自动化

自动化可以帮助我们完成许多重复的,繁琐的事情。例如每次编写/更改完代码后的语法检查,单元测试,集成测试,以及以上的发布代码包,为啥我们不直接打个tag,发布个release,包就自动推送到对应的包管理器上呢?

首先,我们需要在项目下边添加 .github/workflows 文件夹,在里边添加一个 release.yml (文件名取决于你),这个文件会被github监测到,里边的内容会被读取,里边声明的事件,则会在其对应的行为里边被执行。

发布包

这里我们执行了两个任务,一个是发布包到 registry.npmjs.org,另一个是发布包到 npm.pkg.github.com

注意:如果该代码包为闭源的仓库,则下边的 npm-release 任务理应被删除。除非你用的是 registry.npmjs.org 的私有库功能,但本文并不打算涉及相关内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
name: Node.js Package

# 在release被创建时执行
on:
release:
types: [created]

jobs:
npm-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14.x'
registry-url: 'https://registry.npmjs.org'
- run: npm install
- run: npm run lint
- run: npm run build
- run: npm publish
# 公开的包,需要将上边修改为以下命令执行
# - run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}

pkg-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14.x'
registry-url: 'https://npm.pkg.github.com'
# 修改组织名
scope: '@org'
- run: npm install
- run: npm run lint
- run: npm run build
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.PKG_ACCESS_TOKEN }}

注:以下为作者于2021/11/28所标识生成方式,如系统更新,需按照新的方式操作。

推送包文件需要对应的token来验证权限,所以我们还需要到github对应的包仓库上边添加对应的 secret,找到仓库下 Settings/Secrets/New repository secret 添加对应的名为 NPM_ACCESS_TOKEN 以及 PKG_ACCESS_TOKEN

  • NPM_ACCESS_TOKEN 的获取就登录npmjs后,找到 Access Token 生成。

  • PKG_ACCESS_TOKEN 的获取则登录到github的个人账户下 Settings/Developer settings/Personal access tokens 生成即可。

存在了这个文件之后,我们在创建release的时候,github action就会执行上边两个任务 npm-releasepkg-releaseregistry.npmjs.org 以及 npm.pkg.github.com 推送代码包了。

安装包

安装包的方式跟安装普通的包几乎没有区别,都是通过 npm install 来完成,只不过特殊的在于私有包的安装,我们可以选择一个个的指定安装的包所对应的包源。

而作者避免繁琐,这里需要用到我们上边提到的 .npmrc 文件来指定该组织的包源。同时,因为是私有仓库的原因,我们还需要给添加上对应的token,即上边提到的 NPM_ACCESS_TOKEN(npmjs.org源) 以及 PKG_ACCESS_TOKEN(github packages源)。

1
2
3
4
# 我们可以通过环境变量会获取 NPM_AUTH_TOKEN 的值
@org:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${AUTH_TOKEN}
#always-auth=true

但一般我们都不推荐把 token 这么重要的东西直接放置于代码当中,这样子很不安全,同时利用到github action的自动化功能来完成一些重复性工作,于是编写一下流程文件,来完成release时的自动打包并推送到对应的仓库release文件列表下边。

这里我们拿一个常见的前端SPA项目的打包来举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
name: release

on:
# release被创建时执行
release:
types: [created]

jobs:
release:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [14.x]

steps:
- name: Use Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}

- name: Pull Repository
# 打包分支
uses: actions/checkout@master

- name: Build Repository
# dist为生成后的文件夹
run: |
npm install
npm run build
tar zcvf web.tar.gz dist
env:
NPM_AUTH_TOKEN: ${{ secrets.PKG_ACCESS_TOKEN }}
- name: Upload Asset
uses: PeerXu/upload-asset@v1
with:
file: web.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

同样的,我们在该仓库对应下边的 Settings/Secrets 添加 PKG_ACCESS_TOKEN 即可。

总结

能交给机器的就交给机器吧,人是要去做更有意义的事情的。