microsoft/TypeScript

18 workflows · maturity 83% · 8 patterns · GitHub ↗

Security 44.44/100

Practices

✓ Matrix✓ Permissions✓ Security scan○ AI review✓ Cache✓ Concurrency○ Reusable workflows

Detected patterns

Security dimensions

permissions
23.6
security scan
20.8
supply chain
0
secret handling
0
harden runner
0

Tools: github/codeql-action/analyze, github/codeql-action/autobuild, github/codeql-action/init, github/codeql-action/upload-sarif, ossf/scorecard-action

Workflows (18)

accept-baselines-fix-lints perms .github/workflows/accept-baselines-fix-lints.yaml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
build
Commands
  • git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" npm ci git rm -r --quiet tests/baselines/reference npx hereby runtests-parallel --ci --fix || true npx hereby baseline-accept npx hereby format git add ./src git add ./tests/baselines/reference git diff --cached git commit -m "Update Baselines, Applied Lint Fixes, and/or Formatted" git push
View raw YAML
name: Accept Baselines, Fix Lints, and Format

on:
  workflow_dispatch: {}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'

      - name: Configure Git, Run Tests, Update Baselines, Apply Fixes
        run: |
          git config user.email "typescriptbot@microsoft.com"
          git config user.name "TypeScript Bot"
          npm ci
          git rm -r --quiet tests/baselines/reference
          npx hereby runtests-parallel --ci --fix || true
          npx hereby baseline-accept
          npx hereby format
          git add ./src
          git add ./tests/baselines/reference
          git diff --cached
          git commit -m "Update Baselines, Applied Lint Fixes, and/or Formatted"
          git push
ci matrix perms .github/workflows/ci.yml
Triggers
push, pull_request, merge_group
Runs on
${{ matrix.config.os }}, self-hosted, 1ES.Pool=TypeScript-1ES-GitHub-Large, 1ES.ImageOverride=azure-linux-3, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest, ubuntu-latest
Jobs
test, coverage, lint, knip, format, browser-integration, typecheck, smoke, package-size, misc, self-check, baselines, required
Matrix
config, config.bundle, config.node-version, config.os, config.skip, exclude, exclude.config→ ${{ github.event_name == 'merge_group' }}, ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}, 14, 16, 18, 20, 22, 24, False, True, lts/*, macos-latest, ubuntu-latest, windows-latest
Actions
codecov/codecov-action
Commands
  • npm ci
  • npm run test -- --no-lint --bundle="$BUNDLE"
  • npx hereby baseline-accept git add tests/baselines/reference git diff --staged --exit-code
  • npm ci
  • npm test -- --no-lint --coverage
  • npm ci
  • npm run lint
  • npm ci
View raw YAML
name: CI

on:
  push:
    branches:
      - main
      - release-*
  pull_request:
    branches:
      - main
      - release-*
  merge_group:
    branches:
      - main
      # - release-*

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  test:
    strategy:
      fail-fast: ${{ github.event_name == 'merge_group' }}
      matrix:
        config:
          # PRs only check the newest and oldest Node versions.
          # macOS only ever checks the neest and oldest Node versions, but never in PR runs.
          - os: ubuntu-latest
            node-version: '24'
            bundle: true
          - os: windows-latest
            node-version: '24'
            bundle: true
            skip: ${{ github.event_name == 'merge_group' }}
          - os: macos-latest
            node-version: '24'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}

          - os: ubuntu-latest
            node-version: '22'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
          - os: windows-latest
            node-version: '22'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}

          - os: ubuntu-latest
            node-version: '20'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
          - os: windows-latest
            node-version: '20'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}

          - os: ubuntu-latest
            node-version: '18'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
          - os: windows-latest
            node-version: '18'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}

          - os: ubuntu-latest
            node-version: '16'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
          - os: windows-latest
            node-version: '16'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
          - os: macos-latest
            node-version: '16'
            bundle: true
            skip: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}

          - os: ubuntu-latest
            node-version: '14'
            bundle: true
            skip: ${{ github.event_name == 'merge_group' }}
          - os: windows-latest
            node-version: '14'
            bundle: true
            skip: ${{ github.event_name == 'merge_group' }}
            # Node 14 does not support macOS ARM.

          # --no-bundle build
          - os: ubuntu-latest
            node-version: 'lts/*'
            bundle: false
            skip: ${{ github.event_name == 'merge_group' }}

        exclude:
          - config:
              skip: true

    runs-on: ${{ matrix.config.os }}
    name: Test Node ${{ matrix.config.node-version }} on ${{ matrix.config.os }}${{ (!matrix.config.bundle && ' with --no-bundle') || '' }}

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Use node version ${{ matrix.config.node-version }}
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: ${{ matrix.config.node-version }}
          check-latest: true
      - run: npm ci

      - name: Tests
        id: test
        # run tests, but lint separately
        env:
          BUNDLE: ${{ matrix.config.bundle }}
        run: npm run test -- --no-lint --bundle="$BUNDLE"

      - name: Print baseline diff on failure
        if: ${{ failure() && steps.test.conclusion == 'failure' }}
        run: |
          npx hereby baseline-accept
          git add tests/baselines/reference
          git diff --staged --exit-code

  coverage:
    if: ${{ github.event_name != 'merge_group' }}

    runs-on:
      - 'self-hosted'
      - '1ES.Pool=TypeScript-1ES-GitHub-Large'
      - '1ES.ImageOverride=azure-linux-3'

    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Run tests with coverage
        run: npm test -- --no-lint --coverage

      - name: Upload coverage artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: coverage
          path: coverage

      - uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3
        with:
          use_oidc: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork) }}
          disable_search: true
          files: ./coverage/codecov.json

  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Linter
        run: npm run lint

  knip:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Unused exports
        run: npm run knip

  format:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
        with:
          path: ~/.cache/dprint
          key: ${{ runner.os }}-dprint-${{ hashFiles('package-lock.json', '.dprint.jsonc') }}
          restore-keys: |
            ${{ runner.os }}-dprint-

      - name: Check formatting
        run: npx dprint check

  browser-integration:
    if: ${{ github.event_name != 'merge_group' }}

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Installing browsers
        run: npx playwright install --with-deps

      - name: Validate the browser can import TypeScript
        run: npx hereby test-browser-integration

  typecheck:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Build src
        run: npx hereby build-src

  smoke:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version

      - run: npm ci

      - run: npx hereby lkg
      - run: |
          node ./scripts/addPackageJsonGitHead.mjs package.json
          npm pack
          mv typescript*.tgz typescript.tgz
          echo "package=$PWD/typescript.tgz" >> "$GITHUB_OUTPUT"
        id: pack

      - name: Smoke test
        env:
          PACKAGE: ${{ steps.pack.outputs.package }}
        run: |
          cd "$(mktemp -d)"
          npm init --yes
          npm install "$PACKAGE"

          echo "Testing tsc..."
          npx tsc --version

          echo "Testing tsserver..."
          echo '{"seq": 1, "command": "status"}' | npx tsserver

          node $GITHUB_WORKSPACE/scripts/checkModuleFormat.mjs typescript
          node $GITHUB_WORKSPACE/scripts/checkModuleFormat.mjs typescript/lib/tsserverlibrary

  package-size:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          path: pr

      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          path: base
          ref: ${{ github.base_ref }}

      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm

      - run: |
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
        working-directory: ./pr

      - run: npm ci
        working-directory: ./pr

      - run: npm ci
        id: base-npm-ci
        continue-on-error: true
        working-directory: ./base

      - run: npx hereby lkg
        working-directory: ./pr

      - run: npx hereby lkg
        id: base-lkg
        continue-on-error: true
        if: ${{ steps.base-npm-ci.outcome == 'success' }}
        working-directory: ./base

      - run: |
          echo "See $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID for more info."
          node ./pr/scripts/checkPackageSize.mjs ./base ./pr >> $GITHUB_STEP_SUMMARY
        if: ${{ steps.base-lkg.outcome == 'success' }}

  misc:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Build scripts
        run: npx hereby scripts

      - name: ESLint tests
        run: npx hereby run-eslint-rules-tests

  self-check:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Build tsc
        run: npx hereby tsc

      - name: Clean
        run: npx hereby clean-src

      - name: Self build
        run: npx hereby build-src --built

  baselines:
    if: ${{ github.event_name != 'merge_group' }}

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: npm ci

      - name: Remove all baselines
        run: rm -rf tests/baselines/reference

      - name: Run tests
        run: npm test &> /dev/null || exit 0

      - name: Accept baselines
        run: |
          npx hereby baseline-accept
          git add tests/baselines/reference

      - name: Check baselines
        id: check-baselines
        run: |
          function print_diff() {
            if ! git diff --staged --exit-code --quiet --diff-filter=$1; then
              echo "$2:"
              git diff --staged --name-only --diff-filter=$1
            fi
          }

          if ! git diff --staged --exit-code --quiet; then
            print_diff ACR "Missing baselines"
            print_diff MTUXB "Modified baselines"
            print_diff D "Unused baselines"
            git diff --staged > fix_baselines.patch
            exit 1
          fi

      - name: Upload baseline diff artifact
        if: ${{ failure() && steps.check-baselines.conclusion == 'failure' }}
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: fix_baselines.patch
          path: fix_baselines.patch

  required:
    runs-on: ubuntu-latest
    if: ${{ always() }}
    needs:
      - test
      - coverage
      - lint
      - knip
      - format
      - browser-integration
      - typecheck
      - smoke
      - package-size
      - misc
      - self-check
      - baselines

    steps:
      - name: Check required jobs
        env:
          NEEDS: ${{ toJson(needs) }}
        run: |
          ! echo $NEEDS | jq -e 'to_entries[] | { job: .key, result: .value.result } | select((.result == "success" or .result == "skipped") | not)'
close-issues perms .github/workflows/close-issues.yml
Triggers
schedule, workflow_dispatch
Runs on
ubuntu-latest
Jobs
close-issues
Commands
  • DATE=$(date --date='2 days ago' --iso-8601) close_issues() { echo "Closing issues marked as '$1'." for issue in $(gh issue list --limit 100 --label "$1" --repo "$REPO" --state open --search "updated:<$DATE" --json number --jq '.[].number'); do echo "Closing https://github.com/$REPO/issues/$issue" gh issue close $issue --repo "$REPO" --reason "not planned" --comment "This issue has been marked as \"$1\" and has seen no recent activity. It has been automatically closed for house-keeping purposes." done } close_issues "Duplicate" close_issues "Unactionable" close_issues "Not a Defect" close_issues "External" close_issues "Working as Intended" close_issues "Question" close_issues "Out of Scope" close_issues "Declined" close_issues "Won't Fix" close_issues "Too Complex" close_issues "Design Limitation"
View raw YAML
name: Close issues

on:
  schedule:
    - cron: '0 1 * * *'
  workflow_dispatch:

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  close-issues:
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'
    permissions:
      contents: read # Apparently required to create issues
      issues: write

    steps:
      - name: Close issues
        env:
          GH_TOKEN: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          REPO: ${{ github.repository }}
        run: |
          DATE=$(date --date='2 days ago' --iso-8601)

          close_issues() {
            echo "Closing issues marked as '$1'."
            for issue in $(gh issue list --limit 100 --label "$1" --repo "$REPO" --state open --search "updated:<$DATE" --json number --jq '.[].number'); do
              echo "Closing https://github.com/$REPO/issues/$issue"
              gh issue close $issue --repo "$REPO" --reason "not planned" --comment "This issue has been marked as \"$1\" and has seen no recent activity. It has been automatically closed for house-keeping purposes."
            done
          }

          close_issues "Duplicate"
          close_issues "Unactionable"
          close_issues "Not a Defect"
          close_issues "External"
          close_issues "Working as Intended"
          close_issues "Question"
          close_issues "Out of Scope"
          close_issues "Declined"
          close_issues "Won't Fix"
          close_issues "Too Complex"
          close_issues "Design Limitation"
codeql perms security .github/workflows/codeql.yml
Triggers
push, pull_request, schedule
Runs on
ubuntu-latest
Jobs
CodeQL-Build
Actions
github/codeql-action/init, github/codeql-action/autobuild, github/codeql-action/analyze
View raw YAML
name: 'Code Scanning - Action'

on:
  push:
    branches:
      - main
      - release-*
  pull_request:
    branches:
      - main
      - release-*
  schedule:
    #        ┌───────────── minute (0 - 59)
    #        │  ┌───────────── hour (0 - 23)
    #        │  │ ┌───────────── day of the month (1 - 31)
    #        │  │ │ ┌───────────── month (1 - 12 or JAN-DEC)
    #        │  │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
    #        │  │ │ │ │
    #        │  │ │ │ │
    #        │  │ │ │ │
    #        *  * * * *
    - cron: '30 1 * * 0'

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  CodeQL-Build:
    # CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    permissions:
      # required for all workflows
      security-events: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
        with:
          config-file: ./.github/codeql/codeql-configuration.yml
        # Override language selection by uncommenting this and choosing your languages
        # with:
        #   languages: go, javascript, csharp, python, cpp, java

      # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
      # If this step fails, then you should remove it and run the build manually (see below).
      - name: Autobuild
        uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1

      # ℹ️ Command-line programs to run using the OS shell.
      # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

      # ✏️ If the Autobuild fails above, remove it and uncomment the following
      #    three lines and modify them (or add more) to build your code if your
      #    project uses a compiled language

      #- run: |
      #     make bootstrap
      #     make release

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
copilot-setup-steps .github/workflows/copilot-setup-steps.yml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
copilot-setup-steps
Commands
  • npm ci
  • npx hereby check-format || true
View raw YAML
name: 'Copilot Setup Steps'
on: workflow_dispatch

jobs:
  # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
  copilot-setup-steps:
    runs-on: ubuntu-latest

    # Set the permissions to the lowest permissions possible needed for your steps.
    # Copilot will be given its own token for its operations.
    permissions:
      # If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
      contents: read

    # You can define any steps you want, and they will run before the agent starts.
    # If you do not check out your code, Copilot will do this for you.
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
      - run: npm ci
      # pull dprint caches before network access is blocked
      - run: npx hereby check-format || true
create-cherry-pick-pr perms .github/workflows/create-cherry-pick-pr.yml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
open-pr
Actions
microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result
View raw YAML
name: Create cherry pick PR

on:
  workflow_dispatch:
    inputs:
      pr:
        description: PR number to cherry-pick
        required: true
        type: number
      target_branch:
        description: Target branch to cherry-pick to
        required: true
        type: string

      # Inputs provided by the bot
      distinct_id:
        description: '(bot) A distinct ID'
        required: false
        default: ''
      source_issue:
        description: '(bot) The issue that triggered this workflow'
        required: false
        default: ''
      requesting_user:
        description: '(bot) The user who requested this workflow'
        required: false
        default: ''
      status_comment:
        description: '(bot) The comment to update with the status of this workflow'
        required: false
        default: ''

run-name: ${{ github.workflow }}${{ inputs.distinct_id && format(' (bot run {0})', inputs.distinct_id) || '' }}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  open-pr:
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          filter: blob:none # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
          fetch-depth: 0 # Default is 1; need to set to 0 to get the benefits of blob:none.
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}

      - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
        id: open-pr
        env:
          PR: ${{ inputs.pr }}
          TARGET_BRANCH: ${{ inputs.target_branch }}
          DISTINCT_ID: ${{ inputs.distinct_id }}
          SOURCE_ISSUE: ${{ inputs.source_issue }}
          REQUESTING_USER: ${{ inputs.requesting_user }}
          STATUS_COMMENT: ${{ inputs.status_comment }}
        with:
          retries: 3
          github-token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          result-encoding: string
          script: |
            const {
              PR,
              TARGET_BRANCH,
              DISTINCT_ID,
              SOURCE_ISSUE,
              REQUESTING_USER,
              STATUS_COMMENT,
            } = process.env;

            const pr = await github.rest.pulls.get({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: +PR,
            });

            if (!pr.data.merge_commit_sha) throw new Error("No merge commit sha found");

            const pickBranch = `cherry-pick/${PR}/${TARGET_BRANCH}`;

            const title = `🤖 Pick PR #${PR} (${pr.data.title.substring(0, 35)}${pr.data.title.length > 35 ? "..." : ""}) into ${TARGET_BRANCH}`;

            await exec.exec("git", ["config", "user.email", "typescriptbot@microsoft.com"]);
            await exec.exec("git", ["config", "user.name", "TypeScript Bot"]);
            await exec.exec("git", ["switch", "--detach", `origin/${TARGET_BRANCH}`]);
            await exec.exec("git", ["switch", "-c", pickBranch]);

            let updatedBaselinesMessage = "";
            try {
              await exec.exec("git", ["cherry-pick", "-m", "1", pr.data.merge_commit_sha]);
            } catch (e) {
              console.log(e);

              // The cherry-pick failed. If all of the conflicts are in tests/baselines,
              // try to run the tests and accept the new baselines.

              await exec.exec("git", ["add", "tests/baselines"]);
              // This will fail if any other files were modified.
              await exec.exec("git", ["-c", "core.editor=true", "cherry-pick", "--continue"]);

              await exec.exec("npm", ["ci"]);

              try {
                await exec.exec("npm", ["test", "--", "--no-lint"]);
              } catch {
                // Expected to fail.
              }

              await exec.exec("npx", ["hereby", "baseline-accept"]);
              await exec.exec("git", ["add", "tests/baselines"]);
              await exec.exec("git", ["commit", "-m", "Update baselines"]);

              updatedBaselinesMessage = " This involved updating baselines; please check the diff.";
            }

            await exec.exec("git", ["push", "--force", "--set-upstream", "origin", pickBranch]);

            const existingPulls = await github.rest.pulls.list({
              owner: context.repo.owner,
              repo: context.repo.repo,
              head: `${context.repo.owner}:${pickBranch}`,
            });

            let commentBody;

            if (existingPulls.data.length === 0) {
              console.log(`No existing PRs found for ${pickBranch}`);

              const body = `This cherry-pick was triggered by a request on #${PR}.\n\nPlease review the diff and merge if no changes are unexpected.${updatedBaselinesMessage}`;

              const newPr = await github.rest.pulls.create({
                owner: context.repo.owner,
                repo: context.repo.repo,
                base: TARGET_BRANCH,
                head: pickBranch,
                title,
                body,
              });

              await github.rest.issues.addAssignees({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: newPr.data.number,
                assignees: ["DanielRosenwasser"],
              });

              await github.rest.pulls.requestReviewers({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: newPr.data.number,
                reviewers: ["DanielRosenwasser", REQUESTING_USER],
              });

              commentBody = `I've created #${newPr.data.number} for you.${updatedBaselinesMessage}`;
            }
            else {
              const existing = existingPulls.data[0];
              console.log(`Found existing PR #${existing.number} for ${pickBranch}`);

              await github.rest.pulls.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: existing.number,
                title,
              });

              commentBody = `I've updated #${existing.number} for you.${updatedBaselinesMessage}`;
            }

            return commentBody;

      - uses: microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result@master
        if: ${{ !cancelled() && inputs.distinct_id }}
        with:
          success_comment: ${{ steps.open-pr.outputs.result }}
          failure_comment: 'I was unable to cherry-pick this PR.'
          github_token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          distinct_id: ${{ inputs.distinct_id }}
          source_issue: ${{ inputs.source_issue }}
          requesting_user: ${{ inputs.requesting_user }}
          status_comment: ${{ inputs.status_comment }}
insiders perms .github/workflows/insiders.yaml
Triggers
workflow_dispatch, repository_dispatch
Runs on
ubuntu-latest, ubuntu-latest
Jobs
test, publish
Commands
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • npm ci npx hereby configure-insiders npm test
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • npm whoami npm ci npx hereby configure-insiders npx hereby LKG node ./scripts/addPackageJsonGitHead.mjs package.json npm publish --tag insiders
View raw YAML
name: Publish Insiders

on:
  workflow_dispatch: {}
  repository_dispatch:
    types: [publish-insiders]

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  test:
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - name: Test insiders
        run: |
          npm ci
          npx hereby configure-insiders
          npm test

  publish:
    needs: test

    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
          # Use NODE_AUTH_TOKEN environment variable to authenticate to this registry.
          registry-url: https://registry.npmjs.org/
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - name: Setup and publish insiders
        run: |
          npm whoami
          npm ci
          npx hereby configure-insiders
          npx hereby LKG
          node ./scripts/addPackageJsonGitHead.mjs package.json
          npm publish --tag insiders
        env:
          NODE_AUTH_TOKEN: ${{secrets.npm_token}}
lkg perms .github/workflows/lkg.yml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
build
Commands
  • if [[ ! "$BRANCH_NAME" =~ ^release- ]]; then echo "Branch name must start with 'release-'" exit 1 fi
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • npm ci npx hereby LKG git add --force ./lib git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git commit -m 'Update LKG' git push
View raw YAML
name: Update LKG

on:
  workflow_dispatch:
    inputs:
      branch_name:
        description: Release branch name to LKG
        required: true
        type: string

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - env:
          BRANCH_NAME: ${{ inputs.branch_name }}
        run: |
          if [[ ! "$BRANCH_NAME" =~ ^release- ]]; then
            echo "Branch name must start with 'release-'"
            exit 1
          fi

      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ inputs.branch_name }}
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - run: |
          npm ci
          npx hereby LKG
          git add --force ./lib
          git config user.email "typescriptbot@microsoft.com"
          git config user.name "TypeScript Bot"
          git commit -m 'Update LKG'
          git push
new-release-branch perms .github/workflows/new-release-branch.yaml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
build
Actions
microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result
Commands
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • git checkout -b "$BRANCH_NAME" sed -i -e 's/"version": ".*"/"version": "'"$PACKAGE_VERSION"'"/g' package.json sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' src/compiler/corePublic.ts sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' tests/baselines/reference/api/typescript.d.ts sed -i -e 's/const version\(: string\)\{0,1\} = .*;/const version = "'"$PACKAGE_VERSION"'" as string;/g' src/compiler/corePublic.ts npm ci npm install # update package-lock.json to ensure the version bump is included npx hereby LKG npm test git diff git add package.json package-lock.json git add src/compiler/corePublic.ts git add tests/baselines/reference/api/typescript.d.ts git add --force ./lib git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git commit -m "Bump version to $PACKAGE_VERSION and LKG" git push --set-upstream origin "$BRANCH_NAME"
View raw YAML
name: New Release Branch

on:
  workflow_dispatch:
    inputs:
      branch_name:
        description: Release branch name to create
        required: true
        type: string
      package_version:
        description: Release package version
        required: true
        type: string
      core_major_minor:
        description: Release core major.minor version
        required: true
        type: string

      # Inputs provided by the bot
      distinct_id:
        description: '(bot) A distinct ID'
        required: false
        default: ''
      source_issue:
        description: '(bot) The issue that triggered this workflow'
        required: false
        default: ''
      requesting_user:
        description: '(bot) The user who requested this workflow'
        required: false
        default: ''
      status_comment:
        description: '(bot) The comment to update with the status of this workflow'
        required: false
        default: ''

run-name: ${{ github.workflow }}${{ inputs.distinct_id && format(' (bot run {0})', inputs.distinct_id) || '' }}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          filter: blob:none # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
          fetch-depth: 0 # Default is 1; need to set to 0 to get the benefits of blob:none.
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - env:
          BRANCH_NAME: ${{ inputs.branch_name }}
          PACKAGE_VERSION: ${{ inputs.package_version }}
          CORE_MAJOR_MINOR: ${{ inputs.core_major_minor }}
        run: |
          git checkout -b "$BRANCH_NAME"
          sed -i -e 's/"version": ".*"/"version": "'"$PACKAGE_VERSION"'"/g' package.json
          sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' src/compiler/corePublic.ts
          sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' tests/baselines/reference/api/typescript.d.ts
          sed -i -e 's/const version\(: string\)\{0,1\} = .*;/const version = "'"$PACKAGE_VERSION"'" as string;/g' src/compiler/corePublic.ts
          npm ci
          npm install # update package-lock.json to ensure the version bump is included
          npx hereby LKG
          npm test
          git diff
          git add package.json package-lock.json
          git add src/compiler/corePublic.ts
          git add tests/baselines/reference/api/typescript.d.ts
          git add --force ./lib
          git config user.email "typescriptbot@microsoft.com"
          git config user.name "TypeScript Bot"
          git commit -m "Bump version to $PACKAGE_VERSION and LKG"
          git push --set-upstream origin "$BRANCH_NAME"

      - uses: microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result@master
        if: ${{ !cancelled() && inputs.distinct_id }}
        with:
          success_comment: "I've created ${{ inputs.branch_name }} with version ${{ inputs.package_version }} for you."
          failure_comment: 'I was unable to create the new release branch.'
          github_token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          distinct_id: ${{ inputs.distinct_id }}
          source_issue: ${{ inputs.source_issue }}
          requesting_user: ${{ inputs.requesting_user }}
          status_comment: ${{ inputs.status_comment }}
nightly perms .github/workflows/nightly.yaml
Triggers
schedule, workflow_dispatch
Runs on
ubuntu-latest, ubuntu-latest
Jobs
test, publish
Commands
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • npm ci npx hereby configure-nightly npm test
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • npm whoami npm ci npx hereby configure-nightly npx hereby LKG node ./scripts/addPackageJsonGitHead.mjs package.json npm publish --tag next
View raw YAML
name: Publish Nightly

on:
  schedule:
    - cron: '0 7 * * *'
  # enable users to manually trigger with workflow_dispatch
  workflow_dispatch: {}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  test:
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - name: Setup and test nightly
        run: |
          npm ci
          npx hereby configure-nightly
          npm test

  publish:
    needs: [test]
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
          # Use NODE_AUTH_TOKEN environment variable to authenticate to this registry.
          registry-url: https://registry.npmjs.org/
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - name: Setup and publish nightly
        run: |
          npm whoami
          npm ci
          npx hereby configure-nightly
          npx hereby LKG
          node ./scripts/addPackageJsonGitHead.mjs package.json
          npm publish --tag next
        env:
          NODE_AUTH_TOKEN: ${{secrets.npm_token}}
pr-modified-files perms .github/workflows/pr-modified-files.yml
Triggers
pull_request_target
Runs on
ubuntu-latest
Jobs
manage-prs
Commands
  • curl -s https://raw.githubusercontent.com/microsoft/TypeScript/main/.github/pr_owners.txt > pr_owners.txt if grep -Fxq -m1 "$PR_AUTHOR" pr_owners.txt; then echo "pr_owner=true" >> "$GITHUB_OUTPUT" else echo "pr_owner=false" >> "$GITHUB_OUTPUT" fi
  • cat > is_changed.sh <<'EOF' #!/bin/bash FILENAME=changed_files.txt if [ ! -f $FILENAME ]; then # The gh command only returns info for the first 100 files. To get # the rest, we have to use the graphql API. See: # https://github.com/cli/cli/issues/5368#issuecomment-1344253654 gh api graphql -f query=' query($endCursor: String) { repository(owner: "microsoft", name: "TypeScript") { pullRequest(number: '"$PR_NUMBER"') { files(first: 100, after: $endCursor) { pageInfo{ hasNextPage, endCursor } nodes { path } } } } }' --paginate --jq '.data.repository.pullRequest.files.nodes.[].path' > $FILENAME fi for file in "$@"; do grep -Fxq -m1 "$file" $FILENAME && exit 0 done exit 1 EOF chmod +x is_changed.sh cat > already_commented.sh <<'EOF' #!/bin/bash FILENAME=bot_comments.txt if [ ! -f $FILENAME ]; then gh pr view $PR_NUMBER --repo $REPO \ --json 'comments' --jq '.comments[] | select(.author.login == "typescript-bot") | .body' > $FILENAME fi exec grep -Fq -m1 "$1" $FILENAME EOF chmod +x already_commented.sh
  • if ./is_changed.sh "src/lib/dom.generated.d.ts" \ "src/lib/dom.iterable.generated.d.ts" \ "src/lib/webworker.generated.d.ts" \ "src/lib/webworker.iterable.generated.d.ts"; then MESSAGE="It looks like you've sent a pull request to update some generated declaration files related to the DOM." MESSAGE+=" These files aren't meant to be edited by hand, as they are synchronized with files in" MESSAGE+=" [the TypeScript-DOM-lib-generator repository](https://github.com/microsoft/TypeScript-DOM-lib-generator)." MESSAGE+=" You can [read more here](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md#contributing-libdts-fixes)." MESSAGE+=" For house-keeping purposes, this pull request will be closed." gh pr close "$PR_NUMBER" --repo "$REPO" --comment "$MESSAGE" exit 1 # Stop the pipeline; we just closed the PR. fi
  • if ./is_changed.sh "src/server/protocol.ts"; then MESSAGE="Thanks for the PR! It looks like you've changed the TSServer protocol in some way." MESSAGE+=" Please ensure that any changes here don't break consumers of the current TSServer API." MESSAGE+=" For some extra review, we'll ping @sheetalkamat, @mjbvz, and @joj for you." MESSAGE+=" Feel free to loop in other consumers/maintainers if necessary." if ./already_commented.sh "It looks like you've changed the TSServer protocol in some way."; then echo "Already commented." else gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$MESSAGE" fi fi
  • if ./is_changed.sh "tests/baselines/reference/api/typescript.d.ts"; then MESSAGE="Looks like you're introducing a change to the public API surface area." MESSAGE+=" If this includes breaking changes, please document them" MESSAGE+=" [on our wiki's API Breaking Changes page](https://github.com/microsoft/TypeScript/wiki/API-Breaking-Changes)." MESSAGE+=$'\n\n' MESSAGE+="Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up." if ./already_commented.sh "Looks like you're introducing a change to the public API surface area."; then echo "Already commented." else gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$MESSAGE" fi fi
View raw YAML
name: Check modified files
on:
  # For security reasons, we have to use pull_request_target here.
  # This differs from pull_request in that it runs at the _base_ of the PR,
  # e.g. main. This allows us to access secrets. In this workflow, we should
  # never actually clone the PR, as it may contain malicious code.
  # https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
  pull_request_target:
    branches:
      - main

# We only ever need one of these running on a single PR.
# Just let the newest one complete if there are multiple running.
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  manage-prs:
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    # No need to set explicit permissions; we are using typescript-bot's token, not github-actions' token.

    env:
      GH_TOKEN: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      PR_NUMBER: ${{ github.event.pull_request.number }}
      PR_AUTHOR: ${{ github.event.pull_request.user.login }}
      REPO: ${{ github.repository }}

    steps:
      - name: Check if PR author is in pr_owners.txt
        id: pr_owner
        run: |
          curl -s https://raw.githubusercontent.com/microsoft/TypeScript/main/.github/pr_owners.txt > pr_owners.txt
          if grep -Fxq -m1 "$PR_AUTHOR" pr_owners.txt; then
            echo "pr_owner=true" >> "$GITHUB_OUTPUT"
          else
            echo "pr_owner=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Create scripts
        run: |
          cat > is_changed.sh <<'EOF'
            #!/bin/bash
            FILENAME=changed_files.txt
            if [ ! -f $FILENAME ]; then
              # The gh command only returns info for the first 100 files. To get
              # the rest, we have to use the graphql API. See:
              # https://github.com/cli/cli/issues/5368#issuecomment-1344253654
              gh api graphql -f query='
                query($endCursor: String) {
                  repository(owner: "microsoft", name: "TypeScript") {
                    pullRequest(number: '"$PR_NUMBER"') {
                      files(first: 100, after: $endCursor) {
                        pageInfo{ hasNextPage, endCursor }
                        nodes {
                          path
                        }
                      }
                    }
                  }
                }' --paginate --jq '.data.repository.pullRequest.files.nodes.[].path' > $FILENAME
            fi
            for file in "$@"; do
              grep -Fxq -m1 "$file" $FILENAME && exit 0
            done
            exit 1
          EOF
          chmod +x is_changed.sh

          cat > already_commented.sh <<'EOF'
            #!/bin/bash
            FILENAME=bot_comments.txt
            if [ ! -f $FILENAME ]; then
              gh pr view $PR_NUMBER --repo $REPO \
                --json 'comments' --jq '.comments[] | select(.author.login == "typescript-bot") | .body' > $FILENAME
            fi
            exec grep -Fq -m1 "$1" $FILENAME
          EOF
          chmod +x already_commented.sh

      - name: Generated DOM files
        if: steps.pr_owner.outputs.pr_owner == 'false'
        run: |
          if ./is_changed.sh "src/lib/dom.generated.d.ts" \
              "src/lib/dom.iterable.generated.d.ts" \
              "src/lib/webworker.generated.d.ts" \
              "src/lib/webworker.iterable.generated.d.ts"; then
            MESSAGE="It looks like you've sent a pull request to update some generated declaration files related to the DOM."
            MESSAGE+=" These files aren't meant to be edited by hand, as they are synchronized with files in"
            MESSAGE+=" [the TypeScript-DOM-lib-generator repository](https://github.com/microsoft/TypeScript-DOM-lib-generator)."
            MESSAGE+=" You can [read more here](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md#contributing-libdts-fixes)."
            MESSAGE+=" For house-keeping purposes, this pull request will be closed."

            gh pr close "$PR_NUMBER" --repo "$REPO" --comment "$MESSAGE"
            exit 1 # Stop the pipeline; we just closed the PR.
          fi

      - name: Check if PR modifies protocol.ts
        run: |
          if ./is_changed.sh "src/server/protocol.ts"; then
            MESSAGE="Thanks for the PR! It looks like you've changed the TSServer protocol in some way."
            MESSAGE+=" Please ensure that any changes here don't break consumers of the current TSServer API."
            MESSAGE+=" For some extra review, we'll ping @sheetalkamat, @mjbvz, and @joj for you."
            MESSAGE+=" Feel free to loop in other consumers/maintainers if necessary."

            if ./already_commented.sh "It looks like you've changed the TSServer protocol in some way."; then
              echo "Already commented."
            else
              gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$MESSAGE"
            fi
          fi

      - name: Check for breaking changes
        run: |
          if ./is_changed.sh "tests/baselines/reference/api/typescript.d.ts"; then
            MESSAGE="Looks like you're introducing a change to the public API surface area."
            MESSAGE+=" If this includes breaking changes, please document them"
            MESSAGE+=" [on our wiki's API Breaking Changes page](https://github.com/microsoft/TypeScript/wiki/API-Breaking-Changes)."
            MESSAGE+=$'\n\n'
            MESSAGE+="Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up."

            if ./already_commented.sh "Looks like you're introducing a change to the public API surface area."; then
              echo "Already commented."
            else
              gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$MESSAGE"
            fi
          fi
release-branch-artifact perms .github/workflows/release-branch-artifact.yaml
Triggers
push
Runs on
ubuntu-latest
Jobs
build
Commands
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • npm ci npm test
  • npx playwright install --with-deps
  • npx hereby test-browser-integration
  • npx hereby LKG npx hereby clean node ./scripts/addPackageJsonGitHead.mjs package.json npm pack ./ mv typescript-*.tgz typescript.tgz
View raw YAML
name: Create Releasable Package Drop

on:
  push:
    branches:
      - release-*

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      - name: npm install and test
        run: |
          npm ci
          npm test
      - name: Installing browsers
        run: npx playwright install --with-deps
      - name: Validate the browser can import TypeScript
        run: npx hereby test-browser-integration
      - name: LKG, clean, and pack
        run: |
          npx hereby LKG
          npx hereby clean
          node ./scripts/addPackageJsonGitHead.mjs package.json
          npm pack ./
          mv typescript-*.tgz typescript.tgz
      - name: Upload built tarfile
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: tgz
          path: typescript.tgz
scorecard perms security .github/workflows/scorecard.yml
Triggers
branch_protection_rule, schedule, push
Runs on
ubuntu-latest
Jobs
analysis
Actions
ossf/scorecard-action, github/codeql-action/upload-sarif
View raw YAML
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.

name: Scorecard supply-chain security
on:
  # For Branch-Protection check. Only the default branch is supported. See
  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
  branch_protection_rule:
  # To guarantee Maintained check is occasionally updated. See
  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
  schedule:
    - cron: '19 15 * * 4'
  push:
    branches: ['main']

# Declare default permissions as read only.
permissions: read-all

jobs:
  analysis:
    name: Scorecard analysis
    runs-on: ubuntu-latest
    permissions:
      # Needed to upload the results to code-scanning dashboard.
      security-events: write
      # Needed to publish results and get a badge (see publish_results below).
      id-token: write

    steps:
      - name: 'Checkout code'
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: 'Run analysis'
        uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
        with:
          results_file: results.sarif
          results_format: sarif

          # Publish results to OpenSSF REST API for easy access by consumers
          # Allows the repository to include the Scorecard badge.
          # See https://github.com/ossf/scorecard-action#publishing-results.
          publish_results: true

      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
      # format to the repository Actions tab.
      - name: 'Upload artifact'
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: SARIF file
          path: results.sarif
          retention-days: 5

      # Upload the results to GitHub's code scanning dashboard.
      - name: 'Upload to code-scanning'
        uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
        with:
          sarif_file: results.sarif
set-version perms .github/workflows/set-version.yaml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
build
Actions
microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result
Commands
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • sed -i -e 's/"version": ".*"/"version": "'"$PACKAGE_VERSION"'"/g' package.json sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' src/compiler/corePublic.ts sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' tests/baselines/reference/api/typescript.d.ts sed -i -e 's/const version\(: string\)\{0,1\} = .*;/const version = "'"$PACKAGE_VERSION"'" as string;/g' src/compiler/corePublic.ts npm ci npm install # update package-lock.json to ensure the version bump is included npx hereby LKG npm test git diff git add package.json package-lock.json git add src/compiler/corePublic.ts git add tests/baselines/reference/api/typescript.d.ts git add --force ./lib git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git commit -m "Bump version to $PACKAGE_VERSION and LKG" git push
View raw YAML
name: Set branch version

on:
  workflow_dispatch:
    inputs:
      branch_name:
        description: Release branch name to create
        required: true
        type: string
      package_version:
        description: Release package version
        required: true
        type: string
      core_major_minor:
        description: Release core major.minor version
        required: true
        type: string

      # Inputs provided by the bot
      distinct_id:
        description: '(bot) A distinct ID'
        required: false
        default: ''
      source_issue:
        description: '(bot) The issue that triggered this workflow'
        required: false
        default: ''
      requesting_user:
        description: '(bot) The user who requested this workflow'
        required: false
        default: ''
      status_comment:
        description: '(bot) The comment to update with the status of this workflow'
        required: false
        default: ''

run-name: ${{ github.workflow }}${{ inputs.distinct_id && format(' (bot run {0})', inputs.distinct_id) || '' }}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ inputs.branch_name }}
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version
      # notably, this is essentially the same script as `new-release-branch.yaml` (with fewer inputs), but it assumes the branch already exists
      # do note that executing the transform below will prevent the `configurePrerelease` script from running on the source, as it makes the
      # `version` identifier no longer match the regex it uses
      # required client_payload members:
      # branch_name - the target branch
      # package_version - the full version string (eg, `3.9.1-rc` or `3.9.2`)
      # core_major_minor - the major.minor pair associated with the desired package_version (eg, `3.9` for `3.9.3`)
      - env:
          PACKAGE_VERSION: ${{ inputs.package_version }}
          CORE_MAJOR_MINOR: ${{ inputs.core_major_minor }}
        run: |
          sed -i -e 's/"version": ".*"/"version": "'"$PACKAGE_VERSION"'"/g' package.json
          sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' src/compiler/corePublic.ts
          sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "'"$CORE_MAJOR_MINOR"'"/g' tests/baselines/reference/api/typescript.d.ts
          sed -i -e 's/const version\(: string\)\{0,1\} = .*;/const version = "'"$PACKAGE_VERSION"'" as string;/g' src/compiler/corePublic.ts
          npm ci
          npm install # update package-lock.json to ensure the version bump is included
          npx hereby LKG
          npm test
          git diff
          git add package.json package-lock.json
          git add src/compiler/corePublic.ts
          git add tests/baselines/reference/api/typescript.d.ts
          git add --force ./lib
          git config user.email "typescriptbot@microsoft.com"
          git config user.name "TypeScript Bot"
          git commit -m "Bump version to $PACKAGE_VERSION and LKG"
          git push

      - uses: microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result@master
        if: ${{ !cancelled() && inputs.distinct_id }}
        with:
          success_comment: "I've set the version of ${{ inputs.branch_name }} to ${{ inputs.package_version }} for you."
          failure_comment: 'I was unable set the version.'
          github_token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          distinct_id: ${{ inputs.distinct_id }}
          source_issue: ${{ inputs.source_issue }}
          requesting_user: ${{ inputs.requesting_user }}
          status_comment: ${{ inputs.status_comment }}
sync-branch perms .github/workflows/sync-branch.yaml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
build
Actions
microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result
Commands
  • git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git fetch origin main git merge origin/main --no-ff npm ci npx hereby LKG git add --force ./lib git commit -m 'Update LKG' git push
View raw YAML
name: Sync branch with master

on:
  workflow_dispatch:
    inputs:
      branch_name:
        description: Release branch name to create
        required: true
        type: string

      # Inputs provided by the bot
      distinct_id:
        description: '(bot) A distinct ID'
        required: false
        default: ''
      source_issue:
        description: '(bot) The issue that triggered this workflow'
        required: false
        default: ''
      requesting_user:
        description: '(bot) The user who requested this workflow'
        required: false
        default: ''
      status_comment:
        description: '(bot) The comment to update with the status of this workflow'
        required: false
        default: ''

run-name: ${{ github.workflow }}${{ inputs.distinct_id && format(' (bot run {0})', inputs.distinct_id) || '' }}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ inputs.branch_name }}
          filter: blob:none # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
          fetch-depth: 0 # Default is 1; need to set to 0 to get the benefits of blob:none.
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      # required client_payload members:
      # branch_name - the target branch
      - run: |
          git config user.email "typescriptbot@microsoft.com"
          git config user.name "TypeScript Bot"
          git fetch origin main
          git merge origin/main --no-ff
          npm ci
          npx hereby LKG
          git add --force ./lib
          git commit -m 'Update LKG'
          git push

      - uses: microsoft/typescript-bot-test-triggerer/.github/actions/post-workflow-result@master
        if: ${{ !cancelled() && inputs.distinct_id }}
        with:
          success_comment: "I've pulled main into ${{ inputs.branch_name }} for you."
          failure_comment: 'I was unable merge main into ${{ inputs.branch_name }}.'
          github_token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          distinct_id: ${{ inputs.distinct_id }}
          source_issue: ${{ inputs.source_issue }}
          requesting_user: ${{ inputs.requesting_user }}
          status_comment: ${{ inputs.status_comment }}
sync-wiki perms .github/workflows/sync-wiki.yml
Triggers
gollum
Runs on
ubuntu-latest
Jobs
sync
Commands
  • R=${GITHUB_REPOSITORY%?wiki}; echo "BASENAME=${R##*/}" >> $GITHUB_ENV
  • ./.github/workflows/sync
