Skip to content

Comments

Add unassign-first option to assign-to-user safe output#16542

Merged
pelikhan merged 4 commits intomainfrom
copilot/fix-assign-unassign-issues
Feb 18, 2026
Merged

Add unassign-first option to assign-to-user safe output#16542
pelikhan merged 4 commits intomainfrom
copilot/fix-assign-unassign-issues

Conversation

Copy link
Contributor

Copilot AI commented Feb 18, 2026

GitHub's issues.addAssignees API is additive - it doesn't replace existing assignees. Reassigning issues requires explicit unassignment first, but users were reporting that assign-to-user operations appeared successful yet had no effect when assignees already existed.

Changes

  • Configuration: Added unassign-first boolean field to assign-to-user safe output config
  • Handler logic: When enabled, fetches current assignees via issues.get() and removes them via removeAssignees() before calling addAssignees()
  • Schema: Updated JSON schema validation to accept the new field (default: false)
  • Tests: Added unit tests covering unassign-first enabled/disabled, with/without existing assignees

Usage

safe-outputs:
  assign-to-user:
    unassign-first: true  # Removes current assignees before assigning
    max: 5

Backward compatible - existing workflows continue unchanged with default false behavior.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw -nolocalimports -importcfg git conf�� user.name Test User (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw /tmp/go-build139rev-parse x_amd64/compile git rev-�� --show-toplevel x_amd64/compile /usr/bin/git 3972128/b001/exeiptables --conditions ache/go/1.25.0/x-t git (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw /tmp/go-build139rev-parse k/gh-aw/gh-aw/ac--show-toplevel git rev-�� gh-aw/actions/setup/sh/sanitize_path.sh' '/usr/bin:/usr/local/bin' && echo "$PATH" /opt/hostedtoolcTest User /usr/bin/git test-DKA2zw/compiptables --conditions ndor/bin/git git (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha 0tF5/xM7--4q6idt8vjQJ0tF5 sh /opt/pipx_bin/sh om/user/repo.gitgit 64/pkg/tool/linurev-parse 64/pkg/tool/linu--show-toplevel sh 8672�� git status --porcelain --ignore-submodules | head -n 10 867259/b371/_testmain.go ache/go/1.25.0/x64/pkg/tool/linux_amd64/link ep .cfg modules/@npmcli/--show-toplevel ache/go/1.25.0/x64/pkg/tool/linux_amd64/link (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v2
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v2 --jq .object.sha --show-toplevel 64/pkg/tool/linuowner=github /usr/bin/git 85/001/test-frongit --conditions bin/sh git rev-�� --show-toplevel /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linurev-parse /usr/bin/git 5140-16884/test-infocmp -importcfg cfg git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v2 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git node --conditions tartedAt,updated/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git rev-�� port PATH="$(finremote.origin.url go r: $owner, name: $name) { hasDiscussionsEnabled } } k && vitest run infocmp bash cfg git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/11bd71901bbe5b1630ceea73d27597364c9af683
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/11bd71901bbe5b1630ceea73d27597364c9af683 --jq .object.sha --show-toplevel 64/pkg/tool/linuowner=github /usr/bin/git 85/001/test-compinfocmp --conditions 64/pkg/tool/linuxterm-color git rev-�� nner/work/gh-aw/gh-aw/actions/setup/sh/sanitize_path.sh' '/usr/bin:/usr/local/bin:::' && echo "$/usr/bin/gh 64/pkg/tool/linux_amd64/vet x_amd64/compile /tmp/go-handler-infocmp bash cfg x_amd64/compile (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha node ser:token@github.com/repo.git.ur-c=4 k/node_modules/.bin/node --experimental-igit --require /home/REDACTED/wor--show-toplevel /opt/hostedtoolcache/node/24.13.Test User ache�� 5140-16884/test-3578867552/.github/workflows --conditions /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/git --experimental-igit --require /home/REDACTED/wor--show-toplevel git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha ings.cjs forks.js /usr/local/sbin/bash hacked --check x_amd64/vet bash --no�� --noprofile x_amd64/vet 0/x64/bin/node vil.com 64/pkg/tool/linurev-parse 64/pkg/tool/linu--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha vaScript2481029385/001/test-complex-frontmatter-with-tools.md forks.js Name,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle hacked grep x_amd64/vet ache/go/1.25.0/x64/pkg/tool/linux_amd64/link t-ha�� ring3323831704/001/test1.md x_amd64/vet 867259/b404/importcfg.link vil.com 64/pkg/tool/linurev-parse 64/pkg/tool/linu--show-toplevel -JPGyIl2vB7_F/G9sEDD2pLhLMDAgEAiXu/X6R5OoPF4X40d7UERB47/kI2eOA--echo (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha --show-toplevel /tmp/go-build505867259/b401/_testmain.go /usr/bin/git se 4540027/b074/vetrev-parse ules/.bin/go git rev-�� --git-dir ache/go/1.25.0/x-tests /usr/bin/git .go l 0/x64/bin/node git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha test-DKA2zw/complex.go --conditions nfig/composer/vendor/bin/git --experimental-igit --require /home/REDACTED/wor--show-toplevel vo/9kfMsjtzGOFIi51OI_-c/tFE_Q0UwmvwlVjEnf88q show�� / --quiet 64/pkg/tool/linux_amd64/vet assign-to-user\|docker ./pkg/parser/schpull k/node_modules/.test/concurrent-image:v1.0.0 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -v origin 0/x64/bin/node x55To0DC_ .cfg 64/pkg/tool/linu--show-toplevel 0/x64/bin/node -o /tmp/go-build505867259/b386/fileutil.test -importcfg /usr/bin/git -s -w -buildmode=exe git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha image:v1.0.0 test-branch (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/cgo /usr/bin/git node --conditions ptables git rev-�� --show-toplevel go /usr/bin/git /tmp/go-handler-/usr/bin/unpigz tail es/.bin/node git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v7 --jq .object.sha go1.25.0 -c=4 -nolocalimports -importcfg /tmp/go-build2047890279/b001/importcfg -pack /tmp/go-build2047890279/b001/_testmain.go rev-�� ref/tags/v1 git /usr/bin/git --no-file-parall/opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/link --quiet t git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v7 --jq .object.sha --show-toplevel x_amd64/compile /usr/bin/git -bool -buildtags tions/setup/js/n--noprofile git rev-�� --show-toplevel ache/go/1.25.0/x64/pkg/tool/linurev-parse repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } 1906378282/.githgit --quiet tnet/tools/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v7 --jq .object.sha --show-toplevel go /usr/bin/git un8-gFRi_ ode_modules/viteapi cal/bin/sh git rev-�� --show-toplevel rtcfg /usr/bin/git g/cli/fileutil/fgit g/cli/fileutil/f-C ache/go/1.25.0/x/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha featurewhoami .cfg 0/x64/bin/node .js' --ignore-panode om/spf13/cobra@v/home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/tsc�� ache/go/1.25.0/x--noEmit 0/x64/bin/node (http block)
    • Triggering command: `/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha REDACTED main:main modules/@npmcli/run-script/lib/node-gyp-bin/node 0062059/b265/_pkgit ./actions/setup/commit st/suppress-warn-m st/dist/workers/Add unassign-first field to assign-to-user safe output

Co-authored-by: pelikhan-ifaceassert /tsc�� -m Update"; echo hacked 0/x64/bin/node on' --ignore-pat/opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet .json 64/bin/bash 0/x64/bin/node` (http block)

  • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha se 4540027/b007/vet.cfg tions/setup/node_modules/.bin/git 0062059/b334/_pkgit ./actions/setup/commit de/node/bin/grep-m UOpvBl5XgcBk /vit�� --abbrev-ref HEAD 0/x64/bin/node on' --ignore-pat/opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/compile ay-config.schema-o es/.bin/sh 0/x64/bin/node (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/4dc6199c7b1a012772edbd06daecab0f50c9053c
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/4dc6199c7b1a012772edbd06daecab0f50c9053c --jq .object.sha --show-toplevel oJ/BhqTCoRMGewfsowner=github /usr/bin/git k && vitest run /usr/bin/gh bash _.a git rev-�� --show-toplevel git /usr/bin/git celain --ignore-/usr/bin/gh cuD0kDpqDtar ache/go/1.25.0/xgraphql git (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha bot-detection.md forks.js /usr/bin/tail hacked grep run-script/lib/n--show-toplevel tail -80 5140-16884/test-4243039857 x_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v5 --jq .object.sha --show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v5 --jq .object.sha --show-toplevel git /usr/bin/git es grep 64/pkg/tool/linu/home/REDACTED/work/gh-aw/gh-aw/.github/workflows tUgd7KJ/1xSoWkmKrev-parse rev-�� ithub-script/git/ref/tags/v8 64/pkg/tool/linu-trimpath 7597c5feb15238cacdbbe3b6484f194d-d node cfg k/gh-aw/gh-aw/acxterm-color git (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v6 --jq .object.sha Value: ${{ github.actor }} x_amd64/vet /usr/bin/git -unreachable=falgit /tmp/go-build139rev-parse k/gh-aw/node_mod--show-toplevel git rev-�� --show-toplevel k/gh-aw/gh-aw/actions/setup/js/n-dwarf=false /usr/bin/git test-80lOfI/errobash node 0/x64/lib/node_m--noprofile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v6 --jq .object.sha --show-toplevel x_amd64/link /usr/bin/git test-7fYToK/textbash sh tions/setup/js/n--noprofile git rev-�� --show-toplevel L1/BH39Jih_oyS2LvJ_3yZB/SkE-TZwGBfwFK-8npHOd /usr/bin/git --verify --quiet p/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v6 --jq .object.sha --show-toplevel x_amd64/vet $name) { hasDiscussionsEnabled } } test-7fYToK/textbash -tests tions/node_modul--noprofile git rev-�� --show-toplevel git /usr/bin/git 3933223146 --quiet git git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha ings.cjs tmain.go /usr/sbin/bash hacked --check x_amd64/vet bash --no�� --noprofile x_amd64/vet 867259/b334/vet.cfg vil.com 64/pkg/tool/linurev-parse 64/pkg/tool/linu--show-toplevel git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq .object.sha --show-toplevel x_amd64/cgo /usr/bin/git -unreachable=falgit /tmp/go-build139rev-parse k/gh-aw/gh-aw/ac--show-toplevel git rev-�� --show-toplevel k/gh-aw/gh-aw/actions/setup/js/n-dwarf=false /usr/bin/git test-80lOfI/errobash node it git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq .object.sha --show-toplevel 0/x64/bin/node /usr/bin/git hub/workflows sh /usr/local/.ghcu--noprofile git rev-�� --show-toplevel tions/setup/js/node_modules/viteremote.origin.url /usr/bin/git 1500852787 --quiet rgo/bin/git git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq .object.sha --show-toplevel git /usr/bin/git n' && echo "$PATgit x_amd64/vet e/git git rev-�� --show-toplevel e/git /usr/bin/git feature$(whoami)docker om/github/gh-aw /bin/sh git (http block)
  • https://api.github.com/repos/anchore/sbom-action/git/ref/tags/v0
    • Triggering command: /usr/bin/gh gh api /repos/anchore/sbom-action/git/ref/tags/v0 --jq .object.sha --show-toplevel go /usr/bin/git 01/test2.md bash cfg git rev-�� --show-toplevel git /usr/bin/git t.go t_test.go 0/x64/bin/node git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/anchore/sbom-action/git/ref/tags/v0 --jq .object.sha --show-toplevel /opt/hostedtoolcowner=github /usr/bin/git 5140-16884/test-/usr/bin/gh bash sh git rev-�� --show-toplevel rtcfg /usr/bin/git om/aymanbagabas/docker om/aymanbagabas/image ache/go/1.25.0/xinspect git (http block)
  • https://api.github.com/repos/docker/build-push-action/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v6 --jq .object.sha --show-toplevel go /usr/bin/git 4243039857 bash cfg git rev-�� tch git /usr/bin/git ir_test.go st/dist/workers/-C ache/go/1.25.0/x/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v6 --jq .object.sha --show-toplevel /tmp/go-build1646323416/b001/exe/test-cwd /usr/bin/git VAyE7WnBC bash /usr/sbin/git git rev-�� --show-toplevel rtcfg /usr/bin/git dcfg x_amd64/vet util.test git (http block)
  • https://api.github.com/repos/docker/login-action/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/docker/login-action/git/ref/tags/v3 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git 8XRVZoB2f bash ache/go/1.25.0/x/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git rev-�� 40\} tch /usr/bin/git ternal/tools/actgit st/dist/workers/-C 64/pkg/tool/linu/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/login-action/git/ref/tags/v3 --jq .object.sha --show-toplevel /opt/hostedtoolcowner=github e/git 5140-16884/test-git --conditions /home/REDACTED/wor/home/REDACTED/work/gh-aw/gh-aw/.github/workflows e/git rev-�� --show-toplevel git /usr/bin/git _messages.go _messages_test.g-d 64/pkg/tool/linu-c git (http block)
  • https://api.github.com/repos/docker/metadata-action/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/docker/metadata-action/git/ref/tags/v5 --jq .object.sha --show-toplevel sF/788KaSlanoh1Qowner=github /usr/bin/git 5140-16884/test-git ode_modules/vite-C cfg git f]\{�� --show-toplevel git /usr/bin/git celain --ignore-git st/dist/workers/-C 0/x64/bin/node git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/metadata-action/git/ref/tags/v5 --jq .object.sha --show-toplevel /opt/hostedtoolcache/node/24.13.0/x64/bin/node /usr/bin/git 5140-16884/test-/usr/bin/gh --conditions bin/git git rev-�� --show-toplevel git /usr/bin/git feature | cat /e/usr/bin/unpigz x_amd64/vet 0/x64/bin/node git (http block)
  • https://api.github.com/repos/docker/setup-buildx-action/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/docker/setup-buildx-action/git/ref/tags/v3 --jq .object.sha --show-toplevel /tmp/go-build2723554978/b001/exe/complex /usr/bin/git 5140-16884/test-gh bash cfg git rev-�� --show-toplevel e79be59ecd5e303fa00441fe..HEAD /usr/bin/git gn-unassign-issugh st/dist/workers/api ngutil.test git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/setup-buildx-action/git/ref/tags/v3 --jq .object.sha --show-toplevel /opt/hostedtoolcache/go/1.25.0/x/tmp/go-build505867259/b410/_testmain.go /usr/bin/git x_amd64/compile bash cfg git rev-�� --show-toplevel git /usr/bin/git celain --ignore-git x_amd64/vet util.test git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 /tmp/go-build1394540027/b240/vet.cfg bin/go mport-meta-resolgit **/*.cjs ode-gyp-bin/node--show-toplevel k/gh-aw/gh-aw/actions/setup/js/node_modules/vitetypecheck /hom�� ty-test.md sh de_modules/.bin/node .js' --ignore-pagit grep k/gh-aw/node_mod--get git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 /tmp/go-build1394540027/b121/vet-ifaceassert 0/x64/bin/node "prettier" --wrigit grep 64/bin/sh 0/x64/bin/node /hom�� test-7fYToK/text-output.go sh ache/node/24.13.0/x64/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/git ve grep tions/setup/js/nadd tions/setup/js/norigin (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 -buildtags 0/x64/bin/node -errorsas -ifaceassert -nilfunc 0/x64/bin/node /hom�� test-7fYToK/text-output.go -tests bin/git ve grep tions/setup/js/nuser.name tions/setup/js/nTest User (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 TOKEN"; }; f get ache/go/1.25.0/x64/pkg/tool/linu-nilfunc mport-meta-resolgit **/*.cjs k/gh-aw/gh-aw/acuser.email ache/go/1.25.0/xtest@example.com /hom�� hub/workflows/test.md hub/workflows/test.lock.yml attributes "prettier" --wrigit grep modules/.bin/nod--git-dir git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 /tmp/go-build139main ache/go/1.25.0/x-lang=go1.25 mport-meta-resolgit **/*.cjs k/gh-aw/gh-aw/ac--show-toplevel k/gh-aw/gh-aw/ac-dwarf=false /hom�� test-7fYToK/textgo1.25.0 sh ules/.bin/node .js' --ignore-pagit 546644a44721820arev-parse it-cloneAfskOk/n--show-toplevel git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 /tmp/go-build1394540027/b245/vet.cfg ache/go/1.25.0/x64/pkg/tool/linux_amd64/compile mport-meta-resolgit **/*.cjs k/gh-aw/gh-aw/actions/setup/js/n/tmp/gh-aw-test-runs/20260218-075140-16884/test-107266980/.github/workflows ache/go/1.25.0/x64/pkg/tool/linuconfig /hom�� ../../../.prettinode ache/go/1.25.0/x--conditions bin/node .js' --ignore-pagit grep it-cloneAfskOk/n--show-toplevel git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 /tmp/go-build139-w ache/go/1.25.0/x-buildmode=exe mport-meta-resolgit **/*.cjs k/gh-aw/gh-aw/acuser.name ache/go/1.25.0/xTest User /hom�� ../../../.prettinode ache/go/1.25.0/x--conditions ode .js' --ignore-pagit grep ode_modules/.bin/home/REDACTED/wor--show-toplevel git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path feature rm -rf /--experimental-import-meta-resolve .cfg x_amd64/compile h ../../../.pretnode ./actions/setup//home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/tsc�� ode_modules/vite--noEmit x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 grep ode_modules/vite-bool ode_modules/vite-buildtags rev-�� --abbrev-ref HEAD odules/npm/node_-nilfunc th .prettierignogit s-config.schema.rev-parse ndor/bin/bash ache/go/1.25.0/x-tests (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 -ifaceassert -nilfunc x_amd64/compile -ato�� test-UVkocv/test.go .com/repo.git.url ules/.bin/sh -errorsas -ifaceassert -nilfunc ache/node/24.13.Test User (http block)
  • https://api.github.com/repos/github/gh-aw/contents/.github%2Fworkflows%2Faudit-workflows.md
    • Triggering command: /opt/hostedtoolcache/node/24.13.0/x64/bin/node /opt/hostedtoolcache/node/24.13.0/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vitest/dist/workers/forks.js erignore -lang=go1.24 iptables -w */*.ts' '**/*.json' --ignore-path ../../../.pret.prettierignore chemas/mcp-tools.json 0/x64/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/sh OUTPUT -d (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/c4e091835c7a94dc7d3acb8ed3ae145afb4995f3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/c4e091835c7a94dc7d3acb8ed3ae145afb4995f3 --jq .object.sha --show-toplevel ache/node/24.13.0/x64/bin/node /usr/bin/git 107266980/.githubash -tests e_modules/.bin/g--noprofile git rev-�� create_pull_request" k/gh-aw/gh-aw/actions/setup/js/nrev-parse /usr/bin/git tc/passwd --quiet x_amd64/link git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha -bool .com/repo.git.url ules/.bin/node mport-meta-resolgit -ifaceassert k/gh-aw/gh-aw/actions/setup/js/n/home/REDACTED/work/gh-aw/gh-aw/.github/workflows ache/node/24.13.0/x64/bin/node 0/x6�� 3578867552/.github/workflows -tests /home/REDACTED/work/gh-aw/node_modules/.bin/git mport-meta-resolgit grep k/gh-aw/gh-aw/ac--git-dir k/gh-aw/gh-aw/actions/setup/js/n-trimpath (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/-
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/- --jq .object.sha --show-toplevel a00441fe..HEAD /usr/bin/git es forks.js 64/pkg/tool/linu/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git rev-�� --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git node --conditions tartedAt,updated/home/REDACTED/work/gh-aw/gh-aw/.github/workflows git (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha test-UVkocv/test.go .com/repo.git.url ode -errorsas -ifaceassert -nilfunc ache/node/24.13.test@example.com 0/x6�� HEAD -tests k/gh-aw/gh-aw/actions/setup/node-nolocalimports mport-meta-resolgit grep k/gh-aw/gh-aw/ac--show-toplevel k/gh-aw/gh-aw/actions/setup/js/n/tmp/go-build505867259/b404/_testmain.go (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion "prettier" --wrigit pkg/workflow/engrev-parse k/_temp/ghcca-no--show-toplevel RaLwacw/9A3hOJJAdQTrqtkOD-DA --co�� node --conditions de/node/bin/git --experimental-igit --require /home/REDACTED/wor--show-toplevel git (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo de/node/bin/git h ../../../.pretnode to_created_issue/home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/vit�� ode_modules/viterun ode_modules/vite--no-file-parallelism (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo ndor/bin/git h ../../../.pretnode ./actions/setup//home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/vit�� cal/bin/git ache/go/1.25.0/x--no-file-parallelism (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: `/tmp/go-build505867259/b368/cli.test /tmp/go-build505867259/b368/cli.test -test.testlogfile=/tmp/go-build505867259/b368/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true mport-meta-resolsh om/charmbracelet-c ode_modules/vitetsc --noEmit ode_modules/vitest/dist/workers/--conditions tion�� 4540027/b076/pkg.a main:main ache/go/1.25.0/x64/pkg/tool/linu/home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vite-bool 0062059/b307/_pkgit ./actions/setup/commit son ache/go/1.25.0/xAdd unassign-first field to assign-to-user safe output

Co-authored-by: pelikhan-ifaceassert` (http block)

  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name feature rm -rf / .cfg 0/x64/bin/node h ../../../.pretnode ./actions/setup//home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/tsc�� ode_modules/vite--noEmit ode_modules/vitest/dist/workers/forks.js (http block)
  • https://api.github.com/user
    • Triggering command: /usr/bin/gh gh api user --jq .login er w_recompile_need-nolocalimports 64/bin/grep er sion.cjs (http block)
    • Triggering command: /usr/bin/gh gh api user --jq .login w/js/**/*.json' --ignore-path group.test.cjs ep er ked_domains.cjs ndor/bin/grep grep -l unassign_from_user js/assign_milestone.cjs ode_modules/.bin/node er ent_core.cjs 64/bin/grep ns-lock.json does not exist yet"; \ fi (http block)
    • Triggering command: /usr/bin/gh gh api user --jq .login er t.cjs /opt/pipx_bin/grep er s 64/bin/grep grep -l unassign_from_user js/handle_agent_failure.test.cjs odules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/sh er and_edit_comment--norc ache/go/1.25.0/x--noprofile grep (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>assign-to-user / unassign-from-user safe outputs are ignored</issue_title>
<issue_description>Steps to reproduce

  1. Implement safe outputs that re-assign a user (assign to user A, un-assign to existing asignee) based on the formal docs
  2. Run a trial in a case where assignment is needed (e.g. have a rule - if alice is assigned assign bob and unassign alice, else do the opposite etc)
  3. Workflow run successfully and reports success on these actions, no errors.
  4. The action is not performed

Version:

gh aw version v0.45.0</issue_description>

Comments on the Issue (you are @copilot in this section)

@pelikhan do you have a run URL we can look at? @pelikhan /scout research the source of these safe outputs @pelikhan Add field assign-to-user.unassign-first: true which unassigns the user before re-assigning.

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits February 18, 2026 07:51
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix issue with safe outputs for user assignment Add unassign-first option to assign-to-user safe output Feb 18, 2026
Copilot AI requested a review from pelikhan February 18, 2026 08:06
@pelikhan pelikhan marked this pull request as ready for review February 18, 2026 12:17
Copilot AI review requested due to automatic review settings February 18, 2026 12:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an unassign-first boolean configuration option to the assign-to-user safe output to address the issue where GitHub's addAssignees API is additive rather than replacing existing assignees. When enabled, the handler fetches current assignees via issues.get() and removes them via removeAssignees() before calling addAssignees().

Changes:

  • Added unassign-first boolean field to AssignToUserConfig struct (default: false)
  • Updated handler logic to fetch and remove current assignees when the option is enabled
  • Added JSON schema validation and comprehensive test coverage
  • Updated documentation to describe the new feature

Reviewed changes

Copilot reviewed 43 out of 43 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pkg/workflow/assign_to_user.go Added UnassignFirst boolean field to the configuration struct
pkg/workflow/compiler_safe_outputs_config.go Added config builder call to include unassign_first in handler config when true
actions/setup/js/assign_to_user.cjs Implemented unassign logic: fetch current assignees and remove them before assigning new ones
actions/setup/js/assign_to_user.test.cjs Added unit tests for unassign-first enabled/disabled scenarios
pkg/workflow/compiler_safe_outputs_config_test.go Added test to verify unassign_first is correctly serialized in handler config
pkg/parser/schemas/main_workflow_schema.json Added schema validation for the new unassign-first boolean field
docs/src/content/docs/reference/safe-outputs.md Documented the new configuration option with usage example
docs/src/content/docs/reference/safe-outputs-specification.md Added specification details for the unassign-first feature
pkg/cli/workflows/test-assign-unassign-first.md Added test workflow to validate the feature
.changeset/patch-assign-to-user-unassign-first.md Added changeset entry describing the patch
Multiple .lock.yml files Regenerated lock files (includes unrelated updates to add_comment/hide_comment descriptions)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +349 to +485
it("should unassign current assignees when unassign_first is true", async () => {
vi.clearAllMocks(); // Clear all mocks before this test

const { main } = require("./assign_to_user.cjs");
const handler = await main({
max: 10,
unassign_first: true,
});

// Mock getting current assignees
mockGithub.rest.issues.get = vi.fn().mockResolvedValue({
data: {
assignees: [{ login: "old-user1" }, { login: "old-user2" }],
},
});

mockGithub.rest.issues.removeAssignees = vi.fn().mockResolvedValue({});
mockGithub.rest.issues.addAssignees = vi.fn().mockResolvedValue({}); // Recreate the mock

const message = {
type: "assign_to_user",
assignees: ["new-user1"],
};

const result = await handler(message, {});

expect(result.success).toBe(true);
expect(result.assigneesAdded).toEqual(["new-user1"]);

// Verify that get was called to fetch current assignees
expect(mockGithub.rest.issues.get).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
issue_number: 123,
});

// Verify that removeAssignees was called with current assignees
expect(mockGithub.rest.issues.removeAssignees).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
issue_number: 123,
assignees: ["old-user1", "old-user2"],
});

// Verify that addAssignees was called with new assignees
expect(mockGithub.rest.issues.addAssignees).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
issue_number: 123,
assignees: ["new-user1"],
});
});

it("should skip unassignment when there are no current assignees", async () => {
vi.clearAllMocks(); // Clear all mocks before this test

const { main } = require("./assign_to_user.cjs");
const handler = await main({
max: 10,
unassign_first: true,
});

// Mock getting no current assignees
mockGithub.rest.issues.get = vi.fn().mockResolvedValue({
data: {
assignees: [],
},
});

mockGithub.rest.issues.removeAssignees = vi.fn().mockResolvedValue({});
mockGithub.rest.issues.addAssignees = vi.fn().mockResolvedValue({}); // Recreate the mock

const message = {
type: "assign_to_user",
assignees: ["new-user1"],
};

const result = await handler(message, {});

expect(result.success).toBe(true);
expect(result.assigneesAdded).toEqual(["new-user1"]);

// Verify that get was called
expect(mockGithub.rest.issues.get).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
issue_number: 123,
});

// Verify that removeAssignees was NOT called since there are no current assignees
expect(mockGithub.rest.issues.removeAssignees).not.toHaveBeenCalled();

// Verify that addAssignees was still called
expect(mockGithub.rest.issues.addAssignees).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
issue_number: 123,
assignees: ["new-user1"],
});
});

it("should not unassign when unassign_first is false (default)", async () => {
vi.clearAllMocks(); // Clear all mocks before this test

const { main } = require("./assign_to_user.cjs");
const handler = await main({
max: 10,
unassign_first: false, // explicitly false
});

mockGithub.rest.issues.get = vi.fn().mockResolvedValue({});
mockGithub.rest.issues.removeAssignees = vi.fn().mockResolvedValue({});
mockGithub.rest.issues.addAssignees = vi.fn().mockResolvedValue({}); // Recreate the mock

const message = {
type: "assign_to_user",
assignees: ["new-user1"],
};

const result = await handler(message, {});

expect(result.success).toBe(true);

// Verify that get was NOT called
expect(mockGithub.rest.issues.get).not.toHaveBeenCalled();

// Verify that removeAssignees was NOT called
expect(mockGithub.rest.issues.removeAssignees).not.toHaveBeenCalled();

// Verify that addAssignees was called directly
expect(mockGithub.rest.issues.addAssignees).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
issue_number: 123,
assignees: ["new-user1"],
});
});
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test coverage for error scenarios when unassign_first is enabled. Consider adding tests for the following cases:

  1. When issues.get() fails while fetching current assignees
  2. When removeAssignees() fails during the unassignment operation

These error scenarios should be caught by the existing try-catch block, but explicit test coverage would ensure the error handling works as expected and would make the code more robust. The current tests only cover the happy path (successful unassignment) and the case where there are no assignees to remove.

Copilot uses AI. Check for mistakes.
@pelikhan pelikhan merged commit 66682b9 into main Feb 18, 2026
130 checks passed
@pelikhan pelikhan deleted the copilot/fix-assign-unassign-issues branch February 18, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

assign-to-user / unassign-from-user safe outputs are ignored

2 participants