GitHub Actions GitHub CLI

The GitHub CLI, called gh, is a command-line tool that manages issues, pull requests, releases, and workflow runs. GitHub-hosted runners include it already. Workflows use it to talk to GitHub with simple one-line commands instead of long scripts.

The CLI in Simple Words

Think of a TV remote. You press one button, and the television does a complex job. The gh tool is a remote for GitHub. One short command creates a release, posts a comment, or starts another workflow.

Authentication

The tool needs a token. Pass GITHUB_TOKEN through the GH_TOKEN environment variable.

env:
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Set the variable at step level to limit exposure, or at job level when several steps use the tool. The token follows the permissions you declared in the workflow.

How a Command Travels

+-----------------+     +----------+     +------------+     +--------------+
| Workflow step   | --> | gh       | --> | GitHub API | --> | Issue, PR or |
| run: gh ...     |     | command  |     | (HTTPS)    |     | release done |
+-----------------+     +----------+     +------------+     +--------------+

Common Commands

TaskCommand
Create an issuegh issue create --title "Bug" --body "Details"
Comment on a pull requestgh pr comment 12 --body "Checked"
Add a labelgh issue edit 5 --add-label bug
List recent runsgh run list --limit 5
Start a workflowgh workflow run deploy.yml
Create a releasegh release create v1.0.0 --generate-notes

Example: Comment on Every Pull Request

name: PR Comment

on:
  pull_request:
    types: [ opened ]

permissions:
  pull-requests: write

jobs:
  comment:
    runs-on: ubuntu-latest
    steps:
      - name: Post checklist
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          gh pr comment "$PR_NUMBER" \
            --repo "${{ github.repository }}" \
            --body "Please confirm tests pass and the changelog is updated."

The --repo flag matters when the job does not check out the repository. Without a checkout, the tool cannot detect the repository on its own.

Example: Create an Issue When a Job Fails

      - name: Open issue on failure
        if: failure()
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh issue create \
            --repo "${{ github.repository }}" \
            --title "Nightly build failed" \
            --body "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"

The issue requires the issues: write permission at the workflow or job level.

Calling Any API Endpoint

The gh api command reaches any GitHub REST endpoint. The tool fills in the authentication header for you.

gh api repos/${{ github.repository }}/releases/latest --jq '.tag_name'

The --jq flag filters the JSON response down to one value. The command above prints only the latest release tag.

Using Output in Later Steps

- name: Find latest tag
  id: latest
  env:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    TAG=$(gh api repos/${{ github.repository }}/releases/latest --jq '.tag_name')
    echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- run: echo "Latest is ${{ steps.latest.outputs.tag }}"

CLI Versus Marketplace Actions

Marketplace actions package common tasks with inputs and tested behavior. The CLI offers flexibility for tasks without a ready-made action. Choose the CLI when one command solves the problem. Choose an action when the task needs many options.

Safety Tips

  • Grant only the permissions that the command needs.
  • Pass user-controlled text, such as issue titles, through environment variables instead of pasting them into the command line. The practice prevents script injection.
  • Test commands on your own computer first with gh auth login.