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
11 changes: 11 additions & 0 deletions .codacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@
# deliberately ignores and the repo's own hadolint-check + DeepSource Docker already cover.
# - dotnet-data1/Program.cs: Codacy's CA1054 wants URI-typed params, but [JSImport] partial methods can only
# marshal `string` across the JS boundary; DeepSource covers the C# there and reports no such issue.
# - .github/workflows/ + .github/actions/: Codacy flags GitHub Actions `uses:` not pinned to a commit SHA, but
# this repo deliberately pins actions by tag (config/zizmor.yaml turns off zizmor's matching hash-pin policy for
# the same reason). Workflows + composite actions are already linted by actionlint, zizmor, action-validator, the
# ast-grep gha rules, and the gha* conftest policies; since Codacy cannot disable an individual pattern in-repo,
# excluding these trees is the only way to silence its pin rule globally.
# - CLAUDE.md: Codacy's prose rules (undefined-acronym, absolute-rule-without-escape-hatch) fight this
# agent-instructions doc, which is imperative and full of deliberate absolutes ("NEVER ...", "ALWAYS ...") by
# design; dprint + typos + editorconfig already lint it, so Codacy adds only false positives here.
exclude_paths:
- ".github/actions/**"
- ".github/workflows/**"
- "CLAUDE.md"
- "Dockerfile"
- "config/semgrep/**"
- "services/ws-modules/dotnet-data1/Program.cs"
7 changes: 7 additions & 0 deletions .deepsource.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ exclude_patterns = ["**/pkg/**", "generated/**", "services/ws-web-runner/mingw-s
# Repo convention: tests live in a `tests/` directory or in source files prefixed `test_`.
test_patterns = ["**/test_*.py", "**/tests/**"]

# Dart is explicitly deactivated; its coverage comes from the mise pipeline's check:dart instead.
# DeepSource's Dart support is an AI-only analyzer (no classic static analysis), so with AI review off it
# auto-surfaces as a perpetually-skipped "DeepSource: Dart" check on every PR.
[[analyzers]]
enabled = false
name = "dart"

[[analyzers]]
enabled = true
name = "python"
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/install-mise-tools/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ runs:
- name: Install mise binary
uses: ./.github/actions/install-mise
with:
install-action: ${{ inputs.install-action-tools }}
install-action-tools: ${{ inputs.install-action-tools }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

Correcting this input name from install-action to install-action-tools is vital. GitHub Actions does not error on undeclared inputs, which previously caused the install-mise-tools action to skip installing cargo-llvm-cov, leading to missing coverage data.


# Optional npm backend, installed before the main `mise install`.
# Only useful when js env is loaded (it's the backend for npm:* tools, all of which live in config.js.toml); skip
Expand Down
90 changes: 90 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
name: coverage

"on":
pull_request:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read
# Codecov's tokenless upload uses an OIDC id-token instead of a repository upload token.
id-token: write

concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

defaults:
run:
shell: bash --noprofile --norc -euo pipefail {0}

env:
# Exact full guest-language set -- gha.rego pins this literal value at the workflow level.
# (It's what lets `build-modules` build every ws-module so the Rust tests run.) The coverage job appends the
# `coverage` env at job level below, mirroring test.yaml's override job's `,${{ matrix.compiler }}`.
MISE_ENV: dart,dotnet,java,js,python,rust,zig

jobs:
coverage:
runs-on: ubuntu-latest
timeout-minutes: 150
env:
MISE_ENV: dart,dotnet,java,js,python,rust,zig,coverage
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false

- name: Free disk space on Linux
uses: jlumbroso/free-disk-space@v1.3.1

- name: Install Mesa Vulkan drivers (lavapipe)
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends mesa-vulkan-drivers

- name: Install mise + coverage tools
uses: ./.github/actions/install-mise-tools
timeout-minutes: 20
with:
github-token: ${{ github.token }}
install-action-tools: cargo-llvm-cov,cargo-nextest

- name: Prefetch dependencies
timeout-minutes: 15
env:
GITHUB_TOKEN: ${{ github.token }}
run: mise run prefetch-ci

- name: Build WASM modules
timeout-minutes: 25
env:
GITHUB_TOKEN: ${{ github.token }}
run: mise run build-modules

- name: Collect Rust coverage + test results
timeout-minutes: 75
run: mise run cargo-llvm-cov

- name: Upload coverage to Codecov (OIDC)
uses: codecov/codecov-action@v5
with:
use_oidc: true
files: lcov.info
fail_ci_if_error: true

# Upload test results even when tests failed.
# nextest still wrote the JUnit report, and a failing run is exactly when the per-test results on Codecov
# matter most; `report_type: test_results` selects the JUnit upload path.
- name: Upload test results to Codecov (OIDC)
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
use_oidc: true
report_type: test_results
files: target/nextest/ci/junit.xml
fail_ci_if_error: true
4 changes: 4 additions & 0 deletions .github/workflows/docker-linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ jobs:
run: |
args="--target test --build-arg BASE_IMAGE --build-arg MISE_ENV"
args="$args --secret id=gh_token,env=GITHUB_TOKEN -t et-test"
# $args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
docker build $args .

# The check stage needs `.git/` + every tracked Dockerfile.
Expand All @@ -110,6 +112,8 @@ jobs:
git ls-files '*Dockerfile' '*Dockerfile.*' | xargs -I{} cp --parents {} "$CTX/"
args="--target check --build-arg BASE_IMAGE --build-arg MISE_ENV"
args="$args --build-context extras=$CTX --secret id=gh_token -t $TAG"
# $args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
docker build $args .

# Capture image + intermediate stage sizes after the builds.
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/docker-windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ jobs:
args="$args --build-arg WINDOWS_VERSION=${{ matrix.windows_version }}"
fi
args="$args --target build-minimal -t $IMAGE_TAG"
# $args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
docker build $args .

# Diagnose whether the et-rp (rustpython) binary actually runs inside this base image.
Expand Down Expand Up @@ -139,17 +141,19 @@ jobs:
DOCKERFILE: ${{ steps.dockerfile.outputs.dockerfile }}
run: |
if [ "${{ matrix.base }}" = "servercore" ]; then
target=test
target="test"
tag="-t et-windows-test"
else
target=precompile
target="precompile"
tag=""
fi
args="-f $DOCKERFILE --build-arg MISE_ENV"
if [ "${{ matrix.runner }}" != "windows-2022" ]; then
args="$args --build-arg WINDOWS_VERSION=${{ matrix.windows_version }}"
fi
args="$args --target $target $tag"
# $args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
docker build $args .

# Run the test suite split the same way docker-linux does.
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ jobs:
# Compute the OS list here in the strategy block, where `github.*` IS in scope.
# `matrix` context isn't available in job-level `if:`, so we compute the
# OS list right here:
# pull_request -> ubuntu-latest + ubuntu-24.04-arm + macos-latest
# + windows-latest (skip slow Intel Mac;
# pull_request -> ubuntu-24.04-arm + macos-latest + windows-latest
# (ubuntu-latest x64 is exercised by coverage.yaml, so
# it's dispatch-only here; skip slow Intel Mac;
# ubuntu-26.04 + windows-11-arm are dispatch-only)
# workflow_dispatch -> the OS picked in the dropdown, or all of them
# The combos are emitted as a fully-formed list of `{os, timeout}`
Expand All @@ -81,8 +82,7 @@ jobs:
|| github.event.inputs.os == 'windows-latest' && '[{"os":"windows-latest","timeout":120}]'
|| github.event.inputs.os == 'windows-11-arm' && '[{"os":"windows-11-arm","timeout":60}]'
)
|| format('[{0},{1},{2},{3}]',
'{"os":"ubuntu-latest","timeout":40}',
|| format('[{0},{1},{2}]',
'{"os":"ubuntu-24.04-arm","timeout":40}',
'{"os":"macos-latest","timeout":45}',
'{"os":"windows-latest","timeout":120}')
Expand Down
20 changes: 17 additions & 3 deletions .github/workflows/upstream-cache.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ jobs:
run: |
sudo apt-get update
pkgs="autoconf automake bison flex libtool-bin libxml2-dev libreadline-dev pkg-config"
# $pkgs is a word-split package list by design; do not quote it.
# shellcheck disable=SC2086
sudo apt-get install -y --no-install-recommends $pkgs

# On macOS, brew the build deps, mirroring the fork's build.yml `macos` job.
Expand Down Expand Up @@ -334,6 +336,8 @@ jobs:
installdir="$RUNNER_TEMP/install"
mkdir -p "$installdir"
clone_args="--depth 1 --branch $AUG_REF --recurse-submodules"
# $clone_args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
git clone $clone_args "$AUG_FORK_REPO" "$srcdir"
cd "$srcdir"
if [ "$RUNNER_OS" = "macOS" ]; then
Expand All @@ -347,6 +351,8 @@ jobs:
fi
autogen_args="--prefix=$installdir --disable-static --disable-gnulib-tests"
autogen_args="$autogen_args --disable-dependency-tracking"
# $autogen_args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
./autogen.sh $autogen_args
make -j"$(nproc 2>/dev/null || sysctl -n hw.ncpu)"
make install
Expand All @@ -361,6 +367,8 @@ jobs:
sudo apt-get install -y --no-install-recommends patchelf
for f in bin/* lib/lib*.so*; do
[ -f "$f" ] && [ ! -L "$f" ] || continue
# '$ORIGIN' is a literal rpath token for the dynamic linker; single quotes are intentional.
# shellcheck disable=SC2016
patchelf --set-rpath '$ORIGIN/../lib' "$f" 2>/dev/null || true
done
else
Expand Down Expand Up @@ -397,6 +405,8 @@ jobs:
# otool -L on augtool tells us
# which absolute brew paths got baked in; copy each, rewrite
# its install_name + nested refs, and rewrite consumers.
# $1 is awk's field reference inside a single-quoted awk program, not a shell expansion.
# shellcheck disable=SC2016
brew_filter='NR>1 && $1 ~ /^\/(usr\/local|opt\/homebrew)\// {print $1}'
brew_deps_otool=$(otool -L bin/augtool lib/libaugeas*.dylib lib/libfa*.dylib 2>/dev/null)
queue=$(echo "$brew_deps_otool" | awk "$brew_filter" | sort -u)
Expand Down Expand Up @@ -542,9 +552,11 @@ jobs:
echo "::notice::$asset already in $DTG_RELEASE_TAG; skipping"
echo "work=" >> "$GITHUB_OUTPUT"
else
echo "work=yes" >> "$GITHUB_OUTPUT"
echo "triple=$triple" >> "$GITHUB_OUTPUT"
echo "asset=$asset" >> "$GITHUB_OUTPUT"
{
echo "work=yes"
echo "triple=$triple"
echo "asset=$asset"
} >> "$GITHUB_OUTPUT"
fi

# No explicit setup-rust step is needed for this build.
Expand All @@ -564,6 +576,8 @@ jobs:
# otherwise pick gnullvm and trip the same build failure we're working around.
cargo_args="--version $DTG_VERSION --root $installdir"
cargo_args="$cargo_args --target x86_64-pc-windows-msvc --locked"
# $cargo_args is a word-split flag list by design; do not quote it.
# shellcheck disable=SC2086
cargo install dart-typegen $cargo_args
ls "$installdir/bin"
# `cd` into the dir and tar a relative path to avoid the colon.
Expand Down
26 changes: 26 additions & 0 deletions .mise/config.coverage.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Coverage env (MISE_ENV includes `coverage`).
# A special stackable env like mingw/msvc, not a language -- so it is deliberately NOT in config.toml's ALL_LANGS
# and the *-all tasks never touch it. Selected only by the coverage workflow, stacked on the language envs it also
# loads (rust + the guest langs whose ws-modules the coverage build exercises, so the module-loading tests run
# rather than self-skip). Houses the cargo-llvm-cov task so it stays out of the always-loaded config.toml.
# cargo-llvm-cov and cargo-nextest are not mise [tools] -- the workflow co-installs them via
# taiki-e/install-action -- so there is no [tools] table here.

[tasks.cargo-llvm-cov]
description = "Rust coverage (cargo-llvm-cov) + JUnit test results (nextest); emits lcov.info + junit.xml"
# cargo-llvm-cov and cargo-nextest are deliberately NOT mise [tools] (like cargo-unmaintained).
# The coverage workflow installs both via taiki-e/install-action; this task just runs them. cargo-llvm-cov needs
# the `llvm-tools-preview` rustup component, which it adds on demand against the mise-managed toolchain.
# Running the suite through nextest (NEXTEST_PROFILE=ci) emits target/nextest/ci/junit.xml for the Codecov
# test-results upload; et-ws-web-runner is serialized by the `web-runner` test-group in config/nextest.toml
# rather than RUST_TEST_THREADS, which nextest ignores; `--config-file config/nextest.toml` selects that config.
# No `--doc` pass: the workspace sets `[lib] doctest = false` on essentially every crate (doc comments are prose,
# not runnable examples), and `cargo llvm-cov --doc` ignores that setting -- it drives rustdoc directly and chokes
# on the generated et-rest-client's backtick prose. So coverage stays on stable, tests-only. `--no-report` defers
# the report so `report` writes lcov.info from the nextest run's profiles.
env = { NEXTEST_PROFILE = "ci" }
run = """
cargo llvm-cov --no-report nextest --config-file config/nextest.toml
cargo llvm-cov report --lcov --output-path lcov.info
"""
shell = "bash -euo pipefail -c"
39 changes: 35 additions & 4 deletions .mise/config.dotnet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
[tools]
# Pinned: SDK churn re-keys the wasm-tools workload manifest, forcing a ~1.5GB pack re-download on every bump.
dotnet = "10.0.300"
dotnet-core = "10.0.300"
"dotnet:roslynator.dotnet.cli" = "latest"

[vars]
# MSBuild dir inside the mise dotnet SDK, for the roslynator `-m` flags below.
# `$DOTNET_ROOT` stays literal here; the task shell expands it. The version segment is the [tools] dotnet
# pin above -- bump together.
dotnet_msbuild = "$DOTNET_ROOT/sdk/10.0.300"

[tasks.dotnet-fmt]
description = "Format dotnet C# code"
run = "dotnet format"
Expand All @@ -14,15 +19,41 @@ run = "dotnet format"
description = "Check dotnet C# formatting"
run = "dotnet format --verify-no-changes"

# Namespaced aggregators picked up by the default config's globbed `check`/`fmt`.
[tasks.roslynator-check]
description = "Analyze C# sources (Roslynator)"
# Roslynator analyzes with its embedded analyzer assemblies, against the mise dotnet SDK's own MSBuild.
# The dotnet:roslynator.dotnet.cli tool ships the analyzers, so the csproj needs no analyzer
# PackageReference. Diagnostics at the default info-and-up severity fail the task; loading the project
# performs an implicit restore, so no `dotnet restore` dependency is needed.
#
# `-m` pins MSBuild to the mise dotnet SDK instead of MSBuildLocator's automatic discovery. On Windows the
# inline-task shell is busybox ash (windows_default_inline_shell_args), and busybox-w32 rewrites `\` to `/`
# in every env var it passes to children -- DOTNET_ROOT arrives as `C:/Users/...`, a form hostfxr accepts
# (dotnet-check works) but MSBuildLocator's SDK discovery does not, failing with:
# Cannot choose MSBuild location automatically. Use option '-m, --msbuild-path' to specify MSBuild location
# Observed on commit ef55945932f5d417b8d205530f0868cff6d73ffa (locally; reproduced under `mise exec` by
# setting a forward-slashed DOTNET_ROOT). The env var itself is fine as the `-m` argument -- mise's core
# dotnet plugin exports DOTNET_ROOT on every OS, and the forward-slashed form ash delivers on Windows is
# accepted there; only MSBuildLocator's own probing of it breaks.
run = 'roslynator analyze -m "{{ vars.dotnet_msbuild }}" services/ws-modules/dotnet-data1/dotnet-data1.csproj'

[tasks.roslynator-fix]
description = "Apply Roslynator diagnostics' machine-applicable C# fixes in place"
run = 'roslynator fix -m "{{ vars.dotnet_msbuild }}" services/ws-modules/dotnet-data1/dotnet-data1.csproj'

# Namespaced aggregators picked up by the default config's globbed `check`/`fmt`/`fix`.
[tasks."check:dotnet"]
depends = ["dotnet-check"]
description = "Run .NET checks (format verification)"
depends = ["dotnet-check", "roslynator-check"]
description = "Run .NET checks (format verification + Roslynator analysis)"

[tasks."fmt:dotnet"]
depends = ["dotnet-fmt"]
description = "Format .NET sources"

[tasks."fix:dotnet"]
depends = ["roslynator-fix"]
description = "Apply .NET lint-fix passes (roslynator fix)"

[tasks.build-ws-dotnet-data1-module]
description = "Build the dotnet-data1 C# WASM workflow module"
dir = "services/ws-modules/dotnet-data1"
Expand Down
Loading
Loading