duplicate checks on pull_request event

I tried to create an action to check WIP status by watching PR title/label changes, but my implementation generates duplicate checks on every pull_request event.

Is there any way to avoid duplicate checks?

24 Likes

Can you provide your workflow description?  That will help understand what the triggers should be executing.

My implementation simply checks the PR title and label changes on pull_request event, then return exit code if these changes contain ‘WIP’ string.

Here’s my workflow file:

name: WIP

on:
  pull_request:
    types: [labeled,unlabeled,opened,edited,reopened,synchronize]

jobs:
  check:

    runs-on: ubuntu-latest

    steps:
    - name: WIP
      uses: mjhd-devlion/wip-kun-action@master
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        owner: mjhd-devlion
        repo: wip-kun-action
        label: 'work-in-progress'
        title: 'WIP: '
        commits: 'wip,fixup!'

https://github.com/mjhd-devlion/wip-kun-action/pull/5

Looks like my previous comment somehow disappeared.

I have the same issue where duplicate checks are generated. This becomes a big issue when using “Require status checks to pass before merging” on an action where this can happen. Let’s say you have an action which is triggered by the following:

on:  
pull\_request:  
types: [opened, reopened, edited, closed]  

The action that is run validates the title of a Pull Request. When first opening the Pull Request the action is fired on the “opened” event and then fails that action because the title was wrong. The user now edits the Pull Request title and the action is rerun but this time with the “edited” event. This time the title was correct and the action succeeds. We now have two status checks on that Pull Request. One failed and one succeeded.

Since they are not grouped together it’s now impossible to merge this PR due to the “Require status checks to pass before merging” check still seeing the check that was trigged on “opened” as failed.

I think that these checks should be grouped by the actual job that is selected under “Require status checks to pass before merging” and use the latest ran to set the check as successful or not.

4 Likes

I’m having the same issue.

I was able to work around it by writing my own action and having it send status checks through the API, then making that status check required - but not the actions themselves. This way the actions always succeed - but there will only ever be one status check that matters (gets overwritten every time title changes, for instance).

It seems like there should be a better way though. Either we should be able to de-clutter the “checks” to hide actions that are duplicated, or won’t fail - or there should be a way of grouping them all under a single “check” in the interface obviating the need for and explicit status check call.

7 Likes

This is a good hack to get around the ‘required to be passing’ issue, but the underlying issue of multiple checks and check clutter is still there. I think the question is why aren’t these being grouped? If one just does on: pull_request, I’m faily sure the open, synchronize, reopen event types are being grouped.

Hi Chris, 

We are also experiencing a similar problem and it seems like this could be a solution to us, but I am not quiet sure how you implemented it, would you explain?

How does you action look like and how does your workflow uses it?

Thanks :slight_smile:

I am also seeing a similar problem… Has anyone been able to find out if this is intended behavior or discovered a work around?

I have managed to implement something that works for me (I suspect it is similar to what @christopherscott mentioned in his post).

I have removed all failures from my action, and added review status checks to dictate whether or not the action has been a success.

For example:

if (hasPassed) {
  client.pulls.createReview({
    owner: pullRequest.owner,
    repo: pullRequest.repo,
    pull_number: pullRequest.number,
    body: 'Changes Requested',
    event: 'REQUEST_CHANGES'
  });
} else {
  client.pulls.createReview({
    owner: pullRequest.owner,
    repo: pullRequest.repo,
    pull_number: pullRequest.number,
    body: 'Approved',
    event: 'APPROVE'
  });
}

The event options available are:

  • ‘COMMENT’
  • ‘APPROVE’
  • ‘REQUEST_CHANGES’

This then creates a comment on the pull request with either an approval or a request for changes and the action can run and duplicate as many times as it needs:

Screenshot 2020-01-06 at 23.06.40.png

I hope this is useful and helps.

Sam

I’m seeing the same behavior.  My workflow is triggered by

