Skip to main content

使用 GitHub Actions 发布和安装包

您可以配置 GitHub Actions 中的工作流程以自动发布或安装 GitHub Packages 的包。

谁可以使用此功能?

GitHub Packages 适用于 GitHub Free、GitHub Pro、面向组织的 GitHub Free、GitHub Team、GitHub Enterprise Cloud、GitHub Enterprise Server 3.0 或更高版本。
GitHub Packages 不适用于使用旧版按仓库计划的帐户所拥有的私有仓库。 此外,使用旧版按存储库计划的帐户无法访问支持精细权限的注册表,因为这些帐户按存储库计费。 有关支持精细权限的注册表的列表,请参阅“关于 GitHub Packages 的权限”。 有关详细信息,请参阅“GitHub 的计划”。

关于 GitHub Packages 与 GitHub Actions

GitHub Actions 帮助您在您存储代码的同一位置自动执行软件开发工作流程,并协作处理拉取请求和议题。 您可以写入个别任务,称为操作,并结合它们创建一个自定义的工作流程。 通过 GitHub Actions 可直接在仓库中构建端到端持续集成 (CI) 和持续部署 (CD) 功能。 有关详细信息,请参阅“了解 GitHub Actions”。

您可以通过在工作流程中发布或安装包来扩展仓库的 CI 和 CD 功能。

使用精细权限对包注册表进行身份验证

某些 GitHub Packages 注册表支持精细权限。 这意味着你可以选择允许包的范围限定为用户或组织,或者链接到存储库。 有关支持精细权限的注册表的列表,请参阅“关于 GitHub Packages 的权限”。

对于支持精细权限的注册表,如果 GitHub Actions 工作流使用 personal access token 向注册表进行身份验证,则强烈建议更新工作流以使用 GITHUB_TOKEN。 有关如何更新通过 personal access token 向注册表进行身份验证的工作流的指南,请参阅“使用 GitHub Actions 发布和安装包”。

注意:GitHub Actions 工作流使用 REST API 删除和还原包的功能目前提供公共 beta 版本,可能会发生更改。

如果令牌具有对包的 admin 权限,你可以在 GitHub Actions 工作流中使用 GITHUB_TOKEN,通过 REST API 来删除或还原包。 使用工作流发布包的存储库,以及已经显式连接到包的存储库,会自动获得对存储库中包的 admin 权限。

有关 GITHUB_TOKEN 的详细信息,请参阅“自动令牌身份验证”。 有关在操作中使用注册表时的最佳做法的详细信息,请参阅“GitHub Actions 的安全强化”。

使用存储库范围的权限对包注册表进行身份验证

某些 GitHub Packages 注册表仅支持存储库范围的权限,不支持精细权限。 有关这些注册表的列表,请参阅“关于 GitHub Packages 的权限”。

如果要让工作流访问不支持精细权限的 GitHub Packages 注册表,则我们建议使用 GitHub 在你启用 GitHub Actions 时自动为注册表创建的 GITHUB_TOKEN。 应在工作流文件中设置此访问令牌的权限,以授予 contents 范围的读取访问权限,并授予 packages 范围的写入访问权限。 对于分支,向 GITHUB_TOKEN 授予了对父存储库的读取访问权限。 有关详细信息,请参阅“自动令牌身份验证”。

可使用 ${{ secrets.GITHUB_TOKEN }} 上下文在工作流文件中引用 GITHUB_TOKEN。 有关详细信息,请参阅“自动令牌身份验证”。

关于权限和包访问

范围限定为用户或组织的包

支持精细权限的注册表允许用户在组织级别将包作为独立资源来创建和管理。 包的范围可以限定为组织或个人帐户,你可以自定义与存储库权限分开的每个包访问权限。

访问支持精细权限的注册表的所有工作流都应使用 GITHUB_TOKEN 而不是 personal access token。 有关安全最佳做法的详细信息,请参阅“GitHub Actions 的安全强化”。

范围限定为存储库的包

启用 GitHub 操作后,GitHub 会在您的仓库中安装 GitHub 应用程序。 GITHUB_TOKEN 机密是 GitHub 应用安装访问令牌。 您可以使用安装访问令牌代表仓库中安装的 GitHub 应用程序进行身份验证。 令牌的权限仅限于包含您的工作流程的仓库。 有关详细信息,请参阅“自动令牌身份验证”。

使用 GitHub Packages 能通过可用于 GitHub Actions 工作流的 GITHUB_TOKEN 推送和拉取包。

