-
Notifications
You must be signed in to change notification settings - Fork 1
Q2 2026 — System.Text.Json migration + quarterly work #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9f07424
4e601c8
082ae39
2dc8c66
75fd44e
ede4661
d677aa9
254f7ac
1220a65
f896c87
8c470e4
65eefd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,9 +2,9 @@ name: Build (Windows) | |
|
|
||
| on: | ||
| push: | ||
| branches: [ "master", "main" ] | ||
| branches: [ "master", "main", "sow/**" ] | ||
| pull_request: | ||
| branches: [ "master", "main" ] | ||
| branches: [ "master", "main", "sow/**" ] | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
|
|
@@ -35,6 +35,36 @@ jobs: | |
|
|
||
| - name: Setup MSBuild | ||
| uses: microsoft/setup-msbuild@v2 | ||
| - name: Compute SAMVersion | ||
| id: ver | ||
| shell: pwsh | ||
| run: | | ||
| $ErrorActionPreference = 'Stop' | ||
| # Prefer head_ref when its a sow branch (release-promotion PRs from sow/* to main), | ||
| # else use base_ref on PR events / ref_name on push events. | ||
| $headRef = '${{ github.head_ref }}' | ||
| $baseRef = '${{ github.base_ref }}' | ||
| $refName = '${{ github.ref_name }}' | ||
| if ($headRef -match '^sow/\d{4}-Q\d$') { | ||
| $ref = $headRef | ||
| } elseif ('${{ github.event_name }}' -eq 'pull_request') { | ||
| $ref = $baseRef | ||
| } else { | ||
| $ref = $refName | ||
| } | ||
| # .NET AssemblyVersion components are UInt16 (max 65535). Cap to 60000 for headroom. | ||
| $run = ${{ github.run_number }} % 60000 | ||
| if ($ref -match 'sow/(\d{4})-Q(\d)') { | ||
| $v = "$($Matches[1]).$($Matches[2]).$run.0" | ||
| $src = "branch '$ref'" | ||
| } else { | ||
| $now = (Get-Date).ToUniversalTime() | ||
| $quarter = [int][Math]::Ceiling($now.Month / 3.0) | ||
| $v = "$($now.Year).$quarter.$run.0" | ||
| $src = "date $($now.ToString('yyyy-MM-dd')) (ref '$ref' not sow/yyyy-Qx)" | ||
| } | ||
| Write-Host "SAMVersion = $v (from $src)" | ||
| "samversion=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 | ||
|
|
||
| - name: Clone dependency repos (siblings) | ||
| shell: pwsh | ||
|
|
@@ -55,10 +85,32 @@ jobs: | |
| $deps = $buildOrder[0..($buildOrder.Count-2)] | ||
| foreach ($r in $deps) { | ||
| if (Test-Path $r) { continue } | ||
| Write-Host "Cloning https://github.com/$org/$r.git" | ||
| git clone --depth 1 "https://github.com/$org/$r.git" $r | ||
| $headRef = '${{ github.head_ref }}' | ||
| $baseRef = '${{ github.base_ref }}' | ||
| $refName = '${{ github.ref_name }}' | ||
| $candidates = @() | ||
| if ($headRef) { $candidates += $headRef } | ||
| # Current sow branch: base_ref on PR events, ref_name on push events. | ||
| $sowRef = if ($baseRef -match '^sow/') { $baseRef } elseif ($refName -match '^sow/') { $refName } else { '' } | ||
| if ($sowRef -and $sowRef -ne $headRef) { $candidates += $sowRef } | ||
| $candidates += 'sow/2026-Q2' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new fallback candidate forces dependency repos to Useful? React with 👍 / 👎. |
||
| $cloned = $false | ||
| foreach ($cand in $candidates) { | ||
| $has = (git ls-remote --heads "https://github.com/$org/$r.git" $cand 2>$null | Out-String).Trim() | ||
| if ($has) { | ||
| Write-Host "Cloning $org/$r @ $cand" | ||
| git clone --depth 1 --branch $cand "https://github.com/$org/$r.git" $r | ||
| $cloned = $true | ||
| break | ||
| } | ||
| } | ||
| if (-not $cloned) { | ||
| Write-Host "Cloning $org/$r @ default branch" | ||
| git clone --depth 1 "https://github.com/$org/$r.git" $r | ||
| } | ||
| } | ||
|
|
||
|
|
||
| # Ensure ReferencePath exists even before SAM_Windows builds | ||
| New-Item -ItemType Directory -Force -Path "SAM_Windows\build" | Out-Null | ||
|
|
||
|
|
@@ -77,6 +129,7 @@ jobs: | |
| '/v:m' | ||
| '/p:Configuration=Release' | ||
| '/p:UseSharedCompilation=false' | ||
| '/p:SAMVersion=${{ steps.ver.outputs.samversion }}' | ||
| '/p:RunPostBuildEvent=OnOutputUpdated' | ||
| "/p:ReferencePath=$windowsRef" | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| <Project> | ||
|
|
||
| <PropertyGroup> | ||
| <!-- Local dev builds default to 1.0.0.0. CI passes /p:SAMVersion=YYYY.Q.<run_number>.0. --> | ||
| <SAMVersion Condition="'$(SAMVersion)' == ''">1.0.0.0</SAMVersion> | ||
| <AssemblyVersion>$(SAMVersion)</AssemblyVersion> | ||
| <FileVersion>$(SAMVersion)</FileVersion> | ||
| <!-- | ||
| InformationalVersion: the content-identity stamp (SemVer +build metadata). | ||
| Composed from SAMVersion + SAMSourceRevision when CI sets the latter. If CI already | ||
| set InformationalVersion directly (e.g. SAM_Deploy installer.yml does this), respect | ||
| that and don't overwrite. Local dev builds leave both empty -> no SHA attribute emitted. | ||
| --> | ||
| <InformationalVersion Condition="'$(InformationalVersion)' == '' AND '$(SAMSourceRevision)' != ''">$(SAMVersion)+$(SAMSourceRevision)</InformationalVersion> | ||
| <!-- | ||
| Suppress the SDK's SourceLink auto-append behaviour. By default, when SourceLink is | ||
| configured on a project (via NuGet or repo settings), the SDK appends the project's | ||
| OWN commit SHA to InformationalVersion (e.g. '2026.2.164.0+998af06.dd02a4c2...'). | ||
| We set InformationalVersion explicitly to SAM_Deploy's SHA (which encodes all 22 | ||
| submodule pointers), so the SDK's extra append is noise. False = keep our value clean. | ||
| --> | ||
| <IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion> | ||
| <Deterministic>true</Deterministic> | ||
| </PropertyGroup> | ||
|
|
||
| <!-- | ||
| Projects where SDK assembly-attribute generation is disabled (legacy AssemblyInfo.cs | ||
| with GenerateAssemblyInfo=false) OR projects where the SDK doesn't auto-generate | ||
| attributes at all (classic-style csprojs that don't set the property — '' evaluates | ||
| as not 'true') ignore the AssemblyVersion/FileVersion MSBuild properties above. | ||
| Inject the attributes via a generated source file so those assemblies also get | ||
| stamped by CI. | ||
| --> | ||
| <Target Name="_GenerateSAMVersionFile" | ||
| BeforeTargets="CoreCompile" | ||
| Condition="'$(GenerateAssemblyInfo)' != 'true'"> | ||
| <ItemGroup> | ||
| <_SAMVersionLine Include="// <auto-generated />" /> | ||
| <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyVersionAttribute("$(SAMVersion)")]" /> | ||
| <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyFileVersionAttribute("$(SAMVersion)")]" /> | ||
| <!-- Only emit InformationalVersion attribute when CI provided a value (SDK projects | ||
| would otherwise get it via PropertyGroup -> SDK auto-gen). --> | ||
| <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyInformationalVersionAttribute("$(InformationalVersion)")]" Condition="'$(InformationalVersion)' != ''" /> | ||
| </ItemGroup> | ||
| <MakeDir Directories="$(IntermediateOutputPath)" /> | ||
| <WriteLinesToFile | ||
| File="$(IntermediateOutputPath)SAMVersion.g.cs" | ||
| Lines="@(_SAMVersionLine)" | ||
| Overwrite="true" | ||
| WriteOnlyWhenDifferent="true" /> | ||
| <ItemGroup> | ||
| <Compile Include="$(IntermediateOutputPath)SAMVersion.g.cs" KeepDuplicates="false" /> | ||
| <FileWrites Include="$(IntermediateOutputPath)SAMVersion.g.cs" /> | ||
| </ItemGroup> | ||
| </Target> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,9 @@ | ||
| using Newtonsoft.Json.Linq; | ||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||
| // Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors | ||
| using System; | ||
| using System.Drawing; | ||
| using System.Text.Json; | ||
| using System.Text.Json.Nodes; | ||
|
|
||
| namespace SAM.Core.Python | ||
| { | ||
|
|
@@ -67,7 +70,7 @@ public object Value | |
| } | ||
| } | ||
|
|
||
| public bool FromJObject(JObject jObject) | ||
| public bool FromJsonObject(JsonObject jObject) | ||
| { | ||
| if (jObject == null) | ||
| { | ||
|
|
@@ -76,30 +79,30 @@ public bool FromJObject(JObject jObject) | |
|
|
||
| if (jObject.ContainsKey("VariableType")) | ||
| { | ||
| variableType = new VariableType(jObject.Value<JObject>("VariableType")); | ||
| variableType = new VariableType(jObject["VariableType"] as JsonObject); | ||
| } | ||
|
|
||
| if (jObject.ContainsKey("Value")) | ||
| { | ||
| value = jObject.Value<object>("Value"); | ||
| value = jObject["Value"]?.Deserialize<object>(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| public JObject ToJObject() | ||
| public JsonObject ToJsonObject() | ||
| { | ||
| JObject jObject = new JObject(); | ||
| JsonObject jObject = new JsonObject(); | ||
| jObject.Add("_type", Query.FullTypeName(this)); | ||
|
|
||
| if (variableType != null) | ||
| { | ||
| jObject.Add("VariableType", variableType.ToJObject()); | ||
| jObject.Add("VariableType", variableType.ToJsonObject()); | ||
| } | ||
|
|
||
| if (value != null) | ||
| { | ||
| jObject.Add("Value", value as dynamic); | ||
| jObject.Add("Value", JsonValue.Create(value)); | ||
| } | ||
|
|
||
| return jObject; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These assignments interpolate untrusted ref names directly inside single-quoted PowerShell literals. Branch names can legally contain apostrophes (for example
feature/don't-break), which would terminate the string early and break the workflow script at parse time on PRs/pushes using such refs.Useful? React with 👍 / 👎.