Automate Your Workflow: Using GitHub CLI with GitHub ActionsAutomation is the backbone of modern software development. Combining the GitHub CLI (gh) and GitHub Actions lets you script and streamline repository workflows with the same tools you use locally — but running them on GitHub’s CI/CD platform. This article explains what the GitHub CLI and GitHub Actions are, why combining them is powerful, common use cases, step‑by‑step examples, best practices, and troubleshooting tips so you can start automating confidently.
Why use GitHub CLI inside GitHub Actions?
- Consistency: Use the same commands locally and in CI, reducing context-switching.
- Simplicity: gh exposes high-level operations (issues, PRs, releases) that otherwise require REST or GraphQL calls.
- Flexibility: Script complex flows in any language while using gh for repository interactions.
- Authentication: Actions provide secure secrets for authenticating gh, simplifying permissions.
- Extensibility: gh has extensions and workflow‑friendly output (JSON) that integrate well with actions.
Key concepts
GitHub CLI (gh)
gh is a command-line tool that wraps the GitHub API to perform repository, issue, PR, release, and other operations. It supports both interactive usage and noninteractive scripting with flags and JSON output.
Important features for automation:
- gh pr, gh issue, gh release, gh api
- JSON output:
--json
and--jq
for parsing - Extensions: add custom commands
- Noninteractive mode via
--confirm
or providing inputs
GitHub Actions
A CI/CD platform built into GitHub. Workflows are defined in YAML, triggered by events (push, PR, schedule, manual). Steps run in runners (GitHub-hosted or self-hosted) and can use actions or run arbitrary commands.
Important concepts:
- Workflow triggers: on: push, pull_request, schedule, workflow_dispatch
- Jobs and steps: jobs run in runners; steps run commands or actions
- Secrets and tokens: secure storage for credentials; GITHUB_TOKEN auto-generated
- Artifacts and caching: persist data between steps or workflows
Common use cases
- Automating release creation and publishing (tag, changelog, release notes, upload assets)
- Managing pull requests (auto-merge, add reviewers, post comments, update labels)
- Creating issues from templates or external systems
- Backporting PRs to maintenance branches
- Orchestrating multi-repository workflows (create PRs across repos)
- Running repository maintenance tasks (close stale issues, sync files)
Authentication inside Actions
Use the built-in GITHUB_TOKEN or a personal access token (PAT) stored as a secret.
- GITHUB_TOKEN: good for many repo-level tasks; automatically scoped to the repository and avoids manual rotation.
- PAT: required for cross-repo operations or when needing broader permissions (org-level actions, releasing to other repos).
Example in a workflow step:
- Configure gh with a token:
- echo “$GITHUB_TOKEN” | gh auth login –with-token
Note: In scripted runs, prefer noninteractive authentication (gh auth login --with-token
) instead of interactive flows.
Example workflows
Below are practical, ready-to-adapt examples showing how to use gh inside GitHub Actions.
1) Create a release with autogenerated notes and upload assets
Filename: .github/workflows/release.yml
name: Create Release on: push: tags: - 'v*.*.*' jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up gh run: | sudo apt update && sudo apt install -y curl curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null sudo apt update && sudo apt install -y gh echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token - name: Create GitHub Release env: TAG: ${{ github.ref_name }} run: | gh release create "$TAG" --generate-notes - name: Upload assets if: always() run: | gh release upload "$TAG" ./build/*.zip --clobber
Notes:
- Uses tag push trigger; gh generates release notes from commits.
- GITHUB_TOKEN is piped for noninteractive auth.
- Adjust asset paths and installation for different runners.
2) Auto-add reviewers and label when PR opened
Filename: .github/workflows/pr-label-review.yml
name: PR Label & Review on: pull_request: types: [opened] jobs: label-and-request-review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install gh run: | sudo apt update && sudo apt install -y gh echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token - name: Add labels run: | gh pr edit ${{ github.event.pull_request.number }} --add-label "needs-review" - name: Request review run: | gh pr review --request "alice,bob" ${{ github.event.pull_request.number }} || true
Notes:
- Uses event context to pick PR number.
- gh pr review –request may require comma-separated list of logins.
- The || true avoids failing if reviewers can’t be requested (insufficient permissions).
3) Backport merged PR to a maintenance branch
Filename: .github/workflows/backport.yml
name: Backport PR on: workflow_dispatch: inputs: pr_number: description: 'Merged PR number' required: true target_branch: description: 'Branch to backport to (e.g., release-1.2)' required: true jobs: backport: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install gh run: | sudo apt update && sudo apt install -y gh echo "${{ secrets.PAT }}" | gh auth login --with-token - name: Create backport branch run: | gh pr checkout ${{ github.event.inputs.pr_number }} git switch -c backport/${{ github.event.inputs.pr_number }}-to-${{ github.event.inputs.target_branch }} git rebase --onto ${{ github.event.inputs.target_branch }} $(git merge-base HEAD ${{ github.event.inputs.target_branch }}) git push origin HEAD - name: Open backport PR run: | gh pr create --base ${{ github.event.inputs.target_branch }} --head backport/${{ github.event.inputs.pr_number }}-to-${{ github.event.inputs.target_branch }} --title "Backport PR #${{ github.event.inputs.pr_number }} to ${{ github.event.inputs.target_branch }}" --body "Automated backport"
Notes:
- Uses a PAT for cross-branch or repo permissions if needed.
- Rebase strategy may need adjusting for complex histories.
Parsing gh JSON output
gh can return JSON for many commands, which is useful in workflows:
Example: get PR title and body
pr_json=$(gh pr view 123 --json title,body) pr_title=$(echo "$pr_json" | jq -r .title) pr_body=$(echo "$pr_json" | jq -r .body)
Use jq (available on runners) to extract fields and conditionally act on them.
Best practices
- Use GITHUB_TOKEN where possible; use PATs only when necessary and store them in repo/org secrets.
- Cache gh installation (or use actions that provide gh) to speed runs.
- Prefer
gh ... --json
for structured output instead of parsing plain text. - Make steps idempotent — actions can run multiple times.
- Fail gracefully: capture nonfatal errors and continue when appropriate.
- Limit permission scopes of tokens to the minimum needed.
- Use workflow_dispatch for manual run and testing.
- Test locally with gh and act (or a dry run) to validate flow before enabling in prod.
Troubleshooting common issues
- Authentication errors: verify secret name, token scopes, and that you’re piping the token correctly (
echo "$TOKEN" | gh auth login --with-token
). - Permission denied on cross-repo ops: use a PAT with appropriate scopes (repo, workflow).
- gh installation differences across runners: use official install instructions or prebuilt actions that include gh.
- Rate limits: check API rate limits; prefer GITHUB_TOKEN where possible; handle retries.
- JSON parsing issues: ensure
--json
supports requested fields; check gh version compatibility.
Extensions and ecosystem
- gh extensions let you add custom commands (search gh extension marketplace).
- Combine gh with Actions marketplace actions (e.g., release-drafter, actions/upload-release-asset) to mix high-level automation with native actions.
- Use community actions that already wrap gh for common patterns.
Summary
Using GitHub CLI within GitHub Actions gives you consistency between local and CI workflows, simplifies interactions with GitHub resources, and lets you script complex repository operations more naturally. Start with simple tasks (labeling PRs, creating releases) and gradually move to multi-repo orchestration. Follow best practices for authentication, JSON parsing, and idempotency to build reliable, maintainable automation.
Leave a Reply