Implement workflow to label Issue as "blocked" based on dependencies

160 views Asked by At

I am trying to implement a GitHub Actions workflow that automatically labels an issue as "blocked" if it has dependencies on tasks that are still in progress. The action should be triggered when an issue is opened, edited, or reopened. Technical solution:

  • Create a YAML file in the .github/workflows directory of the repository.
  • The workflow should be triggered on issue events: opened, edited, and reopened.
  • Use the GitHub CLI tool to fetch the state of dependent issues.
  • Use jq to parse and filter JSON data.
  • If a dependent issue is found to be open, label the current issue as "blocked".

So far I have

  • Created file label-blocked-issues.yml in .github/workflows:

    on:
      issues:
        types:
          - opened
          - edited
          - reopened
    
    jobs:
      label-blocked-issues:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout Repository
            uses: actions/checkout@v3
    
          - name: Install GitHub CLI
            run: |
              sudo apt-get update
              sudo apt-get install gh
    
          - name: Authenticate with GitHub
            run: |
              echo -e "machine github.com\nlogin $GITHUB_ACTOR\npassword ${{ secrets.GITHUB_TOKEN }}" > ~/.netrc
              chmod 600 ~/.netrc
    
          - name: Find and Label Blocked Issues
            id: find-blocked-issues
            run: |
              body=$(jq -r .issue.body $GITHUB_EVENT_PATH)
              dependencies=$(echo "$body" | grep -oE "#[0-9]+" | sed 's/#//g' || true)
    
              found_blocked=false
              for issue in $dependencies; do
                status=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
                  -H "Accept: application/vnd.github.v3+json" \
                  "https://api.github.com/repos/${{ github.repository }}/issues/$issue" | jq -r .state)
    
                if [ "$status" != "closed" ]; then
                  echo "Issue #$issue is still open"
                  found_blocked=true
                fi
              done
    
              if [[ "$found_blocked" == true ]]; then
                echo "::set-output name=blocked::true"
              fi
    
          - name: Label Issue as Blocked if
            if: steps.find-blocked-issues.outputs.blocked == 'true'
            run: |
              echo "Labeling issue as blocked..."
              echo "GitHub Repository: ${{ github.repository }}"
              echo "Issue Number: ${{ github.event.issue.number }}"
    
              # Use the GitHub token directly in the command
              gh api --method POST \
                -H "Accept: application/vnd.github+json" \
                -H "X-GitHub-Api-Version: 2022-11-28" \
                -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
                /repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/labels \
                -f "labels[]=blocked"
    
  • Created file test-event.json within same directory:

    {
      "action": "opened",
      "issue": {
        "number": 1,
        "title": "Test Issue",
        "body": "Depends on #123",
        "state": "open"
      }
    }
    
  • Tested steps from file label-blocked-issues.yml together with test-event.json using Nektos/Act tool with Act Commands:

    act -v -e .github/workflows/test-event.json -W . -j label-blocked-issues

    or for simplicity:

    act -e .github/workflows/test-event.json -W . -j label-blocked-issues

    All steps runs and passed successfully, except of the last one "Label Issue as Blocked if", when this step runs I get the following output:

    [label-blocked-issues.yml/label-blocked-issues] ⭐ Run Main Label Issue as Blocked if
    [label-blocked-issues.yml/label-blocked-issues]     docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/4] user= workdir=
    | Labeling issue as blocked...
    | GitHub Repository: treasure-house-of-projects/skarb-ngo
    | Issue Number: 1
    | Welcome to GitHub CLI!
    | 
    | To authenticate, please run `gh auth login`.
    [label-blocked-issues.yml/label-blocked-issues]   ❌  Failure - Main Label Issue as Blocked if
    [label-blocked-issues.yml/label-blocked-issues] exitcode '4': failure
    [label-blocked-issues.yml/label-blocked-issues]   Job failed
    Error: Job 'label-blocked-issues' failed
    

    So I am not able to pass GitHub CLI authentication.

I have tried different approaches related to GITHUB_TOKEN, secrets.GITHUB_TOKEN, etc., also I try to include the authentication directly in the steps where it's needed:

gh auth login --with-token ${{ secrets.GITHUB_TOKEN }}

But nothing that I have done can pass the GitHub CLI authentication withing Nektos/Act test tool.

1

There are 1 answers

0
jonrsharpe On BEST ANSWER

It seems like your problem is only with authenticating when running the workflow locally. Per the act documentation:

GITHUB_TOKEN

GitHub automatically provides a GITHUB_TOKEN secret when running workflows inside GitHub.

If your workflow depends on this token, you need to create a personal access token and pass it to act as a secret:

act -s GITHUB_TOKEN=[insert token or leave blank and omit equals for secure input]

If GitHub CLI is installed, the gh auth token command can be used to automatically pass the token to act

act -s GITHUB_TOKEN="$(gh auth token)"

WARNING: GITHUB_TOKEN will be logged in shell history if not inserted through secure input or (depending on your shell config) the command is prefixed with a whitespace.

You're missing this -s parameter to provide valid token locally. Alternatively, if you have e.g. a .env file, you can use --secret-file, again per the docs:

Secrets

To run act with secrets, you can enter them interactively, supply them as environment variables or load them from a file. The following options are available for providing secrets:

  • act -s MY_SECRET=somevalue - use somevalue as the value for MY_SECRET.
  • act -s MY_SECRET - check for an environment variable named MY_SECRET and use it if it exists. If the environment variable is not defined, prompt the user for a value.
  • act --secret-file my.secrets - load secrets values from my.secrets file.
    • secrets file format is the same as .env format