Skip to content

Duplicate GitHub Actions runs when updating stacked PRs after base branch changes #966

@cerrorism

Description

@cerrorism

Description

When using git-spice to manage stacked PRs, GitHub Actions workflows with pull_request triggers are being kicked off twice for each PR in the stack after running gs upstack restack and gs stack submit. This occurs when the base branch (e.g., main) has changed while working on the stack.

Test Repository

I've created a public test repository to demonstrate this issue:
https://github.com/cerrorism/test-git-spice

You can examine the PRs, workflow runs, and event payloads directly.

Environment

  • Tool: git-spice
  • Repository: GitHub
  • Workflow trigger: pull_request (types: opened, synchronize, reopened)

Reproduction Steps

I can consistently reproduce this issue with the following steps:

  1. Create a stack with two branches (stack-base-1 and stack-base-2)
  2. Submit both branches as PRs to GitHub:
  3. Update the main branch directly on GitHub (simulating another team member merging a PR)
  4. Make changes to files in the mid-stack branch
  5. Run gs upstack restack
  6. Run gs stack submit

Result: Both PRs trigger two separate GitHub Actions workflow runs each.

Concrete Evidence

Workflow Configuration

The test repository uses a simple workflow (.github/workflows/test.yaml.yml) that logs event details:

name: Automatic Test Execution
on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Mock a test
        run: |
          echo "GitHub Event Name: ${{ github.event_name }}"
          echo "Before SHA: ${{ github.event.before.sha }}"
          echo "After SHA: ${{ github.event.after.sha }}"
          echo "Base SHA: ${{ github.event.pull_request.base.sha }}}"

Duplicate Runs

After running gs upstack restack and gs stack submit (following main branch changes), both PRs triggered duplicate workflow runs at the exact same timestamp:

PR #1 Duplicate Runs (created at 2025-12-05T18:34:37-38Z):

PR #2 Duplicate Runs (created at 2025-12-05T18:35:29Z):

Note that each pair of runs was created at the exact same second, confirming they were triggered by separate, nearly-simultaneous events.

Analysis

Findings

By examining the workflow logs in the test repository, I confirmed that the two events are not identical. Both events have:

  • Same before SHA
  • Same after SHA
  • Same event name: pull_request
  • Same action type: synchronize

However, the pull_request.base.sha values are different between the two events.

This suggests that git-spice is performing two separate operations that each trigger a pull_request synchronize event:

  1. Updating the PR's feature branch (head)
  2. Updating the PR's base reference

Impact

This duplicate triggering causes several issues:

1. Resource Waste

  • Unnecessary compute resources consumed by duplicate pipeline runs
  • Can be partially mitigated by adding a concurrency group to cancel redundant runs

2. Branch Protection Rule Issues (Critical)

The more serious problem occurs with concurrency groups and branch protection rules:

  • When two events are sent simultaneously, GitHub cannot guarantee which run gets cancelled
  • Sometimes the first (top) run gets cancelled instead of the second
  • If branch protection rules require specific checks to pass (e.g., "XXX check must be passed before merge"), a cancelled top run means the PR becomes stuck
  • The PR will wait indefinitely for a successful check that will never complete

Expected Behavior

When updating stacked PRs after base branch changes, each PR should trigger only one pull_request synchronize event, not two.

This should be achievable because when performing the equivalent steps manually, no duplicate pipelines are triggered:

  1. Fetch origin/main
  2. Rebase the PR feature branch locally
  3. Push the feature branch once

With this manual approach:

  • GitHub automatically detects and updates the base relationship
  • Only one pull_request synchronize event is triggered

Additional Context

The test repository at https://github.com/cerrorism/test-git-spice is public and was created specifically to reproduce this issue. You can:

  • View the workflow file
  • Examine the Actions tab to see all duplicate runs
  • Check the specific workflow run logs linked above to see the event data differences
  • Review the commit history showing the main branch changes

I've tested this multiple times and the behavior is consistently reproducible. Happy to provide additional logs, run more tests, or provide any other debugging information if needed.

Thank you for looking into this!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions