Skip to content

Commit 75e5ace

Browse files
authored
Merge branch 'main' into bryanchen-d/bump-xterm-overview-ruler-fix
2 parents 5e51757 + 5c4d9a2 commit 75e5ace

274 files changed

Lines changed: 14124 additions & 2601 deletions

File tree

Some content is hidden

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

.github/workflows/screenshot-test.yml

Lines changed: 82 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ jobs:
2222
screenshots:
2323
name: Checking Component Screenshots
2424
runs-on: ubuntu-latest
25-
continue-on-error: true # TODO(hediet): Remove once screenshot pipeline is stable
2625
steps:
2726
- name: Checkout
2827
uses: actions/checkout@v6
@@ -78,7 +77,9 @@ jobs:
7877
if (!errs.length) { console.log('No fixture errors.'); process.exit(0); }
7978
console.log(errs.length + ' fixture(s) with errors:');
8079
for (const f of errs) {
81-
console.log('::error::' + f.fixtureId + ': ' + (f.error || 'unknown error'));
80+
const msg = f.error?.message || (typeof f.error === 'string' ? f.error : null) || 'unknown error';
81+
console.log('::error::' + f.fixtureId + ': ' + msg);
82+
if (f.error?.stack) { console.log(' stack: ' + f.error.stack); }
8283
if (f.events?.length) {
8384
for (const e of f.events) { console.log(' event: ' + JSON.stringify(e)); }
8485
}
@@ -88,6 +89,12 @@ jobs:
8889
8990
- name: Check blocks-ci screenshots
9091
id: blocks-ci
92+
# The service URL is baked into the committed blocks-ci-screenshots.md
93+
# as `![screenshot](<service-url>/images/<hash>)` (see
94+
# build/lib/screenshotBlocksCi.ts). It is passed here so the script
95+
# regenerates the markdown using the same URL prefix; otherwise the
96+
# equality check against the committed file would always fail. No HTTP
97+
# call is made — the URL is purely a string written into the markdown.
9198
run: |
9299
node build/lib/screenshotBlocksCi.ts \
93100
test/componentFixtures/.screenshots/current/manifest.json \
@@ -104,19 +111,34 @@ jobs:
104111
echo "BLOCKS_CI_EOF" >> "$GITHUB_OUTPUT"
105112
}
106113
107-
- name: Upload screenshots
114+
- name: Upload screenshots as artifact
108115
uses: actions/upload-artifact@v7
109116
with:
110117
name: screenshots
111118
path: test/componentFixtures/.screenshots/current/
112119

