[GH-ISSUE #2641] Invocation of gh client results in "command not found" #1198

Open
opened 2026-03-01 21:49:37 +03:00 by kerem · 6 comments
Owner

Originally created by @socketbox on GitHub (Jan 30, 2025).
Original GitHub issue: https://github.com/nektos/act/issues/2641

Discussed in https://github.com/nektos/act/discussions/2639

Originally posted by socketbox January 29, 2025

In a job that uses the ubuntu-latest runner, I've got a step that calls the GitHub API with the gh client, like so:

       - id: get-github-issue-url
        run: |
          issue_url=$(gh api -H "Accept: application/vnd.github+json"\                                                                            
            "repos/foo/baz-next/issues?per_page=1\&sort=created\&direction=desc&labels=npm,audit" |\
            jq -r '.[0].html_url')
          echo issue_url=$issue_url >> $GITHUB_OUTPUT

However, the step fails when I run the workflow with the following command (I'm using the GitHub-extension-installed version of act):
gh act schedule -v -s GITHUB_TOKEN=github_pat_foo -W ./.github/workflows/npm-audit.yml

The full job looks like this:

  parse:
    name: Parse audit report
    needs: scan
    if: always() && github.event_name == 'push' || github.event_name == 'schedule'
    runs-on: ubuntu-latest
    outputs:
      audit_link: ${{steps.get-github-issue-url.outputs.issue_url}}
      is-vulnerable: ${{steps.parse-audit-report.outputs.is-vulnerable}}
    steps:
      - id: get-github-issue-url
        run: |
          issue_url=$(gh api -H "Accept: application/vnd.github+json"\                                                                            
            "repos/foo/baz-next/issues?per_page=1\&sort=created\&direction=desc&labels=npm,audit" |\
            jq -r '.[0].html_url')
          echo issue_url=$issue_url >> $GITHUB_OUTPUT
      - id: parse-audit-report
        shell: python
        run: |
          import os
          import json
          
          report_dict = json.loads(os.environ.get("REPORT"))
          vulns = report_dict.get('metadata').get('vulnerabilities')
          is_vulnerable = any(vulns[severity] > 0 for severity in ['moderate', 'high', 'critical'])
          print(f"Vulnerabilities have been found: {is_vulnerable}")
          with open(os.getenv('GITHUB_OUTPUT'), 'a') as fh:
              print(f'is-vulnerable={is_vulnerable}', file=fh)
        env:
          REPORT: ${{needs.scan.outputs.audit-report}}

Here's the error I receive with verbose output:

[npm audit/Parse audit report] [DEBUG] Working directory '/home/socketbox/code/work/foo/baz-next/RWEB-8995-npm-audit-workflow'
| /var/run/act/workflow/get-github-issue-url: line 5: gh: command not found
[npm audit/Parse audit report]   ❌  Failure - Main 
issue_url=$(gh api -H "Accept: application/vnd.github+json" "repos/foo/baz-next/issues?per_page=1\&sort=created\&direction=desc&labels=npm,audit")
echo issue_url=$issue_url >> $GITHUB_OUTPUT
[npm audit/Parse audit report] exitcode '127': command not found, please refer to https://github.com/nektos/act/issues/107 for more information
[npm audit/Parse audit report] [DEBUG] Loading revision from git directory

What's got me puzzled (among other things) is that the catthehacker runner images seem to contain gh: https://github.com/catthehacker/docker_images/blob/master/linux/ubuntu/scripts/gh.sh

Update: thinking it was possible that I was using a non-standard image for the runner, I logged in to GHCR and then ran act with the -P flag:
gh act schedule -P ubuntu-latest="ghcr.io/catthehacker/ubuntu:act-22.04" -v -s GITHUB_TOKEN=github_foo -W ./.github/workflows/npm-audit.yml Still the same result. I also tried the 20.04 image, thinking that it might have been removed in the 22.04 image. No luck.

Then I shelled into the pulled image and tried to find gh. Nothing:

[2025-01-29 23:18:54]❮ docker run -i -t 0fbcdbe238bf /bin/bash
root@97ca12c2a7cf:/tmp# which gh
root@97ca12c2a7cf:/tmp# gh
bash: gh: command not found
root@97ca12c2a7cf:/tmp# echo $PATH
/opt/acttoolcache/node/18.20.5/x64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Versions:

[2025-01-30 09:16:16]» gh extensions list
NAME         REPO                       VERSION
gh act       nektos/gh-act              v0.2.71
gh copilot   github/gh-copilot          v1.0.6
gh sbom      advanced-security/gh-sbom  v0.1.0
gh worktree  despreston/gh-worktree     v1.0.0
[origin RWEB-8995-npm-audit-workflow][RWEB-8995-npm-audit-workflow]
[2025-01-30 09:16:20]» gh --version
gh version 2.65.0 (2025-01-06)
https://github.com/cli/cli/releases/tag/v2.65.0
Originally created by @socketbox on GitHub (Jan 30, 2025). Original GitHub issue: https://github.com/nektos/act/issues/2641 ### Discussed in https://github.com/nektos/act/discussions/2639 <div type='discussions-op-text'> <sup>Originally posted by **socketbox** January 29, 2025</sup> In a job that uses the `ubuntu-latest` runner, I've got a step that calls the GitHub API with the `gh` client, like so: ``` - id: get-github-issue-url run: | issue_url=$(gh api -H "Accept: application/vnd.github+json"\ "repos/foo/baz-next/issues?per_page=1\&sort=created\&direction=desc&labels=npm,audit" |\ jq -r '.[0].html_url') echo issue_url=$issue_url >> $GITHUB_OUTPUT ``` However, the step fails when I run the workflow with the following command (I'm using the GitHub-extension-installed version of act): `gh act schedule -v -s GITHUB_TOKEN=github_pat_foo -W ./.github/workflows/npm-audit.yml` The full job looks like this: ``` parse: name: Parse audit report needs: scan if: always() && github.event_name == 'push' || github.event_name == 'schedule' runs-on: ubuntu-latest outputs: audit_link: ${{steps.get-github-issue-url.outputs.issue_url}} is-vulnerable: ${{steps.parse-audit-report.outputs.is-vulnerable}} steps: - id: get-github-issue-url run: | issue_url=$(gh api -H "Accept: application/vnd.github+json"\ "repos/foo/baz-next/issues?per_page=1\&sort=created\&direction=desc&labels=npm,audit" |\ jq -r '.[0].html_url') echo issue_url=$issue_url >> $GITHUB_OUTPUT - id: parse-audit-report shell: python run: | import os import json report_dict = json.loads(os.environ.get("REPORT")) vulns = report_dict.get('metadata').get('vulnerabilities') is_vulnerable = any(vulns[severity] > 0 for severity in ['moderate', 'high', 'critical']) print(f"Vulnerabilities have been found: {is_vulnerable}") with open(os.getenv('GITHUB_OUTPUT'), 'a') as fh: print(f'is-vulnerable={is_vulnerable}', file=fh) env: REPORT: ${{needs.scan.outputs.audit-report}} ``` Here's the error I receive with verbose output: ``` [npm audit/Parse audit report] [DEBUG] Working directory '/home/socketbox/code/work/foo/baz-next/RWEB-8995-npm-audit-workflow' | /var/run/act/workflow/get-github-issue-url: line 5: gh: command not found [npm audit/Parse audit report] ❌ Failure - Main issue_url=$(gh api -H "Accept: application/vnd.github+json" "repos/foo/baz-next/issues?per_page=1\&sort=created\&direction=desc&labels=npm,audit") echo issue_url=$issue_url >> $GITHUB_OUTPUT [npm audit/Parse audit report] exitcode '127': command not found, please refer to https://github.com/nektos/act/issues/107 for more information [npm audit/Parse audit report] [DEBUG] Loading revision from git directory ``` What's got me puzzled (among other things) is that the catthehacker runner images _seem_ to contain `gh`: https://github.com/catthehacker/docker_images/blob/master/linux/ubuntu/scripts/gh.sh **Update:** thinking it was possible that I was using a non-standard image for the runner, I logged in to GHCR and then ran `act` with the `-P` flag: `gh act schedule -P ubuntu-latest="ghcr.io/catthehacker/ubuntu:act-22.04" -v -s GITHUB_TOKEN=github_foo -W ./.github/workflows/npm-audit.yml` Still the same result. I also tried the `20.04` image, thinking that it might have been removed in the `22.04` image. No luck. Then I shelled into the pulled image and tried to find `gh`. Nothing: ``` [2025-01-29 23:18:54]❮ docker run -i -t 0fbcdbe238bf /bin/bash root@97ca12c2a7cf:/tmp# which gh root@97ca12c2a7cf:/tmp# gh bash: gh: command not found root@97ca12c2a7cf:/tmp# echo $PATH /opt/acttoolcache/node/18.20.5/x64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin ``` **Versions**: ``` [2025-01-30 09:16:16]» gh extensions list NAME REPO VERSION gh act nektos/gh-act v0.2.71 gh copilot github/gh-copilot v1.0.6 gh sbom advanced-security/gh-sbom v0.1.0 gh worktree despreston/gh-worktree v1.0.0 [origin RWEB-8995-npm-audit-workflow][RWEB-8995-npm-audit-workflow] [2025-01-30 09:16:20]» gh --version gh version 2.65.0 (2025-01-06) https://github.com/cli/cli/releases/tag/v2.65.0 ``` </div>
Author
Owner

@ChristopherHX commented on GitHub (Jan 31, 2025):

tags that would contain gh, your selected image does not ship gh

  • full-24.04
  • custom-24.04

If you really want avoid program not found download the full image, it's almost a 1 : 1 snapshot of the GitHub Hosted Runners, but this one is big use -v of act to not assume act stalled.

<!-- gh-comment-id:2626880594 --> @ChristopherHX commented on GitHub (Jan 31, 2025): tags that would contain gh, your selected image does not ship gh - full-24.04 - custom-24.04 If you really want avoid program not found download the full image, it's almost a 1 : 1 snapshot of the GitHub Hosted Runners, but this one is big use `-v` of act to not assume act stalled.
Author
Owner

@socketbox commented on GitHub (Jan 31, 2025):

@ChristopherHX Thanks for your response.

It seems that I was mistaken regarding this script: https://github.com/catthehacker/docker_images/blob/master/linux/ubuntu/scripts/gh.sh . I thought it was executed as part of all ubuntu-based image builds: github.com/catthehacker/docker_images@844d48050c/linux/ubuntu/Dockerfile (L25)

<!-- gh-comment-id:2627448203 --> @socketbox commented on GitHub (Jan 31, 2025): @ChristopherHX Thanks for your response. It seems that I was mistaken regarding this script: https://github.com/catthehacker/docker_images/blob/master/linux/ubuntu/scripts/gh.sh . I thought it was executed as part of all ubuntu-based image builds: https://github.com/catthehacker/docker_images/blob/844d48050c644ed19d504d10f63cf91ba196c6a1/linux/ubuntu/Dockerfile#L25
Author
Owner

@ToppDev commented on GitHub (Jan 31, 2025):

Another solution to this is, to add a step installing the GitHub CLI

name: 'install_gh_cli'
description: 'Install the GitHub CLI'

runs:
  using: "composite"
  steps:
    # https://github.com/cli/cli/blob/trunk/docs/install_linux.md
    - name: Install GitHub CLI
      shell: bash
      if: ${{ env.ACT && runner.os == 'Linux' }}
      run: |
        (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
          && sudo mkdir -p -m 755 /etc/apt/keyrings \
          && out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
          && cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
          && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
          && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/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 gh -y

<!-- gh-comment-id:2628411278 --> @ToppDev commented on GitHub (Jan 31, 2025): Another solution to this is, to add a step installing the GitHub CLI ```yml name: 'install_gh_cli' description: 'Install the GitHub CLI' runs: using: "composite" steps: # https://github.com/cli/cli/blob/trunk/docs/install_linux.md - name: Install GitHub CLI shell: bash if: ${{ env.ACT && runner.os == 'Linux' }} run: | (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \ && sudo mkdir -p -m 755 /etc/apt/keyrings \ && out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \ && cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/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 gh -y ```
Author
Owner

@robtaylor commented on GitHub (May 14, 2025):

I only found this out from this bug, maybe a doc update would help for the possible images to use?

<!-- gh-comment-id:2880931428 --> @robtaylor commented on GitHub (May 14, 2025): I only found this out from this bug, maybe a doc update would help for the possible images to use?
Author
Owner

@matheusmazzoni commented on GitHub (Aug 10, 2025):

I went through the same issue and it would be interesting to mention in the doc that the default image does not have the gh cli

<!-- gh-comment-id:3172849108 --> @matheusmazzoni commented on GitHub (Aug 10, 2025): I went through the same issue and it would be interesting to mention in the doc that the default image does not have the gh cli
Author
Owner

@ChristopherHX commented on GitHub (Aug 10, 2025):

If you want to document this, you can contribute to https://github.com/nektos/act-docs then everybody using act might benefit.

It's just markdown Formatting, very similar to the GitHub Comments / Readme files.

<!-- gh-comment-id:3172976370 --> @ChristopherHX commented on GitHub (Aug 10, 2025): If you want to document this, you can contribute to <https://github.com/nektos/act-docs> then everybody using act might benefit. It's just markdown Formatting, very similar to the GitHub Comments / Readme files.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/act#1198
No description provided.