Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: CI

on:
push:
branches: [master]
# Feature branches included so work that cannot be compiled in the authoring environment
# gets a real build run before it reaches a pull request.
branches: [master, 'claude/**']
paths-ignore:
- '**.md'
- '.vscode/**'
Expand Down
173 changes: 173 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
name: Direct XAML Compiler

on:
push:
# Feature branches are included deliberately: this workflow exists to verify code that
# cannot be compiled in the authoring environment, so it has to run before the PR stage.
branches: [master, 'claude/**']
paths:
- 'compiler/**'
- 'dotnet/build/DirectXaml.*'
- 'dotnet/src/Easydict.WinUI/Views/Controls/MinimalServiceResultItem.xaml'
- '.github/workflows/rust.yml'
pull_request:
branches: [master]
paths:
- 'compiler/**'
- 'dotnet/build/DirectXaml.*'
- 'dotnet/src/Easydict.WinUI/Views/Controls/MinimalServiceResultItem.xaml'
- '.github/workflows/rust.yml'
workflow_dispatch:

permissions:
contents: read

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -D warnings

jobs:
compiler:
name: fmt, clippy, test
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: compiler

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust
run: rustup toolchain install stable --profile minimal --component rustfmt,clippy

- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
compiler/target
key: ${{ runner.os }}-cargo-${{ hashFiles('compiler/**/Cargo.toml') }}
restore-keys: ${{ runner.os }}-cargo-

- name: Check formatting
run: cargo fmt --all --check

- name: Clippy
run: cargo clippy --all-targets --all-features

- name: Test
run: cargo test --all-features

# `cargo test` writes the golden on first run. Publishing it — together with the IR compiled
# from the shipping card — is how an environment that cannot build the compiler still obtains
# the artifacts it has to check in.
- name: Compile the shipping card
if: always()
run: |
cargo run -p dxaml-cli -- compile \
--input ../dotnet/src/Easydict.WinUI/Views/Controls/MinimalServiceResultItem.xaml \
--output ./out || true

- name: Upload compiled IR
if: always()
uses: actions/upload-artifact@v4
with:
name: direct-xaml-ir
path: |
compiler/crates/dxaml-cli/tests/fixtures/MinimalServiceResultItem.dxir.json
compiler/out/MinimalServiceResultItem.dxir.json
compiler/out/MinimalServiceResultItem.bindings.g.cs
if-no-files-found: warn

# Drift check. `cargo test` creates the golden when it is absent, so an untracked file only
# means it has not been committed yet — failing on that would deadlock anyone who cannot run
# the compiler locally, since CI is the only place the file can be produced. What must fail
# is a *tracked* golden that no longer matches what the compiler emits.
- name: Verify the IR golden is current
run: |
golden=crates/dxaml-cli/tests/fixtures/MinimalServiceResultItem.dxir.json
status="$(git status --porcelain -- "$golden")"
case "$status" in
"")
echo "IR golden is committed and current." ;;
'??'*)
echo "::warning file=compiler/$golden::IR golden is not committed yet. Download it from the direct-xaml-ir artifact and commit it to enable regression checking." ;;
*)
echo "::error file=compiler/$golden::IR golden is stale. Run 'cargo test' locally and commit the result."
git --no-pager diff -- "$golden"
exit 1 ;;
esac

- name: Compile the shipping card end to end
run: |
cargo run -p dxaml-cli -- compile \
--input ../dotnet/src/Easydict.WinUI/Views/Controls/MinimalServiceResultItem.xaml \
--output "$RUNNER_TEMP/dxir"
cat "$RUNNER_TEMP/dxir/MinimalServiceResultItem.dxir.json"

# The full card is deliberately outside v0; if it ever compiles, the subset has drifted.
- name: Confirm the full card is still rejected
run: |
if cargo run -p dxaml-cli -- compile \
--input ../dotnet/src/Easydict.WinUI/Views/Controls/ServiceResultItem.xaml \
--check; then
echo "::error::ServiceResultItem.xaml compiled under Direct XAML v0, which the spec says it must not."
exit 1
fi

compiler-tools:
name: compiler tool (${{ matrix.rid }})
runs-on: windows-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-pc-windows-msvc
rid: win-x64
vs_arch: x64
- target: aarch64-pc-windows-msvc
rid: win-arm64
vs_arch: arm64
defaults:
run:
working-directory: compiler

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust target
shell: pwsh
run: |
rustup toolchain install stable --profile minimal
rustup target add ${{ matrix.target }}

- name: Build compiler
# The runner's ordinary PATH can resolve Git for Windows' GNU `link.exe`.
# Enter the matching MSVC developer shell so cargo sees the actual linker and
# architecture-specific Windows SDK / CRT libraries.
shell: cmd
run: |
set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
for /f "usebackq delims=" %%I in (`"%VSWHERE%" -latest -products * -property installationPath`) do set "VSINSTALL=%%I"
if not defined VSINSTALL exit /b 1
call "%VSINSTALL%\Common7\Tools\VsDevCmd.bat" -arch=${{ matrix.vs_arch }} -host_arch=x64 -no_logo
cargo build --release -p dxaml-cli --target ${{ matrix.target }}

- name: Stage compiler
shell: pwsh
run: |
$destination = Join-Path $env:RUNNER_TEMP '${{ matrix.rid }}'
New-Item -ItemType Directory -Force $destination | Out-Null
Copy-Item 'target/${{ matrix.target }}/release/dxamlc.exe' $destination

- name: Upload compiler
uses: actions/upload-artifact@v4
with:
name: direct-xaml-compiler-${{ matrix.rid }}
path: ${{ runner.temp }}/${{ matrix.rid }}/dxamlc.exe
if-no-files-found: error
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ tmp/
# Common build artifacts
**/*.dll
**/*.exe
!dotnet/build/tools/win-x64/dxamlc.exe
!dotnet/build/tools/win-arm64/dxamlc.exe
**/*.pdb
**/*.ilk
**/*.obj
Expand Down Expand Up @@ -50,6 +52,9 @@ project.lock.json
worker/node_modules/
worker/.wrangler/

# Rust (Direct XAML compiler)
compiler/target/

# macOS
.DS_Store

Expand Down
3 changes: 3 additions & 0 deletions compiler/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Fixtures and goldens are hashed and compared byte-for-byte. Pin them to LF so a Windows
# checkout with core.autocrlf=true produces the same content hash as a Linux one.
crates/dxaml-cli/tests/fixtures/** text eol=lf
Loading
Loading