Search code examples
node.jsgithubnpmgithub-actionsbuilding-github-actions

GitHub Action: Pass npm package output to variable


I'm having trouble accessing the output of a global npm command in GitHub Actions. Running any global linting npm package (I've tried a few different ones) always exits with: Process completed with exit code 1..

The funky thing is, I can run these bash commands just fine on my local machine.

Here's a simplified version of what I'm trying to do:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16.13.2

      - name: Install npm package
        run: npm install markdownlint-cli --location=global

      - name: Run standard-markdown
        id: run_md_lint
        run: |
          VAR=$((markdownlint **/*.md --ignore node_modules) 2>&1)
          echo "::set-output name=LINT_RESULT::$VAR"

      - name: Run a one-line script
        run: echo "Resultes ${{ steps.run_md_lint.outputs.LINT_RESULT }}"

The expected output from the run step is logged in the GitHub action logs, but accessing the result and saving it to a variable isn't possible—I'm guessing due to the exit error.

enter image description here

I should mention that the ultimate goal of this is to capture the output and add it to a comment when a PR is opened.

      - name: Add PR comment
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: "${{ steps.run_md_lint.outputs.LINT_RESULT }}"
            })

Any ideas are appreciated.


EDIT: IT WORKS!

Thank you so much to @VonC for helping solve my problem. A few notes:

  • As explained below, I needed to add || true to the command to return a different exit status.
  • set-output only works for one-line strings. I needed to replace newlines and carriage returns to save multiple lines.
  • The npm package has to be installed with -g. -location=global does not work.

Here's the working GitHub Action:

name: Lint the docs!
on:
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      # Set up Node.js
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16.13.2

      - name: Install markdownlint
        run: npm install -g markdownlint-cli

      - name: Run standard-markdown
        id: run_md_lint
        run: |
          LINT=$(((markdownlint **/*.md --ignore node_modules) 2>&1) || true)
          LINT="${LINT//'%'/'%25'}"
          LINT="${LINT//$'\n'/'%0A'}"
          LINT="${LINT//$'\r'/'%0D'}"
          echo "::set-output name=LINT_RESULT::$LINT"

      - name: Add PR comment
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `Lint results:
              \`\`\`bash
              ${{ steps.run_md_lint.outputs.LINT_RESULT }}
              \`\`\`
              `
            })

Solution

  • From this thread, try and add || true on the command returning an exit status different from 0 (illustration)

    Something like:

    VAR=$(((markdownlint **/*.md --ignore node_modules) 2>&1) || true)
    # or
    VAR=$(((markdownlint **/*.md --ignore node_modules) || true) 2>&1)
    

    That would force GitHub script run step to not consider the step as failed.


    The OP confirms it works with the first syntax:

          - name: Install markdownlint
            run: npm install -g markdownlint-cli
    
         - name: Run standard-markdown
            id: run_md_lint
            run: |
              LINT=$(((markdownlint **/*.md --ignore node_modules) 2>&1) || true)
              LINT="${LINT//'%'/'%25'}"
              LINT="${LINT//$'\n'/'%0A'}"
              LINT="${LINT//$'\r'/'%0D'}"
              echo "name=LINT_RESULT::$LINT" >> $GITHUB_OUTPUT
    
          - name: Add PR comment
            uses: actions/github-script@v6
            with:
              script: |
                github.rest.issues.createComment({
                  issue_number: context.issue.number,
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  body: `Lint results:
                  \`\`\`bash
                  ${{ steps.run_md_lint.outputs.LINT_RESULT }}
                  \`\`\`
                  `
                })
    

    Note: I have used $GITHUB_OUTPUT, since the command ::set-output command has now (Oct. 2022) been deprecated.