View raw YAML
name: Sync Two Wiki Repos

on: [gollum]

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: Get repo name
        run: R=${GITHUB_REPOSITORY%?wiki}; echo "BASENAME=${R##*/}" >> $GITHUB_ENV
      - name: Checkout ${{ env.BASENAME }}-wiki
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          repository: '${{ GITHUB.repository_owner }}/${{ env.BASENAME }}-wiki'
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          fetch-depth: 0
      - name: Run sync
        run: ./.github/workflows/sync
        env:
          PUSHER: typescript-bot <bot@typescriptlang.org>
          AUTH: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
twoslash-repros perms .github/workflows/twoslash-repros.yaml
Triggers
schedule, repository_dispatch, workflow_dispatch
Runs on
ubuntu-latest
Jobs
run
Actions
microsoft/TypeScript-Twoslash-Repro-Action
View raw YAML
name: Twoslash Code Sample Repros

on:
  schedule:
    - cron: '0 8 * * *'
  repository_dispatch:
    types: [run-twoslash-repros]
  workflow_dispatch:
    inputs:
      issue:
        description: Limits run to a single issue.
        required: false
        type: string
      bisect:
        description: If set, runs a git bisect on an existing repro. Requires 'issue' to be set. Value can be revision labels (e.g. `good v4.7.3 bad main`) or `true` to infer bisect range.
        required: false
        type: string

      # Inputs provided by the bot
      distinct_id:
        description: '(bot) A distinct ID'
        required: false
        default: ''
      source_issue:
        description: '(bot) The issue that triggered this workflow'
        required: false
        default: ''
      requesting_user:
        description: '(bot) The user who requested this workflow'
        required: false
        default: ''
      status_comment:
        description: '(bot) The comment to update with the status of this workflow'
        required: false
        default: ''

run-name: ${{ github.workflow }}${{ inputs.distinct_id && format(' (bot run {0})', inputs.distinct_id) || '' }}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  run:
    if: ${{ github.repository == 'microsoft/TypeScript' }}
    runs-on: ubuntu-latest
    steps:
      - if: ${{ github.event.inputs.bisect }}
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          filter: blob:none # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
          fetch-depth: 0 # Default is 1; need to set to 0 to get the benefits of blob:none.
      - if: ${{ !github.event.inputs.bisect }}
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - uses: microsoft/TypeScript-Twoslash-Repro-Action@master
        with:
          github-token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
          issue: ${{ github.event.inputs.issue }}
          bisect: ${{ github.event.inputs.bisect }}
update-package-lock perms .github/workflows/update-package-lock.yaml
Triggers
schedule, workflow_dispatch
Runs on
ubuntu-latest
Jobs
build
Commands
  • npm --version # corepack enable npm npm install -g $(jq -r '.packageManager' < package.json) npm --version
  • rm package-lock.json npm install if git diff --exit-code --name-only package-lock.json; then echo "No change." else npm test npx hereby LKG git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git add -f package-lock.json git commit -m "Update package-lock.json" git push fi
View raw YAML
name: Update package-lock.json

on:
  schedule:
    # This is probably 6am UTC, which is 10pm PST or 11pm PDT
    # Alternatively, 6am local is also fine
    - cron: '0 6 * * *'
  workflow_dispatch: {}

permissions:
  contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest
    if: github.repository == 'microsoft/TypeScript'

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 'lts/*'
      - run: |
          npm --version
          # corepack enable npm
          npm install -g $(jq -r '.packageManager' < package.json)
          npm --version

      - name: Update package-lock.json and push
        run: |
          rm package-lock.json
          npm install

          if git diff --exit-code --name-only package-lock.json; then
            echo "No change."
          else
            npm test
            npx hereby LKG
            git config user.email "typescriptbot@microsoft.com"
            git config user.name "TypeScript Bot"
            git add -f package-lock.json
            git commit -m "Update package-lock.json"
            git push
          fi