113-
- name: Skip notice (fork PR)
114-
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
115-
run: echo "::notice::Skipping screenshot upload and diff — OIDC is not available for fork PRs"
120+
- name: Determine base SHA
121+
id: base
122+
run: |
123+
if [ "${{ github.event_name }}" = "pull_request" ]; then
124+
# For PRs, diff against the merge-base with the target branch.
125+
# This isolates the visual effect of just this PR's divergence
126+
# from target. Using pull_request.base.sha would be wrong: it's
127+
# the target-branch tip at PR creation time and can be stale,
128+
# causing unrelated target-branch commits to show up as diffs.
129+
TARGET_REF="origin/${{ github.event.pull_request.base.ref }}"
130+
git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.ref }}"
131+
BASE_SHA=$(git merge-base "${{ github.sha }}" "$TARGET_REF")
132+
else
133+
# For push events, diff against the parent commit.
134+
BASE_SHA=$(git rev-parse "${{ github.sha }}^")
135+
fi
136+
echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
137+
echo "Using base SHA: $BASE_SHA (base for ${{ github.sha }})"
116138
117-
- name: Get OIDC token
139+
- name: Get OIDC token (non-fork only)
118140
id: oidc
119-
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
141+
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
120142
run: |
121143
TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
122144
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://hediet-screenshots.azurewebsites.net" \
@@ -129,38 +151,63 @@ jobs:
129151
run: |
130152
cd test/componentFixtures/.screenshots/current
131153
zip -qr "$GITHUB_WORKSPACE/screenshots.zip" .
132-
curl -sS -f -X POST "https://hediet-screenshots.azurewebsites.net/upload" \
154+
# Tolerate service outages: warn instead of failing the step so the
155+
# rest of the workflow (and CI) is not blocked when the screenshot
156+
# service is unreachable.
157+
set +e
158+
STATUS=$(curl -sS -o /tmp/screenshot-upload.out -w '%{http_code}' \
159+
-X POST "https://hediet-screenshots.azurewebsites.net/upload" \
133160
-H "Content-Type: application/zip" \
134161
-H "Authorization: Bearer $SCREENSHOT_SERVICE_TOKEN" \
135-
--data-binary @"$GITHUB_WORKSPACE/screenshots.zip"
162+
--data-binary @"$GITHUB_WORKSPACE/screenshots.zip")
163+
CURL_EXIT=$?
164+
set -e
165+
if [ "$CURL_EXIT" -ne 0 ]; then
166+
echo "::warning::Screenshot service unreachable (curl exit $CURL_EXIT) -- skipping upload."
167+
elif [ "${STATUS:0:1}" != "2" ]; then
168+
echo "::warning::Screenshot service returned HTTP $STATUS -- skipping upload."
169+
cat /tmp/screenshot-upload.out || true
170+
else
171+
echo "Uploaded screenshots (HTTP $STATUS)."
172+
fi
136173
env:
137174
SCREENSHOT_SERVICE_TOKEN: ${{ steps.oidc.outputs.token }}
138175

139-
- name: Diff screenshots against merge base
140-
id: diff
141-
if: steps.oidc.outputs.token
176+
- name: Fetch base commit manifest
177+
id: base_manifest
178+
env:
179+
BASE_SHA: ${{ steps.base.outputs.base_sha }}
142180
run: |
143-
if [ "${{ github.event_name }}" = "pull_request" ]; then
144-
# For PRs, diff against the merge-base with the target branch.
145-
# This isolates the visual effect of just this PR's divergence
146-
# from target. Using pull_request.base.sha would be wrong: it's
147-
# the target-branch tip at PR creation time and can be stale,
148-
# causing unrelated target-branch commits to show up as diffs.
149-
TARGET_REF="origin/${{ github.event.pull_request.base.ref }}"
150-
git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.ref }}"
151-
BASE_SHA=$(git merge-base "${{ github.sha }}" "$TARGET_REF")
181+
BASE_MANIFEST=/tmp/base-manifest.json
182+
URL="https://hediet-screenshots.azurewebsites.net/commits/${{ github.repository_owner }}/${{ github.event.repository.name }}/$BASE_SHA"
183+
# Tolerate service outages: bash `set -e` would otherwise abort this
184+
# step if curl can't connect (since the `STATUS=$(...)` substitution
185+
# propagates the non-zero exit). Capture the exit code explicitly
186+
# and emit a warning instead.
187+
set +e
188+
STATUS=$(curl -sS -o "$BASE_MANIFEST" -w '%{http_code}' "$URL")
189+
CURL_EXIT=$?
190+
set -e
191+
if [ "$CURL_EXIT" -ne 0 ]; then
192+
echo "::warning::Screenshot service unreachable (curl exit $CURL_EXIT) -- skipping diff."
193+
elif [ "$STATUS" = "200" ]; then
194+
echo "path=$BASE_MANIFEST" >> "$GITHUB_OUTPUT"
195+
echo "Fetched base manifest for $BASE_SHA"
152196
else
153-
# For push events, diff against the parent commit.
154-
BASE_SHA=$(git rev-parse "${{ github.sha }}^")
197+
echo "::warning::Base manifest unavailable (HTTP $STATUS) -- skipping diff."
198+
cat "$BASE_MANIFEST" || true
155199
fi
156-
echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
157-
echo "Using base SHA: $BASE_SHA (base for ${{ github.sha }})"
200+
201+
- name: Diff screenshots
202+
id: diff
203+
if: steps.base_manifest.outputs.path
204+
run: |
158205
BODY=$(node build/lib/screenshotDiffReport.ts \
159206
https://hediet-screenshots.azurewebsites.net \
160-
${{ github.repository_owner }} \
161-
${{ github.event.repository.name }} \
162-
"$BASE_SHA" \
163-
${{ github.sha }})
207+
"${{ steps.base.outputs.base_sha }}" \
208+
${{ github.sha }} \
209+
"${{ steps.base_manifest.outputs.path }}" \
210+
test/componentFixtures/.screenshots/current/manifest.json)
164211
if [ -n "$BODY" ]; then
165212
echo "has_changes=true" >> "$GITHUB_OUTPUT"
166213
echo "body<<SCREENSHOT_EOF" >> "$GITHUB_OUTPUT"
@@ -170,13 +217,11 @@ jobs:
170217
echo "No screenshot changes to report."
171218
fi
172219
if [ -f .tmp/screenshotDiffReport.json ]; then
173-
echo "::group::Compare response JSON"
220+
echo "::group::Diff JSON"
174221
cat .tmp/screenshotDiffReport.json
175222
echo "::endgroup::"
176223
fi
177224
continue-on-error: true
178-
env:
179-
SCREENSHOT_SERVICE_TOKEN: ${{ steps.oidc.outputs.token }}
180225

