Skip to main content

在运行器上使用 GitHub CLI

如何使用高级 GitHub Actions 功能进行持续集成 (CI)。

注: GitHub 托管的运行器目前在 GitHub Enterprise Server 上不受支持。 您可以在 GitHub 公共路线图 上查看有关未来支持计划的更多信息。

示例概述

This article uses an example workflow to demonstrate some of the main CI features of GitHub Actions. 此工作流程被触发时,它会自动运行一个脚本,用于检查 GitHub 文档网站是否有任何断开的链接。 如果发现任何断开的链接,工作流程将使用 GitHub CLI 创建包含详细信息的 GitHub 议题。

The following diagram shows a high level view of the workflow's steps and how they run within the job:

工作流程步骤概览图

此示例中使用的功能

The example workflow demonstrates the following capabilities of GitHub Actions:

功能实现
Running a workflow at regular intervals:schedule
Setting permissions for the token:permissions
Preventing a job from running unless specific conditions are met:if
Referencing secrets in a workflow:Secrets
Cloning your repository to the runner:actions/checkout
Installing node on the runner:actions/setup-node
使用第三方操作:peter-evans/create-issue-from-file

示例工作流程

The following workflow was created by the GitHub Docs Engineering team. To review the latest version of this file in the github/docs repository, see check-all-english-links.yml.

Note: Each line of this workflow is explained in the next section at "Understanding the example."

YAML
name: Check all English links

# **What it does**: This script once a day checks all English links and reports in issues.
# **Why we have it**: We want to know if any links break.
# **Who does it impact**: Docs content.

on:
  workflow_dispatch:
  schedule:
    - cron: '40 19 * * *' # once a day at 19:40 UTC / 11:40 PST

permissions:
  contents: read
  issues: write

jobs:
  check_all_english_links:
    name: Check all links
    if: github.repository == 'github/docs-internal'
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES }}
      FIRST_RESPONDER_PROJECT: Docs content first responder
      REPORT_AUTHOR: docubot
      REPORT_LABEL: broken link report
      REPORT_REPOSITORY: github/docs-content
    steps:
      - name: Check out repo's default branch
        uses: actions/checkout@v3
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 16.13.x
          cache: npm
      - name: npm ci
        run: npm ci
      - name: npm run build
        run: npm run build
      - name: Run script
        run: |
          script/check-english-links.js > broken_links.md

      # check-english-links.js returns 0 if no links are broken, and 1 if any links
      # are broken. When an Actions step's exit code is 1, the action run's job status
      # is failure and the run ends. The following steps create an issue for the
      # broken link report only if any links are broken, so `if: ${{ failure() }}`
      # ensures the steps run despite the previous step's failure of the job.

      - if: ${{ failure() }}
        name: Get title for issue
        id: check
        run: echo "::set-output name=title::$(head -1 broken_links.md)"
      - if: ${{ failure() }}
        name: Create issue from file
        id: broken-link-report
        uses: peter-evans/create-issue-from-file@b4f9ee0a9d4abbfc6986601d9b1a4f8f8e74c77e
        with:
          token: ${{ env.GITHUB_TOKEN }}

          title: ${{ steps.check.outputs.title }}
          content-filepath: ./broken_links.md
          repository: ${{ env.REPORT_REPOSITORY }}
          labels: ${{ env.REPORT_LABEL }}
      - if: ${{ failure() }}
        name: Close and/or comment on old issues
        env:
          NEW_REPORT_URL: 'https://github.com/${{ env.REPORT_REPOSITORY }}/issues/${{ steps.broken-link-report.outputs.issue-number }}'
        run: |
          gh alias set list-reports "issue list \
                                       --repo ${{ env.REPORT_REPOSITORY }} \
                                       --author ${{ env.REPORT_AUTHOR }} \
                                       --label '${{ env.REPORT_LABEL }}'"

          # Link to the previous report from the new report that triggered this
          # workflow run.

          previous_report_url=$(gh list-reports \
                                  --state all \
                                  --limit 2 \
                                  --json url \
                                  --jq '.[].url' \
                                  | grep -v ${{ env.NEW_REPORT_URL }} | head -1)

          gh issue comment ${{ env.NEW_REPORT_URL }} --body "⬅️ [Previous report]($previous_report_url)"

          # If an old report is open and assigned to someone, link to the newer
          # report without closing the old report.

          for issue_url in $(gh list-reports \
                                  --json assignees,url \
                                  --jq '.[] | select (.assignees != []) | .url'); do
            if [ "$issue_url" != "${{ env.NEW_REPORT_URL }}" ]; then
              gh issue comment $issue_url --body "➡️ [Newer report](${{ env.NEW_REPORT_URL }})"
            fi
          done

          # Link to the newer report from any older report that is still open,
          # then close the older report and remove it from the first responder's
          # project board.

          for issue_url in $(gh list-reports \
                                  --search 'no:assignee' \
                                  --json url \
                                  --jq '.[].url'); do
            if [ "$issue_url" != "${{ env.NEW_REPORT_URL }}" ]; then
              gh issue comment $issue_url --body "➡️ [Newer report](${{ env.NEW_REPORT_URL }})"
              gh issue close $issue_url
              gh issue edit $issue_url --remove-project "${{ env.FIRST_RESPONDER_PROJECT }}"
            fi
          done

