Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Format, lint, build and test on every pull request and on each push to main that changes code.
# The full protected set (TestLocal shards, gate, bound runs, LSP and API oracles, np-suite) stays in
# the revision pipeline (scripts/goport/candidate.sh). This workflow is a fast check that the tree
# builds and its own tests pass on Linux and macOS.
# builds and its own tests pass on Linux (x64 and arm64) and macOS.
name: CI

on:
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
fail-fast: false
matrix:
# Blacksmith runners (the pingdotgg org has the app), as T3 Code uses.
runner: [blacksmith-16vcpu-ubuntu-2404, blacksmith-12vcpu-macos-26]
runner: [blacksmith-16vcpu-ubuntu-2404, blacksmith-16vcpu-ubuntu-2404-arm, blacksmith-12vcpu-macos-26]
runs-on: ${{ matrix.runner }}
timeout-minutes: 120
env:
Expand Down
34 changes: 24 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# Builds, packs and tests the tsc-rs release: the npm packages tsc-rs, @tsc-rs/linux-x64 and
# @tsc-rs/darwin-arm64, and one standalone archive per platform (tsc and the lib files).
# Builds, packs and tests the tsc-rs release: the npm packages tsc-rs, @tsc-rs/linux-x64,
# @tsc-rs/linux-arm64 and @tsc-rs/darwin-arm64, and one standalone archive per platform (tsc and
# the lib files).
#
# A tag v<version> also publishes the npm packages and creates a GitHub release. A stable version
# (v0.1.0) goes to the dist-tag `latest` and a normal release. A prerelease version (v0.2.0-beta.1)
# goes to `next` and a GitHub prerelease. npm trusted publishing (OIDC) authenticates the
# publish: no npm token. Each of the 3 packages trusts this workflow file and the environment `npm`
# publish: no npm token. Each of the 4 packages trusts this workflow file and the environment `npm`
# (npm/README.md, "Trusted publishing"). Pull requests that change the release files, and a manual
# run, do everything but the release and the publish.
#
# These builds are the plain shipped profile (fat LTO), without the PGO and BOLT of
# crates/ts_goport/scripts/build-release.sh, which needs a host with BOLT and the project inputs.
# Linux is static musl and non-PIE, so it starts on any x86-64 Linux, Alpine too (npm/README.md,
# "Linux libc").
# Linux is static musl and non-PIE, so it starts on any x86-64 or arm64 Linux, Alpine too
# (npm/README.md, "Linux libc"). Each Linux tsc builds natively on a Blacksmith runner of its arch.
name: Release

on:
Expand Down Expand Up @@ -73,6 +74,9 @@ jobs:
- platform: linux-x64
target: x86_64-unknown-linux-musl
runner: blacksmith-16vcpu-ubuntu-2404
- platform: linux-arm64
target: aarch64-unknown-linux-musl
runner: blacksmith-16vcpu-ubuntu-2404-arm
# jemalloc does not cross-build for macOS with zig, so this builds on a Mac.
- platform: darwin-arm64
target: aarch64-apple-darwin
Expand All @@ -97,7 +101,11 @@ jobs:
- name: Build
run: |
if [[ $RUNNER_OS == Linux ]]; then
export CC_x86_64_unknown_linux_musl=musl-gcc
target=${{ matrix.target }}
export "CC_${target//-/_}=musl-gcc"
# jemalloc stops at start when the kernel page is bigger than its build page. arm64 kernels
# use 4, 16 or 64 KiB pages; 2^16 covers all three.
[[ $target != aarch64-* ]] || export JEMALLOC_SYS_WITH_LG_PAGE=16
export RUSTFLAGS="-C target-feature=+crt-static -C relocation-model=static"
JEMALLOC_SYS_WITH_MALLOC_CONF=$(sed -n 's/^const JEMALLOC_CONF: &str = "\([^"]*\)";$/\1/p' crates/ts_goport/src/bin/tsgo.rs | head -1)
[[ -n $JEMALLOC_SYS_WITH_MALLOC_CONF ]] || { echo "::error::no JEMALLOC_CONF in bin/tsgo.rs"; exit 1; }
Expand Down Expand Up @@ -179,14 +187,15 @@ jobs:
bins="$RUNNER_TEMP/bins"
chmod +x "$bins"/tsc-*/tsc
scripts/goport/npm-pack.sh --name tsc-rs --package-version "$VERSION" \
--also "darwin-arm64=$bins/tsc-darwin-arm64/tsc" "$RUNNER_TEMP/pkg" "$bins/tsc-linux-x64/tsc"
--also "linux-arm64=$bins/tsc-linux-arm64/tsc" --also "darwin-arm64=$bins/tsc-darwin-arm64/tsc" \
"$RUNNER_TEMP/pkg" "$bins/tsc-linux-x64/tsc"
# One archive per platform: the platform package's lib dir (tsc and the lib files, which a
# noembed tsc reads next to it), LICENSE and NOTICE.txt.
- name: Archives
run: |
pkg="$RUNNER_TEMP/pkg" dist="$RUNNER_TEMP/dist"
mkdir -p "$dist"
for platform in linux-x64 darwin-arm64; do
for platform in linux-x64 linux-arm64 darwin-arm64; do
name="tsc-rs-$VERSION-$platform"
mkdir -p "$RUNNER_TEMP/archive/$name"
cp -r "$pkg/tsc-rs-$platform/lib/." "$pkg/tsc-rs-$platform/LICENSE" "$pkg/tsc-rs-$platform/NOTICE.txt" "$RUNNER_TEMP/archive/$name/"
Expand All @@ -201,7 +210,9 @@ jobs:
path: ${{ runner.temp }}/dist
if-no-files-found: error

# Installs the npm packages in a fresh project on each platform, as a user would.
# Installs the npm packages in a fresh project on each platform, as a user would. These are
# GitHub-hosted runners, so the check runs on another host than the build. ubuntu-24.04-arm is
# GitHub's arm64 standard runner (2 vCPU in a private repo, 4 in a public one).
verify:
name: verify (${{ matrix.platform }})
needs: [version, package]
Expand All @@ -211,6 +222,8 @@ jobs:
include:
- platform: linux-x64
runner: ubuntu-latest
- platform: linux-arm64
runner: ubuntu-24.04-arm
- platform: darwin-arm64
runner: macos-latest
runs-on: ${{ matrix.runner }}
Expand Down Expand Up @@ -280,7 +293,8 @@ jobs:
tag=latest
[[ $VERSION != *-* ]] || tag=next
echo "dist-tag $tag"
for pkg in @tsc-rs/linux-x64:tsc-rs-linux-x64 @tsc-rs/darwin-arm64:tsc-rs-darwin-arm64 tsc-rs:tsc-rs; do
for pkg in @tsc-rs/linux-x64:tsc-rs-linux-x64 @tsc-rs/linux-arm64:tsc-rs-linux-arm64 \
@tsc-rs/darwin-arm64:tsc-rs-darwin-arm64 tsc-rs:tsc-rs; do
name=${pkg%%:*} file=./dist/${pkg#*:}-$VERSION.tgz
[[ -f $file ]] || { echo "::error::missing package $file"; exit 1; }
if npm view "$name@$VERSION" version > /dev/null 2>&1; then
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ npx tsc-rs -p tsconfig.json
with the `typescript` package. Each [release](https://github.com/pingdotgg/ts-rust/releases) also
has a standalone archive per platform: the `tsc` binary with the lib files next to it.

Platforms: Linux x64 (static, any distribution) and macOS arm64. Windows and Linux arm64 are not
available yet.
Platforms: Linux x64 (static, any distribution) and macOS arm64. Linux arm64 (static) comes in
the first release after 0.1.0. Windows is not available yet.

To use it in VS Code, see the [npm package README](npm/tsc-rs-readme.md#vs-code).

Expand Down
23 changes: 14 additions & 9 deletions npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ is not the default.

`tsc-rs` is the same set under the port's own names: the main package `tsc-rs` (bin `tsc-rs`, so it
does not clash with the `tsc` of a `typescript` install) and one platform package per platform,
`@tsc-rs/linux-x64` and `@tsc-rs/darwin-arm64`. Its `lib/getExePath.js` finds
`@tsc-rs/linux-x64`, `@tsc-rs/linux-arm64` and `@tsc-rs/darwin-arm64`. Its `lib/getExePath.js` finds
`@tsc-rs/<platform>-<arch>`.

The npm version (`--package-version`) is the port's own. The tsc is not stamped with it: it reports
Expand All @@ -66,11 +66,13 @@ The release workflow (`.github/workflows/release.yml`) makes a release:

1. Push a tag `v<version>`, for example `git tag v0.1.0 && git push origin v0.1.0`. The npm
version is the tag without the `v`.
2. It builds the tsc on Linux (static musl, non-PIE: it starts on any x86-64 Linux) and on a Mac
(jemalloc does not cross-build for macOS with zig), from the same source.
3. It packs the set with `npm-pack.sh --name tsc-rs --package-version <v> --also darwin-arm64=<tsc>`,
2. It builds the tsc on Linux x64 and Linux arm64 (static musl, non-PIE: it starts on any Linux of
its arch; each builds natively on a Blacksmith runner of that arch) and on a Mac (jemalloc does
not cross-build for macOS with zig), from the same source.
3. It packs the set with `npm-pack.sh --name tsc-rs --package-version <v> --also linux-arm64=<tsc> --also darwin-arm64=<tsc>`,
makes one archive per platform (the tsc, the lib files, LICENSE and NOTICE.txt) and installs
the packages in a fresh project on each platform.
the packages in a fresh project on each platform (GitHub-hosted `ubuntu-latest`,
`ubuntu-24.04-arm` and `macos-latest`).
4. It publishes the platform packages, then `tsc-rs`, and creates a GitHub release with the
archives, the .tgz files and `SHA256SUMS`. A stable version goes to the dist-tag `latest` and a
normal release. A version with a prerelease part (`0.2.0-beta.1`) goes to `next` and a GitHub
Expand All @@ -89,24 +91,27 @@ and pack and test it by hand:

```sh
GOPORT_PIN=<pin> scripts/goport/npm-pack.sh --name tsc-rs --package-version <v> \
--also linux-arm64=<linux-arm64 tsc from the release workflow> \
--also darwin-arm64=<darwin tsc from the release workflow> <out>/pkg <out>/linux-x64/bin/tsgo
scripts/goport/npm-test.sh --name tsc-rs <out>/pkg <out>/test
```

### Trusted publishing

npm trusts the workflow file `release.yml` of `pingdotgg/ts-rust`, in the GitHub environment
`npm`, to publish each of the 3 packages (OIDC, no token). Set it up once with
`npm`, to publish each of the 4 packages (OIDC, no token). Set it up once with
`npm/trust-setup.sh`, logged in to npm with 2FA and npm 11.15.0 or later. It publishes a
`0.0.0-placeholder` version of a package that is not on npm yet, because npm can only trust a
workflow for a package that exists. The workflow refuses `0.0.x` tags, so a release never
collides with a placeholder. npm drops a new trust that publishes nothing in 2 days, so run it
shortly before the first tag. Add required reviewers to the `npm` environment (repo settings,
Environments) to approve each publish by hand.

The first publish binds each trust to the repo's GitHub ID, not only its name. The repo was
recreated on 2026-10-07 (history cleanup), so before the next release run
`npm/trust-setup.sh --relink`: it revokes the old trusts and creates new ones for the new repo.
The first publish binds each trust to the repo's GitHub ID, not only its name. After the repo is
recreated, run `npm/trust-setup.sh --relink`: it revokes the old trusts and creates new ones for
the new repo. The 2026-10-07 recreation needs no relink: v0.1.0 already published from the new
repo. To add a platform package, run plain `npm/trust-setup.sh` shortly before the next tag: it
publishes the new package's placeholder, adds its trust and leaves the other packages as they are.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

While the repo is private, npm publishes with no provenance. From a public repo it adds
provenance by itself.
Expand Down
10 changes: 6 additions & 4 deletions npm/trust-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# One-time setup of npm trusted publishing for the tsc-rs packages. Run it by hand, logged in to
# npm as an owner of tsc-rs and the @tsc-rs org, with 2FA on (npm asks for a code once).
#
# For each package (tsc-rs, @tsc-rs/linux-x64, @tsc-rs/darwin-arm64) it:
# For each package (tsc-rs, @tsc-rs/linux-x64, @tsc-rs/linux-arm64,
# @tsc-rs/darwin-arm64) it:
# 1. publishes a 0.0.0-placeholder version when the package is not on npm yet: npm can only
# trust a workflow for a package that exists. The release workflow refuses 0.0.x tags, so a
# release never collides with a placeholder (tsc-rs has a 0.0.1 placeholder).
Expand All @@ -11,15 +12,16 @@
# revoke command (it does not revoke by itself).
# npm drops a new trust that publishes nothing in 2 days. So run this shortly before the first tag.
# The first publish binds a trust to the repo's GitHub ID, not only its name. After the repo is
# recreated (as on 2026-10-07), run it with --relink: it revokes every trust of each package first.
# recreated, run it with --relink: it revokes every trust of each package first. The 2026-10-07
# recreation needs no relink: v0.1.0 already published from the new repo.
#
# usage: npm/trust-setup.sh [--relink] needs npm 11.15.0 or later (npm trust)
set -euo pipefail
[[ ${1:-} != help ]] || { sed -n '2,16p' "$0" >&2; exit 2; }
[[ ${1:-} != help ]] || { sed -n '2,18p' "$0" >&2; exit 2; }
relink=0
[[ ${1:-} != --relink ]] || relink=1
repo=pingdotgg/ts-rust
packages=(tsc-rs @tsc-rs/linux-x64 @tsc-rs/darwin-arm64)
packages=(tsc-rs @tsc-rs/linux-x64 @tsc-rs/linux-arm64 @tsc-rs/darwin-arm64)

npm_version=$(npm --version)
[[ $(printf '%s\n' 11.15.0 "$npm_version" | sort -V | head -1) == 11.15.0 ]] ||
Expand Down
5 changes: 3 additions & 2 deletions npm/tsc-rs-readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ allow it when VS Code asks:
{ "js/ts.tsdk.path": "node_modules/@tsc-rs/linux-x64/lib" }
```

On macOS, use `@tsc-rs/darwin-arm64`.
On Linux arm64, use `@tsc-rs/linux-arm64`. On macOS, use `@tsc-rs/darwin-arm64`.

## Platforms

- Linux x64 (static, any distribution)
- Linux arm64 (static, any distribution)
- macOS arm64

Windows and Linux arm64 are not available yet.
Windows is not available yet.

## Known problems

Expand Down
Loading