Skip to content

feat(ci): auto-convert external PRs to draft mode#8896

Merged
jdx merged 5 commits intomainfrom
feat/auto-draft-pr
Apr 4, 2026
Merged

feat(ci): auto-convert external PRs to draft mode#8896
jdx merged 5 commits intomainfrom
feat/auto-draft-pr

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 4, 2026

Summary

  • Adds a GHA workflow that auto-converts PRs from external contributors to draft mode
  • Leaves a comment telling the author to mark it ready when they want human review
  • Skips PRs from jdx and renovate[bot]

Test plan

  • Open a test PR from a non-owner account and verify it gets converted to draft with the comment

🤖 Generated with Claude Code


Note

Medium Risk
Uses pull_request_target plus a write-scoped token to modify and comment on incoming PRs, so misconfiguration could create a security/abuse surface. Scope is limited to a single new workflow and guarded by author/draft checks.

Overview
Adds a new GitHub Actions workflow (auto-draft-pr.yml) that triggers when a PR is opened and automatically converts it to draft for non-org contributors (excluding renovate[bot] and already-draft PRs).

The workflow uses the GitHub CLI to run gh pr ready --undo and posts a comment instructing the author to mark the PR Ready for review when they want human review, using MISE_PR_COMMENT_TOKEN with pull-requests: write permission.

Reviewed by Cursor Bugbot for commit 0f989d1. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds a workflow that automatically converts PRs from non-owner/non-renovate
authors to draft, with a comment telling them to mark ready when they want review.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jdx jdx force-pushed the feat/auto-draft-pr branch from f12cd67 to b0779a9 Compare April 4, 2026 15:29
mise-en-dev is the release bot that creates release PRs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request removes a test command from registry/carp.toml that was causing issues in non-interactive shells. Feedback highlights a significant discrepancy between the PR description and the actual code changes, suggesting that intended workflow files may have been omitted. Additionally, it is recommended to replace the removed test with a more robust alternative, such as command -v carp or a version check, to maintain validation for the registry entry.

I am having trouble creating individual review comments. Click here to see my feedback.

registry/carp.toml (2)

high

The changes in this pull request do not align with the title and description. The description specifies the addition of a GitHub Actions workflow to auto-convert external PRs to draft mode, but the actual change is the removal of a test command in registry/carp.toml. It appears the intended workflow file might have been omitted from this commit.

registry/carp.toml (2)

medium

Removing the test command reduces the validation of this registry entry. If which carp hangs in non-interactive shells, consider using a more robust alternative like command -v carp or checking the version with carp --version instead of removing the test entirely.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7519bc0. Configure here.

Comment thread .github/workflows/auto-draft-pr.yml Outdated
steps:
- name: Convert to draft and comment
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

GITHUB_TOKEN lacks permission for draft PR conversion

High Severity

