GitHub Actions Tutorial — Troubleshooting Exercises

3 minute read

Practice Exercises — Troubleshooting

Test your understanding of debug logging, common errors, act, reading logs, and debugging strategies with these hands-on exercises.


Exercise 1 — Enable Debug Logging

Task: You have a workflow that fails with a cryptic error. Describe two methods to enable debug logging and explain when you’d use each one.

Show Solution

Method 1 — Repository Secret (persistent):

Set a secret ACTIONS_RUNNER_DEBUG=true in the repository settings.

  • Use when: You need debug output for multiple runs while investigating
  • Drawback: Affects ALL workflow runs; verbose output; remember to remove it

Method 2 — Re-run with Debug (one-time):

Go to the failed run → click “Re-run jobs” → check “Enable debug logging” → “Re-run”.

  • Use when: You want debug output for a single investigation
  • Benefit: No secret to clean up; only affects one run

Bonus — Step-level debug:

Add ACTIONS_STEP_DEBUG=true as a secret for even more detail (condition evaluation, input resolution, file matching).


Exercise 2 — Diagnose Common Errors

Task: For each error message, identify the cause and write the fix:

  1. Error: Resource not accessible by integration
  2. Can't find 'action.yml' under '/home/runner/work/_actions/my-org/my-action/v99'
  3. Error: Input required and not supplied: token
Show Solution

Error 1 — Resource not accessible:

Cause: GITHUB_TOKEN lacks required permissions.

Fix:


permissions:
  contents: read
  pull-requests: write    # add the permission you need

Error 2 — Action not found:

Cause: The action version v99 doesn’t exist.

Fix: Check the action repository for valid tags:


- uses: my-org/my-action@v1    # use a tag that exists

Error 3 — Input required:

Cause: A required input wasn’t provided, or the secret name is misspelled.

Fix: Check the secret name matches exactly (case-sensitive):


- uses: my-action@v1
  with:
    token: ${{ secrets.MY_TOKEN }}    # verify this name exists in Settings → Secrets


Exercise 3 — Local Testing with Act

Task: Write the act commands to:

  1. List all jobs in your workflows
  2. Run only the test job
  3. Pass a secret GITHUB_TOKEN and an environment variable NODE_ENV=test
  4. Use the medium-sized runner image
Show Solution
# 1. List all jobs
act -l

# 2. Run only the test job
act -j test

# 3. Pass secret and env var
act -j test -s GITHUB_TOKEN=ghp_xxxxx --env NODE_ENV=test

# 4. Use medium image
act -j test \
  -P ubuntu-latest=catthehacker/ubuntu:act-latest \
  -s GITHUB_TOKEN=ghp_xxxxx \
  --env NODE_ENV=test

Note: Add secrets to a .secrets file and env vars to a .env file for convenience. Add both to .gitignore.


Exercise 4 — Debug a Failing Workflow

Task: This workflow fails. Add debugging steps to diagnose the issue:


name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

Add:

  1. Environment dump before the failing step
  2. continue-on-error on the failing step
  3. A diagnostic step that runs only on failure
  4. A tmate session as a last resort
Show Solution

name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # 1. Environment dump
      - name: Debug environment
        run: |
          echo "Node: $(node --version)"
          echo "NPM: $(npm --version)"
          echo "Working dir: $(pwd)"
          ls -la
          cat package.json

      - run: npm ci

      # 2. continue-on-error on the suspect step
      - name: Run tests
        id: test
        continue-on-error: true
        run: npm test

      # 3. Diagnostic step on failure
      - name: Gather diagnostics
        if: steps.test.outcome == 'failure'
        run: |
          echo "Tests failed — gathering info"
          cat test-results.xml 2>/dev/null || echo "No results file"
          ls -la node_modules/ | head -20
          npm ls --depth=0

      # 4. tmate session as last resort
      - name: SSH debug session
        if: steps.test.outcome == 'failure'
        uses: mxschmitt/action-tmate@v3
        timeout-minutes: 15

      # Fail the job if tests actually failed
      - name: Check test result
        if: steps.test.outcome == 'failure'
        run: exit 1


Exercise 5 — Log Organization

Task: Rewrite this step to use log groups and annotations for better readability:


- run: |
    echo "Installing..."
    npm ci
    echo "Linting..."
    npm run lint
    echo "Testing..."
    npm test
    echo "Building..."
    npm run build

Show Solution

- run: |
    echo "::group::📦 Install dependencies"
    npm ci
    echo "::endgroup::"

    echo "::group::🔍 Lint"
    npm run lint
    echo "::endgroup::"

    echo "::group::🧪 Test"
    npm test
    echo "::endgroup::"

    echo "::group::🏗️ Build"
    npm run build
    echo "::endgroup::"

    echo "::notice::All stages completed successfully"

Each group appears as a collapsible section in the GitHub UI. The ::notice:: annotation creates a visible banner in the run summary.


← Back to: Chapter 14: Troubleshooting

Next Chapter: Chapter 15: Practice Projects →

Updated: