mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-02 07:34:45 +08:00
fix(ci): upstream Windows SDK validation support (#3327)
* fix(ci): upstream Windows SDK validation support Port remaining Windows validation tooling from GitLab independently of the combined MXC runtime port. Preserve locked SDK dependencies and guard temporary launcher cleanup. Co-authored-by: Shailendra Singh <shailendras@nvidia.com> Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> * fix(ci): install native TypeScript dependencies before validation Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> --------- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> Co-authored-by: Shailendra Singh <shailendras@nvidia.com>
This commit is contained in:
co-authored by
Shailendra Singh
parent
8751e35e28
commit
d95bab5436
@@ -213,6 +213,10 @@ compatibility under emulation is not part of these tasks. The aggregate
|
||||
commands above on an ARM64 host.
|
||||
|
||||
The repository-wide `mise run pre-commit` task is also supported on Windows.
|
||||
Run `rust:lockfiles:check`, `sdk:ts:ci`, `go:ci`, and `test:e2e-parity` through
|
||||
the Windows-aware tasks when validating those surfaces. Do not count the Go
|
||||
Windows ARM64 race-detector exclusion or POSIX permission-bit skips as security
|
||||
coverage. SDK test dependencies must remain at their lockfile versions.
|
||||
Its Rust check, Clippy, and test dependencies enter the same MSVC environment
|
||||
for the native host target and use an inherited compiler wrapper when it is
|
||||
available. Linux glibc
|
||||
|
||||
+18
@@ -48,6 +48,24 @@ mise run test:rust # cargo test --workspace
|
||||
|
||||
Rust validation checks tracked Cargo lockfiles; run `mise run rust:lockfiles:check` to check them directly. If one is stale, refresh it with Cargo using its adjacent manifest, review the diff, and commit the update.
|
||||
|
||||
### Native Windows validation
|
||||
|
||||
Use `mise run --skip-tools pre-commit` with the existing Rust/MSVC toolchain.
|
||||
Windows now checks tracked Cargo lockfiles through PowerShell rather than
|
||||
skipping them. The deterministic gateway parity task uses Git for Windows Bash,
|
||||
with temporary Python launchers confined to a unique checkout-owned directory.
|
||||
|
||||
`mise run --skip-tools sdk:ts:ci` selects the x64 Biome executable on Windows
|
||||
(including ARM64 hosts running it under emulation), resolves the protobuf
|
||||
plugin through its Windows `.cmd` launcher, and installs the matching locked
|
||||
ARM64 Rolldown binding when Node itself is ARM64. The helper preserves lockfile
|
||||
resolution; it must not upgrade unrelated test dependencies.
|
||||
|
||||
`mise run --skip-tools go:ci` retains race detection except on Windows ARM64,
|
||||
where Go does not support it. Windows token-file tests explicitly skip POSIX
|
||||
mode-bit assertions; those skips do not establish Windows ACL protection.
|
||||
Use a checkout with LF text files when running Unix-shell fixture checks.
|
||||
|
||||
## Python Unit Tests
|
||||
|
||||
Python unit tests use the `*_test.py` suffix convention (not `test_*` prefix)
|
||||
|
||||
@@ -108,6 +108,12 @@ async functions caused by cfg-gated Windows stubs. Repository-wide pre-commit
|
||||
skips only Linux-specific installer, build-environment shell-helper, and
|
||||
packaging-asset tests; its
|
||||
cross-platform Python, Markdown, license, and documentation checks still run.
|
||||
Tracked Cargo lockfiles are checked natively through PowerShell. Deterministic
|
||||
gateway parity uses Git for Windows Bash with temporary, checkout-scoped Python
|
||||
launchers. The TypeScript SDK uses Windows protobuf plugin paths and x64 Biome
|
||||
under emulation on ARM64, while its test binding follows Node's architecture
|
||||
and the locked Rolldown version. Go tests retain race coverage wherever the
|
||||
toolchain supports it; POSIX permission-bit checks are not Windows ACL tests.
|
||||
Test tasks require the Rust target architecture to match the Windows host, so
|
||||
an ARM64 test result is native coverage rather than x64 emulation coverage.
|
||||
By default it enables bundled Z3 for reproducible Windows builds. `z3-sys`
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestUserConfigDir_XDGUnset(t *testing.T) {
|
||||
|
||||
func TestSystemGatewayDir(t *testing.T) {
|
||||
dir := systemGatewayDir()
|
||||
assert.Equal(t, "/etc/openshell/gateways", dir)
|
||||
assert.Equal(t, filepath.FromSlash("/etc/openshell/gateways"), dir)
|
||||
}
|
||||
|
||||
func TestResolveGatewayDir_UserDir(t *testing.T) {
|
||||
|
||||
@@ -24,9 +24,8 @@ func TestBrowserCommand_Platform(t *testing.T) {
|
||||
assert.Equal(t, "xdg-open", name)
|
||||
assert.Equal(t, []string{"https://example.com/auth"}, args)
|
||||
case "windows":
|
||||
assert.Equal(t, "cmd", name)
|
||||
assert.Contains(t, args, "/c")
|
||||
assert.Contains(t, args, "start")
|
||||
assert.Equal(t, "rundll32", name)
|
||||
assert.Equal(t, []string{"url.dll,FileProtocolHandler", "https://example.com/auth"}, args)
|
||||
default:
|
||||
// Unknown platform should still return something (even if it fails).
|
||||
assert.NotEmpty(t, name)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -41,9 +42,7 @@ func TestWriteToken_ReplacesInsecureExistingFileWithOwnerOnlyFile(t *testing.T)
|
||||
|
||||
require.NoError(t, writeToken(dir, &oauth2.Token{AccessToken: "secret"}))
|
||||
|
||||
info, err := os.Stat(path)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, os.FileMode(0o600), info.Mode().Perm())
|
||||
assertOwnerOnlyFilePermissions(t, path)
|
||||
}
|
||||
|
||||
func TestWriteToken_ExpiresInCalculated(t *testing.T) {
|
||||
@@ -187,8 +186,16 @@ func TestWriteToken_FilePermissions(t *testing.T) {
|
||||
err := writeToken(dir, tok)
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := os.Stat(filepath.Join(dir, "oidc_token.json"))
|
||||
assertOwnerOnlyFilePermissions(t, filepath.Join(dir, "oidc_token.json"))
|
||||
}
|
||||
|
||||
func assertOwnerOnlyFilePermissions(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("POSIX file permission bits are not supported on Windows")
|
||||
}
|
||||
|
||||
info, err := os.Stat(path)
|
||||
require.NoError(t, err)
|
||||
// File should be owner-only readable (0600).
|
||||
assert.Equal(t, os.FileMode(0o600), info.Mode().Perm())
|
||||
}
|
||||
|
||||
+44
-4
@@ -6,7 +6,17 @@
|
||||
["go:test"]
|
||||
description = "Run Go SDK unit tests with coverage"
|
||||
dir = "sdk/go"
|
||||
run = "go test -coverprofile=coverage.out -coverpkg=./openshell/... -race ./..."
|
||||
run = """
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$(go env GOOS)" = "windows" ] && [ "$(go env GOARCH)" = "arm64" ]; then
|
||||
echo "Go race detection is unsupported on windows/arm64; running without -race."
|
||||
go test -coverprofile=coverage.out -coverpkg=./openshell/... ./...
|
||||
else
|
||||
go test -coverprofile=coverage.out -coverpkg=./openshell/... -race ./...
|
||||
fi
|
||||
"""
|
||||
hide = true
|
||||
|
||||
["go:test:integration"]
|
||||
@@ -120,11 +130,26 @@ if find proto -maxdepth 1 -name '*.proto' -print -quit | grep -q .; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BUF_TEMPLATE="$SDK_ROOT/buf.gen.yaml"
|
||||
if command -v cygpath &>/dev/null; then
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
GO_PLUGIN=$(cygpath -m "$(command -v protoc-gen-go)")
|
||||
GRPC_PLUGIN=$(cygpath -m "$(command -v protoc-gen-go-grpc)")
|
||||
GO_PLUGIN=${GO_PLUGIN//&/\\&}
|
||||
GRPC_PLUGIN=${GRPC_PLUGIN//&/\\&}
|
||||
sed \
|
||||
-e "s|local: protoc-gen-go$|local: $GO_PLUGIN|" \
|
||||
-e "s|local: protoc-gen-go-grpc$|local: $GRPC_PLUGIN|" \
|
||||
"$SDK_ROOT/buf.gen.yaml" > "$WORK_DIR/buf.gen.yaml"
|
||||
BUF_TEMPLATE="$WORK_DIR/buf.gen.yaml"
|
||||
fi
|
||||
|
||||
# Clean previous output before regeneration
|
||||
find proto -name '*.pb.go' -delete 2>/dev/null || true
|
||||
find proto -mindepth 1 -type d -empty -delete 2>/dev/null || true
|
||||
|
||||
(cd "$REPO_ROOT" && buf generate --template "$SDK_ROOT/buf.gen.yaml")
|
||||
(cd "$REPO_ROOT" && buf generate --template "$BUF_TEMPLATE")
|
||||
|
||||
echo "Proto generation complete."
|
||||
echo "Generated packages:"
|
||||
@@ -162,8 +187,23 @@ if find proto -maxdepth 1 -name '*.proto' -print -quit | grep -q .; then
|
||||
fi
|
||||
|
||||
# Generate to temp directory with adjusted output path
|
||||
CHECK_TEMPLATE=$(sed 's|out: sdk/go|out: '"$WORK_DIR"'|' buf.gen.yaml)
|
||||
(cd "$REPO_ROOT" && buf generate --template "$CHECK_TEMPLATE")
|
||||
BUF_OUTPUT_DIR="$WORK_DIR"
|
||||
if command -v cygpath &>/dev/null; then
|
||||
BUF_OUTPUT_DIR=$(cygpath -m "$WORK_DIR")
|
||||
fi
|
||||
sed "s|out: sdk/go|out: $BUF_OUTPUT_DIR|" "$SDK_ROOT/buf.gen.yaml" > "$WORK_DIR/buf.gen.yaml"
|
||||
if command -v cygpath &>/dev/null; then
|
||||
GO_PLUGIN=$(cygpath -m "$(command -v protoc-gen-go)")
|
||||
GRPC_PLUGIN=$(cygpath -m "$(command -v protoc-gen-go-grpc)")
|
||||
GO_PLUGIN=${GO_PLUGIN//&/\\&}
|
||||
GRPC_PLUGIN=${GRPC_PLUGIN//&/\\&}
|
||||
sed \
|
||||
-e "s|local: protoc-gen-go$|local: $GO_PLUGIN|" \
|
||||
-e "s|local: protoc-gen-go-grpc$|local: $GRPC_PLUGIN|" \
|
||||
"$WORK_DIR/buf.gen.yaml" > "$WORK_DIR/buf.gen.windows.yaml"
|
||||
mv "$WORK_DIR/buf.gen.windows.yaml" "$WORK_DIR/buf.gen.yaml"
|
||||
fi
|
||||
(cd "$REPO_ROOT" && buf generate --template "$WORK_DIR/buf.gen.yaml")
|
||||
|
||||
DIFF_OUTPUT=$(diff -r "$WORK_DIR/proto" "$SDK_ROOT/proto" 2>&1) || true
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
["test:e2e-parity"]
|
||||
description = "Run deterministic schema-v1/schema-v2 parity harness tests"
|
||||
run = "bash e2e/parity/test.sh"
|
||||
run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/run-git-bash.ps1 e2e/parity/test.sh"
|
||||
hide = true
|
||||
|
||||
["e2e:parity:podman"]
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ hide = true
|
||||
["rust:lockfiles:check"]
|
||||
description = "Verify all tracked Cargo lockfiles are current"
|
||||
run = "tasks/scripts/check-cargo-lockfiles.sh"
|
||||
run_windows = "echo Skipping rust:lockfiles:check: Cargo lockfile validation uses a Unix shell helper."
|
||||
run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/check-cargo-lockfiles.ps1"
|
||||
hide = true
|
||||
|
||||
["rust:lint"]
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = (& git rev-parse --show-toplevel).Trim()
|
||||
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($repoRoot)) {
|
||||
throw "Unable to resolve the repository root"
|
||||
}
|
||||
Set-Location -LiteralPath $repoRoot
|
||||
|
||||
$lockfiles = @(& git ls-files -- ':(glob)**/Cargo.lock')
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Unable to enumerate tracked Cargo.lock files"
|
||||
}
|
||||
if ($lockfiles.Count -eq 0) {
|
||||
throw "No tracked Cargo.lock files found"
|
||||
}
|
||||
|
||||
$failed = $false
|
||||
foreach ($lockfile in $lockfiles) {
|
||||
$lockfileDirectory = Split-Path -Parent $lockfile
|
||||
$manifest = if ([string]::IsNullOrEmpty($lockfileDirectory)) {
|
||||
"Cargo.toml"
|
||||
} else {
|
||||
Join-Path $lockfileDirectory "Cargo.toml"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $manifest -PathType Leaf)) {
|
||||
Write-Error "Tracked lockfile $lockfile has no adjacent Cargo.toml"
|
||||
$failed = $true
|
||||
continue
|
||||
}
|
||||
|
||||
Write-Output "Checking $lockfile"
|
||||
& cargo metadata --locked --format-version 1 --manifest-path $manifest | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Validation failed for $lockfile"
|
||||
$failed = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($failed) {
|
||||
throw "Resolve the reported errors. If a lockfile needs updating, refresh it with Cargo and commit the result."
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory = $true, Position = 0)]
|
||||
[string]$Script,
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
[string[]]$Arguments
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$gitCommand = Get-Command git.exe -ErrorAction Stop
|
||||
$gitRoot = Split-Path -Parent $gitCommand.Source
|
||||
$bash = $null
|
||||
# Git can expose cmd/git.exe, mingw64/bin/git.exe, or clangarm64/bin/git.exe.
|
||||
for ($level = 0; $level -lt 4 -and $gitRoot; $level++) {
|
||||
$candidate = Join-Path $gitRoot 'bin\bash.exe'
|
||||
if (Test-Path -LiteralPath $candidate -PathType Leaf) {
|
||||
$bash = $candidate
|
||||
break
|
||||
}
|
||||
$gitRoot = Split-Path -Parent $gitRoot
|
||||
}
|
||||
if (-not $bash) {
|
||||
throw "Git for Windows bash.exe was not found beside $($gitCommand.Source)"
|
||||
}
|
||||
|
||||
$repoRoot = (& git rev-parse --show-toplevel).Trim()
|
||||
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($repoRoot)) {
|
||||
throw 'Unable to resolve the repository root'
|
||||
}
|
||||
$repoPrefix = [IO.Path]::GetFullPath($repoRoot).TrimEnd('\', '/') + [IO.Path]::DirectorySeparatorChar
|
||||
$shimDirectory = [IO.Path]::GetFullPath((Join-Path $repoRoot ('.git-bash-shim-' + [guid]::NewGuid().ToString('N'))))
|
||||
if (-not $shimDirectory.StartsWith($repoPrefix, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw 'Git Bash shim directory escaped the repository'
|
||||
}
|
||||
$shimCreated = $false
|
||||
$previousPath = $env:PATH
|
||||
$previousTmpdir = $env:TMPDIR
|
||||
$python = $env:UV_PYTHON
|
||||
if ([string]::IsNullOrWhiteSpace($python)) {
|
||||
$worktreePython = Join-Path $repoRoot ".venv\Scripts\python.exe"
|
||||
if (Test-Path -LiteralPath $worktreePython -PathType Leaf) {
|
||||
$python = $worktreePython
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
New-Item -ItemType Directory -Path $shimDirectory | Out-Null
|
||||
$shimCreated = $true
|
||||
if (-not [string]::IsNullOrWhiteSpace($python)) {
|
||||
$python = [IO.Path]::GetFullPath($python)
|
||||
if ($python -notmatch '^(?<drive>[A-Za-z]):\\(?<tail>.*)$') {
|
||||
throw "Python must use an absolute drive path for Git Bash: $python"
|
||||
}
|
||||
$bashPython = "/$($Matches.drive.ToLowerInvariant())/$($Matches.tail.Replace('\', '/'))"
|
||||
if ($bashPython.Contains("'")) {
|
||||
throw "Python path cannot contain a single quote: $python"
|
||||
}
|
||||
$launcher = "#!/usr/bin/env bash`nexec '$bashPython' `"`$@`"`n"
|
||||
$utf8WithoutBom = [Text.UTF8Encoding]::new($false)
|
||||
foreach ($launcherName in @("python", "python3")) {
|
||||
[IO.File]::WriteAllText(
|
||||
(Join-Path $shimDirectory $launcherName),
|
||||
$launcher,
|
||||
$utf8WithoutBom
|
||||
)
|
||||
}
|
||||
}
|
||||
$bashTemp = Join-Path $shimDirectory "tmp"
|
||||
New-Item -ItemType Directory -Path $bashTemp | Out-Null
|
||||
$env:TMPDIR = $bashTemp.Replace("\", "/")
|
||||
$env:PATH = "$shimDirectory;$gitRoot\usr\bin;$gitRoot\bin;$env:PATH"
|
||||
& $bash $Script @Arguments
|
||||
$exitCode = $LASTEXITCODE
|
||||
} finally {
|
||||
$env:PATH = $previousPath
|
||||
$env:TMPDIR = $previousTmpdir
|
||||
if ($shimCreated -and (Test-Path -LiteralPath $shimDirectory)) {
|
||||
$resolvedShim = (Resolve-Path -LiteralPath $shimDirectory).ProviderPath
|
||||
if (-not $resolvedShim.StartsWith($repoPrefix, [StringComparison]::OrdinalIgnoreCase) -or
|
||||
((Get-Item -LiteralPath $shimDirectory).Attributes -band [IO.FileAttributes]::ReparsePoint)) {
|
||||
throw 'Refusing to remove an unexpected Git Bash shim directory'
|
||||
}
|
||||
Remove-Item -LiteralPath $shimDirectory -Recurse -Force
|
||||
}
|
||||
}
|
||||
|
||||
exit $exitCode
|
||||
@@ -0,0 +1,40 @@
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$nodeArchitecture = (& node -p "process.arch").Trim()
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Unable to determine the Node.js process architecture (exit code $LASTEXITCODE)."
|
||||
}
|
||||
if ($nodeArchitecture -notin @('x64', 'arm64')) {
|
||||
throw "Unsupported Windows Node.js architecture '$nodeArchitecture'."
|
||||
}
|
||||
|
||||
$previousCpu = $env:npm_config_cpu
|
||||
try {
|
||||
$env:npm_config_cpu = $nodeArchitecture
|
||||
& npm ci
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Unable to install TypeScript SDK dependencies (exit code $LASTEXITCODE)."
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$env:npm_config_cpu = $previousCpu
|
||||
}
|
||||
|
||||
$nativePackages = @(
|
||||
"@biomejs/cli-win32-$nodeArchitecture",
|
||||
"@bufbuild/buf-win32-$nodeArchitecture",
|
||||
"@rolldown/binding-win32-$nodeArchitecture-msvc"
|
||||
)
|
||||
foreach ($package in $nativePackages) {
|
||||
$manifest = Join-Path 'node_modules' (Join-Path $package 'package.json')
|
||||
if (-not (Test-Path -LiteralPath $manifest -PathType Leaf)) {
|
||||
throw "The lockfile-pinned native dependency '$package' was not installed."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$repository = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
$sdkRoot = Join-Path $repository 'sdk\typescript'
|
||||
$sourceTemplate = Join-Path $sdkRoot 'buf.gen.yaml'
|
||||
$buf = (Resolve-Path (Join-Path $sdkRoot 'node_modules\.bin\buf.cmd')).Path
|
||||
$plugin = (Resolve-Path (Join-Path $sdkRoot 'node_modules\.bin\protoc-gen-es.cmd')).Path
|
||||
$temporaryRoot = Join-Path ([IO.Path]::GetTempPath()) "openshell-ts-proto-$([guid]::NewGuid().ToString('N'))"
|
||||
$windowsTemplate = Join-Path $temporaryRoot 'buf.gen.windows.yaml'
|
||||
$tempPrefix = [IO.Path]::GetFullPath([IO.Path]::GetTempPath()).TrimEnd('\', '/') + [IO.Path]::DirectorySeparatorChar
|
||||
if (-not [IO.Path]::GetFullPath($temporaryRoot).StartsWith($tempPrefix, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw 'Protobuf temporary directory escaped the temporary root'
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Path $temporaryRoot | Out-Null
|
||||
try {
|
||||
$pluginPath = $plugin.Replace('\', '/')
|
||||
$template = [IO.File]::ReadAllText($sourceTemplate).Replace(
|
||||
'./node_modules/.bin/protoc-gen-es',
|
||||
$pluginPath
|
||||
)
|
||||
[IO.File]::WriteAllText(
|
||||
$windowsTemplate,
|
||||
$template,
|
||||
[Text.UTF8Encoding]::new($false)
|
||||
)
|
||||
|
||||
Push-Location $sdkRoot
|
||||
try {
|
||||
& $buf generate --template $windowsTemplate
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "TypeScript protobuf generation failed with exit code $LASTEXITCODE."
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (
|
||||
(Test-Path -LiteralPath $temporaryRoot) -and
|
||||
(Split-Path -Leaf $temporaryRoot) -like 'openshell-ts-proto-*'
|
||||
) {
|
||||
$resolvedTemp = (Resolve-Path -LiteralPath $temporaryRoot).ProviderPath
|
||||
if (-not $resolvedTemp.StartsWith($tempPrefix, [StringComparison]::OrdinalIgnoreCase) -or
|
||||
((Get-Item -LiteralPath $temporaryRoot).Attributes -band [IO.FileAttributes]::ReparsePoint)) {
|
||||
throw 'Refusing to remove an unexpected protobuf temporary directory'
|
||||
}
|
||||
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
description = "Install TypeScript SDK dependencies"
|
||||
dir = "sdk/typescript"
|
||||
run = "npm ci"
|
||||
run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File ../../tasks/scripts/typescript-install.ps1"
|
||||
hide = true
|
||||
|
||||
["sdk:ts:proto"]
|
||||
@@ -16,6 +17,7 @@ description = "Generate TypeScript protobuf stubs for the SDK"
|
||||
depends = ["sdk:ts:install"]
|
||||
dir = "sdk/typescript"
|
||||
run = "npm run gen"
|
||||
run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File ../../tasks/scripts/typescript-proto.ps1"
|
||||
|
||||
# Lints the repo-level proto module (buf.yaml at the root) against STANDARD.
|
||||
# buf ships only in the SDK's devDependencies today, so this depends on the
|
||||
|
||||
Reference in New Issue
Block a user