on:
  pull_request:
    types: [opened, synchronize, reopened, edited]

 and validates the PR title and body.  If the workflow fails initially (which in turn creates a failed Check in the UI), I update the title and/or body to fix the issue, but a new check gets created every time I edit the PR and the original failed workflow/check is not removed or updated. 

Any fixes for this one? I am having the same issue with using “pull_request” where we get many duplicate checks.

Created a new github action that uses the approve flow to fix this!

https://github.com/cschubiner/action-pr-title

Usage

name: PR Title

on:
  pull_request:
    types: [review_requested, edited, opened, assigned]

jobs:
  pr_title:
    runs-on: ubuntu-latest
    steps:
    - uses: cschubiner/action-pr-title@master
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        allowed_prefixes: 'BREAKING CHANGE:,chore:,docs:,feat:,fix:,perf:,refactor:,style:,test:'
        prefix_case_sensitive: true
        min_length: 7 # Min length of the title
        max_length: 200 # Max length of the title

Is this expected behaviour when specifying multiple types?

Seems a strange approach if it is the expected behaviour.

Or is it logged anywhere as an issue?

I’m hitting this same issue. Here’s my workflow:

name: Lint front matter
on:
  pull_request:
    types: [opened, synchronize, reopened, labeled, unlabeled]
    paths:
      - '**.md'

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Setup node
        uses: actions/setup-node@v1
        with:
          node-version: '12.x'

      - name: Cache node_modules
        uses: actions/cache@v1
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install
        run: npm ci

      - name: Git diff
        id: git_diff
        uses: futuratrepadeira/changed-files@v3.0.1
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Lint yaml front matter
        id: lint_front_matter
        uses: ./.github/actions/lint-front-matter
        with:
          added: ${{ steps.git_diff.outputs.files_created }}
          modified: ${{ steps.git_diff.outputs.files_updated }}
        # Only run the linter if the previous step indicated that files were
        # added or modified in the pull request.
        if: steps.git_diff.outputs.files_created || steps.git_diff.outputs.files_updated

      - name: Find comment
        id: find_comment
        uses: ./.github/actions/find-comment
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
        if: always() && steps.lint_front_matter.outputs.message

      - name: Create or update comment
        uses: peter-evans/create-or-update-comment@v1.1.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ github.event.number }}
          comment-id: ${{ steps.find_comment.outputs.comment-id }}
          body: |
            ${{ steps.lint_front_matter.outputs.message }}
          edit-mode: replace
        if: always() && steps.lint_front_matter.outputs.message

What this does is lint the yaml frontmatter of any changed markdown files, then it posts a comment saying whether it passed or failed. If it failed, a developer can add a label to the pull request which will rerun the workflow and tell it to skip the previously failing tests.

Adding the labeled and unlabeled types seemed to cause the problem. It seems like perhaps opened/synchronize/reopened are considered one kind of check, and labeled/unlabled are treated as a separate check.

**EDIT**

I just tried removing the types array and relying on the default behavior of pull_request. According to the docs, this should run the workflow on opened, synchronize, and reopened. What I found was if you close and reopen the pull request it will create a duplicate check. However, if you push a new commit (synchronize) it will clear all status checks and only show one check. This seems like a bug?

Had this problem too when using the edited trigger. I’ve implemented a workaround for now in my linter v.1.1.0

Basically for now:

* When the check fails, the bot requests changes and comments with the failure message

* If the check succeeds in the future, the bot will dismiss its review (intentionally don’t ‘approve’ to allow for code review workflows)

Would be nice if there were a good way to do this as OP mentions though.

I spoke with GitHub support and it looks like they’ve since fixed this issue. I was able to confirm today that it’s no longer producing duplicate checks for me.

This still seems to be an issue, a duplicate step that always fails. 

https://github.com/square/workflow/pull/1136/checks?check_run_id=650433831

I experience duplicate checks on unlabeled event when more then one label is added/removed. This prevents me to use labeling to manage some further pipelines.

I published “skip-duplicate-actions” to solve this problem: https://github.com/marketplace/actions/skip-duplicate-actions
You could give it a try if this is still an issue.