Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f0e99fe
Add independent VS Code extension releases
jakebailey Sep 2, 2026
c600717
Require real signing for extension releases
jakebailey Sep 2, 2026
b99e410
Open a PR for extension version bumps
jakebailey Sep 3, 2026
9e5a0e2
Isolate extension bump credentials
jakebailey Sep 3, 2026
980acb4
Make extension bump workflow resumable
jakebailey Sep 3, 2026
7225576
Refine extension release workflow inputs
jakebailey Sep 3, 2026
4844ad5
Automate VS Code extension release tagging
jakebailey Sep 3, 2026
986fbb6
Restrict manual release tags to main
jakebailey Sep 3, 2026
7a8559f
Simplify automatic extension release tagging
jakebailey Sep 3, 2026
5dfbe43
Make automatic release tagging idempotent
jakebailey Sep 3, 2026
e6a159b
Serialize automatic release tagging
jakebailey Sep 3, 2026
810aa9b
Remove redundant Marketplace version checks
jakebailey Sep 4, 2026
f4a7b90
Remove obsolete placeholder version checks
jakebailey Sep 4, 2026
da43566
Add manual extension publish approval
jakebailey Sep 4, 2026
fd480d6
Use existing TypeScript approval team
jakebailey Sep 4, 2026
4e2c401
Remove stale Marketplace auth precheck
jakebailey Sep 4, 2026
bbdce34
Use DevDiv Key Vault for GitHub releases
jakebailey Sep 4, 2026
7464a7a
Use central npm package proxy in Azure
jakebailey Sep 4, 2026
73da4b2
Share pinned vsce release setup
jakebailey Sep 4, 2026
4aa9f3e
Check release pipelines use pinned vsce
jakebailey Sep 4, 2026
fa6e27e
Validate active vsce pipeline configuration
jakebailey Sep 4, 2026
744e7e3
Harden VS Code extension releases
jakebailey Sep 4, 2026
51383b7
Preserve existing extension release assets
jakebailey Sep 4, 2026
71e5a2d
Reject noncanonical extension versions
jakebailey Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions .github/workflows/bump-vscode-typescript.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
name: Bump vscode-typescript

on:
workflow_dispatch:
inputs:
bump:
description: Version component to bump
required: true
type: choice
options:
- patch
- minor
- major

run-name: Bump vscode-typescript (${{ inputs.bump }})

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
prepare:
if: github.repository == 'microsoft/TypeScript'
runs-on: ubuntu-latest
outputs:
source-sha: ${{ steps.source.outputs.sha }}

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: main
filter: blob:none
fetch-depth: 0
persist-credentials: false

- name: Record source commit
id: source
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 'lts/*'

- run: npm ci

- name: Update extension version
env:
BUMP: ${{ inputs.bump }}
run: |
set -euo pipefail
npm version "$BUMP" \
--workspace native-preview \
--no-git-tag-version \

packageVersion="$(jq -r '.version' packages/vscode-typescript/package.json)"
lockVersion="$(jq -r '.packages["packages/vscode-typescript"].version' package-lock.json)"
if [ "$packageVersion" != "$lockVersion" ]; then
echo "package.json version $packageVersion does not match package-lock.json version $lockVersion." >&2
exit 1
fi

- run: npm test -w native-preview

- name: Package extension
run: npx hereby vscode-typescript:pack --forRelease --vscodeTypescriptRelease

- name: Create version bump patch
run: git diff --binary -- packages/vscode-typescript/package.json package-lock.json > vscode-typescript-bump.patch

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: vscode-typescript-bump
path: vscode-typescript-bump.patch
if-no-files-found: error

create-pr:
needs: prepare
if: github.repository == 'microsoft/TypeScript'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
environment:
name: azure
deployment: false

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.prepare.outputs.source-sha }}
filter: blob:none
fetch-depth: 0
persist-credentials: false

- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: vscode-typescript-bump
path: ${{ runner.temp }}

- name: Apply version bump
run: |
set -euo pipefail
git apply --index "$RUNNER_TEMP/vscode-typescript-bump.patch"

mapfile -t changedFiles < <(git diff --cached --name-only)
expectedFiles=("package-lock.json" "packages/vscode-typescript/package.json")
if [ "${changedFiles[*]}" != "${expectedFiles[*]}" ]; then
echo "Unexpected files in version bump: ${changedFiles[*]}" >&2
exit 1
fi

- uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

- name: Create GitHub App token
id: app-token
uses: microsoft/create-github-app-token-via-key-vault@5ba0d436e9c3cac52feff4d1f2f66f9698ce4a2d # v1
with:
client-id: ${{ vars.TYPESCRIPT_AUTOMATION_GITHUB_APP_CLIENT_ID }}
key-id: ${{ vars.TYPESCRIPT_AUTOMATION_GITHUB_APP_KEY_ID }}
owner: microsoft
repositories: TypeScript
permission-contents: write
permission-pull-requests: write