通过工作流程修改的包的默认权限和访问设置

对于支持精细权限的注册表中的包,当你通过工作流程创建、安装、修改或删除包时,有一些默认权限和访问设置用于确保管理员能够访问工作流程。 您也可以调整这些访问设置。 有关支持精细权限的注册表的列表,请参阅“关于 GitHub Packages 的权限”。

例如,默认情况下,如果工作流使用 GITHUB_TOKEN 创建包,则:

  • 包继承运行工作流程的存储库的可见性和权限模型。
  • 在创建包后,工作流程运行的存储库管理员将成为包的管理员。

以下是管理包的工作流程的默认权限如何运作的更多示例。

GitHub Actions 工作流程任务默认权限和访问权限
下载现有项- 如果包是公开的,则任何存储库中运行的任何工作流程都可以下载包。
- 如果包是内部的,则在企业帐户拥有的任何存储库中运行的所有工作流都可以下载包。 对于企业拥有的组织,你可以读取企业中的任何存储库
- 如果包是专用的,则只有在存储库中运行且具有对该包的读取权限的工作流才可下载包。 如果授予公共存储库对专用包的访问权限,存储库的分支可能能够访问专用包。
上传新版本到现有包- 如果包是私有、内部或公共的,则只有在该包上获得写入权限的存储库中运行的工作流程才可将新版本上传到包中。
删除包或包的版本- 如果包是私有、内部或公共的,则只有在该容器上获得管理权限的存储库中运行的工作流才可删除包的现有版本。

还可以使用更精细的方式调整对包的访问,或调整一些默认权限行为。 有关详细信息,请参阅“配置包的访问控制和可见性”。

使用操作发布包

您可以使用 GitHub Actions 在持续集成 (CI) 流程中自动发布包。 如果代码符合您的质量标准,可使用这种持续部署 (CD) 方法自动创建新的包版本。 例如,您可以创建一个每当开发者向特定分支推送代码时运行 CI 测试的工作流程。 如果测试通过,则工作流程可以将新的包版本发布到 GitHub Packages。

配置步骤因包客户端而异。 有关为 GitHub Actions 配置工作流的一般信息,请参阅“使用工作流”。

下面的示例演示如何使用 GitHub Actions 构建应用程序,然后自动创建 Docker 映像并将其发布到 GitHub Packages: 代码中解释了相关设置。 有关工作流中每个元素的完整详细信息,请参阅“GitHub Actions 的工作流语法”。

在存储库中创建新的工作流文件(例如 .github/workflows/deploy-image.yml),并添加以下 YAML。

注意:****

  • 此工作流使用未通过 GitHub 认证的操作。 这些操作由第三方提供,并受单独的服务条款、隐私政策和支持文档的管辖。
  • GitHub 建议将操作固定到提交 SHA。 若要获取较新版本,需要更新 SHA。 还可以引用标记或分支,但该操作可能会更改而不发出警告。
YAML
name: Create and publish a Docker image
on:
  push:
    branches: ['release']

Configures this workflow to run every time a change is pushed to the branch called release.

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

Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.

jobs:
  build-and-push-image:
    runs-on: ubuntu-latest

There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.

    permissions:
      contents: read
      packages: write

Sets the permissions granted to the GITHUB_TOKEN for the actions in this job.

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

Uses the docker/login-action action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

This step uses docker/metadata-action to extract tags and labels that will be applied to the specified image. The id "meta" allows the output of this step to be referenced in a subsequent step. The images value provides the base name for the tags and labels.

      - name: Build and push Docker image
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

This step uses the docker/build-push-action action to build the image, based on your repository's Dockerfile. If the build succeeds, it pushes the image to GitHub Packages. It uses the context parameter to define the build's context as the set of files located in the specified path. For more information, see "Usage" in the README of the docker/build-push-action repository. It uses the tags and labels parameters to tag and label the image with the output from the "meta" step.

#
name: Create and publish a Docker image

# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
  push:
    branches: ['release']

# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
  build-and-push-image:
    runs-on: ubuntu-latest
    # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
    permissions:
      contents: read
      packages: write
      # 
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
      # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
      # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
      - name: Build and push Docker image
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

每次将更改推送到存储库中名为 release 的分支时,这个新工作流都会自动运行。 可在“操作”选项卡中查看进度。

工作流程完成几分钟后,新包将在您的存储库中可见。 若要查找可用的包,请参阅“查看包”。

使用操作安装包

