SuperAPI AI Directory

repos-pull-request-write

Coding & development

View repository

Updated 10-15 21:11

About this skill

Pull Request Creation and Modification

This Skill takes theauthor'sperspective when handling PRs: creating a PR from the current local branch, and modifying an existing PR. It does not provide manual completion or merging of PRs; to merge, set auto-complete, or ask the user to do it in the web UI. Reviews, comments, replies, and votes use repos-pull-request-review。

Repository Determination

In the git working directory, extract the organization, project, and repository from the remote URL, and get the current branch:

git remote get-url origin
git rev-parse --abbrev-ref HEAD
Remote URL Format Description
https://{org}@dev.azure.com/{org}/{project}/_git/{repository} HTTPS URL copied from the web UI
https://dev.azure.com/{org}/{project}/_git/{repository} HTTPS URL without a username
https://{org}.visualstudio.com/[DefaultCollection/]{project}/_git/{repository} Legacy domain;DefaultCollection/ optional
git@ssh.dev.azure.com:v3/{org}/{project}/{repository} SSH URL
  • Names in the URL may be URL-encoded (e.g., My%20App): use them as-is when putting them into the API path, and decode them first when displaying to the user.

  • When the organization in the remote URL and AZURE_DEVOPS_ORG differ, ask the user once which one to use.

  • rev-parse Returns HEAD indicates detached HEAD: ask the user to first switch to the branch for which the PR is to be created, and stop.

  • When the current directory is not a git repository, the remote is not Azure DevOps, or the user wants to handle a different repository, ask the user to provide the project and repository names; if still not provided, list the projects and repositories for the user to choose:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/projects?%24top=500&api-version=7.1"
    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories?api-version=7.1"
    

    Display value[].name;isDisabled as true repositories marked as disabled. Rule 1 must be executed in that repository's local working directory.

Connection and Authentication

Always use curl to call the Azure DevOps REST API directly, with each command carrying its own authentication parameters.

  • Organization: read the environment variable AZURE_DEVOPS_ORG(organization name, e.g., contoso). If not set, ask the user once; if the user provides a URL, extract the organization name from https://dev.azure.com/{org} or https://{org}.visualstudio.com .
  • Host: apart from dev.azure.com, the host of the Identities API that looks up reviewer identity by email or name is vssps.dev.azure.com。
  • Token: send the PAT with Basic authentication:-u ":$AZURE_DEVOPS_PAT"; when only AZURE_DEVOPS_EXT_PATis set (the variable used by the Azure CLI azure-devops extension), use it instead. When using a Microsoft Entra ID token instead, switch to -H "Authorization: Bearer $AZURE_DEVOPS_TOKEN". If neither is set, ask the user to set AZURE_DEVOPS_PAT in their own terminal and retry, then stop. Tokens are only read from environment variables: do not ask the user to paste tokens into the conversation, and do not print or write them to files.
  • PAT Permission Scopes: required for reading: Code (Read), Identity (Read) (to look up reviewers), Work Items (Read) (to confirm work items); required for writing: Code (Read & write) (to create and modify PRs).
  • Encoding: project and repository names in the path, and branch names and reviewer names in the query string must be URL-encoded (spaces written as %20, and characters such as Chinese and # must also be encoded); in the query string, $ is written as %24(e.g. %24top), to avoid shell expansion.
  • Error: HTTP 401, 403, 203, or a response that is an HTML login page means the token is invalid, expired, or lacks permission; report it and stop. HTTP 404 means the organization, project, repository, or PR ID is wrong. When creating a PR, HTTP 409 (TF401179) means there is already an in-progress PR for the same source and target branches; switch to rule 2 to modify it.
  • Windows PowerShell: Call curl.exe(not the curl alias), write environment variables as $env:AZURE_DEVOPS_PAT; PowerShell does not support <<'EOF', so first write the JSON body to a temporary file, then send it with --data-binary "@body.json" .

Current user

Checking the PR author and setting auto-complete require the current user's identity ID (this endpoint does not carry api-version):

curl -sS -u ":$AZURE_DEVOPS_PAT" "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/connectionData"

Use authenticatedUser.id;authenticatedUser.providerDisplayName is the display name.

Rules

1. Create a PR from the current branch

  1. Confirm the source branch has been pushed:

    git status --porcelain
    git ls-remote --heads origin {branch}
    
    • If there are uncommitted changes, remind the user: these changes will not be included in the PR.
    • ls-remote no output means the remote does not have this branch: ask the user whether to run git push -u origin {branch}, and only push after they agree.
    • The remote already has the branch, but after git fetch origin {branch} , git rev-list --count origin/{branch}..HEAD is greater than 0 (there are unpushed commits), likewise ask first, then git push。
  2. Determine the target branch: if the user specified one, use it; otherwise use the repository's defaultBranch(e.g. refs/heads/main). Also note down id and webUrl:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repository}?api-version=7.1"
    

    If the source and target branches are the same, stop.

  3. Check whether a PR already exists:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repository}/pullrequests?searchCriteria.sourceRefName=refs/heads/{branch}&searchCriteria.status=active&api-version=7.1"
    

    The same source branch may have multiple in-progress PRs (with different target branches). If there is a PR whose targetRefName equals the target branch, show its ID and link, ask whether to modify it instead (rule 2), and do not create a duplicate.

  4. Draft the title and description:

    git fetch origin {targetBranch}
    git log --oneline --no-merges origin/{targetBranch}..HEAD
    
    • If there are no commits, stop: this branch has no changes to merge.
    • Only one commit: use its first line as the title, and the rest of its body as the description (git log -1 --format=%b)。
    • Multiple commits: the title summarizes the overall purpose, and the description lists the key changes in bullet points.
    • A title or description provided by the user takes priority. The description is limited to 4000 characters; if it exceeds that, condense it.
  5. Apply the PR template: the template is only auto-filled when creating a PR on the web; when creating via the API, you must read and fill it in yourself. Templates are always taken fromthe default branch, and file names and folders are case-insensitive:

    git fetch origin {defaultBranch}
    git ls-tree -r --name-only origin/{defaultBranch} \
      | grep -i -E '^(\.azuredevops/|\.vsts/|docs/)?pull_request_template(\.md|\.txt|/)'
    git show "origin/{defaultBranch}:{templatePath}"
    

    Search in order in .azuredevops/、.vsts/、docs/and the repository root, and use the first matching template:

    1. Branch-specific templates:pull_request_template/branches/ under it, the .md or .txtnamed after the target branch. You can match only the first level (release.md applies to release and all release/*), or use nested folders to match multiple levels (release/october.md applies to release/october and release/october/*)。
    2. Default templates:pull_request_template.md or pull_request_template.txt。

    pull_request_template/(excluding branches/); the other files in it areoptional templates, append only when the user requests it. When applying the template, keep its heading and checklist, and fill the change summary from step 4 into the corresponding section.

  6. Link work items: Find work item IDs from the branch name and commit messages, for example AB#101、#101、feature/101-login. List the candidate IDs for the user to confirm, and link only the confirmed items. You can first look up titles and states to help confirm (IDs that do not exist or that you lack permission for are value in null):

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/wit/workitems?ids=101,102&fields=System.Title,System.State,System.WorkItemType&errorPolicy=omit&api-version=7.1"
    
  7. Resolve reviewers: When the user specifies reviewers by email or name, look up the identity IDs:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://vssps.dev.azure.com/$AZURE_DEVOPS_ORG/_apis/identities?searchFilter=General&filterValue={emailOrName}&api-version=7.1"
    

    Use value[].id;providerDisplayName is the display name,properties.Mail.$value is the email. Teams or groups are written as [{project}]\{team}(for example [Contoso]\Contoso Team, sent after URL encoding). When multiple matches are found, ask the user to choose; when none are found, report it and do not guess. Set required reviewers to isRequired: true。

  8. Confirm and create: List the content about to be sent for the user, and execute only after one confirmation: repository, source → target branch, title, full description, whether it is a draft, reviewers (required/optional), work items, and tags.

    curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repository}/pullrequests?api-version=7.1" \
      --data-binary @- <<'EOF'
    {
      "sourceRefName": "refs/heads/feature/101-login",
      "targetRefName": "refs/heads/main",
      "title": "新增登入頁面",
      "description": "## 變更內容\n- 新增登入表單\n- 補上單元測試",
      "isDraft": false,
      "reviewers": [{"id": "{reviewerId}", "isRequired": true}],
      "workItemRefs": [{"id": "101"}],
      "labels": [{"name": "frontend"}]
    }
    EOF
    

    On success it returns HTTP 201; note the pullRequestId. Omit the field when there are no reviewers, work items, or tags. When the description contains newlines and quotes, first use jq -n --arg title "..." --arg description "..." to generate JSON, to avoid escaping errors.

  9. Auto-complete cannot be set at creation time. When the user wants auto-complete, after creation proceed to "Set auto-complete" in rule 2.

Example: "Help me open a PR from the current branch to main", "Open a draft PR, the reviewer is someone@contoso.com」

2. Modify an existing PR

First get the PR (no need to know the repository), and note the repository.id、status、isDraft、createdBy.id、autoCompleteSetBy、completionOptions、targetRefName and reviewers[]:

curl -sS -u ":$AZURE_DEVOPS_PAT" \
  "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/pullrequests/{pullRequestId}?api-version=7.1"

createdBy.id is not the current user, first remind the user that this is not their PR.status is completed PRs cannot be modified.

Before each modification, list the PR (ID and title), the fields to change, the current values, and the new values for the user, and execute only after one confirmation. Except for adding reviewers, use the same PATCH endpoint and send only the fields to change:

curl -sS -u ":$AZURE_DEVOPS_PAT" -X PATCH -H "Content-Type: application/json" \
  "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repositoryId}/pullrequests/{pullRequestId}?api-version=7.1" \
  -d '{"isDraft":false}'
Action Body
Publish draft {"isDraft":false}
Convert back to draft {"isDraft":true}
Modify title or description {"title":"...","description":"..."}
Change target branch {"targetRefName":"refs/heads/release"}
Cancel auto-complete {"autoCompleteSetBy":{"id":"00000000-0000-0000-0000-000000000000"}}
Abandon {"status":"abandoned"}
Reactivate an abandoned PR {"status":"active"}
  • The updatable fields listed in the Learn documentation are status、title、description(limit 4000 characters),completionOptions、mergeOptions、autoCompleteSetBy.id and targetRefName(the PR retargeting feature must be enabled); other fields may be ignored or return an error.isDraft is not in the list, but the Azure DevOps CLI's az repos pr update --draft uses this PATCH to send isDraft. After sending, check the response's isDraft; when there is no change, report it and ask the user to operate in the web UI.
  • To cancel auto-complete, use an empty GUID, the same as az repos pr update --auto-complete false ; after sending, get the PR again and confirm that autoCompleteSetBy no longer exists.
  • Do not provide "status":"completed"(manual completion), and do not provide bypassPolicy(bypass policy).

Set auto-complete: Automatically complete the PR after all required (blocking) policies pass. A draft PR will not complete, so publish it first.

  1. Query the merge strategies allowed for the target branch.type.id is fa4e907d-c16b-4a4c-9dfa-4916e5d171ab(Require a merge strategy) and isEnabled is true , only settings in allowNoFastForward、allowSquash、allowRebase、allowRebaseMerge is true is available; without this policy, all are available:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/policy/configurations?repositoryId={repositoryId}&refName=refs/heads/main&api-version=7.1"
    
  2. Confirm the merge strategy, whether to delete the source branch, and whether to transition the work item status with the user, then submit ({myId} taken from "current user"):

    curl -sS -u ":$AZURE_DEVOPS_PAT" -X PATCH -H "Content-Type: application/json" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repositoryId}/pullrequests/{pullRequestId}?api-version=7.1" \
      -d '{"autoCompleteSetBy":{"id":"{myId}"},"completionOptions":{"mergeStrategy":"squash","deleteSourceBranch":true,"transitionWorkItems":true}}'
    

    mergeStrategy:noFastForward(create a merge commit),squash(squash into a single commit),rebase(fast-forward after rebase),rebaseMerge(create a merge commit after rebase). To customize the merge message, add mergeCommitMessage. On success, the response's autoCompleteSetBy.id equals {myId}。

Add reviewer: look up the identity ID according to rule 1 step 7; do not submit again for anyone already in reviewers[] , to avoid overwriting existing votes. One call per reviewer:

curl -sS -u ":$AZURE_DEVOPS_PAT" -X PUT -H "Content-Type: application/json" \
  "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repositoryId}/pullRequests/{pullRequestId}/reviewers/{reviewerId}?api-version=7.1" \
  -d '{"vote":0,"isRequired":false}'

For a required reviewer, set isRequired to true. To remove a reviewer, ask the user to do it on the web page.

Examples: "Publish PR 101", "Add someone@contoso.com to PR 101 as a required reviewer", "Set PR 101 to squash auto-complete and delete the branch", "Cancel PR 101's auto-complete", "Abandon PR 101"

Present the result

The PR link format is {repository.webUrl}/pullrequest/{pullRequestId}; remove refs/heads/from branch names; display dates as YYYY/MM/DD。

  • Confirmation before creation: list each field to be submitted, display descriptions in full (do not give only a summary), and indicate the template source file and the detected work item.
  • After creation: PR ID (clickable link), title (add 📝 for draft), source → target branch, reviewers (mark required ones as "Required"), linked work items (https://dev.azure.com/{organization}/{project}/_workitems/edit/{ID})。
  • When a PR already exists: list the existing PR's ID, title, target branch, and link, and ask whether to modify it instead.
  • After modification: the PR link, and each field's "before → after"; for auto-complete, list the merge strategy, whether to delete the source branch, and work item transitions.
  • On failure: display the HTTP status code and the messagein the response; do not automatically retry writes.