- name: Commit, push, and open pull request
env:
SOURCE_SHA: ${{ needs.prepare.outputs.source-sha }}
GITHUB_APP_TOKEN: ${{ steps.app-token.outputs.token }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
set -euo pipefail
EXTENSION_VERSION="$(jq -r '.version' packages/vscode-typescript/package.json)"
branch="vscode-typescript-release/v$EXTENSION_VERSION"
git switch -c "$branch"
git config user.email "290192711+typescript-automation[bot]@users.noreply.github.com"
git config user.name "typescript-automation[bot]"
git config core.hooksPath /dev/null
git commit -m "Bump vscode-typescript to $EXTENSION_VERSION"

basic_auth="$(node -e 'process.stdout.write(Buffer.from("x-access-token:" + process.env.GITHUB_APP_TOKEN).toString("base64"))')"
echo "::add-mask::$basic_auth"
git config --local http.https://github.com/.extraheader "AUTHORIZATION: basic ${basic_auth}"

if git ls-remote --exit-code --heads origin "$branch" >/dev/null; then
git fetch origin "refs/heads/$branch:refs/remotes/origin/$branch"
existingCommit="$(git rev-parse "origin/$branch")"
existingParent="$(git rev-parse "origin/$branch^")"
if [ "$existingParent" != "$SOURCE_SHA" ] || ! git diff --quiet HEAD "$existingCommit"; then
echo "Existing branch $branch does not match this release bump." >&2
exit 1
fi
else
git push --set-upstream origin "$branch"
fi

existingPr="$(gh pr list \
--repo microsoft/TypeScript \
--base main \
--head "$branch" \
--state open \
--json url \
--jq '.[0].url // empty')"
if [ -n "$existingPr" ]; then
echo "Pull request already exists: $existingPr"
else
gh pr create \
--repo microsoft/TypeScript \
--base main \
--head "$branch" \
--title "Bump vscode-typescript to $EXTENSION_VERSION" \
--body "Updates the vscode-typescript extension to $EXTENSION_VERSION."
fi
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
- uses: ./.github/actions/setup-go
- run: npm ci
- run: npx hereby typescript:release --forRelease --setPrerelease dev.0.0
- run: npx hereby vscode-typescript:release --forRelease --vscodeTypescriptRelease

extension:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -331,6 +332,7 @@ jobs:
- run: npm ci
- run: go -C ./tools run ./cmd/checkmodpaths "$PWD"
- run: npx hereby check:herebyfile
- run: npx hereby check:vsce-version
- run: npx hereby check:scripts
- run: npx hereby typescript:check-platforms

Expand Down
116 changes: 116 additions & 0 deletions .github/workflows/tag-vscode-typescript.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Tag vscode-typescript release

on:
pull_request_target:
types: [closed]
branches: [main]
paths:
- packages/vscode-typescript/package.json

run-name: Tag vscode-typescript release

concurrency:
group: tag-vscode-typescript-${{ github.event.pull_request.merge_commit_sha }}
cancel-in-progress: false

permissions:
contents: read
id-token: write

defaults:
run:
shell: bash

jobs:
tag:
if: >-
github.repository == 'microsoft/TypeScript' &&
github.event.pull_request.merged == true
runs-on: ubuntu-latest
environment:
name: azure
deployment: false

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
filter: blob:none
fetch-depth: 2
persist-credentials: false

- name: Check for extension version bump
id: version
run: |
set -euo pipefail
packagePath="packages/vscode-typescript/package.json"
previousVersion="$(git show "HEAD^:$packagePath" | jq -r '.version')"
version="$(jq -r '.version' "$packagePath")"

if [ "$previousVersion" = "$version" ]; then
echo "$packagePath changed without changing its version."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi

if ! [[ "$version" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
echo "Invalid extension version: $version" >&2
exit 1
fi

lockVersion="$(jq -r '.packages["packages/vscode-typescript"].version' package-lock.json)"
if [ "$version" != "$lockVersion" ]; then
echo "package.json version $version does not match package-lock.json version $lockVersion." >&2
exit 1
fi

echo "changed=true" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"

- uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0
if: steps.version.outputs.changed == 'true'
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

- name: Create GitHub App token
if: steps.version.outputs.changed == 'true'
id: app-token
uses: microsoft/create-github-app-token-via-key-vault@5ba0d436e9c3cac52feff4d1f2f66f9698ce4a2d # v1
with:
client-id: ${{ vars.TYPESCRIPT_AUTOMATION_GITHUB_APP_CLIENT_ID }}
key-id: ${{ vars.TYPESCRIPT_AUTOMATION_GITHUB_APP_KEY_ID }}
owner: microsoft
repositories: TypeScript
permission-contents: write

- name: Create release tag
if: steps.version.outputs.changed == 'true'
env:
EXTENSION_VERSION: ${{ steps.version.outputs.version }}
GITHUB_APP_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
set -euo pipefail
tag="vscode-typescript/v$EXTENSION_VERSION"
git config user.email "290192711+typescript-automation[bot]@users.noreply.github.com"
git config user.name "typescript-automation[bot]"
git config core.hooksPath /dev/null

basic_auth="$(node -e 'process.stdout.write(Buffer.from("x-access-token:" + process.env.GITHUB_APP_TOKEN).toString("base64"))')"
echo "::add-mask::$basic_auth"
git config --local http.https://github.com/.extraheader "AUTHORIZATION: basic ${basic_auth}"

if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null; then
git fetch origin "refs/tags/$tag:refs/tags/$tag"
existingCommit="$(git rev-list -n 1 "$tag")"
if [ "$existingCommit" != "$(git rev-parse HEAD)" ]; then
echo "Tag $tag already exists at $existingCommit." >&2
exit 1
fi
echo "Tag $tag already exists at the release commit."
exit 0
fi

git tag --annotate "$tag" --message "vscode-typescript $EXTENSION_VERSION"
git push origin "refs/tags/$tag"
Loading