Skip to content

Commit 8c3989d

Browse files
authored
[automated] Merge branch 'prerelease' => 'release' (#8609)
2 parents 2effc41 + ff3ca2a commit 8c3989d

File tree

114 files changed

+2674
-3633
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+2674
-3633
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: branch_classification
2+
description: Branch classification configuration for repository
3+
resource: repository
4+
disabled: false
5+
where:
6+
configuration:
7+
branchClassificationSettings:
8+
defaultClassification: nonproduction
9+
ruleset:
10+
- name: prod-branches
11+
branchNames:
12+
- main
13+
- prerelease
14+
- release
15+
classification: production
16+
- name: nonprod-branches
17+
branchNames:
18+
- feature
19+
classification: nonproduction
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Create GitHub Release
2+
on:
3+
push:
4+
tags:
5+
- 'v2.*'
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
# This job runs against the yaml defined in the tag we were triggered on.
12+
# So we can modify the release creation without having to wait for the change to flow into the commit
13+
# that we're tagging, we call a reusable workflow from main
14+
create-release:
15+
uses: dotnet/vscode-csharp/.github/workflows/release-reusable.yml@main
16+
with:
17+
tag: ${{ github.ref_name }}
18+
secrets: inherit
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
name: Release Comment Handler
2+
3+
on:
4+
issues:
5+
types:
6+
- labeled
7+
8+
jobs:
9+
comment_on_label:
10+
if: github.event.label.name == 'prerelease' || github.event.label.name == 'fixed'
11+
runs-on: ubuntu-latest
12+
permissions:
13+
issues: write
14+
contents: read
15+
steps:
16+
- name: Gather participants
17+
id: participants
18+
uses: actions/github-script@v7
19+
with:
20+
script: |
21+
console.log("=== WORKFLOW START ===");
22+
const issue_number = context.payload.issue.number;
23+
const repo = context.repo;
24+
25+
console.log(`Processing issue #${issue_number} in ${repo.owner}/${repo.repo}`);
26+
27+
// Get issue details (for author)
28+
const issue = context.payload.issue;
29+
const author = issue.user.login;
30+
console.log(`Issue author: ${author}`);
31+
32+
// Use a Set to track all unique participants (normalized to lowercase for deduplication)
33+
const all_participants = new Set();
34+
35+
// Add the issue author
36+
all_participants.add(author.toLowerCase());
37+
console.log(`Added author to participants: ${author.toLowerCase()}`);
38+
39+
// Get all comments and add commenters
40+
console.log("=== FETCHING COMMENTS ===");
41+
const comments = await github.paginate(
42+
github.rest.issues.listComments,
43+
{ ...repo, issue_number }
44+
);
45+
console.log(`Found ${comments.length} comments`);
46+
47+
if (comments.length === 0) {
48+
console.log("❌ NO COMMENTS FOUND - This might be why no users are tagged");
49+
}
50+
51+
comments.forEach((c, index) => {
52+
const commenter = c.user.login.toLowerCase();
53+
all_participants.add(commenter);
54+
console.log(`Comment #${index + 1}: Added commenter: ${commenter} (original: ${c.user.login})`);
55+
});
56+
57+
// Get all reactions from comments
58+
let totalCommentReactions = 0;
59+
for (const comment of comments) {
60+
const reactions = await github.paginate(
61+
github.rest.reactions.listForIssueComment,
62+
{ ...repo, comment_id: comment.id }
63+
);
64+
totalCommentReactions += reactions.length;
65+
reactions.forEach(r => {
66+
const reactor = r.user.login.toLowerCase();
67+
all_participants.add(reactor);
68+
console.log(`Added comment reactor: ${reactor}`);
69+
});
70+
}
71+
console.log(`Processed ${totalCommentReactions} reactions from comments`);
72+
73+
// Get reactions on main issue body
74+
const issue_reactions = await github.paginate(
75+
github.rest.reactions.listForIssue,
76+
{ ...repo, issue_number }
77+
);
78+
console.log(`Found ${issue_reactions.length} reactions on issue body`);
79+
80+
issue_reactions.forEach(r => {
81+
const reactor = r.user.login.toLowerCase();
82+
all_participants.add(reactor);
83+
console.log(`Added issue reactor: ${reactor}`);
84+
});
85+
86+
console.log(`Total unique participants before bot filtering: ${all_participants.size}`);
87+
console.log(`Participants: ${Array.from(all_participants).join(', ')}`);
88+
89+
// Filter out bot users
90+
const isBotUser = (username) => {
91+
const lowerUsername = username.toLowerCase();
92+
return lowerUsername.endsWith('[bot]') ||
93+
lowerUsername === 'dependabot' ||
94+
lowerUsername === 'renovate' ||
95+
lowerUsername === 'greenkeeper' ||
96+
lowerUsername === 'codecov' ||
97+
lowerUsername === 'coveralls' ||
98+
lowerUsername.startsWith('dependabot[') ||
99+
lowerUsername.includes('-bot') ||
100+
lowerUsername.includes('_bot');
101+
};
102+
103+
// Convert Set to array and filter out bots
104+
const all_users = Array.from(all_participants).filter(user => !isBotUser(user));
105+
106+
const filteredBots = Array.from(all_participants).filter(user => isBotUser(user));
107+
console.log(`Filtered out ${filteredBots.length} bot users: ${filteredBots.join(', ')}`);
108+
console.log(`Final participants count: ${all_users.length}`);
109+
console.log(`Final participants: ${all_users.join(', ')}`);
110+
111+
if (all_users.length === 0) {
112+
console.log("No participants to mention after filtering");
113+
const fs = require('fs');
114+
fs.appendFileSync(process.env.GITHUB_ENV, 'MENTIONS=\n');
115+
return;
116+
}
117+
118+
const mentions = all_users.map(u => `@${u}`).join(' ');
119+
console.log(`Generated mentions: ${mentions}`);
120+
console.log(`Setting environment variable 'MENTIONS' to: "${mentions}"`);
121+
122+
const fs = require('fs');
123+
fs.appendFileSync(process.env.GITHUB_ENV, `MENTIONS=${mentions}\n`);
124+
return { mentions: mentions };
125+
result-encoding: string
126+
127+
- name: Add label comment
128+
uses: actions/github-script@v7
129+
with:
130+
script: |
131+
console.log("=== STEP 2: ADD COMMENT ===");
132+
console.log("Environment variable access:");
133+
console.log("process.env.MENTIONS:", process.env.MENTIONS);
134+
135+
const mentions = process.env.MENTIONS || '';
136+
const labelName = context.payload.label.name;
137+
138+
console.log(`Processing label: ${labelName}`);
139+
console.log(`Mentions received: "${mentions}"`);
140+
console.log(`Mentions length: ${mentions.length}`);
141+
console.log(`Mentions trimmed length: ${mentions.trim().length}`);
142+
143+
let message;
144+
145+
if (labelName === 'prerelease') {
146+
console.log("Processing prerelease label");
147+
if (mentions.trim() === "") {
148+
console.log("No participants to mention for prerelease. Skipping comment creation.");
149+
return;
150+
}
151+
message = `${mentions}\n\nA fix for this issue is now available in the next pre-releases of C#DK/C#. If you'd like to try out the fix, please see [these instructions](https://github.com/microsoft/vscode-dotnettools/wiki/Installing-and-updating-pre%E2%80%90release-versions-of-C%23-Dev-Kit-and-C%23-Extension) to update or try pre-release versions.`;
152+
console.log("Generated prerelease message");
153+
} else if (labelName === 'fixed') {
154+
console.log("Processing fixed label");
155+
message = mentions.trim() !== ""
156+
? `${mentions}\n\nThis issue has been fixed! Please update to the latest versions of VS Code, C# Dev Kit, and the C# extension.`
157+
: `This issue has been fixed! Please update to the latest versions of VS Code, C# Dev Kit, and the C# extension.`;
158+
console.log(`Generated fixed message ${mentions.trim() !== "" ? "with" : "without"} mentions`);
159+
}
160+
161+
console.log(`Final message length: ${message.length}`);
162+
console.log(`Creating comment on issue #${context.payload.issue.number}`);
163+
164+
await github.rest.issues.createComment({
165+
...context.repo,
166+
issue_number: context.payload.issue.number,
167+
body: message
168+
});
169+
170+
console.log("Comment created successfully");
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Reusable - Create Release from Changelog
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
tag:
7+
description: Tag name to create a release for (e.g. v2.88.0 or v2.88.0-prerelease)
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
create-release:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout tag
19+
uses: actions/checkout@v4
20+
with:
21+
ref: refs/tags/${{ inputs.tag }}
22+
23+
- name: Create release from CHANGELOG
24+
uses: actions/github-script@v7
25+
env:
26+
TAG: ${{ inputs.tag }}
27+
with:
28+
github-token: ${{ secrets.GITHUB_TOKEN }}
29+
script: |
30+
const { readFile } = require('fs/promises');
31+
32+
const tag = process.env.TAG;
33+
core.info(`Creating release for tag: ${tag}`);
34+
35+
if (!tag || !tag.startsWith('v2.')) {
36+
core.setFailed('Invalid tag name. Tag name must start with "v2."');
37+
return;
38+
}
39+
40+
// Read CHANGELOG.md and extract the latest section (first single '#' header)
41+
const changelog = await readFile('CHANGELOG.md', 'utf8');
42+
const headerMatch = changelog.match(/^# .+$/m);
43+
if (!headerMatch) {
44+
core.setFailed('Could not find a top-level # header in CHANGELOG.md');
45+
return;
46+
}
47+
const startIdx = changelog.indexOf(headerMatch[0]);
48+
let endIdx = changelog.indexOf('\n# ', startIdx + headerMatch[0].length);
49+
if (endIdx === -1) {
50+
endIdx = changelog.length;
51+
}
52+
const releaseNotes = changelog.substring(startIdx, endIdx).trim();
53+
54+
const isPrerelease = tag.includes('-prerelease');
55+
core.info(`Prerelease: ${isPrerelease}`);
56+
57+
try {
58+
const response = await github.rest.repos.createRelease({
59+
owner: context.repo.owner,
60+
repo: context.repo.repo,
61+
tag_name: tag,
62+
name: tag,
63+
body: releaseNotes,
64+
prerelease: isPrerelease,
65+
});
66+
core.info(`Release created: ${response.data.html_url}`);
67+
} catch (err) {
68+
if (err && err.status === 422 && err.message && String(err.message).includes('already_exists')) {
69+
core.warning(`Release for tag '${tag}' already exists.`);
70+
} else {
71+
core.setFailed(`Error creating release: ${err?.message ?? err}`);
72+
}
73+
}

.mocharc.jsonc

Lines changed: 0 additions & 6 deletions
This file was deleted.
File renamed without changes.

.vscode/launch.json

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,38 @@
1111
"outFiles": ["${workspaceRoot}/dist/*.js"],
1212
"preLaunchTask": "packageDev"
1313
},
14+
{
15+
"name": "[Untrusted] Run Integration Test",
16+
"type": "extensionHost",
17+
"request": "launch",
18+
"runtimeExecutable": "${execPath}",
19+
"args": [
20+
// Launch VSCode using a specific profile to ensure that user settings are not used.
21+
// This profile must be imported into vscode before running this launch configuration.
22+
// The profile can be found under /test/csharp-test-profile.
23+
"--profile",
24+
"csharp-test-profile",
25+
"${workspaceRoot}/test/untrustedWorkspace/integrationTests/testAssets/empty/.vscode/empty.code-workspace",
26+
"--extensionDevelopmentPath=${workspaceRoot}",
27+
"--extensionTestsPath=${workspaceRoot}/out/test/untrustedWorkspace/integrationTests",
28+
"--log",
29+
"ms-dotnettools.csharp:trace"
30+
],
31+
"env": {
32+
"CODE_EXTENSIONS_PATH": "${workspaceRoot}",
33+
},
34+
"sourceMaps": true,
35+
"outFiles": [
36+
"${workspaceRoot}/dist/*.js",
37+
"${workspaceRoot}/out/test/**/*.js"
38+
],
39+
"resolveSourceMapLocations": [
40+
"${workspaceFolder}/**",
41+
"!**/node_modules/**"
42+
],
43+
"preLaunchTask": "packageDev",
44+
"internalConsoleOptions": "openOnSessionStart"
45+
},
1446
{
1547
"name": "[Roslyn] Run Current File Integration Tests",
1648
"type": "extensionHost",
@@ -187,9 +219,9 @@
187219
"args": ["updatePackageDependencies"],
188220
"env": {
189221
"NEW_DEPS_ID": "OmniSharp",
190-
"NEW_DEPS_URLS": "https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-x64-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-x86-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-arm64-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-osx-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-win-x64-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-win-arm64-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-musl-x64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-musl-arm64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-x64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-linux-arm64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-osx-x64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-osx-arm64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-win-x64-net6.0-1.39.12.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.12/omnisharp-win-arm64-net6.0-1.39.12.zip",
191-
"OLD_DEPS_VERSION": "1.39.11",
192-
"NEW_DEPS_VERSION": "1.39.12"
222+
"NEW_DEPS_URLS": "https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-x64.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-x86.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-arm64.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-osx.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-win-x64.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-win-arm64.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-musl-x64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-musl-arm64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-x64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-linux-arm64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-osx-x64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-osx-arm64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-win-x64-net6.0.zip,https://roslynomnisharp.blob.core.windows.net/releases/1.39.14/omnisharp-win-arm64-net6.0.zip",
223+
"OLD_DEPS_VERSION": "1.39.12",
224+
"NEW_DEPS_VERSION": "1.39.14"
193225
},
194226
"cwd": "${workspaceFolder}"
195227
},

.vscode/tasks.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"group": {
1616
"kind": "build",
1717
"isDefault": true
18-
}
18+
},
19+
"problemMatcher": "$tsc",
1920
},
2021
{
2122
"label": "buildDev",
@@ -25,7 +26,8 @@
2526
"group": {
2627
"kind": "build",
2728
"isDefault": true
28-
}
29+
},
30+
"problemMatcher": "$tsc",
2931
},
3032
{
3133
"label": "package",
@@ -35,7 +37,8 @@
3537
"group": {
3638
"kind": "build",
3739
"isDefault": true
38-
}
40+
},
41+
"problemMatcher": "$tsc",
3942
},
4043
{
4144
"label": "packageDev",
@@ -45,7 +48,8 @@
4548
"group": {
4649
"kind": "build",
4750
"isDefault": true
48-
}
51+
},
52+
"problemMatcher": "$tsc",
4953
},
5054
{
5155
"label": "test",

.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typings/**
2929
vsix/**
3030
node_modules
3131
azure-pipelines
32+
init.ps1
3233

3334
**/*.map
3435
*.vsix

0 commit comments

Comments
 (0)