181226
- name: Write job summary
182227
if: steps.diff.outputs.has_changes == 'true' || steps.blocks-ci.outputs.match == 'false'
@@ -195,8 +240,8 @@ jobs:
195240
COMMENT_BODY: ${{ steps.diff.outputs.body }}
196241
BLOCKS_CI_CONTENT: ${{ steps.blocks-ci.outputs.content }}
197242

198-
- name: Post PR comment
199-
if: github.event_name == 'pull_request'
243+
- name: Post PR comment (non-fork PR only)
244+
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
200245
uses: actions/github-script@v9
201246
with:
202247
script: |
@@ -262,26 +307,18 @@ jobs:
262307
env:
263308
COMMENT_BODY: ${{ steps.diff.outputs.body }}
264309
BLOCKS_CI_CONTENT: ${{ steps.blocks-ci.outputs.content }}
265-
BASE_SHA: ${{ steps.diff.outputs.base_sha }}
310+
BASE_SHA: ${{ steps.base.outputs.base_sha }}
266311
CURRENT_SHA: ${{ github.sha }}
267312

268313
- name: Fail if blocks-ci hashes changed
269314
if: steps.blocks-ci.outputs.match == 'false'
270315
run: |
271-
echo "::error::blocks-ci screenshot hashes do not match committed file. See PR comment for updated content."
316+
echo "::error::blocks-ci screenshot hashes do not match committed file. See PR comment or job summary for the updated content."
272317
echo ""
273318
echo "Diff between committed and expected blocks-ci-screenshots.md:"
274319
diff -u test/componentFixtures/blocks-ci-screenshots.md /tmp/blocks-ci-updated.md || true
275320
exit 1
276321
277-
# - name: Compare screenshots
278-
# id: compare
279-
# run: |
280-
# ./node_modules/.bin/component-explorer screenshot:compare \
281-
# --project ./test/componentFixtures \
282-
# --report ./test/componentFixtures/.screenshots/report
283-
# continue-on-error: true
284-
285322
# - name: Prepare explorer artifact
286323
# run: |
287324
# mkdir -p /tmp/explorer-artifact/screenshot-report
@@ -296,14 +333,6 @@ jobs:
296333
# name: component-explorer
297334
# path: /tmp/explorer-artifact/
298335

