Skip to content

Interop: a member filter that hides an indexer hides a wrapped collec… #1789

Interop: a member filter that hides an indexer hides a wrapped collec…

Interop: a member filter that hides an indexer hides a wrapped collec… #1789

Workflow file for this run

name: Build
on:
push:
branches: [ main, 4.x, 3.x ]
paths-ignore:
- 'doc/**'
- '**.md'
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
# vstest gives a testhost 90 seconds to connect back, and aborts the whole run when it does not.
# These jobs run four test assemblies at once on a four-core runner, and the net472 host is the one
# that loses that race: it has the slowest start and goes last. The abort reads as a red leg with no
# failing test in it -- every assembly reports "Passed!" and the step still exits 1 -- so it costs a
# diagnosis every time. Five minutes is startup contention rather than a hang; anything genuinely
# stuck is caught by the suite's own per-test budgets, not by this.
VSTEST_CONNECTION_TIMEOUT: 300
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Setup NET
uses: actions/setup-dotnet@v6
with:
# 8.0 alongside 10.0 because Jint.Tests and Jint.Tests.PublicInterface run a net8.0 leg:
# net8.0 is the asset most consumers resolve, and it used to be compiled but never executed.
# global.json still pins the SDK to 10.0.100, so 10.0 is what actually builds.
dotnet-version: |
8.0
10.0
- name: Checkout source code
uses: actions/checkout@v7
# This job (push to main) is the only one that seeds a cache the PR workflow can read: PR jobs
# can restore caches from the base branch, but a cache saved inside a PR is scoped to that PR
# and invisible to other PRs. Restore/save are split (rather than the combined actions/cache)
# so the suite is cached even when a later step fails. The combined action saves in a post-step
# gated on success(); the "Push with dotnet" publish can fail (e.g. MyGet quota) and would then
# skip the save, leaving the main-scoped cache empty so no PR ever gets a hit. The explicit save
# below runs right after the suite is generated, before publishing.
- name: Restore Test262 generated suite
id: cache-test262
uses: actions/cache/restore@v6
with:
path: Jint.Tests.Test262/Generated
key: test262-generated-${{ hashFiles('Jint.Tests.Test262/Test262Harness.settings.json') }}
# Seed a cross-OS cache so the PR workflow's Windows/macOS/ARM jobs can restore it too.
enableCrossOsArchive: true
- name: Test
run: dotnet test --configuration Release --logger "console;verbosity=quiet" --logger "GitHubActions;summary-include-passed=false;summary-include-skipped=false"
- name: Save Test262 generated suite
if: steps.cache-test262.outputs.cache-hit != 'true'
uses: actions/cache/save@v6
with:
path: Jint.Tests.Test262/Generated
key: test262-generated-${{ hashFiles('Jint.Tests.Test262/Test262Harness.settings.json') }}
enableCrossOsArchive: true
- name: Pack with dotnet
run: dotnet pack Jint/Jint.csproj --output artifacts --configuration Release -p:VersionSuffix=preview-$GITHUB_RUN_NUMBER -p:ContinuousIntegrationBuild=True
- name: Push with dotnet
run: dotnet nuget push artifacts/*.nupkg --api-key ${{ secrets.MYGET_API_KEY }} --skip-duplicate --source https://www.myget.org/F/jint/api/v2/package
# The mirror of the PR workflow's "linux - native aot" job, and there for the reason the Test step above is:
# a merge is not the commit CI ran on. Its own file documents what it verifies; the short version is that
# <IsAotCompatible> is a property, and the published binary is the only evidence.
aot:
runs-on: ubuntu-latest
steps:
- name: Setup NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0
- name: Checkout source code
uses: actions/checkout@v7
- name: Ensure the Native AOT toolchain is present
run: |
if command -v clang > /dev/null && dpkg -s zlib1g-dev > /dev/null 2>&1; then
echo "already present: $(clang --version | head -1)"
else
sudo apt-get update
sudo apt-get install -y --no-install-recommends clang zlib1g-dev
fi
- name: Publish Jint.AotExample with Native AOT
run: |
set -o pipefail
dotnet publish Jint.AotExample/Jint.AotExample.csproj --configuration Release 2>&1 | tee aot-publish.log
- name: Run the native binary
run: |
set -o pipefail
./artifacts/publish/Jint.AotExample/release/Jint.AotExample | tee aot-run.log
grep -q '^ALL PROBES PASSED' aot-run.log
- name: Summarise the trim and AOT analysis warnings
if: always()
run: |
{
echo '### Native AOT analysis diagnostics'
echo
echo '| code | count |'
echo '| --- | --- |'
grep -hoE 'IL[0-9]{4}' aot-publish.log 2>/dev/null | sort | uniq -c | sort -rn | awk '{ print "| " $2 " | " $1 " |" }'
echo
echo "total: $(grep -hcE 'IL[0-9]{4}' aot-publish.log 2>/dev/null || echo 0)"
} >> "$GITHUB_STEP_SUMMARY"
# The mirror of the PR workflow's "windows - packaged generator" job, and there for the same reason
# the Test step above is: a merge is not the commit CI ran on. It packs its own copy rather than
# reusing the one the build job publishes, so that this job says something even when that one is
# skipped or fails. Its own file carries the reasoning; the short version is that a ProjectReference
# proves nothing about whether the [JsAccessible] generator travels inside the package.
package-consumer:
runs-on: windows-latest
steps:
- name: Setup NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0
- name: Checkout source code
uses: actions/checkout@v7
- name: Pack
run: dotnet pack Jint/Jint.csproj --configuration Release
- name: The package carries the interop generator, and only that one
shell: pwsh
run: |
$nupkg = Get-ChildItem artifacts/package/release/Jint.*.nupkg | Select-Object -First 1
if (-not $nupkg) { throw 'dotnet pack produced no Jint package' }
Write-Host "inspecting $($nupkg.Name)"
Add-Type -AssemblyName System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::OpenRead($nupkg.FullName)
$analyzers = @($zip.Entries | Where-Object { $_.FullName -like 'analyzers/*' } | ForEach-Object { $_.FullName })
$zip.Dispose()
$analyzers | ForEach-Object { Write-Host " $_" }
if ($analyzers -notcontains 'analyzers/dotnet/cs/Jint.SourceGenerators.Interop.dll') {
throw 'the package carries no [JsAccessible] generator, so no consumer can obtain the feature'
}
if ($analyzers | Where-Object { $_ -like '*/Jint.SourceGenerators.dll' }) {
throw 'the package carries Jint.SourceGenerators.dll, whose post-initialization output does not compile outside Jint'
}
- name: Build the consumer against the package
run: dotnet build tools/package-consumer/PackageConsumer.csproj --configuration Release
- name: Run it on net10.0
shell: bash
run: |
set -o pipefail
./tools/package-consumer/bin/Release/net10.0/PackageConsumer.exe | tee net10.log
grep -q '^ALL PROBES PASSED' net10.log
- name: Run it on net472
shell: bash
run: |
set -o pipefail
./tools/package-consumer/bin/Release/net472/PackageConsumer.exe | tee net472.log
grep -q '^ALL PROBES PASSED' net472.log
- name: A promoted decline fails the consumer's build
shell: bash
run: |
printf '\n[*.cs]\ndotnet_diagnostic.JINT033.severity = error\n' >> tools/package-consumer/.editorconfig
if dotnet build tools/package-consumer/PackageConsumer.csproj --configuration Release -f net10.0 --no-incremental > promoted.log 2>&1; then
echo 'the build succeeded, so .editorconfig severity did not reach JINT033'
cat promoted.log
exit 1
fi
grep -q 'error JINT033' promoted.log