The gh pr ready --undo command uses the convertPullRequestToDraft GraphQL mutation, which is not supported by the default GITHUB_TOKEN — even with pull-requests: write. This is a known GitHub CLI limitation (cli/cli#8910). The workflow will fail at runtime. Other workflows in this repo use secrets.MISE_GH_TOKEN (likely a PAT) for elevated operations, which would work here instead.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7519bc0. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 4, 2026

Greptile Summary

This PR adds a new GitHub Actions workflow (.github/workflows/auto-draft-pr.yml) that automatically converts newly opened PRs from external contributors to draft mode and leaves a comment prompting them to mark it ready for review when prepared.

Key design decisions made correctly:

  • Uses pull_request_target (not pull_request) so the workflow runs in the base repo context and can access secrets even for fork PRs, while only operating on PR metadata — not checking out fork code — which keeps the risk minimal.
  • The if condition excludes OWNER, MEMBER, and COLLABORATOR associations, plus renovate[bot], and skips PRs already opened in draft state — covering all the expected bypass cases.
  • Permissions are scoped narrowly to pull-requests: write only.
  • PR number is passed as an env variable (PR_NUMBER) rather than interpolated inline, following shell injection best practices for dynamic values.

Confidence Score: 5/5

Safe to merge — the workflow is narrow in scope, uses minimal permissions, and previous reviewer concerns have been addressed.

The only changed file is a new GitHub Actions workflow. Prior review thread concerns (MEMBER/COLLABORATOR not being excluded, and github.repository inline interpolation) have been resolved in this revision — MEMBER and COLLABORATOR are now explicitly excluded, and PR_NUMBER is passed as an env var. The remaining inline use of ${{ github.repository }} in the run block is a low-risk style point already flagged in a previous thread. No logic, security, or reliability issues remain.

No files require special attention.

Important Files Changed

Filename Overview
.github/workflows/auto-draft-pr.yml New workflow that auto-drafts PRs from non-member/non-collaborator contributors; condition logic correctly excludes OWNER, MEMBER, and COLLABORATOR, skips renovate[bot], and already-draft PRs. Permissions are minimal.

Sequence Diagram

sequenceDiagram
    participant C as External Contributor
    participant GH as GitHub
    participant WF as auto-draft-pr workflow
    participant PR as Pull Request

    C->>GH: Opens a new PR
    GH->>WF: pull_request_target (opened)
    WF->>WF: Check author_association<br/>(skip OWNER/MEMBER/COLLABORATOR)
    WF->>WF: Check login<br/>(skip renovate[bot])
    WF->>WF: Check if already draft<br/>(skip if true)
    WF->>PR: gh pr ready --undo (convert to draft)
    WF->>PR: gh pr comment (instruct author)
    PR-->>C: Notified: PR is in draft, mark ready when prepared
    C->>GH: Clicks "Ready for review"
    GH-->>C: PR enters review queue
Loading

Reviews (3): Last reviewed commit: "chore(ci): use fine-grained MISE_PR_COMM..." | Re-trigger Greptile

Comment thread .github/workflows/auto-draft-pr.yml Outdated
Comment thread .github/workflows/auto-draft-pr.yml
jdx and others added 2 commits April 4, 2026 15:33
GITHUB_TOKEN lacks permission for the convertPullRequestToDraft
GraphQL mutation. Use the PAT instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace explicit username checks with author_association checks for
OWNER, MEMBER, and COLLABORATOR. This covers mise-en-dev (COLLABORATOR)
and any future trusted contributors automatically. Keep explicit
renovate[bot] exclusion since it only gets CONTRIBUTOR association.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jdx
Copy link
Copy Markdown
Owner Author

jdx commented Apr 4, 2026

MISE_GH_TOKEN is too broad for a pull_request_target workflow — if an attacker found a way to exploit this, they'd have access to whatever that token covers. Consider using a dedicated fine-grained PAT scoped to only pull request write access.

This comment was generated by Claude Code.

…TOKEN

MISE_GH_TOKEN is too broad for pull_request_target workflows.
Use a dedicated fine-grained PAT scoped to only PR write access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jdx jdx merged commit bb78957 into main Apr 4, 2026
35 checks passed
@jdx jdx deleted the feat/auto-draft-pr branch April 4, 2026 15:53
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 4, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 x -- echo 22.2 ± 0.3 21.3 24.9 1.00
mise x -- echo 22.4 ± 0.4 21.6 24.0 1.01 ± 0.02

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 env 21.7 ± 0.7 20.8 27.1 1.00
mise env 21.9 ± 0.3 21.3 23.9 1.01 ± 0.04

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 hook-env 22.3 ± 0.4 21.5 24.7 1.00
mise hook-env 22.5 ± 0.3 21.7 24.1 1.01 ± 0.02

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 ls 19.5 ± 0.2 18.9 20.4 1.00
mise ls 19.9 ± 0.4 19.3 24.1 1.02 ± 0.03

xtasks/test/perf

Command mise-2026.4.3 mise Variance
install (cached) 148ms 148ms +0%
ls (cached) 77ms 78ms -1%
bin-paths (cached) 82ms 83ms -1%
task-ls (cached) 807ms 799ms +1%

jdx pushed a commit that referenced this pull request Apr 5, 2026
### 🚀 Features

- **(ci)** auto-convert external PRs to draft mode by @jdx in
[#8896](#8896)
- **(deps)** add `depends` field for user-specified tool dependencies by
@cprecioso in [#8776](#8776)
- **(dotnet)** support runtime-only installs by @fragon10 in
[#8524](#8524)
- **(npm)** apply install_before to transitive dependencies by @risu729
in [#8851](#8851)
- **(task)** allow passing arguments to task dependencies via
{{usage.*}} templates by @jdx in
[#8893](#8893)
- add options field to BackendListVersionsCtx by @esteve in
[#8875](#8875)

### 🐛 Bug Fixes

- **(backend)** filter PEP 440 .dev versions in fuzzy version matching
by @richardthe3rd in [#8849](#8849)
- **(ci)** update COPR BuildRequires rust version to match MSRV 1.88 by
@jdx in [#8911](#8911)
- **(ci)** add Ruby build dependencies to e2e Docker image by @jdx in
[#8910](#8910)
- **(ci)** add missing build dependencies to e2e Docker image by @jdx in
[#8912](#8912)
- **(ci)** add missing build dependencies to e2e Docker image by @jdx in
[#8914](#8914)
- **(ci)** use Node 24 LTS for corepack e2e test by @jdx in
[#8915](#8915)
- **(ci)** add libxml2 and pkg-config to e2e Docker image by @jdx in
[#8917](#8917)
- **(ci)** add libxml2-dev to e2e image and disable Swift SPM tests by
@jdx in [#8918](#8918)
- **(docs)** use sans-serif font for badges by @jdx in
[#8887](#8887)
- **(env)** parse --env=VALUE and -E=VALUE flag forms correctly by @jdx
in [#8889](#8889)
- **(exec)** use i64::from() for seccomp syscall numbers to survive
autofix by @jdx in [#8882](#8882)
- **(github)** preserve tool options like filter_bins when version
specified via CLI by @jdx in
[#8888](#8888)
- **(github)** use alias-specific options when tool_alias has its own
config by @jdx in [#8892](#8892)
- **(install)** add locked_verify_provenance setting and detect github
attestations at lock time by @jdx in
[#8901](#8901)
- **(lock)** prune stale version entries during filtered `mise lock
<tool>` runs by @altendky in
[#8599](#8599)
- **(python)** use lockfile URL for precompiled installs by @hehaoqian
in [#8750](#8750)
- **(release)** verify all build targets succeed before releasing by
@jdx in [#8886](#8886)
- **(ruby)** support build revisions for precompiled binaries in
mise.lock by @jdx in [#8900](#8900)
- **(swift)** fall back to Ubuntu 24.04 for unsupported Ubuntu versions
by @jdx in [#8916](#8916)
- **(zsh)** avoid duplicate trust warning after cd by @timothysparg in
[#8898](#8898)
- update flake.lock and add fix for rust-bindgen to default.nix by
@esteve in [#8874](#8874)
- when direnv diff is empty, do not try to parse it by @yaleman in
[#8857](#8857)
- skip trust check for plain .tool-versions in task list by @dportalesr
in [#8876](#8876)

### 🚜 Refactor

- **(go)** rename go_* settings to go.* namespace by @jdbruijn in
[#8598](#8598)

### 📚 Documentation

- **(tasks)** clarify task_config.includes behavior by @risu729 in
[#8905](#8905)

### 🧪 Testing

- **(ci)** run e2e tests inside Docker containers by @jdx in
[#8899](#8899)

### 📦️ Dependency Updates

- bump ubi from 0.8 to 0.9 by @jdx in
[#8906](#8906)
- bump zip from 3 to 8 by @jdx in
[#8908](#8908)
- update lockfile deps (hold back rattler) by @jdx in
[#8909](#8909)
- update bun.lock by @jdx in
[#8913](#8913)

### 📦 Registry

- add turso
([github:tursodatabase/turso-cli](https://github.com/tursodatabase/turso-cli))
by @kenn in [#8884](#8884)
- remove carp test by @jdx in
[#8894](#8894)

### Chore

- **(ci)** add workflow to warn PRs modifying vendored aqua-registry by
@jdx in [#8897](#8897)
- **(ci)** use github.token for draft conversion in auto-draft workflow
by @jdx in [#8903](#8903)
- remove deprecated settings older than 12 months by @jdx in
[#8904](#8904)

### New Contributors

- @dportalesr made their first contribution in
[#8876](#8876)
- @timothysparg made their first contribution in
[#8898](#8898)
- @hehaoqian made their first contribution in
[#8750](#8750)
- @jdbruijn made their first contribution in
[#8598](#8598)
- @cprecioso made their first contribution in
[#8776](#8776)
- @yaleman made their first contribution in
[#8857](#8857)
- @kenn made their first contribution in
[#8884](#8884)
- @fragon10 made their first contribution in
[#8524](#8524)

## 📦 Aqua Registry Updates

#### New Packages (6)

- [`ahkohd/oyo`](https://github.com/ahkohd/oyo)
- [`bellicose100xp/jiq`](https://github.com/bellicose100xp/jiq)
- [`kurama/dealve-tui`](https://github.com/kurama/dealve-tui)
- [`micahkepe/jsongrep`](https://github.com/micahkepe/jsongrep)
- [`textfuel/lazyjira`](https://github.com/textfuel/lazyjira)
- [`ubugeeei/vize`](https://github.com/ubugeeei/vize)

#### Updated Packages (1)

- [`sigstore/cosign`](https://github.com/sigstore/cosign)
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.

1 participant