Skip to content

DYN-10984: Run engine tests (ProtoTest) in GitHub Actions - #17370

Merged
QilongTang merged 12 commits into
masterfrom
DYN-10984-engine-tests-in-ci
Oct 9, 2026
Merged

QilongTang merged 12 commits into
masterfrom
DYN-10984-engine-tests-in-ci

Conversation

@QilongTang

@QilongTang QilongTang commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

DYN-10984: Run the engine test suite in GitHub Actions. Tech-debt item #2 from the 2026-10 codebase review — the DesignScript engine (src/Engine/, 72K lines across 128 files, the highest-blast-radius code in the repo) has 5,274 NUnit tests in test/Engine/ProtoTest, but no GitHub Actions workflow runs them. Engine regressions currently surface only in the downstream Jenkins UI-test chain, hours after merge. The Linux CI workflow even carries a TODO noting dotnet test finds no tests there (build_dynamo_core.yml:98).

Key changes:

  • Added .github/workflows/run_engine_tests.yml: on PRs touching src/Engine/, test/Engine/, or the workflow itself, it restores and builds src/DynamoCore.sln (Release) — the identical commands build_dynamo_core.yml already runs — then runs dotnet test on the ProtoTest project with an NUnit category filter and publishes trx results as an artifact.
  • The category filter defaults to Category=SmokeTest&Category!=Failure (~1,160 of the 5,274 tests) for fast PR feedback. It is a workflow_dispatch input, so the full suite can be run on demand; the default can be widened once the suite's CI runtime is known. The Failure category is the repo's convention for known-failing tests tracking engine defects — they fail by design and must not gate PRs.
  • A post-run guard parses the TRX and fails when the file is missing or reports zero executed tests — dotnet test exits 0 on an empty match (typo'd filter, missing adapter), which would otherwise make the gate silently pass.
  • FFITarget.dll needs no special handling: all projects share one output path (CS_SDK.props OutputPath), so it lands next to ProtoTest.dll automatically. About 50 ProtoTest files import it at runtime via the FFITarget.dll import statement.
  • Documented the engine-test command in AGENTS.md (Running a Single Test section) and .github/copilot-instructions.md, with the command identical in both files.

Review follow-ups addressed (from the first Copilot review + Sonar):

  • Dropped the unneeded checks: write permission — nothing in the job creates checks; the job is now least-privileged (contents: read only).
  • Added the TRX zero-tests guard described above (the pre-flight DLL existence check alone couldn't catch the silent-pass failure mode).
  • Bumped upload-artifact v4 → v7 to match repo convention and the Node.js 24-compatible major.
  • Sonar asks for actions pinned to commit SHAs; this repo pins by tag everywhere (19× actions/checkout@v7 across workflows), so this PR follows repo convention. Happy to switch if maintainers prefer SHA pinning repo-wide.

Scope notes:

  • The Linux TODO is not addressed: engine tests are Windows-first (FFITarget interop). A Linux pass would be a follow-up.
  • The workflow uses --no-build after the msbuild step; dotnet test evaluates the same CS_SDK.props OutputPath, so it finds the msbuild-built assembly.

Declarations

Check these if you believe they are true

Release Notes

N/A

Reviewers

@jasonstratton @QilongTang

Notes to reviewers:

  • The SmokeTest default is a starting point, not a ceiling — if CI shows the full suite runs in acceptable time, change the default filter and this becomes full engine coverage on every engine PR.
  • Jenkins continues to run whatever it runs today; nothing is removed, only added.

FYIs

@DynamoDS/eidos

🤖 Generated with Claude Code

The DesignScript engine (src/Engine/, 72K lines) has 5,274 NUnit
tests in test/Engine/ProtoTest, but no GitHub Actions workflow runs
them — engine regressions surface only in the downstream Jenkins
UI-test chain, hours after merge.

Adds run_engine_tests.yml: on PRs touching src/Engine/** or
test/Engine/**, restore + build DynamoCore.sln (the same commands
build_dynamo_core.yml already runs) and run dotnet test on ProtoTest
with an NUnit category filter, publishing trx results as an artifact.

- Defaults to the SmokeTest category (~1,200 tests) for fast PR
  feedback; widen via the workflow_dispatch input or by changing
  the default once the suite's CI runtime is known.
- Verifies ProtoTest.dll exists in the shared output path before
  running, failing with a clear message if the build missed it.
- FFITarget.dll needs no special handling: all projects share one
  output path (bin/AnyCPU/Release), so it lands next to ProtoTest.dll
  automatically (~50 test files import it at runtime).
- The Linux TODO in build_dynamo_core.yml is not addressed here —
  engine tests are Windows-first (FFITarget interop); a Linux pass
  would be a follow-up.

Documents the engine-test command in AGENTS.md and
copilot-instructions.md.

Co-Authored-By: Claude Code <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 6, 2026 03:24

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the ticket for this pull request: https://autodesk.atlassian.net/browse/DYN-10984

The maiden run failed 24 of 1185 SmokeTest tests — investigation
showed all 24 are marked Category("Failure"), the repo's convention
for known-failing tests that track engine defects (~170 in the suite;
20 of them also carry SmokeTest). They fail by design and must not
gate PRs.

The filter is now Category=SmokeTest && Category!=Failure, which
selects 1150 tests. The workflow comment documents why.

Co-Authored-By: Claude Code <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The new gate currently fails 24 baseline tests and does not prevent zero-test false positives.

Review effort: Balanced
Findings: 1 High severity · 2 Medium severity · 1 Low severity

Open (4)
What changed in this PR

Adds Windows GitHub Actions coverage for DesignScript engine tests.

Changes:

  • Runs filtered ProtoTest tests for engine-related PRs.
  • Publishes TRX results and supports manual filtering.
  • Documents the engine test command.
File Description
AGENTS.md Documents ProtoTest execution.
.github/​workflows/​run_engine_tests.yml Adds engine-test CI workflow.
.github/​copilot-instructions.md Adds matching test guidance.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/run_engine_tests.yml Outdated
Comment on lines +73 to +75
dotnet test ${{ github.workspace }}\Dynamo\test\Engine\ProtoTest\ProtoTest.csproj
--no-build -c Release
--filter "$env:TEST_CATEGORY_FILTER"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in d471268: the 24 failures were all Category("Failure") tests — the repo's convention for known-failing tests tracking engine defects. The default filter now excludes that category (Category=SmokeTest&Category!=Failure), and the follow-up run was green: 1,161 passed, 0 failed. Filed the ~170-test Failure-category triage as a side finding on the ticket for the test-debt backlog.

Comment thread .github/workflows/run_engine_tests.yml Outdated
Comment on lines +61 to +63
- name: Verify test assembly built
run: |
$dll = "${{ github.workspace }}\Dynamo\bin\AnyCPU\Release\ProtoTest.dll"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 1ffea17: added a Verify tests executed step that runs after dotnet test (with if: always()), parses the TRX, and fails when the file is missing or ResultSummary.Counters.executed is zero. The pre-flight DLL check remains as a fast build-sanity check, but the TRX guard is what catches the silent-pass failure mode.

Comment thread .github/workflows/run_engine_tests.yml Outdated
QilongTang and others added 2 commits October 5, 2026 23:34
The folded-scalar run step passed the filter through in a way that
pwsh split on the && operator, so dotnet test received a malformed
filter (Missing operand). Switch to a literal block scalar with
backtick line continuations, the standard pwsh form, so the quoted
filter reaches dotnet test as a single argument.

Co-Authored-By: Claude Code <[email protected]>
The NUnit adapter rejected the filter with Missing operand: vstest's
filter grammar uses single & and | as operators, not &&. The repo's
own AGENTS.md documents this ("Combine with & (AND) or | (OR)").

Filter is now Category=SmokeTest&Category!=Failure.

Co-Authored-By: Claude Code <[email protected]>
Comment thread .github/workflows/run_engine_tests.yml Fixed
- Drop unneeded checks:write permission (nothing creates checks)
- Fail the run when the TRX is missing or reports zero executed tests,
  so a typo'd filter or missing adapter can't silently pass the gate
- Bump upload-artifact v4 -> v7 to match repo convention and the
  Node.js 24-compatible major

Co-Authored-By: Claude Code <[email protected]>
@QilongTang
QilongTang requested a review from a team as a code owner October 7, 2026 05:44
@QilongTang
QilongTang marked this pull request as draft October 7, 2026 05:45

@jasonstratton jasonstratton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@QilongTang , this looks good, but a couple of points that you can decide whether to make adjustments or merge as is:

  1. The docs command doesn't match CI. AGENTS.md and copilot-instructions.md both say --filter "Category=SmokeTest", without &Category!=Failure. Anyone running it locally will hit those 24 known failures and assume they broke something. I'd add the exclusion in both files; they need to stay identical for the parity check.
  2. The smoke-only limit may not be needed. The 1,161 tests ran in 12 seconds, and almost all of the ~3.5-minute job is the build. The full ~5,100 non-Failure tests would probably add about a minute. The PR says it would widen the filter once runtime was known, and the run shows the runtime now. I'd suggest making the default the full suite minus Failure

…lter

Review follow-up from Jason on #17370:

- The smoke-only default is no longer needed: the 1,161 SmokeTest
  tests ran in 12s while the job spends ~3.5 min on the build, so the
  full ~5,200-test suite minus Failure adds only about a minute.
  Default filter is now Category!=Failure (vstest treats tests with
  no category as matching a negative filter, so uncategorized tests
  are included).
- AGENTS.md and copilot-instructions.md said --filter
  "Category=SmokeTest" without the Failure exclusion, so anyone
  running the documented command locally hit the ~190 known-failing
  tests. Both files now show the same Category!=Failure filter CI
  uses (kept identical for the parity check) and note SmokeTest as
  the fast subset.

Co-Authored-By: Claude Code <[email protected]>
@QilongTang

Copy link
Copy Markdown
Contributor Author

Both points addressed in 3992493 — thanks @jasonstratton.

  1. Docs now match CI. AGENTS.md and copilot-instructions.md both show --filter "Category!=Failure" (identical text, so the parity check stays green), with a note that Failure marks known-failing tests and SmokeTest remains the fast subset for a quicker local signal.

  2. Default widened to the full suite minus Failure. The workflow default is now Category!=Failure (~5,014 tests: 5,206 total minus 192 Failure-marked). One subtlety verified before making the change: vstest's negative filter includes tests with no category at all — in the filter evaluation code, a test with no Category value makes Category=Failure evaluate false, so != inverts it to true. That matters here because ~2,000 ProtoTest methods carry no category and must stay in the run.

Since the workflow triggers on changes to itself, this push is running the widened filter on this very PR — the run will confirm the full-suite runtime and pass rate before merge.

@QilongTang
QilongTang marked this pull request as ready for review October 8, 2026 04:05
jasonstratton and others added 2 commits October 8, 2026 19:42
SonarCloud flags third-party actions referenced by a mutable tag as a
high-severity supply-chain issue, which failed the PR quality gate
(Security Rating on New Code: C). Pin microsoft/setup-msbuild to the
commit that v3 currently resolves to.

DYN-10984

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Apply the same pin as run_engine_tests.yml to the existing
build_dynamo_all, build_dynamo_core and dynamo_bin_diff workflows.
SonarCloud only flagged the new file because the others are not new
code, but they carried the same mutable-tag supply-chain exposure.

DYN-10984

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@jasonstratton

Copy link
Copy Markdown
Contributor

@QilongTang FYI: I pushed two small commits to this branch to clear the SonarCloud failures. Summary below.

🤖 The investigation and write-up below came from Claude (AI-assisted research), reviewed by @jasonstratton.

Why SonarCloud failed

Both SonarCloud and SonarCloud Code Analysis failed on the same single finding:

  • .github/workflows/run_engine_tests.yml:53 used microsoft/setup-msbuild@v3.
  • SonarCloud's rule "External GitHub Actions and workflows should be pinned to a commit hash" treats a third-party action referenced by a mutable tag as a high-severity supply-chain issue, since the tag can be re-pointed at different code later.
  • That one finding dropped Security Rating on New Code to C, and the quality gate requires A.
  • GitHub-owned actions (actions/*, github/*) are exempt from this rule, which is why checkout, setup-dotnet and upload-artifact weren't flagged.

What was changed

Commit Change
4a4ac27a1b Pinned microsoft/setup-msbuild in run_engine_tests.yml to 30375c66a4eea26614e0d39710365f22f8b0af57 # v3 (the commit both the v3 and v3.0.0 tags resolve to). Both SonarCloud checks pass after this.
8cb9f809a1 Applied the same pin to the existing workflows that already used setup-msbuild@v3: build_dynamo_all.yml, build_dynamo_core.yml (×2), dynamo_bin_diff.yml (×2). Sonar didn't flag these because they aren't new code in this PR, but they had the same exposure.

No behavior change: the pinned SHA is exactly what v3 points to today.

Not addressed here (possible follow-up)

Other third-party actions in .github/workflows/ are still referenced by tag. They're unrelated to this PR, so they were left alone:

  • tj-actions/changed-files@v46 (check_file_size.yml). Most notable: this action was compromised in March 2025, when its version tags were re-pointed at malicious code. That attack is exactly what SHA pinning prevents.
  • korthout/backport-action@v4 (auto_cherrypick.yml)
  • dawidd6/action-download-artifact@v20, peter-evans/find-comment@v4, peter-evans/create-or-update-comment@v5 (dynamo_post_bin_diff.yml)
  • actions-ecosystem/action-regex-match@v2, frabert/[email protected] (Issues_workflow.yml)
  • leonsteinhaeuser/[email protected] (move_issue.yml)
  • neofinancial/ticket-check-action@v2 (pr_jira_check.yml)

generate_changelog.yml already follows the pinned sha # version convention for metcalfc/changelog-generator.

🤖 Generated with Claude Code

@sonarqubecloud

sonarqubecloud Bot commented Oct 9, 2026

Copy link
Copy Markdown

@QilongTang
QilongTang merged commit 72b753c into master Oct 9, 2026
36 of 37 checks passed
@QilongTang
QilongTang deleted the DYN-10984-engine-tests-in-ci branch October 9, 2026 03:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants