From 7af2c643af288012d0d3d47fa7cc5539ef1308be Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 27 Apr 2026 16:09:20 +0200 Subject: [PATCH] chore: make pr-pinger a workspace extension (#312757) * chore: make pr-pinger a workspace extension * Update .vscode/extensions/vscode-pr-pinger/src/extension.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .vscode/extensions.json | 1 - .../extensions/vscode-pr-pinger/.vscodeignore | 5 + .../vscode-pr-pinger/package-lock.json | 269 ++++++++++++++++++ .../extensions/vscode-pr-pinger/package.json | 42 +++ .../vscode-pr-pinger/src/extension.ts | 241 ++++++++++++++++ .../extensions/vscode-pr-pinger/tsconfig.json | 14 + build/gulpfile.extensions.ts | 1 + build/npm/dirs.ts | 1 + 8 files changed, 573 insertions(+), 1 deletion(-) create mode 100644 .vscode/extensions/vscode-pr-pinger/.vscodeignore create mode 100644 .vscode/extensions/vscode-pr-pinger/package-lock.json create mode 100644 .vscode/extensions/vscode-pr-pinger/package.json create mode 100644 .vscode/extensions/vscode-pr-pinger/src/extension.ts create mode 100644 .vscode/extensions/vscode-pr-pinger/tsconfig.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3fb87652c81..af6d806edbd 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -7,7 +7,6 @@ "github.vscode-pull-request-github", "ms-vscode.vscode-github-issue-notebooks", "ms-vscode.extension-test-runner", - "jrieken.vscode-pr-pinger", "typescriptteam.native-preview", "ms-vscode.ts-customized-language-service" ] diff --git a/.vscode/extensions/vscode-pr-pinger/.vscodeignore b/.vscode/extensions/vscode-pr-pinger/.vscodeignore new file mode 100644 index 00000000000..87d37a706bf --- /dev/null +++ b/.vscode/extensions/vscode-pr-pinger/.vscodeignore @@ -0,0 +1,5 @@ +.gitignore +.vscode/** +.vscode-test/** +src/** +**/tsconfig.json diff --git a/.vscode/extensions/vscode-pr-pinger/package-lock.json b/.vscode/extensions/vscode-pr-pinger/package-lock.json new file mode 100644 index 00000000000..ad347b7bd78 --- /dev/null +++ b/.vscode/extensions/vscode-pr-pinger/package-lock.json @@ -0,0 +1,269 @@ +{ + "name": "vscode-pr-pinger", + "version": "0.0.6", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "vscode-pr-pinger", + "version": "0.0.6", + "license": "MIT", + "dependencies": { + "@octokit/graphql": "^5.0.1" + }, + "engines": { + "vscode": "^1.67.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.2.tgz", + "integrity": "sha512-8/AUACfE9vpRpehE6ZLfEtzkibe5nfsSwFZVMsG8qabqRt1M81qZYUFRZa1B8w8lP6cdfDJfRq9HWS+MbmR7tw==", + "dependencies": { + "@octokit/types": "^7.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/graphql": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.1.tgz", + "integrity": "sha512-sxmnewSwAixkP1TrLdE6yRG53eEhHhDTYUykUwdV9x8f91WcbhunIHk9x1PZLALdBZKRPUO2HRcm4kezZ79HoA==", + "dependencies": { + "@octokit/request": "^6.0.0", + "@octokit/types": "^7.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.10.0.tgz", + "integrity": "sha512-wPQDpTyy35D6VS/lekXDaKcxy6LI2hzcbmXBnP180Pdgz3dXRzoHdav0w09yZzzWX8HHLGuqwAeyMqEPtWY2XA==" + }, + "node_modules/@octokit/request": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.1.tgz", + "integrity": "sha512-gYKRCia3cpajRzDSU+3pt1q2OcuC6PK8PmFIyxZDWCzRXRSIBH8jXjFJ8ZceoygBIm0KsEUg4x1+XcYBz7dHPQ==", + "dependencies": { + "@octokit/endpoint": "^7.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^7.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/request-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.1.tgz", + "integrity": "sha512-ym4Bp0HTP7F3VFssV88WD1ZyCIRoE8H35pXSKwLeMizcdZAYc/t6N9X9Yr9n6t3aG9IH75XDnZ6UeZph0vHMWQ==", + "dependencies": { + "@octokit/types": "^7.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.4.0.tgz", + "integrity": "sha512-ln1GW0p72+P8qeRjHGj0wyR5ePy6slqvczveOqonMk1w1UWua6UgrkwFzv6S0vKWjSqt/ijYXF1ehNVRRRSvLA==", + "dependencies": { + "@octokit/openapi-types": "^13.10.0" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + }, + "dependencies": { + "@octokit/endpoint": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.2.tgz", + "integrity": "sha512-8/AUACfE9vpRpehE6ZLfEtzkibe5nfsSwFZVMsG8qabqRt1M81qZYUFRZa1B8w8lP6cdfDJfRq9HWS+MbmR7tw==", + "requires": { + "@octokit/types": "^7.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.1.tgz", + "integrity": "sha512-sxmnewSwAixkP1TrLdE6yRG53eEhHhDTYUykUwdV9x8f91WcbhunIHk9x1PZLALdBZKRPUO2HRcm4kezZ79HoA==", + "requires": { + "@octokit/request": "^6.0.0", + "@octokit/types": "^7.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.10.0.tgz", + "integrity": "sha512-wPQDpTyy35D6VS/lekXDaKcxy6LI2hzcbmXBnP180Pdgz3dXRzoHdav0w09yZzzWX8HHLGuqwAeyMqEPtWY2XA==" + }, + "@octokit/request": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.1.tgz", + "integrity": "sha512-gYKRCia3cpajRzDSU+3pt1q2OcuC6PK8PmFIyxZDWCzRXRSIBH8jXjFJ8ZceoygBIm0KsEUg4x1+XcYBz7dHPQ==", + "requires": { + "@octokit/endpoint": "^7.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^7.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.1.tgz", + "integrity": "sha512-ym4Bp0HTP7F3VFssV88WD1ZyCIRoE8H35pXSKwLeMizcdZAYc/t6N9X9Yr9n6t3aG9IH75XDnZ6UeZph0vHMWQ==", + "requires": { + "@octokit/types": "^7.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.4.0.tgz", + "integrity": "sha512-ln1GW0p72+P8qeRjHGj0wyR5ePy6slqvczveOqonMk1w1UWua6UgrkwFzv6S0vKWjSqt/ijYXF1ehNVRRRSvLA==", + "requires": { + "@octokit/openapi-types": "^13.10.0" + } + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + } +} diff --git a/.vscode/extensions/vscode-pr-pinger/package.json b/.vscode/extensions/vscode-pr-pinger/package.json new file mode 100644 index 00000000000..27e8b91a0cf --- /dev/null +++ b/.vscode/extensions/vscode-pr-pinger/package.json @@ -0,0 +1,42 @@ +{ + "name": "vscode-pr-pinger", + "displayName": "VSCode PR Pinger", + "description": "PR Pinger shows a PR in the statusbar for you to review (VS Code Team Only)", + "engines": { + "vscode": "^1.67.0" + }, + "version": "0.0.6", + "publisher": "ms-vscode", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode.git" + }, + "main": "out/extension.js", + "activationEvents": [ + "onStartupFinished" + ], + "contributes": { + "configuration": { + "title": "PR Pinger", + "properties": { + "prpinger.presentation": { + "type": "string", + "default": "short", + "enum": [ + "number", + "short" + ], + "description": "How PR are shown in the status bar - either as number or without vowels" + } + } + } + }, + "scripts": { + "watch": "gulp watch-extension:vscode-pr-pinger", + "compile": "gulp compile-extension:vscode-pr-pinger" + }, + "license": "MIT", + "dependencies": { + "@octokit/graphql": "^5.0.1" + } +} diff --git a/.vscode/extensions/vscode-pr-pinger/src/extension.ts b/.vscode/extensions/vscode-pr-pinger/src/extension.ts new file mode 100644 index 00000000000..55f3437fcd2 --- /dev/null +++ b/.vscode/extensions/vscode-pr-pinger/src/extension.ts @@ -0,0 +1,241 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { graphql } from '@octokit/graphql'; + +export function activate(context: vscode.ExtensionContext) { + + const item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 1); + context.subscriptions.push(item); + + let session: vscode.AuthenticationSession | undefined; + + context.subscriptions.push(vscode.commands.registerCommand('pr.promptLogin', async () => { + session = await vscode.authentication.getSession('github', ['repo'], { createIfNone: true }); + updateItem(); + })); + + context.subscriptions.push(vscode.commands.registerCommand('pr.show', async (pr: PrInfo) => { + vscode.env.openExternal(vscode.Uri.parse(pr.url)); + item.hide(); + })); + + let currentShow: vscode.Disposable | undefined = undefined; + context.subscriptions.push(new vscode.Disposable(() => currentShow?.dispose())); + + // monitor focus/unfocus to "nudge harder" after a context switch + let lastGone: number | undefined; + context.subscriptions.push(vscode.window.onDidChangeWindowState(e => { + if (!e.focused) { + // gone + lastGone = Date.now(); + return; + } + + if (lastGone && Date.now() - lastGone > 1000 * 60 * 5) { + // back after 5 minutes + updateItem(true); + } + })); + + async function updateItem(afterAway?: boolean) { + const currentSession = session; + + if (!currentSession) { + item.text = 'Not Logged In'; + item.command = 'pr.promptLogin'; + item.show(); + return; + } + + if (currentShow) { + // already showing a PR + return; + } + + const tooLongAgo = Date.now() - 1000 * 60 * 60 * 24 * 4; + const data: Query = await graphql(query, { headers: { authorization: `Bearer ${currentSession.accessToken}` } }); + + const prs = data.repository.pullRequests.edges.map(edge => edge.node) + .filter(needsTeamReview) // from team + .filter(pr => pr.author.login !== currentSession.account.label) // not YOU + .map(pr => ({ pr, date: new Date(pr.createdAt) })) + .filter(({ date }) => date.getTime() > tooLongAgo) // not dated + .sort((a, b) => b.date.getTime() - a.date.getTime()); // sorted + + if (prs.length === 0) { + return; + } + + // Unless forced you only need to review with a certain chance + if (!afterAway) { + const chance = Math.ceil(prs.length / 7); + if (Math.random() > chance) { + return; + } + } + + // pick a random PR so that not everyone gets the same one + const n = Math.floor(Math.random() * prs.length); + const pr = prs[n].pr; + + item.text = makeLabel(pr); + item.tooltip = new vscode.MarkdownString(`[${pr.title}](${pr.url}) needs your review. Thanks $(heart-filled)`, true); + item.command = { command: 'pr.show', title: 'Show PR', arguments: [pr] }; + item.backgroundColor = afterAway ? new vscode.ThemeColor('statusBarItem.warningBackground') : undefined; + item.show(); + + // refresh every 20 seconds + const checkHandle = setInterval(async function () { + const data: Check = await graphql(check, { + pr: pr.number, + headers: { authorization: `Bearer ${currentSession.accessToken}` }, + }); + if (!needsTeamReview(data.repository.pullRequest)) { + currentShow?.dispose(); + } + }, 1000 * 20); + currentShow = new vscode.Disposable(() => { + clearInterval(checkHandle); + currentShow = undefined; + item.hide(); + }); + } + + vscode.authentication.getSession('github', ['repo']).then(_session => { + session = _session; + updateItem(); + }); + + const handle = setInterval(updateItem, 1000 * 60 * 10); // update every 10 minutes + context.subscriptions.push(new vscode.Disposable(() => clearInterval(handle))); +} + +function makeLabel(pr: PrInfo): string { + const style = vscode.workspace.getConfiguration('prpinger').get<'short' | 'number'>('presentation'); + if (style === 'number') { + return `$(git-pull-request) #${pr.number}`; + } + + const ignore = new Set(['`', '.', ':']); + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + const newTitle: string[] = []; + for (const ch of pr.title) { + if (ignore.has(ch)) { + break; + } + if (newTitle.length > 8 && !/\w/.test(ch)) { + break; + } + if (newTitle.length > 15) { + break; + } + if (!vowels.has(ch)) { + newTitle.push(ch); + } + } + + return `$(git-pull-request) ${newTitle.join('')}`; +} + +function needsTeamReview(pr: PrInfo): boolean { + return pr.authorAssociation === 'MEMBER' + && !pr.isDraft + && pr.reviewRequests.totalCount === 0 + && pr.reviews.totalCount === 0 + && pr.assignees.nodes.length === 1 && pr.assignees.nodes[0].login === pr.author.login; // our PR bot assigns the poster as owner -> we use that as filter +} + +type PrInfo = { + number: number; + author: { login: string }; + authorAssociation: 'MEMBER' | string; + assignees: { nodes: { login: string }[] }; + createdAt: string; + isDraft: string; + reviewRequests: { totalCount: number }; + reviews: { totalCount: number }; + title: string; + url: string; +}; + + +// ---- query + +type Query = { + repository: { + pullRequests: { + edges: { node: PrInfo }[]; + }; + }; +}; + +const query = `{ + repository(owner: "microsoft", name: "vscode") { + pullRequests( + first: 30 + states: OPEN + orderBy: {field: CREATED_AT, direction: DESC} + ) { + edges { + node { + title + number + url + createdAt + authorAssociation + author { + login + } + assignees(first:5) { + nodes { + login + } + } + isDraft + reviewRequests(last: 1) { + totalCount + } + reviews(last:1) { + totalCount + } + } + } + } + } +}`; + +// --- check + +type Check = { + repository: { + pullRequest: PrInfo; + }; +}; + + +const check = `query validate($pr: Int!) { + repository(owner: "microsoft", name: "vscode") { + pullRequest(number: $pr) { + authorAssociation + author { + login + } + assignees(first:5) { + nodes { + login + } + } + isDraft + reviewRequests(last: 1) { + totalCount + } + reviews(last: 1) { + totalCount + } + } + } +}`; diff --git a/.vscode/extensions/vscode-pr-pinger/tsconfig.json b/.vscode/extensions/vscode-pr-pinger/tsconfig.json new file mode 100644 index 00000000000..9133c3bbf4b --- /dev/null +++ b/.vscode/extensions/vscode-pr-pinger/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../extensions/tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./out", + "types": [ + "node" + ] + }, + "include": [ + "src/**/*", + "../../../src/vscode-dts/vscode.d.ts" + ] +} diff --git a/build/gulpfile.extensions.ts b/build/gulpfile.extensions.ts index 83f47e797f3..d5510457fcd 100644 --- a/build/gulpfile.extensions.ts +++ b/build/gulpfile.extensions.ts @@ -97,6 +97,7 @@ const compilations = [ '.vscode/extensions/vscode-selfhost-test-provider/tsconfig.json', '.vscode/extensions/vscode-selfhost-import-aid/tsconfig.json', '.vscode/extensions/vscode-extras/tsconfig.json', + '.vscode/extensions/vscode-pr-pinger/tsconfig.json', ]; const getBaseUrl = (out: string) => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`; diff --git a/build/npm/dirs.ts b/build/npm/dirs.ts index 74b5422b581..468d2df8083 100644 --- a/build/npm/dirs.ts +++ b/build/npm/dirs.ts @@ -63,6 +63,7 @@ export const dirs = [ '.vscode/extensions/vscode-selfhost-import-aid', '.vscode/extensions/vscode-selfhost-test-provider', '.vscode/extensions/vscode-extras', + '.vscode/extensions/vscode-pr-pinger', ]; if (existsSync(`${import.meta.dirname}/../../.build/distro/npm`)) {