您可以使用 GitHub Actions 将安装包作为 CI 流程的一部分。 例如,您可以配置一个工作流程:每当开发者向拉取请求推送代码时,该工作流程就会通过下载并安装 GitHub Packages 托管的包来解析依赖项。 然后,该工作流程就可以运行需要这些依赖项的 CI 测试。

使用 GITHUB_TOKEN 时,通过 GitHub Actions 安装 GitHub Packages 托管的包只需极少的配置或额外身份验证。使用操作安装包时,数据传输也是免费的。 有关详细信息,请参阅“关于 GitHub 包的计费”。

配置步骤因包客户端而异。 有关为 GitHub Actions 配置工作流的一般信息,请参阅“使用工作流”。

升级使用 personal access token 访问注册表的工作流

GitHub Packages 支持用 GITHUB_TOKEN 在你的工作流中进行简单和安全的身份验证。 如果使用的是支持精细权限的注册表,且工作流使用 personal access token 向注册表进行身份验证,则强烈建议更新工作流以使用 GITHUB_TOKEN

有关 GITHUB_TOKEN 的详细信息,请参阅“自动令牌身份验证”。

使用 GITHUB_TOKEN 而不是 personal access token (classic)(包括 repo 范围),可提高存储库的安全性,因为无需使用长期 personal access token,以免提供对运行工作流的存储库的不必要的访问权限。 有关安全最佳做法的详细信息,请参阅“GitHub Actions 的安全强化”。

  1. 导航到包登陆页面。

  2. 为了确保包能够访问你的工作流程,必须添加存储库,其中工作流程存储到包。 在“管理 Actions 访问权限”下,击“添加存储库”并搜索要添加的存储库。

    包设置页的“管理 Actions 访问权限”部分的屏幕截图。 “添加存储库”按钮以橙色边框突出显示。

注意:将存储库添加到包 :使用包的设置中“管理 Actions 访问”下的“添加存储库”**** 按钮 不同于将包连接到存储库。 有关详细信息,请参阅“配置包的访问控制和可见性”和“将仓库连接到包”。

1. (可选)使用 使用“角色”下拉菜单,选择你希望存储库访问你的包所拥有的默认访问级别。 1. 打开工作流程文件。 在登录注册表的行上,将 personal access token 替换为 `${{ secrets.GITHUB_TOKEN }}`。

例如,此工作流将一个 Docker 映像发布到 Container registry 并使用 ${{ secrets.GITHUB_TOKEN }} 进行身份验证。 有关详细信息,请参阅 Docker 文档中的“设置自动生成”。

YAML
name: Demo Push
on:
  push:
    branches:
      - main
      - seed
    tags:
      - v*
  pull_request:

This workflow runs when any of the following occur:

  • A push is made to a branch called main or seed
  • A tag starting with "v" is created
  • A pull request is created or updated
env:
  IMAGE_NAME: ghtoken_product_demo

This creates an environment variable called IMAGE_NAME with the value ghtoken_product_demo.

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

This pushes the image to GitHub Packages.

    steps:
      - uses: actions/checkout@v4
      - name: Build image
        run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"
      - name: Log in to registry
        run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
      - name: Push image
        run: |
          IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

This changes all uppercase characters to lowercase.

          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

This strips the git ref prefix from the version.

          [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

This strips the "v" prefix from the tag name.

          [ "$VERSION" == "main" ] && VERSION=latest
          echo IMAGE_ID=$IMAGE_ID
          echo VERSION=$VERSION
          docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
          docker push $IMAGE_ID:$VERSION

This uses the Docker latest tag convention.

#
name: Demo Push

# This workflow runs when any of the following occur:
# - A push is made to a branch called `main` or `seed`
# - A tag starting with "v" is created
# - A pull request is created or updated
on:
  push:
    branches:
      - main
      - seed
    tags:
      - v*
  pull_request:
  # This creates an environment variable called `IMAGE_NAME ` with the value `ghtoken_product_demo`.
env:
  IMAGE_NAME: ghtoken_product_demo
#
jobs:
  # This pushes the image to GitHub Packages.
  push:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
      #
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"

      - name: Log in to registry
        run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
        #
      - name: Push image
        run: |
          IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME

          # This changes all uppercase characters to lowercase.
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
          # This strips the git ref prefix from the version.
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
          # This strips the "v" prefix from the tag name.
          [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
          # This uses the Docker `latest` tag convention.
          [ "$VERSION" == "main" ] && VERSION=latest
          echo IMAGE_ID=$IMAGE_ID
          echo VERSION=$VERSION
          docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
          docker push $IMAGE_ID:$VERSION