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
12 changes: 12 additions & 0 deletions build/ci/stage-build-linux-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ jobs:
OverWrite: false
flattenFolders: false

## Validate dotnet.js fingerprint matches actual file
- bash: |
$(build.sourcesdirectory)/build/scripts/validate-dotnetjs-fingerprint.sh \
"$(build.sourcesdirectory)/src/Uno.Wasm.Sample.RayTracer/bin/Release/net10.0/publish/wwwroot"
displayName: Validate dotnet.js fingerprint (RayTracer)

## Raytracer validation
- bash: |
$(build.sourcesdirectory)/build/scripts/run-tests.sh \
Expand Down Expand Up @@ -102,6 +108,12 @@ jobs:
OverWrite: false
flattenFolders: false

## Validate dotnet.js fingerprint matches actual file (SWA build)
- bash: |
$(build.sourcesdirectory)/build/scripts/validate-dotnetjs-fingerprint.sh \
"$(build.sourcesdirectory)/src/Uno.Wasm.Sample.RayTracer/bin/Release/net10.0/publish/wwwroot"
displayName: Validate dotnet.js fingerprint (SWA)

- bash: |
$(build.sourcesdirectory)/build/scripts/run-tests-swa.sh \
"$(build.sourcesdirectory)/src/Uno.Wasm.Sample.RayTracer/bin/Release/net10.0/publish/wwwroot" \
Expand Down
6 changes: 6 additions & 0 deletions build/ci/stage-build-macos-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ jobs:
dotnet publish -c Release /m:1 /p:DISABLE_CLIHOST_NET6=true /p:WasmShellEmccLinkOptimization=false /p:WasmShellILLinkerEnabled=false /bl:$(build.artifactstagingdirectory)/SampleNet5-nolinker-macos.binlog
displayName: Build StaticLinking.Interpreter Sample (net5 without linker)

## Validate dotnet.js fingerprint matches actual file
- bash: |
$(build.sourcesdirectory)/build/scripts/validate-dotnetjs-fingerprint.sh \
"$(build.sourcesdirectory)/src/Uno.Wasm.StaticLinking.Interpreter/bin/Release/net10.0/publish/wwwroot"
displayName: Validate dotnet.js fingerprint (StaticLinking.Interpreter)

- bash: |
$(build.sourcesdirectory)/build/scripts/run-tests.sh \
"$(build.sourcesdirectory)/src/Uno.Wasm.StaticLinking.Interpreter/bin/Release/net10.0/publish/wwwroot" \
Expand Down
8 changes: 7 additions & 1 deletion build/ci/stage-build-windows-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,16 @@ jobs:

- pwsh: |
cd $(build.sourcesdirectory)/src/Uno.Wasm.Sample.RayTracer
dotnet clean -c Release
dotnet clean -c Release
dotnet publish -c Release /m:1 /p:WasmShellEmccLinkOptimization=false /bl:$(build.artifactstagingdirectory)/SampleNet5-win.binlog
displayName: Build Raytracer Sample

