Skip to content

Commit 86f0a0e

Browse files
committed
feat(nunit): publish DevTools.NUnit independently via Trusted Publishing
Keep the package version in the MTP csproj and push nuget.org from a workflow-dispatch job using GitHub OIDC, separate from installer tags.
1 parent 3366153 commit 86f0a0e

4 files changed

Lines changed: 174 additions & 10 deletions

File tree

.github/workflows/PublishNUnit.yml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: Publish NUnit
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
push:
7+
description: "Push DevTools.NUnit to nuget.org (OIDC Trusted Publishing)"
8+
type: boolean
9+
default: true
10+
nuget_user:
11+
description: "nuget.org username (profile name, not email). Required when pushing unless NUGET_USER secret exists."
12+
required: false
13+
type: string
14+
15+
concurrency:
16+
group: publish-nunit
17+
cancel-in-progress: false
18+
19+
permissions:
20+
contents: read
21+
id-token: write
22+
23+
jobs:
24+
windows:
25+
name: windows-2025
26+
runs-on: windows-2025
27+
steps:
28+
29+
- name: Checkout
30+
uses: actions/checkout@v6
31+
32+
- name: Cache packages
33+
uses: actions/cache@v5
34+
with:
35+
path: ~/.nuget/packages
36+
key: ${{ runner.os }}-nuget-nunit-${{ hashFiles('source/DevTools.NUnit.Mtp/**/*.csproj', 'Directory.Build.props', 'Directory.Packages.props') }}
37+
restore-keys: ${{ runner.os }}-nuget-
38+
39+
- name: Test MTP
40+
run: dotnet test tests/DevTools.NUnit.Mtp.Tests/DevTools.NUnit.Mtp.Tests.csproj -c Release
41+
42+
- name: Pack DevTools.NUnit
43+
id: pack
44+
shell: pwsh
45+
run: |
46+
$csproj = "source/DevTools.NUnit.Mtp/DevTools.NUnit.Mtp.csproj"
47+
$version = (dotnet msbuild $csproj -nologo -v:q -getProperty:Version).Trim()
48+
if ([string]::IsNullOrWhiteSpace($version)) {
49+
throw "Could not read Version from $csproj"
50+
}
51+
"version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
52+
Write-Host "Package version from csproj: $version"
53+
./scripts/pack-nunit.ps1
54+
55+
- name: Upload nupkg
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: DevTools.NUnit.${{ steps.pack.outputs.version }}
59+
path: output/nuget/DevTools.NUnit.${{ steps.pack.outputs.version }}.nupkg
60+
if-no-files-found: error
61+
retention-days: 14
62+
63+
- name: Resolve nuget.org user
64+
id: nuget-user
65+
if: ${{ github.event.inputs.push == 'true' }}
66+
shell: pwsh
67+
env:
68+
NUGET_USER_SECRET: ${{ secrets.NUGET_USER }}
69+
NUGET_USER_INPUT: ${{ inputs.nuget_user }}
70+
run: |
71+
$user = if (-not [string]::IsNullOrWhiteSpace($env:NUGET_USER_SECRET)) {
72+
$env:NUGET_USER_SECRET
73+
} else {
74+
$env:NUGET_USER_INPUT
75+
}
76+
if ([string]::IsNullOrWhiteSpace($user)) {
77+
throw "Enter nuget.org profile name in the nuget_user input (not email), or set repository secret NUGET_USER."
78+
}
79+
"user=$user" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
80+
81+
- name: NuGet login (OIDC)
82+
if: ${{ github.event.inputs.push == 'true' }}
83+
uses: NuGet/login@v1
84+
id: login
85+
with:
86+
user: ${{ steps.nuget-user.outputs.user }}
87+
88+
- name: Push nuget.org
89+
if: ${{ github.event.inputs.push == 'true' }}
90+
shell: pwsh
91+
env:
92+
NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }}
93+
PACKAGE_VERSION: ${{ steps.pack.outputs.version }}
94+
run: |
95+
$nupkg = "output/nuget/DevTools.NUnit.$($env:PACKAGE_VERSION).nupkg"
96+
if (-not (Test-Path -LiteralPath $nupkg)) {
97+
throw "Missing $nupkg"
98+
}
99+
dotnet nuget push $nupkg --source https://api.nuget.org/v3/index.json --api-key $env:NUGET_API_KEY

docs/product/nunit-host-testing.md

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@ controller ships in that installer. The live CAD host executes the tests.
88

99
## Status
1010

11-
**Experimental.** Discover / run / progress work end-to-end. The public NuGet
12-
package is **not published** yet — consume from source / local pack only until
13-
the first supported release.
11+
**Experimental.** Discover / run / progress work end-to-end. `DevTools.NUnit`
12+
(MTP) is published independently of the RevitDevTool installer. Version is
13+
`<Version>` in `source/DevTools.NUnit.Mtp/DevTools.NUnit.Mtp.csproj` (starts at
14+
`0.0.1`). Run `.github/workflows/PublishNUnit.yml` from GitHub Actions to pack
15+
and push nuget.org (OIDC Trusted Publishing). VSTest stays in-tree and is not
16+
published.
1417

1518
Host-process debugging is **out of scope**. There is no `--debug` CLI, no Test
1619
Explorer Debug attach, and no IDE SDK. Attach the IDE debugger to the host
1720
PID yourself if needed; that is not a product feature.
1821

1922
Two consumer surfaces share the same Runner/Host: MTP (`DevTools.NUnit`) and
2023
VSTest (`DevTools.NUnit.TestAdapter`). Keep them on **separate** test projects.
21-
Neither package is published yet.
2224

2325
## Modules
2426

@@ -110,7 +112,7 @@ Runner ships under the ApplicationPlugins bundle `Contents` folder (publish
110112
| Probe load | **Also shadows**: zip test folder → `%TEMP%\RevitTest\` → extract → `Assembly.LoadFile` on the temp copy (then optional zip-back) | Content-addressed generation shadow of test output + Runtime |
111113
| Transport | Own Console + `PipeTestServer`/`PipeTestClient` (process-named pipe) | Existing `DevToolsPipeServer` + `IHostContextExecutor` |
112114
| IDE surface | VS-oriented + EnvDTE attach | MTP + VSTest samples; no debugger integration |
113-
| Package | ricaun NuGet ecosystem | Intended: `DevTools.NUnit` (MTP) NuGet (**unpublished**); VSTest adapter in-tree |
115+
| Package | ricaun NuGet ecosystem | `DevTools.NUnit` (MTP) NuGet, versioned in the MTP csproj; VSTest adapter in-tree |
114116
| Hosts | Revit-focused product | Revit + AutoCAD family on shared DevTools platform |
115117

116118
**Conflict / coexistence (what actually breaks):**
@@ -163,13 +165,31 @@ options; one intended adapter package aligned with the rest of RevitDevTool.
163165

164166
| Package | Publish status |
165167
|---------|----------------|
166-
| `DevTools.NUnit` (`DevTools.NUnit.Mtp`) | **Not published** — experimental; local/source only |
168+
| `DevTools.NUnit` (`DevTools.NUnit.Mtp`) | Independent of installer tags. Version = csproj `<Version>`. Workflow: `PublishNUnit.yml` |
167169
| `DevTools.NUnit.TestAdapter` | **Not published** — in-tree VSTest samples only |
168170
| Core / Host / Runner | Not consumer NuGet APIs |
169171

170-
When publishing later: pack `DevTools.NUnit` only. Consumers add NUnit,
171-
`DevTools.NUnit`, and `Microsoft.Testing.Platform.MSBuild`; install
172-
[RevitDevTool](https://github.com/trgiangv/RevitDevTool); set the host-run
172+
Bump `<Version>` in `source/DevTools.NUnit.Mtp/DevTools.NUnit.Mtp.csproj`, commit,
173+
then run **Actions → Publish NUnit**. The workflow reads that property, packs
174+
`DevTools.NUnit.{version}.nupkg`, and pushes nuget.org via
175+
[Trusted Publishing](https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing)
176+
(OIDC; no long-lived API key). Uncheck **Push to nuget.org** to pack-only.
177+
Do not use installer tags or `scripts/pack.ps1` for this package. Local pack:
178+
`scripts/pack-nunit.ps1`.
179+
180+
One-time nuget.org setup before the first push:
181+
182+
1. nuget.org → account → **Trusted Publishing** → add policy:
183+
- Repository Owner: `trgiangv`
184+
- Repository: `RevitDevTool`
185+
- Workflow File: `PublishNUnit.yml` (file name only)
186+
- Environment: leave empty
187+
2. Run the workflow with **nuget_user** = nuget.org **profile name** (not email).
188+
Optional later: store that name as repo secret `NUGET_USER`.
189+
This repo is public; the policy should show **Active** after Create.
190+
191+
Consumers add NUnit, `DevTools.NUnit`, and `Microsoft.Testing.Platform.MSBuild`;
192+
install [RevitDevTool](https://github.com/trgiangv/RevitDevTool); set the host-run
173193
properties (`HostName`, `HostVersion`, `HostLaunch`, timeouts); and keep a
174194
test-directory `global.json` with `"test": { "runner": "Microsoft.Testing.Platform" }`
175195
so `dotnet test` uses MTP.
@@ -179,7 +199,8 @@ so `dotnet test` uses MTP.
179199
- Microsoft Testing Platform / VSTest IDE matrix (VS / Rider / C# Dev Kit)
180200
- Full NUnit attribute matrix (Theory, explicit, categories, parallel, …)
181201
- Broader automated host-matrix CI (years × hosts) for NUnit beyond sample smoke
182-
- Public NuGet feed + versioning / changelog
202+
- nuget.org listing after the first `Publish NUnit` run (`0.0.1`)
203+
- Package changelog separate from the installer Changelog.md
183204

184205
## Related
185206

scripts/pack-nunit.ps1

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<#
2+
.SYNOPSIS
3+
Pack the DevTools.NUnit NuGet package from DevTools.NUnit.Mtp.
4+
.DESCRIPTION
5+
Uses <Version> in source/DevTools.NUnit.Mtp/DevTools.NUnit.Mtp.csproj.
6+
Does not push. Does not run the RevitDevTool installer pack pipeline.
7+
.EXAMPLE
8+
scripts/pack-nunit.ps1
9+
scripts/pack-nunit.ps1 -OutputDirectory output/nuget
10+
#>
11+
param(
12+
[string]$OutputDirectory = 'output/nuget'
13+
)
14+
15+
$ErrorActionPreference = "Stop"
16+
. (Join-Path $PSScriptRoot '_lib.ps1')
17+
Assert-RepoRoot
18+
19+
$csproj = Join-RepoPath 'source/DevTools.NUnit.Mtp/DevTools.NUnit.Mtp.csproj'
20+
$outDir = Join-RepoPath $OutputDirectory
21+
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
22+
23+
$version = (dotnet msbuild $csproj -nologo -v:q -getProperty:Version).Trim()
24+
if ([string]::IsNullOrWhiteSpace($version)) {
25+
throw "Could not read Version from $csproj"
26+
}
27+
28+
Write-Host "Packing DevTools.NUnit $version"
29+
dotnet pack $csproj -c Release -o $outDir
30+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
31+
32+
$nupkg = Get-ChildItem -LiteralPath $outDir -Filter "DevTools.NUnit.$version.nupkg" |
33+
Select-Object -First 1
34+
if (-not $nupkg) {
35+
throw "Expected $outDir/DevTools.NUnit.$version.nupkg"
36+
}
37+
38+
Write-Host "Packed $($nupkg.FullName)"
39+
exit 0

source/DevTools.NUnit.Mtp/DevTools.NUnit.Mtp.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77
<RootNamespace>DevTools.NUnit.Mtp</RootNamespace>
88
<AssemblyName>DevTools.NUnit.Mtp</AssemblyName>
99
<PackageId>DevTools.NUnit</PackageId>
10+
<!-- Bump this before running .github/workflows/PublishNUnit.yml.
11+
Independent of the RevitDevTool installer GitVersion. -->
12+
<Version>0.0.1</Version>
1013
<IsPackable>true</IsPackable>
1114
<DevelopmentDependency>true</DevelopmentDependency>
15+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
16+
<PackageProjectUrl>https://github.com/trgiangv/RevitDevTool</PackageProjectUrl>
1217
<Description>Microsoft.Testing.Platform framework that runs NUnit tests inside Revit/AutoCAD hosts. Requires RevitDevTool (https://github.com/trgiangv/RevitDevTool).</Description>
1318
<PackageTags>nunit;revit;autocad;testing;mtp</PackageTags>
1419
<PackageReadmeFile>README.md</PackageReadmeFile>

0 commit comments

Comments
 (0)