-
Notifications
You must be signed in to change notification settings - Fork 12
266 lines (233 loc) · 11.3 KB
/
release.yml
File metadata and controls
266 lines (233 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
name: Package
# Produces the framework NuGet (.nupkg + .snupkg) and the agent skill kit
# (reactor-skill-kit-<version>.zip with bin/x64 + bin/arm64).
#
# Versions come from MinVer (see "Resolve version" step). Both PR and main
# builds get the same MinVer-computed version; they differ by sha in build
# metadata and by workflow run ID. Tag pushes (`v*`) get the tag's version
# verbatim and additionally create a GitHub Release with the assets attached.
# This is the interim distribution path described in
# docs/specs/022-packaging-and-distribution.md §3 (Phase P0) while the
# internal Microsoft NuGet feed is being plumbed through.
#
# Both x64 and arm64 mur binaries are produced on every run so reviewers can
# install either against a feature branch.
on:
pull_request:
paths-ignore:
- 'docs/guide/**' # auto-generated; see CLAUDE.md memory note
push:
# No paths-ignore on push: tag pushes must always run regardless of what
# changed in the tagged commit, and main pushes are infrequent enough
# that running on doc-only changes isn't a real cost.
branches: [main]
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to pack (e.g. 0.1.0-preview.1). When dispatched manually, no Release is created.'
required: true
type: string
permissions:
contents: write # required for creating Releases
# ─── Version strategy ───────────────────────────────────────────────────────
# Versions come from MinVer (commit-height past the latest `v*` tag). Pattern:
#
# - Past tag `v0.1.0-experimental.1` by N commits → `0.1.0-experimental.1.N+<sha7>`
# - Exactly at a tag → that tag's version
# - No tags yet → `0.1.0-experimental.0.<height>+<sha7>` (defaults below)
#
# Bootstrap once: `git tag v0.1.0-experimental.0 && git push --tags`. After
# that, every commit gets a unique, ordered version with zero coordination —
# height strictly increases as commits land. Bump to a new milestone by
# tagging (e.g. `v0.1.0-experimental.1`); MinVer takes it from there.
#
# Tag pushes (`v*`) produce a clean version and create a GitHub Release.
# Pushes to main and PR builds get the same MinVer-computed version (they
# differ by sha → unique workflow artifacts; the .nupkg filename may collide
# across PR pushes from the same merge base, which is acceptable for the
# experimental channel).
jobs:
package:
name: Pack (x64 + arm64)
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # MinVer needs full history to find the latest v* tag
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Install minver-cli
run: dotnet tool install --global minver-cli --version 5.0.0
- name: Install BinSkim
# BinSkim ships as a regular NuGet package containing BinSkim.exe,
# not as a dotnet global tool. Download the package and resolve the
# exe path into an env var for the analyze step.
shell: pwsh
run: |
nuget install Microsoft.CodeAnalysis.BinSkim -OutputDirectory binskim-pkg -ExcludeVersion
$exe = Get-ChildItem binskim-pkg -Filter BinSkim.exe -Recurse |
Where-Object { $_.FullName -like '*win-x64*' } |
Select-Object -First 1 -ExpandProperty FullName
if (-not $exe) { throw 'BinSkim.exe not found in package' }
"BINSKIM_EXE=$exe" >> $env:GITHUB_ENV
Write-Host "BinSkim: $exe"
- name: Resolve version
id: version
shell: pwsh
run: |
$eventName = '${{ github.event_name }}'
if ($eventName -eq 'workflow_dispatch') {
$version = '${{ inputs.version }}'
} else {
# MinVer flags:
# -t v tag prefix
# -p experimental.0 default prerelease identifiers — flags pre-P1 builds as experimental
# -m 0.1 minimum major.minor when no tag (so untagged → 0.1.x)
$version = (& minver -t v -p experimental.0 -m 0.1).Trim()
}
if (-not $version) { throw "Could not resolve version" }
"version=$version" >> $env:GITHUB_OUTPUT
$isTag = '${{ github.ref }}'.StartsWith('refs/tags/v')
"is_tag=$($isTag.ToString().ToLower())" >> $env:GITHUB_OUTPUT
Write-Host "Version: $version (event=$eventName, isTag=$isTag)"
- name: Restore
run: dotnet restore Reactor.slnx
- name: Build framework + analyzers
run: dotnet build Reactor.slnx --no-restore --configuration Release
- name: Pack framework NuGet
run: >
dotnet pack src/Reactor/Reactor.csproj
--no-build --configuration Release
-p:Version=${{ steps.version.outputs.version }}
-o artifacts/nupkg
- name: Pack Templates
run: >
dotnet pack tools\Templates\Microsoft.UI.Reactor.Templates.csproj
--no-build --configuration Release
-p:Version=${{ steps.version.outputs.version }}
-p:Platform=AnyCPU
-o artifacts/nupkg
# Framework-dependent: the consumer's machine supplies the .NET 10
# runtime — saves ~70 MB per RID. install-skill-kit.ps1 checks for it
# and errors out with an install hint if it's missing. See spec 022 §6.
- name: Publish mur (win-x64)
run: >
dotnet publish src/Reactor.Cli/Reactor.Cli.csproj
--configuration Release
--runtime win-x64
--self-contained false
-p:Version=${{ steps.version.outputs.version }}
-o artifacts/mur/x64
- name: Publish mur (win-arm64)
run: >
dotnet publish src/Reactor.Cli/Reactor.Cli.csproj
--configuration Release
--runtime win-arm64
--self-contained false
-p:Version=${{ steps.version.outputs.version }}
-o artifacts/mur/arm64
# Managed-only repo: most native PE-hardening rules no-op against MSIL
# assemblies. The run produces a SARIF for SDL compliance attestation
# (ADO 62373198). Scope is now Reactor-managed outputs only — the
# `runtimes/<rid>/native/` subtree (e.g., `copilot.exe` shipped by
# transitive `GitHub.Copilot.SDK`) is excluded since those binaries are
# not Reactor-authored. SARIF is uploaded unconditionally so reviewers
# can attach it to the work item.
- name: Run BinSkim
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path artifacts/binskim | Out-Null
# Enumerate managed assemblies explicitly and filter out
# `runtimes/` — BinSkim has no path-exclude flag, so passing a
# pre-filtered file list is the cleanest way to scope the scan.
$managed = @()
foreach ($dir in 'artifacts/mur/x64', 'artifacts/mur/arm64') {
$managed += Get-ChildItem $dir -Recurse -File -Include '*.dll', '*.exe' |
Where-Object { $_.FullName -notmatch '[\\/]runtimes[\\/]' } |
Select-Object -ExpandProperty FullName
}
$packages = Get-ChildItem artifacts/nupkg -Filter *.nupkg -File |
Select-Object -ExpandProperty FullName
$targets = @($packages) + @($managed)
Write-Host "BinSkim targets: $($packages.Count) nupkg, $($managed.Count) managed binaries"
& $env:BINSKIM_EXE analyze @targets --output artifacts/binskim/binskim.sarif
if ($LASTEXITCODE -ne 0) {
throw "BinSkim reported policy violations (exit $LASTEXITCODE). See SARIF artifact."
}
- name: Upload BinSkim SARIF
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: binskim-${{ steps.version.outputs.version }}
path: artifacts/binskim/binskim.sarif
retention-days: 30
- name: Assemble skill kit
shell: pwsh
run: |
$version = '${{ steps.version.outputs.version }}'
$stage = 'artifacts/kit-stage/reactor'
New-Item -ItemType Directory -Force -Path $stage | Out-Null
New-Item -ItemType Directory -Force -Path "$stage/bin/x64" | Out-Null
New-Item -ItemType Directory -Force -Path "$stage/bin/arm64" | Out-Null
Copy-Item SKILL.md $stage
Copy-Item -Recurse skills $stage
Copy-Item artifacts/mur/x64/* "$stage/bin/x64/" -Recurse
Copy-Item artifacts/mur/arm64/* "$stage/bin/arm64/" -Recurse
Copy-Item tools/install-skill-kit.ps1 "$stage/install-skill-kit.ps1"
New-Item -ItemType Directory -Force -Path artifacts/kit | Out-Null
$zip = "artifacts/kit/reactor-skill-kit-$version.zip"
# Archive the `reactor` folder itself (not its contents) so the zip
# contains a single top-level `reactor/` folder. Extracting the zip
# gives the directory layout install-skill-kit.ps1 expects.
Compress-Archive -Path artifacts/kit-stage/reactor -DestinationPath $zip -Force
Write-Host "Kit: $zip"
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-${{ steps.version.outputs.version }}
path: |
artifacts/nupkg/*
artifacts/kit/*.zip
retention-days: 30
- name: Create GitHub Release
if: steps.version.outputs.is_tag == 'true'
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
name: Reactor ${{ steps.version.outputs.version }}
tag_name: ${{ github.ref_name }}
draft: false
prerelease: ${{ contains(steps.version.outputs.version, '-') }}
generate_release_notes: true
files: |
artifacts/nupkg/*.nupkg
artifacts/nupkg/*.snupkg
artifacts/kit/*.zip
body: |
**Reactor ${{ steps.version.outputs.version }}**
> Interim distribution — see [spec 022](https://github.com/microsoft/microsoft-ui-reactor/blob/main/docs/specs/022-packaging-and-distribution.md) for the rollout plan.
## Two assets
### `Microsoft.UI.Reactor.${{ steps.version.outputs.version }}.nupkg` — the framework
Drop into a folder and add a NuGet source pointing at it:
```xml
<!-- nuget.config -->
<configuration>
<packageSources>
<add key="reactor-local" value="C:\path\to\folder\with\nupkg" />
</packageSources>
</configuration>
```
Then in your `.csproj`:
```xml
<PackageReference Include="Microsoft.UI.Reactor" Version="${{ steps.version.outputs.version }}" />
```
### `reactor-skill-kit-${{ steps.version.outputs.version }}.zip` — agent skill bundle + `mur` CLI
Extract, then run:
```powershell
cd reactor
.\install-skill-kit.ps1
```
Installs to `~/.claude/skills/reactor/` and adds `bin/<arch>` to your user PATH. After a new shell, `mur --version` should resolve.