跳到主要内容

GitHub Packages

GitHub Packages 是 GitHub 提供的包托管服务,支持 npm、Docker、Maven、Gradle、NuGet、RubyGems 等多种包格式。

概述

GitHub Packages 的优势:

  • 统一管理:代码和包在同一个平台
  • 权限集成:使用 GitHub 权限系统
  • 免费额度:公开包免费,私有包有一定免费额度
  • Actions 集成:与 GitHub Actions 无缝集成

支持的包格式

格式用途注册表地址
npmJavaScript/TypeScriptnpm.pkg.github.com
Docker容器镜像ghcr.io
MavenJavamaven.pkg.github.com
GradleJavamaven.pkg.github.com
NuGet.NETnuget.pkg.github.com
RubyGemsRubyrubygems.pkg.github.com

npm 包发布

配置 package.json

{
"name": "@username/package-name",
"version": "1.0.0",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
},
"repository": {
"type": "git",
"url": "git+https://github.com/username/repo.git"
}
}

包名必须以 @用户名/ 开头,用户名必须小写。

本地认证

创建或编辑 ~/.npmrc 文件:

//npm.pkg.github.com/:_authToken=YOUR_TOKEN
@username:registry=https://npm.pkg.github.com

或使用 npm login 命令:

npm login --scope=@username --registry=https://npm.pkg.github.com

用户名使用 GitHub 用户名,密码使用 Personal Access Token(需要 read:packageswrite:packages 权限)。

发布包

npm publish

安装包

创建项目根目录的 .npmrc 文件:

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

然后安装:

npm install @username/package-name

使用 GitHub Actions 发布

name: Publish Package

on:
release:
types: [created]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://npm.pkg.github.com'
scope: '@username'

- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Docker 镜像

GitHub Container Registry

GitHub Container Registry(GHCR)是 GitHub 的容器镜像仓库,地址为 ghcr.io

本地登录

echo $TOKEN | docker login ghcr.io -u USERNAME --password-stdin

构建并推送镜像

docker build -t ghcr.io/username/image-name:tag .
docker push ghcr.io/username/image-name:tag

镜像可见性

默认情况下,推送的镜像是私有的。可以在 GitHub 网页上修改为公开:

  1. 进入仓库的 Packages 页面
  2. 点击包名称
  3. 点击 "Package settings"
  4. 修改可见性

使用 GitHub Actions

name: Docker Publish

on:
push:
branches: [main]
tags: ['v*']

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

Maven 包发布

配置 pom.xml

<project>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/username/repository</url>
</repository>
</distributionManagement>
</project>

配置 settings.xml

~/.m2/settings.xml 中添加:

<settings>
<servers>
<server>
<id>github</id>
<username>USERNAME</username>
<password>TOKEN</password>
</server>
</servers>
</settings>

发布

mvn deploy

使用 GitHub Actions

name: Publish Maven Package

on:
release:
types: [created]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

- run: mvn -B deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Gradle 包发布

配置 build.gradle

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/username/repository")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.token") ?: System.getenv("TOKEN")
}
}
}
}

发布

./gradlew publish

使用 GitHub Actions

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- uses: gradle/actions/setup-gradle@v3

- run: ./gradlew publish
env:
USERNAME: ${{ github.actor }}
TOKEN: ${{ secrets.GITHUB_TOKEN }}

NuGet 包发布

配置 nuget.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="github" value="https://nuget.pkg.github.com/username/index.json" />
</packageSources>
<packageSourceCredentials>
<github>
<add key="Username" value="USERNAME" />
<add key="ClearTextPassword" value="TOKEN" />
</github>
</packageSourceCredentials>
</configuration>

发布

dotnet nuget push --source "github" package.nupkg

使用 GitHub Actions

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'

- run: dotnet build --configuration Release
- run: dotnet pack --configuration Release

- run: dotnet nuget push **/*.nupkg --source "github"
env:
NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

包管理

查看包

在 GitHub 网页上:

  1. 进入仓库页面
  2. 点击右侧 "Packages" 部分
  3. 查看该仓库发布的所有包

包版本管理

可以在包页面:

  • 查看所有版本
  • 下载特定版本
  • 删除版本(需要权限)

包权限

包权限继承自仓库权限:

  • 仓库管理员可以管理包
  • 仓库写入者可以发布新版本
  • 仓库读取者可以下载包

也可以单独配置包权限。

最佳实践

版本管理

使用语义化版本:

MAJOR.MINOR.PATCH
  • MAJOR:不兼容的 API 变更
  • MINOR:向后兼容的功能新增
  • PATCH:向后兼容的问题修复

自动化发布

结合 GitHub Actions 实现自动化:

name: Publish

on:
release:
types: [published]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- name: 发布包
run: |
echo "发布版本 ${{ github.event.release.tag_name }}"

安全考虑

  1. 使用 GITHUB_TOKEN 而非 Personal Access Token
  2. 配置最小权限
  3. 不要在日志中暴露敏感信息
  4. 定期检查和清理旧版本

参考资源