299-
# - name: Upload screenshot report
300-
# if: steps.compare.outcome == 'failure'
301-
# uses: actions/upload-artifact@v7
302-
# with:
303-
# name: screenshot-diff
304-
# path: |
305-
# test/componentFixtures/.screenshots/current/
306-
# test/componentFixtures/.screenshots/report/
307336

308337
# - name: Set check title
309338
# env:
@@ -339,29 +368,3 @@ jobs:
339368
# {"state":"$STATE","target_url":"$DETAILS_URL","description":"$TITLE","context":"Component Screenshots"}
340369
# EOF
341370

342-
# - name: Post PR comment
343-
# if: github.event_name == 'pull_request'
344-
# env:
345-
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
346-
# run: |
347-
# COMMENT_MARKER="<!-- screenshot-report -->"
348-
# BODY="$COMMENT_MARKER"$'\n'
349-
#
350-
# if [ -f test/componentFixtures/.screenshots/report.md ]; then
351-
# BODY+=$(cat test/componentFixtures/.screenshots/report.md)
352-
# BODY+=$'\n\n'
353-
# BODY+="📦 [Download the \`screenshot-diff\` artifact](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) to review images."
354-
# else
355-
# BODY+="## Screenshots ✅"$'\n\n'
356-
# BODY+="No visual changes detected."
357-
# fi
358-
#
359-
# # Find existing comment
360-
# EXISTING=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \
361-
# --paginate --jq ".[] | select(.body | startswith(\"$COMMENT_MARKER\")) | .id" | head -1)
362-
#
363-
# if [ -n "$EXISTING" ]; then
364-
# gh api "repos/${{ github.repository }}/issues/comments/$EXISTING" -X PATCH -f body="$BODY"
365-
# else
366-
# gh pr comment "${{ github.event.pull_request.number }}" --body "$BODY"
367-
# fi

