Skip to content

Add a note for copilot-setup-steps.yml and using with a merge queue #43246

Open

Description

@jonstacks

Code of Conduct

What article on docs.github.com is affected?

https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment#customizing-copilots-development-environment-with-copilot-setup-steps

What part(s) of the article would you like to see updated?

Somewhat related to #42379

In the github docs, it says that you can add the following to you copilot-setup-steps.yml file:

name: "Copilot Setup Steps"

## Background
# Automatically run the setup steps when they are changed to allow for easy validation, and
# allow manual testing through the repository's "Actions" tab
on:
  workflow_dispatch:
  push:
    paths:
      - .github/workflows/copilot-setup-steps.yml
  pull_request:
    paths:
      - .github/workflows/copilot-setup-steps.yml

While this works, I've found that if you use a merge queue then using the above configuration results in your workflow running every time a PR is added to the merge queue. We are use the larger, custom image GitHub hosted runners and this results in unnecessary runs & costs.

github/copilot-sdk was the first public GitHub repo I found that had the same issue(although this one is just using default ubuntu-latest runners). It helped me figure out that behavior wasn't unique to our setup

Proposed Content Update

I'd like to update the docs to either add an inline comment with commented out code or add a little inline note about if using a merge queue. This is what ended up working for us:

name: "Copilot Setup Steps"

# Automatically run when changed so setup issues surface immediately.
# Also allows manual testing via the "Actions" tab.
on:
  workflow_dispatch:
  push:
    branches-ignore:
      - 'gh-readonly-queue/**'
    paths:
      - .github/workflows/copilot-setup-steps.yml
  pull_request:
    branches:
      - main
    paths:
      - .github/workflows/copilot-setup-steps.yml

Additional information

No response