## Validate dotnet.js fingerprint matches actual file
- pwsh: |
$(build.sourcesdirectory)\build\scripts\validate-dotnetjs-fingerprint.ps1 `
-PublishPath "$(build.sourcesdirectory)\src\Uno.Wasm.Sample.RayTracer\bin\Release\net10.0\publish\wwwroot"
displayName: Validate dotnet.js fingerprint (RayTracer)

- pwsh: |
$(build.sourcesdirectory)\build\scripts\run-tests-windows.ps1 `
"$(build.sourcesdirectory)\src\Uno.Wasm.Sample.RayTracer\bin\Release\net10.0\publish\wwwroot" `
Expand Down
50 changes: 50 additions & 0 deletions build/scripts/validate-dotnetjs-fingerprint.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Validates that uno-config.js references a dotnet.js fingerprint that matches an actual file
param(
[Parameter(Mandatory=$true)]
[string]$PublishPath
)

$ErrorActionPreference = "Stop"

Write-Host "Validating dotnet.js fingerprint in: $PublishPath"

# Find uno-config.js (it could be in a package_* subdirectory)
$unoConfig = Get-ChildItem -Path $PublishPath -Recurse -Filter "uno-config.js" | Select-Object -First 1

if (-not $unoConfig) {
Write-Host "ERROR: uno-config.js not found in $PublishPath"
exit 1
}

Write-Host "Found uno-config.js: $($unoConfig.FullName)"

# Read the content and extract the fingerprint
$content = Get-Content -Path $unoConfig.FullName -Raw
$match = [regex]::Match($content, 'dotnet\.([a-z0-9]+)\.js')

if (-not $match.Success) {
Write-Host "ERROR: Could not extract dotnet.js fingerprint from uno-config.js"
Write-Host "Content of uno-config.js:"
Write-Host $content
exit 1
}

$fingerprint = $match.Groups[1].Value
Write-Host "Fingerprint in uno-config.js: $fingerprint"

# Check if the fingerprinted dotnet.js file exists
$frameworkPath = Join-Path $PublishPath "_framework"
$dotnetJsFile = Join-Path $frameworkPath "dotnet.$fingerprint.js"

if (-not (Test-Path $dotnetJsFile)) {
Write-Host "ERROR: Fingerprint mismatch!"
Write-Host " uno-config.js references: dotnet.$fingerprint.js"
Write-Host " But this file does not exist in: $frameworkPath"
Write-Host ""
Write-Host "Available dotnet.*.js files in _framework:"
Get-ChildItem -Path $frameworkPath -Filter "dotnet.*.js" -ErrorAction SilentlyContinue | ForEach-Object { Write-Host " $($_.Name)" }
exit 1
}

Write-Host "SUCCESS: dotnet.$fingerprint.js exists in _framework"
Write-Host "Fingerprint validation passed!"
51 changes: 51 additions & 0 deletions build/scripts/validate-dotnetjs-fingerprint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash
# Validates that uno-config.js references a dotnet.js fingerprint that matches an actual file
set -e

PUBLISH_PATH=$1

if [ -z "$PUBLISH_PATH" ]; then
echo "Usage: validate-dotnetjs-fingerprint.sh <publish-wwwroot-path>"
exit 1
fi

echo "Validating dotnet.js fingerprint in: $PUBLISH_PATH"

# Find uno-config.js (it could be in a package_* subdirectory)
UNO_CONFIG=$(find "$PUBLISH_PATH" -name "uno-config.js" -type f | head -1)

if [ -z "$UNO_CONFIG" ]; then
echo "ERROR: uno-config.js not found in $PUBLISH_PATH"
exit 1
fi

echo "Found uno-config.js: $UNO_CONFIG"

# Extract the fingerprint from uno-config.js (portable across GNU and BSD grep/sed)
FINGERPRINT=$(sed -n 's/.*dotnet\.\([a-z0-9]*\)\.js.*/\1/p' "$UNO_CONFIG" | head -1)

if [ -z "$FINGERPRINT" ]; then
echo "ERROR: Could not extract dotnet.js fingerprint from uno-config.js"
echo "Content of uno-config.js:"
cat "$UNO_CONFIG"
exit 1
fi

echo "Fingerprint in uno-config.js: $FINGERPRINT"

# Check if the fingerprinted dotnet.js file exists
FRAMEWORK_PATH="$PUBLISH_PATH/_framework"
DOTNET_JS_FILE="$FRAMEWORK_PATH/dotnet.$FINGERPRINT.js"

if [ ! -f "$DOTNET_JS_FILE" ]; then
echo "ERROR: Fingerprint mismatch!"
echo " uno-config.js references: dotnet.$FINGERPRINT.js"
echo " But this file does not exist in: $FRAMEWORK_PATH"
echo ""
echo "Available dotnet.*.js files in _framework:"
ls -la "$FRAMEWORK_PATH"/dotnet.*.js 2>/dev/null || echo " (none found)"
exit 1
fi

echo "SUCCESS: dotnet.$FINGERPRINT.js exists in _framework"
echo "Fingerprint validation passed!"
9 changes: 6 additions & 3 deletions src/Uno.Wasm.Bootstrap/build/Uno.Wasm.Bootstrap.targets
Original file line number Diff line number Diff line change
Expand Up @@ -452,15 +452,18 @@
AfterTargets="ResolvePublishStaticWebAssets">

<!-- Find the dotnet.js StaticWebAsset from publish assets and extract its fingerprint.
We look for assets where AssetMode is 'All' or 'Publish' to get the publish-time fingerprint. -->
We look for assets where AssetMode is 'All' or 'Publish' to get the publish-time fingerprint.
During publish, the RelativePath may already be resolved to the actual fingerprinted value
(e.g., '_framework/dotnet.abc123.js') instead of the placeholder pattern, so we match both. -->
<ItemGroup>
<_UnoDotnetJsAssetPublish Include="@(StaticWebAsset)"
Condition="$([System.String]::Copy('%(RelativePath)').StartsWith('_framework/dotnet#[.{fingerprint}]')) AND $([System.String]::Copy('%(RelativePath)').EndsWith('.js')) AND !$([System.String]::Copy('%(RelativePath)').Contains('.native')) AND !$([System.String]::Copy('%(RelativePath)').Contains('.runtime')) AND ('%(AssetMode)' == 'All' OR '%(AssetMode)' == 'Publish' OR '%(AssetMode)' == '')" />
Condition="($([System.String]::Copy('%(RelativePath)').StartsWith('_framework/dotnet#[.{fingerprint}]')) OR $([System.Text.RegularExpressions.Regex]::IsMatch('%(RelativePath)', '^_framework/dotnet\.[a-z0-9]+\.js$'))) AND $([System.String]::Copy('%(RelativePath)').EndsWith('.js')) AND !$([System.String]::Copy('%(RelativePath)').Contains('.native')) AND !$([System.String]::Copy('%(RelativePath)').Contains('.runtime')) AND ('%(AssetMode)' == 'All' OR '%(AssetMode)' == 'Publish' OR '%(AssetMode)' == '')" />
</ItemGroup>

<!-- Get the last fingerprint (which should be the publish one) by using batching -->
<!-- Get the fingerprint from metadata first, then fall back to extracting from RelativePath if empty -->
<PropertyGroup>
<_UnoDotnetJsFingerprintPublish>%(_UnoDotnetJsAssetPublish.Fingerprint)</_UnoDotnetJsFingerprintPublish>
<_UnoDotnetJsFingerprintPublish Condition="'$(_UnoDotnetJsFingerprintPublish)' == ''">$([System.Text.RegularExpressions.Regex]::Match('%(_UnoDotnetJsAssetPublish.RelativePath)', 'dotnet\.([a-z0-9]+)\.js$').Groups[1].Value)</_UnoDotnetJsFingerprintPublish>
<_UnoConfigJsPath>$(IntermediateOutputPath)unowwwrootassets/uno-config.js</_UnoConfigJsPath>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
<PropertyGroup>
<_appOutput>$(PublishDir)wwwroot/$(WasmShellOutputPackagePath)</_appOutput>
<_unoConfigJsContent>$([System.IO.File]::ReadAllText('$(_appOutput)/uno-config.js'))</_unoConfigJsContent>
<_frameworkPath>$(PublishDir)wwwroot/_framework</_frameworkPath>
<!-- Extract the fingerprint from uno-config.js to verify the file exists -->
<_configDotnetJsFingerprint>$([System.Text.RegularExpressions.Regex]::Match('$(_unoConfigJsContent)', 'dotnet\.([a-z0-9]+)\.js').Groups[1].Value)</_configDotnetJsFingerprint>
</PropertyGroup>

<ItemGroup>
Expand All @@ -72,6 +75,10 @@
<Error Condition="$(_unoConfigJsContent.Contains('_framework/dotnet.js'))"
Text="uno-config.js contains non-fingerprinted _framework/dotnet.js reference in offline_files. Expected fingerprinted path like '_framework/dotnet.abc123.js'" />

<!-- Validate that the fingerprinted dotnet.js file referenced in uno-config.js actually exists -->
<Error Condition="'$(_configDotnetJsFingerprint)' != '' AND !Exists('$(_frameworkPath)/dotnet.$(_configDotnetJsFingerprint).js')"
Text="Fingerprint mismatch: uno-config.js references dotnet.$(_configDotnetJsFingerprint).js but this file does not exist in $(_frameworkPath). The publish-time fingerprint update may have failed." />

<Message Importance="high" Text="Output dist validated" />
</Target>

Expand Down
Loading