Skip to main content

このバージョンの GitHub Enterprise はこの日付をもって終了となりました: 2022-10-12. 重大なセキュリティの問題に対してであっても、パッチリリースは作成されません。 パフォーマンスの向上、セキュリティの向上、新機能の向上を図るために、最新バージョンの GitHub Enterprise にアップグレードします。 アップグレードに関するヘルプについては、GitHub Enterprise サポートにお問い合わせく� さい

Using the GitHub CLI on a runner

How to use advanced GitHub Actions features for continuous integration (CI).

注: GitHub ホステッド ランナーは、現在 GitHub Enterprise Server でサポートされていません。 GitHub public roadmap で、今後の計画的なサポートの詳細を確認できます。

Example overview

この記事では、ワークフローの例を使って、GitHub Actions の主な CI 機能の一部を示します。 When this workflow is triggered, it automatically runs a script that checks whether the GitHub Docs site has any broken links. If any broken links are found, the workflow uses the GitHub CLI to create a GitHub issue with the details.

次の図は、ワークフローの手� �とジョブ内でそれを実行する方法の概要を示したものです。

Overview diagram of workflow steps

Features used in this example

このワークフロー例は、GitHub Actions の次の機能を示しています。

FeatureImplementation
定期的にワークフローを実行する:schedule
トークンのアクセス許可の設定:permissions
特定の条件が満たされない限り、ジョブが実行されないようにする:if
ワークフロー内のシークレットの参照:シークレット
リポジトリをランナーにクローンする:actions/checkout
ランナーへの node のインストール:actions/setup-node
Using a third-party action:peter-evans/create-issue-from-file
Running shell commands on the runner:run
Running a script on the runner:Using script/check-english-links.js
Generating an output file:Piping the output using the > operator
Checking for existing issues using GitHub CLI:gh issue list
Commenting on an issue using GitHub CLI:gh issue comment

Example workflow

次のワークフローは、GitHub ドキュメント エンジニアリング チー� によって作成されました。 github/docs リポジトリ内でこのファイルの最新バージョンを確認するには、次を参照してく� さい。 check-all-english-links.yml.

: このワークフローの各行については、次のセクションの「例の説明」に説明があります。

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@v2
      - name: Setup Node
        uses: actions/setup-node@v2
        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

Understanding the example

次の表では、GitHub Actions ワークフローを作成するときにこれらの各機能がどのように使われるかを説明します。

Code Explanation
YAML
name: Check all English links

GitHub リポジトリの [アクション] タブに表示されるワークフローの名前。

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

Defines the workflow_dispatch and scheduled as triggers for the workflow:

  • The workflow_dispatch lets you manually run this workflow from the UI. For more information, see workflow_dispatch.
  • The schedule event lets you use cron syntax to define a regular interval for automatically triggering the workflow. For more information, see schedule.
YAML
permissions:
  contents: read
  issues: write

Modifies the default permissions granted to GITHUB_TOKEN. This will vary depending on the needs of your workflow. For more information, see "Assigning permissions to jobs."

YAML
jobs:

Groups together all the jobs that run in the workflow file.

YAML
  check_all_english_links:
    name: Check all links

Defines a job with the ID check_all_english_links, and the name Check all links, that is stored within the jobs key.

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

Only run the check_all_english_links job if the repository is named docs-internal and is within the github organization. Otherwise, the job is marked as skipped.

YAML
runs-on: ubuntu-latest

Configures the job to run on an Ubuntu Linux runner. This means that the job will execute on a fresh virtual machine hosted by GitHub. For syntax examples using other runners, see "Workflow syntax for 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

Creates custom environment variables, and redefines the built-in GITHUB_TOKEN variable to use a custom secret. These variables will be referenced later in the workflow.

YAML
    steps:

Groups together all the steps that will run as part of the check_all_english_links job. Each job in the workflow has its own steps section.

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

The uses keyword tells the job to retrieve the action named actions/checkout. This is an action that checks out your repository and downloads it to the runner, allowing you to run actions against your code (such as testing tools). You must use the checkout action any time your workflow will run against the repository's code or you are using an action defined in the repository.

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

This step uses the actions/setup-node action to install the specified version of the node software package on the runner, which gives you access to the npm command.

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

The run keyword tells the job to execute a command on the runner. In this case, the npm ci and npm run build commands are run as separate steps to install and build the Node.js application in the repository.

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

This run command executes a script that is stored in the repository at script/check-english-links.js, and pipes the output to a file called broken_links.md.

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

If the check-english-links.js script detects broken links and returns a non-zero (failure) exit status, then use a workflow command to set an output that has the value of the first line of the broken_links.md file (this is used the next step).

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 }}

Uses the peter-evans/create-issue-from-file action to create a new GitHub issue. This example is pinned to a specific version of the action, using the 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)"

Uses gh issue list to locate the previously created issue from earlier runs. This is aliased to gh list-reports for simpler processing in later steps. To get the issue URL, the jq expression processes the resulting JSON output.

gh issue comment is then used to add a comment to the new issue that links to the previous one.

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

If an issue from a previous run is open and assigned to someone, then use gh issue comment to add a comment with a link to the new issue.

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

If an issue from a previous run is open and is not assigned to anyone, then:

Next steps