Skip to content

Commit 3b3dea1

Browse files
Merge branch 'main' into fix-NoSource-import-bug
2 parents eb7b936 + 4046562 commit 3b3dea1

File tree

7 files changed

+150
-6
lines changed

7 files changed

+150
-6
lines changed

.github/actions/build-vsix/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ runs:
8787
shell: bash
8888

8989
- name: Upload VSIX
90-
uses: actions/upload-artifact@v3
90+
uses: actions/upload-artifact@v4
9191
with:
9292
name: ${{ inputs.artifact_name }}
9393
path: ${{ inputs.vsix_name }}

.github/actions/smoke-tests/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ runs:
4343

4444
# Bits from the VSIX are reused by smokeTest.ts to speed things up.
4545
- name: Download VSIX
46-
uses: actions/download-artifact@v3
46+
uses: actions/download-artifact@v4
4747
with:
4848
name: ${{ inputs.artifact_name }}
4949

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Issues Summary
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 * * 2' # Runs every Tuesday at midnight
6+
workflow_dispatch:
7+
8+
jobs:
9+
generate-summary:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v2
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v2
18+
with:
19+
python-version: '3.x'
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install requests
25+
26+
- name: Run summary script
27+
run: python scripts/generate_summary.py
28+
env:
29+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/pr-file-check.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ name: PR files
33
on:
44
pull_request:
55
types:
6-
# On by default if you specify no types.
76
- 'opened'
87
- 'reopened'
98
- 'synchronize'
10-
# For `skip-label` only.
119
- 'labeled'
1210
- 'unlabeled'
1311

@@ -42,3 +40,15 @@ jobs:
4240
.github/test_plan.md
4341
skip-label: 'skip tests'
4442
failure-message: 'TypeScript code was edited without also editing a ${file-pattern} file; see the Testing page in our wiki on testing guidelines (the ${skip-label} label can be used to pass this check)'
43+
44+
- name: 'Ensure PR has an associated issue'
45+
uses: actions/github-script@v6
46+
with:
47+
script: |
48+
const labels = context.payload.pull_request.labels.map(label => label.name);
49+
if (!labels.includes('skip-issue-check')) {
50+
const issueLink = context.payload.pull_request.body.match(/https:\/\/github\.com\/\S+\/issues\/\d+/);
51+
if (!issueLink) {
52+
core.setFailed('No associated issue found in the PR description.');
53+
}
54+
}

.github/workflows/stale-prs.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Warn about month-old PRs
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 */2 * *' # Runs every other day at midnight
6+
7+
jobs:
8+
stale-prs:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout repository
12+
uses: actions/checkout@v2
13+
14+
- name: Warn about stale PRs
15+
uses: actions/github-script@v4
16+
with:
17+
script: |
18+
const { Octokit } = require("@octokit/rest");
19+
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
20+
21+
const owner = context.repo.owner;
22+
const repo = context.repo.repo;
23+
const staleTime = new Date();
24+
staleTime.setMonth(staleTime.getMonth() - 1);
25+
26+
const prs = await octokit.pulls.list({
27+
owner,
28+
repo,
29+
state: 'open'
30+
});
31+
32+
for (const pr of prs.data) {
33+
const comments = await octokit.issues.listComments({
34+
owner,
35+
repo,
36+
issue_number: pr.number
37+
});
38+
39+
const lastComment = comments.data.length > 0 ? new Date(comments.data[comments.data.length - 1].created_at) : new Date(pr.created_at);
40+
41+
if (lastComment < staleTime) {
42+
await octokit.issues.createComment({
43+
owner,
44+
repo,
45+
issue_number: pr.number,
46+
body: 'This PR has been stale for over a month. Please update or close it.'
47+
});
48+
}
49+
}
50+
env:
51+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

scripts/generate_summary.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import requests
2+
import os
3+
from datetime import datetime, timezone
4+
5+
GITHUB_API_URL = "https://api.github.com"
6+
REPO = "microsoft/vscode-python"
7+
TOKEN = os.getenv("GITHUB_TOKEN")
8+
9+
10+
def fetch_issues():
11+
headers = {"Authorization": f"token {TOKEN}"}
12+
query = f"{GITHUB_API_URL}/repos/{REPO}/issues?state=open&per_page=100"
13+
response = requests.get(query, headers=headers)
14+
response.raise_for_status()
15+
return response.json()
16+
17+
18+
def calculate_thumbs_up_per_day(issue):
19+
created_at = datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ")
20+
now = datetime.now(timezone.utc)
21+
days_open = (now - created_at).days or 1
22+
thumbs_up = next(
23+
(group["count"] for group in issue["reactions"] if group["content"] == "+1"), 0
24+
)
25+
return thumbs_up / days_open
26+
27+
28+
def generate_markdown_summary(issues):
29+
summary = "| URL | Title | 👍/day |\n| --- | ----- | ------ |\n"
30+
for issue in issues:
31+
thumbs_up_per_day = calculate_thumbs_up_per_day(issue)
32+
summary += (
33+
f"| {issue['html_url']} | {issue['title']} | {thumbs_up_per_day:.2f} |\n"
34+
)
35+
return summary
36+
37+
38+
def main():
39+
issues = fetch_issues()
40+
summary = generate_markdown_summary(issues)
41+
with open("endorsement_velocity_summary.md", "w") as f:
42+
f.write(summary)
43+
44+
45+
if __name__ == "__main__":
46+
main()

src/client/common/pipes/namedPipes.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { CancellationError, CancellationToken, Disposable } from 'vscode';
1212
import { traceVerbose } from '../../logging';
1313
import { isWindows } from '../utils/platform';
1414
import { createDeferred } from '../utils/async';
15+
import { noop } from '../utils/misc';
1516

1617
const { XDG_RUNTIME_DIR } = process.env;
1718
export function generateRandomPipeName(prefix: string): string {
@@ -187,6 +188,13 @@ export async function createReaderPipe(pipeName: string, token?: CancellationTok
187188
} catch {
188189
// Intentionally ignored
189190
}
190-
const reader = fs.createReadStream(pipeName, { encoding: 'utf-8' });
191-
return new rpc.StreamMessageReader(reader, 'utf-8');
191+
const fd = await fs.open(pipeName, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK);
192+
const socket = new net.Socket({ fd });
193+
const reader = new rpc.SocketMessageReader(socket, 'utf-8');
194+
socket.on('close', () => {
195+
fs.close(fd).catch(noop);
196+
reader.dispose();
197+
});
198+
199+
return reader;
192200
}

0 commit comments

Comments
 (0)