了解示例

The following table explains how each of these features are used when creating a GitHub Actions workflow.

代码 说明
YAML
name: Check all English links

The name of the workflow as it will appear in the "Actions" tab of the GitHub repository.

YAML
on:
  workflow_dispatch:
  schedule:
    - cron: '40 20 * * *' # once a day at 20:40 UTC / 12:40 PST

将“workflow_dispatch”和“scheduled”定义为工作流程的触发器:

  • “workflow_dispatch”允许您从 UI 手动运行此工作流程。 更多信息请参阅 workflow_dispatch
  • “schedule”事件允许您使用“cron”语法来定义自动触发工作流程的定期间隔。 更多信息请参阅 schedule
YAML
permissions:
  contents: read
  issues: write

修改授予“GITHUB_TOKEN”的默认权限。 这将因工作流程的需求而异。 更多信息请参阅“为作业分配权限”。

YAML
jobs:

将工作流程文件中运行的所有作业组合在一起。

YAML
  check_all_english_links:
    name: Check all links

定义 ID 为“check_all_english_links”和名称为“Check all links”的作业,该作业存储在“jobs”键中。

YAML
if: github.repository == 'github/docs-internal'

仅当存储库名为“docs-internal”并且位于“github”组织内时,才运行“checkall_english_links”作业。 否则,作业将标记为 _skiped

YAML
runs-on: ubuntu-latest

配置作业在 Ubuntu Linux 运行器上运行。 这意味着作业将在由 GitHub 托管的新虚拟机上执行。 有关使用其他运行器的语法示例,请参阅“GitHub Actions 的工作流语法”。

YAML
    env:
      GITHUB_TOKEN: ${{ secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES }}
      REPORT_AUTHOR: docubot
      REPORT_LABEL: broken link report
      REPORT_REPOSITORY: github/docs-content

创建自定义环境变量,并重新定义内置的“GITHUB_TOKEN”变量以使用自定义 secret。 稍后将在工作流程中引用这些变量。

YAML
    steps:

组合将作为“check_all_english_links”作业一部分运行的所有步骤。 工作流程中的每个作业都有自己的“steps”部分。

YAML
      - name: Check out repo's default branch
        uses: actions/checkout@v3

“uses”关键字告诉作业检索名为“actions/checkout”的操作。 这是检出仓库并将其下载到运行器的操作,允许针对您的代码运行操作(例如测试工具)。 只要工作流程针对仓库的代码运行,或者您使用仓库中定义的操作,您都必须使用检出操作。

YAML
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 16.8.x
          cache: npm

此步骤使用“actions/setup-node”操作在运行器上安装指定版本的“node”软件包,这使您可以访问“npm”命令。

YAML
      - name: Run the "npm ci" command
        run: npm ci
      - name: Run the "npm run build" command
        run: npm run build

“run”关键字指示作业在运行器上执行命令。 在这种情况下,“npm ci”和“npm run build”命令作为单独的步骤运行,以在存储库中安装和构建 Node.js 应用程序。

YAML
      - name: Run script
        run: |
          script/check-english-links.js > broken_links.md

此“run”命令执行存储在存储库中“script/check-english-links.js”的脚本,并将输出传递到名为“broken_links.md”的文件。

YAML
      - if: ${{ failure() }}
        name: Get title for issue
        id: check
        run: echo "::set-output name=title::$(head -1 broken_links.md)"

如果“check-english-links.js”脚本检测到断开的链接并返回非零(失败)退出状态,则使用 工作流程命令 来设置具有 “broken_links.md” 文件第一行值的输出(这是在下一步中使用)。

YAML
      - if: ${{ failure() }}
        name: Create issue from file
        id: broken-link-report
        uses: peter-evans/create-issue-from-file@b4f9ee0a9d4abbfc6986601d9b1a4f8f8e74c77e
        with:
          token: ${{ env.GITHUB_TOKEN }}

          title: ${{ steps.check.outputs.title }}
          content-filepath: ./broken_links.md
          repository: ${{ env.REPORT_REPOSITORY }}
          labels: ${{ env.REPORT_LABEL }}

使用“peter-evans/create-issue-from-file”操作创建新的 GitHub 议题。 此示例使用 'b4f9ee0a9d4abbfc6986601d9b1a4f8f8e74c77e' SHA 固定到操作的特定版本。

YAML
      - if: ${{ failure() }}
        name: Close and/or comment on old issues
        env:
          NEW_REPORT_URL: 'https://github.com/${{ env.REPORT_REPOSITORY }}/issues/${{ steps.broken-link-report.outputs.issue-number }}'
        run: |
          gh alias set list-reports "issue list \
                                       --repo ${{ env.REPORT_REPOSITORY }} \
                                       --author ${{ env.REPORT_AUTHOR }} \
                                       --label '${{ env.REPORT_LABEL }}'"
          previous_report_url=$(gh list-reports \
                                  --state all \
                                  --limit 2 \
                                  --json url \
                                  --jq '.[].url' \
                                  | grep -v ${{ env.NEW_REPORT_URL }} | head -1)

          gh issue comment ${{ env.NEW_REPORT_URL }} --body "⬅️ [Previous report]($previous_report_url)"

使用 gh issue list 从早期运行中查找以前创建的议题。 这将aliased 为“gh list-reports”,以便在后续步骤中简化处理。 若要获取议题 URL,“jq”表达式将处理生成的 JSON 输出。

gh issue comment 然后用于向链接到上一个议题的新议题添加注释。

YAML
          for issue_url in $(gh list-reports \
                                  --json assignees,url \
                                  --jq '.[] | select (.assignees != []) | .url'); do
            if [ "$issue_url" != "$" ]; then
              gh issue comment $issue_url --body "➡️ [Newer report]($)"
            fi
          done

如果上一次运行中的议题已打开并分配给某人,请使用 gh issue comment 添加带有指向新议题的链接的注释。

YAML
          for issue_url in $(gh list-reports \
                                  --search 'no:assignee' \
                                  --json url \
                                  --jq '.[].url'); do
            if [ "$issue_url" != "${{ env.NEW_REPORT_URL }}" ]; then
              gh issue comment $issue_url --body "➡️ [Newer report](${{ env.NEW_REPORT_URL }})"
              gh issue close $issue_url
              gh issue edit $issue_url --remove-project "${{ env.FIRST_RESPONDER_PROJECT }}"
            fi
          done

如果上一次运行中的议题已打开且未分配给任何人,则:

后续步骤