Activity

  1. added
    contentThis issue or pull request belongs to the Docs Content team
    on Mar 6, 2026
  2. added
    triageDo not begin working on this issue until triaged by the team
    on Mar 6, 2026
  3. jameswillard515-gif commented on Mar 6, 2026

    @jameswillard515-gif
  4. Destop-Trang1801 commented on Mar 7, 2026

    @Destop-Trang1801
  5. added
    github_actionsPull requests that update GitHub Actions content
    and removed
    triageDo not begin working on this issue until triaged by the team
    on Mar 10, 2026
  6. Sharra-writes commented on Mar 10, 2026

    @Sharra-writes
    Contributor

    @jonstacks I'll take this to the Actions team and see what they think.

  7. jonstacks commented on Mar 20, 2026

    @jonstacks
    Author

    Thank you, @Sharra-writes! I appreciate it.

  8. github-actions commented on Apr 20, 2026

    @github-actions
    Contributor

    A stale label has been added to this issue, because it has been open for 30 days with no activity. If you think this issue should remain open, please add a new comment.

  9. added
    InactiveWill be closed automatically by a stall check if no activity is detected.
    on Apr 20, 2026
  10. removed
    InactiveWill be closed automatically by a stall check if no activity is detected.
    on Apr 22, 2026
  11. github-actions commented on Aug 24, 2026

    @github-actions
    Contributor

    A stale label has been added to this issue, because it has been open for 30 days with no activity. If you think this issue should remain open, please add a new comment.

  12. added
    InactiveWill be closed automatically by a stall check if no activity is detected.
    on Aug 24, 2026
  13. added and removed
    InactiveWill be closed automatically by a stall check if no activity is detected.
    on Aug 24, 2026
  14. subatoi commented on Sep 9, 2026

    @subatoi
    Contributor

    @jonstacks Hi, thanks for raising an issue and a PR, and I'm sorry for the late reply here.

    Based on your PR, I understand the recommended change you've made would've been useful for your specific use case. If I understand correctly, though, this recommendation wouldn't necessarily exclusively apply to that context, it's just that it would've been useful as you were reviewing that article(?)

    I'm wondering if a simpler solution here would've helped, such as some more obvious signposting to https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue?

  15. subatoi commented on Oct 12, 2026

    @subatoi
    Contributor

    @jonstacks 👋 Hi, just to follow up if you've seen the above? Thank you

  16. jonstacks commented on Oct 15, 2026

    @jonstacks
    Author

    Hi @subatoi, thank you for following up and sorry for the delay on my end! Since it's been several months since I originally opened this, I used AI to help re-investigate the exact mechanics, pull workflow logs, and help write up this response.

    I found concrete evidence from GitHub's own public repositories showing that this isn't just an isolated user setup quirk—it is a direct consequence of the starter template YAML provided in the docs.


    The Root Cause

    In the Customize Copilot's environment article, the recommended starter YAML is:

    on:
      workflow_dispatch:
      push:
        paths:
          - .github/workflows/copilot-setup-steps.yml
      pull_request:
        paths:
          - .github/workflows/copilot-setup-steps.yml

    The accompanying doc comment says:

    # Automatically run the setup steps when they are changed to allow for easy validation

    However, because push: does not specify a branches: filter, it defaults to listening on all branches and all Git tags. This causes two unexpected bypass behaviors:

    1. Every Merge Queue entry triggers the workflow:
      When a PR enters a merge queue, GitHub pushes a temporary merge commit to refs/heads/gh-readonly-queue/{base_branch}/{pr_id}. Because the push trigger has no branch restriction, GitHub Actions evaluates the push event on the newly created queue branch. On new branch pushes with synthetic merge commits, path filtering does not prevent execution, causing copilot-setup-steps.yml to trigger on every queued PR regardless of which files were modified.
    2. Every Git tag push triggers the workflow:
      According to the GitHub Actions workflow syntax documentation:

      "Path filters are not evaluated for pushes of tags."
      Because path filters are skipped for tags, pushing any Git tag triggers copilot-setup-steps.yml unconditionally.


    Concrete Examples in GitHub's own copilot-sdk repository

    The github/copilot-sdk repository uses this exact template in .github/workflows/copilot-setup-steps.yml, and we can observe both failure modes in production:

    1. The Merge Queue Bypass

    Look at commit 38603f28cb6e892857c9f64209360447fcc1ee8b (which merged PR #784):

    • PR Update verifying-your-email-address.md #784 modified only 1 file: docs/getting-started.md. It did not touch copilot-setup-steps.yml.
    • When added to the merge queue, github-merge-queue[bot] pushed branch gh-readonly-queue/main/pr-784-d71ef4c6e3c76218b098005b72f69dabd7fbdf1b, which immediately triggered Run 23060638347 of Copilot Setup Steps.
    • Interestingly, once merged into main, GitHub Actions evaluated docs/getting-started.md against main and correctly skipped Copilot Setup Steps. But it ran while in the queue.
    • The exact same queue execution happened on PR #781 (.devcontainer only, Run 23060791638) and PR #783 (dotnet/ only, Run 23060689124).

    2. The Tag Bypass

    Look at commit ffd25c775742f73e13a492093be0287d7885123f:

    • The commit only touched nodejs/package.json and nodejs/src/cliVersion.ts.
    • Yet Copilot Setup Steps ran on Run 38629654860.
    • Checking the job logs (Job 116077712747), the checkout ref was:
      [command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +refs/tags/go/v1.0.22:refs/tags/go/v1.0.22
      * [new tag]         go/v1.0.22 -> go/v1.0.22
      
      Because the release bot pushed the tag refs/tags/go/v1.0.22, it bypassed the paths filter as per the Actions specification.

    Why signposting to managing-a-merge-queue doesn't resolve this

    1. User Journey & Expectations: Developers setting up Copilot Agent follow the Copilot documentation and copy the starter YAML. The comment in the snippet tells them it will only run when the setup steps change. They have no reason to suspect this validation workflow will fire on merge queues or release tags, and wouldn't think to look at merge queue documentation.
    2. Content Gap: The managing-a-merge-queue documentation explains how to configure CI checks to run for merge groups (merge_group:). It does not provide guidance on how to prevent validation/utility workflows from unintentionally running on gh-readonly-queue/**.
    3. Cost Impact: Because copilot-setup-steps.yml frequently uses larger GitHub-hosted runners or self-hosted runners to install heavy dependencies, running on every queue entry and tag push wastes significant compute and runner minutes.

    Proposed Solutions

    Option A (Recommended): Update the starter snippet in the article directly
    Add branches: targeting the default branch to both triggers:

    name: "Copilot Setup Steps"
    
    on:
      workflow_dispatch:
      push:
        branches:
          - main
        paths:
          - .github/workflows/copilot-setup-steps.yml
      pull_request:
        branches:
          - main
        paths:
          - .github/workflows/copilot-setup-steps.yml

    Why this works: Restricting to branches: [main] cleanly eliminates both problems in one shot—it ignores Git tag pushes (closing the tag bypass) and ignores temporary gh-readonly-queue/** branches, while still validating changes on PRs targeting main and pushes to main.

    Option B: Include an inline callout/note
    If the snippet remains open-ended, include a note directly in this section explaining that without branch restrictions, push.paths triggers on merge queue branches (gh-readonly-queue/**) and tag pushes, and recommend adding branches: [YOUR-DEFAULT-BRANCH] or branches-ignore: ['gh-readonly-queue/**'].

    Would the team be open to updating the snippet directly (Option A) or incorporating the callout note (Option B as drafted in #43247)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Waiting on contributorcontentThis issue or pull request belongs to the Docs Content teamgithub_actionsPull requests that update GitHub Actions contentnever-staleDo not close as stale

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions