关于 GitHub Actions 和 GitHub Packages
GitHub Actions 可帮助您在存储代码、协作处理拉取请求和问题的同时自动化软件开发工作流。您可以编写称为 action 的单个任务,并将它们组合起来创建自定义工作流。使用 GitHub Actions,您可以直接在仓库中构建端到端持续集成 (CI) 和持续交付 (CD) 功能。更多信息,请参阅“编写工作流”。
您可以通过在工作流中发布或安装软件包来扩展仓库的 CI 和 CD 功能。
使用细粒度权限对软件包注册表进行身份验证
一些 GitHub Packages 注册表支持细粒度权限。这意味着您可以选择允许软件包的范围限定为用户或组织,或链接到仓库。有关支持细粒度权限的注册表列表,请参阅“GitHub Packages 的权限”。
对于支持细粒度权限的注册表,如果您的 GitHub Actions 工作流正在使用个人访问令牌对注册表进行身份验证,我们强烈建议您更新工作流以使用GITHUB_TOKEN
。有关更新对使用个人访问令牌对注册表进行身份验证的工作流的指导,请参阅“使用 GitHub Actions 发布和安装软件包”。
注意
GitHub Actions 工作流使用 REST API 删除和恢复软件包的功能目前处于公开预览阶段,可能会发生更改。
如果令牌对软件包具有admin
权限,则可以在 GitHub Actions 工作流中使用GITHUB_TOKEN
来使用 REST API 删除或恢复软件包。使用工作流发布软件包的仓库以及您已明确连接到软件包的仓库会自动获得对仓库中软件包的admin
权限。
有关GITHUB_TOKEN
的更多信息,请参阅“自动令牌身份验证”。有关在 Actions 中使用注册表的最佳实践的更多信息,请参阅“GitHub Actions 的安全加固”。
使用仓库范围权限对软件包注册表进行身份验证
一些 GitHub Packages 注册表仅支持仓库范围权限,不支持细粒度权限。有关这些注册表的列表,请参阅“GitHub Packages 的权限”。
如果您希望您的工作流访问不支持细粒度权限的 GitHub Packages 注册表,那么我们建议使用 GitHub 在您启用 GitHub Actions 时自动为您的仓库创建的GITHUB_TOKEN
。您应该在工作流文件中设置此访问令牌的权限,以授予contents
范围的读取访问权限和packages
范围的写入访问权限。对于 fork,GITHUB_TOKEN
将被授予父仓库的读取访问权限。更多信息,请参阅“自动令牌身份验证”。
您可以使用${{ secrets.GITHUB_TOKEN }}
上下文在工作流文件中引用GITHUB_TOKEN
。更多信息,请参阅“自动令牌身份验证”。
关于权限和软件包访问
作用域限定为用户或组织的软件包
支持细粒度权限的注册表允许用户在组织级别创建和管理软件包作为独立资源。软件包的作用域可以限定为组织或个人帐户,您可以单独自定义对每个软件包的访问权限,而无需考虑仓库权限。
所有访问支持细粒度权限的注册表的工作流都应使用GITHUB_TOKEN
而不是个人访问令牌。有关安全最佳实践的更多信息,请参阅“GitHub Actions 的安全加固”。
作用域限定为仓库的软件包
启用 GitHub Actions 后,GitHub 会在您的仓库上安装一个 GitHub 应用。GITHUB_TOKEN
密钥是一个 GitHub 应用安装访问令牌。您可以使用安装访问令牌代表安装在您的仓库上的 GitHub 应用进行身份验证。令牌的权限仅限于包含您的工作流的仓库。更多信息,请参阅“自动令牌身份验证”。
GitHub Packages 允许您通过 GitHub Actions 工作流可用的GITHUB_TOKEN
推送和拉取软件包。
通过工作流修改的软件包的默认权限和访问设置
对于支持细粒度权限的注册表中的软件包,当您通过工作流创建、安装、修改或删除软件包时,会使用一些默认权限和访问设置来确保管理员可以访问工作流。您也可以调整这些访问设置。有关支持细粒度权限的注册表列表,请参阅“GitHub Packages 的权限”。
例如,如果工作流使用GITHUB_TOKEN
创建软件包,则默认情况下:
- 软件包将继承运行工作流的仓库的可见性和权限模型。
- 运行工作流的仓库管理员在软件包创建后将成为该软件包的管理员。
以下是一些有关管理软件包的工作流的默认权限如何工作的更多示例。
GitHub Actions 工作流任务 | 默认权限和访问 |
---|---|
下载现有软件包 | - 如果软件包是公共的,则任何仓库中运行的任何工作流都可以下载该软件包。 - 如果软件包是内部的,则企业帐户拥有的任何仓库中运行的所有工作流都可以下载该软件包。对于企业拥有的组织,您可以读取企业中的任何仓库。 - 如果软件包是私有的,则只有在已授予对该软件包的读取权限的仓库中运行的工作流才能下载该软件包。如果您授予公共仓库对私有软件包的访问权限,则该仓库的 fork 可能能够访问私有软件包。 |
上传新版本到现有软件包 | - 如果软件包是私有的、内部的或公开的,只有在拥有该软件包写入权限的代码库中运行的工作流程才能上传软件包的新版本。 |
删除软件包或软件包的版本 | - 如果软件包是私有的、内部的或公开的,只有在拥有该软件包管理员权限的代码库中运行的工作流程才能删除软件包的现有版本。 |
您还可以更精细地调整软件包的访问权限,或调整一些默认权限行为。更多信息,请参见“配置软件包的访问控制和可见性”。
使用操作发布软件包
您可以使用 GitHub Actions 将软件包作为持续集成 (CI) 流程的一部分自动发布。这种持续交付 (CD) 方法允许您自动化创建新软件包版本,前提是代码符合您的质量标准。例如,您可以创建一个工作流程,在开发人员每次将代码推送到特定分支时运行 CI 测试。如果测试通过,工作流程可以将新软件包版本发布到 GitHub Packages。
配置步骤因软件包客户端而异。有关配置 GitHub Actions 工作流程的一般信息,请参见“编写工作流程”。
以下示例演示如何使用 GitHub Actions 构建您的应用程序,然后自动创建一个 Docker 镜像并将其发布到 GitHub Packages。代码中解释了相关设置。有关工作流程中每个元素的完整详细信息,请参见“GitHub Actions 的工作流程语法”。
在您的代码库中创建一个新的工作流程文件(例如 .github/workflows/deploy-image.yml
),并添加以下 YAML。
注意
- 此工作流程使用未经 GitHub 认证的操作。它们由第三方提供,并受单独的服务条款、隐私政策和支持文档约束。
- GitHub 建议将操作固定到 commit SHA。要获取较新版本,您需要更新 SHA。您也可以引用标签或分支,但操作可能会在未经警告的情况下发生更改。
# 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 attestations: write id-token: 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 id: push uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)." - name: Generate artifact attestation uses: actions/attest-build-provenance@v1 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true
name: Create and publish a Docker image
on:
push:
branches: ['release']
配置此工作流程,以便在每次将更改推送到名为 release
的分支时运行。
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
定义工作流程的两个自定义环境变量。这些用于容器注册表域和此工作流程构建的 Docker 镜像的名称。
jobs:
build-and-push-image:
runs-on: ubuntu-latest
此工作流程中只有一个作业。它配置为在最新版本的 Ubuntu 上运行。
permissions:
contents: read
packages: write
attestations: write
id-token: write
设置授予此作业中操作的 GITHUB_TOKEN
的权限。
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 }}
使用 docker/login-action
操作使用将发布软件包的帐户和密码登录到容器注册表注册表。发布后,软件包的范围将限定在此处定义的帐户。
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
此步骤使用 docker/metadata-action 提取将应用于指定镜像的标签和标签。id
“meta” 允许在后续步骤中引用此步骤的输出。images
值为标签和标签提供基本名称。
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
此步骤使用 docker/build-push-action
操作根据您的代码库的 Dockerfile
构建镜像。如果构建成功,它会将镜像推送到 GitHub Packages。它使用 context
参数将构建的上下文定义为位于指定路径中的一组文件。更多信息,请参见 docker/build-push-action
代码库自述文件中的“用法”。它使用 tags
和 labels
参数使用“meta”步骤的输出来标记和标记镜像。
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
此步骤为镜像生成工件证明,这是一个关于镜像在哪里以及如何构建的不可伪造的声明。它提高了使用该镜像的人员的供应链安全性。更多信息,请参见“使用工件证明来确定构建的来源”。
#
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
attestations: write
id-token: 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
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
每次您将更改推送到代码库中名为 release
的分支时,此新工作流程都会自动运行。您可以在 **操作** 选项卡中查看进度。
工作流程完成几分钟后,新软件包将显示在您的代码库中。要查找可用的软件包,请参见“查看软件包”。
使用操作安装软件包
您可以使用 GitHub Actions 将软件包作为 CI 流程的一部分安装。例如,您可以配置一个工作流程,以便每当开发人员将代码推送到拉取请求时,工作流程都会通过下载和安装 GitHub Packages 托管的软件包来解析依赖项。然后,工作流程可以运行需要依赖项的 CI 测试。
当您使用 GITHUB_TOKEN
时,通过 GitHub Actions 安装 GitHub Packages 托管的软件包只需要最少的配置或额外的身份验证。当操作安装软件包时,数据传输也是免费的。更多信息,请参见“关于 GitHub Packages 的计费”。
配置步骤因软件包客户端而异。有关配置 GitHub Actions 工作流程的一般信息,请参见“编写工作流程”。
升级使用个人访问令牌访问注册表的工作流程
GitHub Packages 支持 GITHUB_TOKEN
,以便在您的工作流程中轻松安全地进行身份验证。如果您使用的是支持细粒度权限的注册表,并且您的工作流程使用个人访问令牌来对注册表进行身份验证,那么我们强烈建议您更新您的工作流程以使用 GITHUB_TOKEN
。
有关 GITHUB_TOKEN
的更多信息,请参见“自动令牌身份验证”。
使用 GITHUB_TOKEN
而不是具有 repo
作用域的个人访问令牌(经典),可以提高代码库的安全性,因为您无需使用提供对运行工作流程的代码库不必要访问权限的长期个人访问令牌。有关安全最佳实践的更多信息,请参见“GitHub Actions 的安全加固”。
-
导航到您的软件包登录页面。
-
为确保您的软件包可以访问您的工作流程,您必须将存储工作流程的代码库添加到您的软件包中。“管理操作访问”下,点击 **添加代码库** 并搜索您要添加的代码库。
注意
使用软件包设置中“管理操作访问”下的 **添加代码库** 按钮将代码库添加到您的软件包与将您的软件包连接到代码库不同。更多信息,请参见“配置软件包的访问控制和可见性”和“将代码库连接到软件包”。
-
可选:使用 **角色** 下拉菜单选择您希望代码库对您的软件包具有的默认访问级别。
-
打开您的工作流程文件。在您登录注册表的行中,将您的个人访问令牌替换为
${{ secrets.GITHUB_TOKEN }}
。
例如,此工作流程将 Docker 镜像发布到容器注册表并使用 ${{ secrets.GITHUB_TOKEN }}
进行身份验证。更多信息,请参见 Docker 文档中的“设置自动化构建”。
# 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 ${{ github.actor }} --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
name: Demo Push
on:
push:
branches:
- main
- seed
tags:
- v*
pull_request:
发生以下任何情况时,此工作流程都会运行
- 将更改推送到名为
main
或seed
的分支 - 创建以“v”开头的标签
- 创建或更新拉取请求
env:
IMAGE_NAME: ghtoken_product_demo
这将创建一个名为 IMAGE_NAME
的环境变量,其值为 ghtoken_product_demo
。
jobs:
push:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
这会将镜像推送到 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 ${{ github.actor }} --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]')
这会将所有大写字符更改为小写。
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
这会从版本中删除 git ref 前缀。
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
这会从标签名称中删除“v”前缀。
[ "$VERSION" == "main" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
这使用了 Docker 的 latest
标签约定。
#
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 ${{ github.actor }} --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