.vscode/notebooks/endgame.github-issues

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{
88
"kind": 2,
99
"language": "github-issues",
10-
"value": "$MILESTONE=milestone:\"1.119.0\"\n\n$TPI_CREATION=2026-03-23 // Used to find fixes that need to be verified"
10+
"value": "$MILESTONE=milestone:\"1.120.0\"\n\n$TPI_CREATION=2026-03-23 // Used to find fixes that need to be verified"
1111
},
1212
{
1313
"kind": 1,

.vscode/notebooks/my-endgame.github-issues

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{
88
"kind": 2,
99
"language": "github-issues",
10-
"value": "$MILESTONE=milestone:\"1.119.0\"\n\n$MINE=assignee:@me"
10+
"value": "$MILESTONE=milestone:\"1.120.0\"\n\n$MINE=assignee:@me"
1111
},
1212
{
1313
"kind": 2,

build/gulpfile.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { compileExtensionMediaTask, compileExtensionsTask, watchExtensionsTask }
1313
import * as compilation from './lib/compilation.ts';
1414
import * as task from './lib/task.ts';
1515
import * as util from './lib/util.ts';
16+
import { runEsbuildTranspile } from './lib/esbuild.ts';
1617

1718
// Extension point names
1819
gulp.task(compilation.compileExtensionPointNamesTask);
@@ -23,9 +24,11 @@ const require = createRequire(import.meta.url);
2324
gulp.task(compilation.compileApiProposalNamesTask);
2425
gulp.task(compilation.watchApiProposalNamesTask);
2526

26-
// SWC Client Transpile
27-
const transpileClientSWCTask = task.define('transpile-client-esbuild', task.series(util.rimraf('out'), compilation.transpileTask('src', 'out', true)));
28-
gulp.task(transpileClientSWCTask);
27+
// Client Transpile
28+
gulp.task(task.define('transpile-client-esbuild', task.series(
29+
compilation.copyCodiconsTask,
30+
task.define('esbuild-out-build', () => runEsbuildTranspile('out', false)),
31+
)));
2932

3033
// Transpile only
3134
const transpileClientTask = task.define('transpile-client', task.series(util.rimraf('out'), compilation.transpileTask('src', 'out')));

build/gulpfile.vscode.ts

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ import { useEsbuildTranspile } from './buildConfig.ts';
3737
import { promisify } from 'util';
3838
import globCallback from 'glob';
3939
import rceditCallback from 'rcedit';
40-
import * as cp from 'child_process';
4140
import { spawnTsgo } from './lib/tsgo.ts';
41+
import { runEsbuildTranspile, runEsbuildBundle } from './lib/esbuild.ts';
4242

4343

4444
const glob = promisify(globCallback);
@@ -166,63 +166,6 @@ const bundleVSCodeTask = task.define('bundle-vscode', task.series(
166166
));
167167
gulp.task(bundleVSCodeTask);
168168

169-
// esbuild-based bundle tasks (drop-in replacement for bundle-vscode / minify-vscode)
170-
function runEsbuildTranspile(outDir: string, excludeTests: boolean): Promise<void> {
171-
return new Promise((resolve, reject) => {
172-
const scriptPath = path.join(root, 'build/next/index.ts');
173-
const args = [scriptPath, 'transpile', '--out', outDir];
174-
if (excludeTests) {
175-
args.push('--exclude-tests');
176-
}
177-
178-
const proc = cp.spawn(process.execPath, args, {
179-
cwd: root,
180-
stdio: 'inherit'
181-
});
182-
183-
proc.on('error', reject);
184-
proc.on('close', code => {
185-
if (code === 0) {
186-
resolve();
187-
} else {
188-
reject(new Error(`esbuild transpile failed with exit code ${code} (outDir: ${outDir})`));
189-
}
190-
});
191-
});
192-
}
193-
194-
function runEsbuildBundle(outDir: string, minify: boolean, nls: boolean, target: 'desktop' | 'server' | 'server-web' = 'desktop', sourceMapBaseUrl?: string): Promise<void> {
195-
return new Promise((resolve, reject) => {
196-
// const tsxPath = path.join(root, 'build/node_modules/tsx/dist/cli.mjs');
197-
const scriptPath = path.join(root, 'build/next/index.ts');
198-
const args = [scriptPath, 'bundle', '--out', outDir, '--target', target];
199-
if (minify) {
200-
args.push('--minify');
201-
args.push('--mangle-privates');
202-
}
203-
if (nls) {
204-
args.push('--nls');
205-
}
206-
if (sourceMapBaseUrl) {
207-
args.push('--source-map-base-url', sourceMapBaseUrl);
208-
}
209-
210-
const proc = cp.spawn(process.execPath, args, {
211-
cwd: root,
212-
stdio: 'inherit'
213-
});
214-
215-
proc.on('error', reject);
216-
proc.on('close', code => {
217-
if (code === 0) {
218-
resolve();
219-
} else {
220-
reject(new Error(`esbuild bundle failed with exit code ${code} (outDir: ${outDir}, minify: ${minify}, nls: ${nls}, target: ${target})`));
221-
}
222-
});
223-
});
224-
}
225-
226169
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
227170
const isCI = !!process.env['CI'] || !!process.env['BUILD_ARTIFACTSTAGINGDIRECTORY'] || !!process.env['GITHUB_WORKSPACE'];
228171
const useCdnSourceMapsForPackagingTasks = isCI;
@@ -260,16 +203,6 @@ gulp.task(task.define('core-ci', task.series(
260203
)
261204
)));
262205

263-
const coreCIPR = task.define('core-ci-pr', task.series(
264-
gulp.task('compile-build-without-mangling') as task.Task,
265-
task.parallel(
266-
gulp.task('minify-vscode') as task.Task,
267-
gulp.task('minify-vscode-reh') as task.Task,
268-
gulp.task('minify-vscode-reh-web') as task.Task,
269-
)
270-
));
271-
gulp.task(coreCIPR);
272-
273206
/**
274207
* Compute checksums for some files.
275208
*

0 commit comments

Comments
 (0)