From e2c19e710c20f2a2c43680a675a7638f02f9022c Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Fri, 15 May 2026 16:45:39 +0200 Subject: [PATCH 01/10] Migrate to System.Text.Json (replace Newtonsoft.Json) SAM-BIM core migrated from Newtonsoft.Json to System.Text.Json.Nodes. - Replace each csproj's Newtonsoft package reference with System.Text.Json 10.0.8 - ShortDateTime: FromJObject/ToJObject -> FromJsonObject/ToJsonObject; JObject -> JsonObject; Value(key) -> indexer + GetValue() Co-Authored-By: Claude Opus 4.7 --- ...M.Analytical.Grasshopper.OpenStudio.csproj | 4 +--- .../SAM.Core.Grasshopper.OpenStudio.csproj | 4 +--- .../SAM.Analytical.OpenStudio.csproj | 2 +- .../Classes/ShortDateTime.cs | 22 +++++++++---------- .../SAM.Core.OpenStudio.csproj | 2 +- .../SAM.Geometry.OpenStudio.csproj | 2 +- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj index fc7f4b3..0dbfa66 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj +++ b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj @@ -79,9 +79,7 @@ runtime - - 13.0.3 - + diff --git a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj index 85f37f2..ee84797 100644 --- a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj +++ b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj @@ -66,9 +66,7 @@ runtime - - 13.0.3 - + diff --git a/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj b/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj index 505f9b6..2709519 100644 --- a/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj @@ -55,7 +55,7 @@ - + diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs b/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs index e1a073b..bbc7c43 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using System.Text.Json.Nodes; using System; namespace SAM.Core.OpenStudio @@ -20,9 +20,9 @@ public ShortDateTime(byte month, byte day, byte hour, byte minute, byte second) this.second = second; } - public ShortDateTime(JObject jObject) + public ShortDateTime(JsonObject jObject) { - FromJObject(jObject); + FromJsonObject(jObject); } public ShortDateTime(ShortDateTime shortDateTime) @@ -94,7 +94,7 @@ public override string ToString() return string.Format("{0}/{1} {2}:{3}:{4}", month, day, hourString, minuteString, secondString); } - public bool FromJObject(JObject jObject) + public bool FromJsonObject(JsonObject jObject) { if(jObject == null) { @@ -106,41 +106,41 @@ public bool FromJObject(JObject jObject) return false; } - month = System.Convert.ToByte(jObject.Value("Month")); + month = System.Convert.ToByte(jObject["Month"]?.GetValue() ?? default(int)); if (!jObject.ContainsKey("Day")) { return false; } - day = System.Convert.ToByte(jObject.Value("Day")); + day = System.Convert.ToByte(jObject["Day"]?.GetValue() ?? default(int)); if (!jObject.ContainsKey("Hour")) { return false; } - hour = System.Convert.ToByte(jObject.Value("Hour")); + hour = System.Convert.ToByte(jObject["Hour"]?.GetValue() ?? default(int)); if (!jObject.ContainsKey("Minute")) { return false; } - minute = System.Convert.ToByte(jObject.Value("Minute")); + minute = System.Convert.ToByte(jObject["Minute"]?.GetValue() ?? default(int)); if (!jObject.ContainsKey("Second")) { return false; } - second = System.Convert.ToByte(jObject.Value("Second")); + second = System.Convert.ToByte(jObject["Second"]?.GetValue() ?? default(int)); return true; } - public JObject ToJObject() + public JsonObject ToJsonObject() { - JObject result = new JObject(); + JsonObject result = new JsonObject(); result.Add("_type", SAM.Core.Query.FullTypeName(this)); result.Add("Month", System.Convert.ToInt32(month)); diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj index 9de89d3..b8c7477 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj @@ -43,7 +43,7 @@ - + diff --git a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj index 8af9ffd..313fc58 100644 --- a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj @@ -43,7 +43,7 @@ - + From 79e54ed06296b98f7fb38275d24efb9ac38a7ee6 Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Fri, 15 May 2026 22:00:53 +0200 Subject: [PATCH 02/10] CI: prefer sow/2026-Q2 for dep clones + trigger on it During the SAM-BIM Newtonsoft.Json -> System.Text.Json migration the quarterly sow/2026-Q2 branch carries the binary-breaking change. CI needs to consume the migrated SAM (and any sibling dep) from sow/2026-Q2, not from master, until the quarter-end merge. - Add "sow/2026-Q2" to push/pull_request branch triggers - For each dep clone, ls-remote sow/2026-Q2 and prefer it when present; fall back to default branch (e.g. master) otherwise. After the quarter merges back to master, this fallback naturally restores prior behaviour. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0484899..72f4052 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,9 @@ name: Build (Windows) on: push: - branches: [ "master", "main" ] + branches: [ "master", "main", "sow/2026-Q2" ] pull_request: - branches: [ "master", "main" ] + branches: [ "master", "main", "sow/2026-Q2" ] workflow_dispatch: jobs: From 082e439217183f257ecec72499880819f9c73e29 Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Fri, 15 May 2026 22:07:47 +0200 Subject: [PATCH 03/10] CI: cascade dep clones to PR head_ref -> sow/2026-Q2 -> default Refines the previous workflow patch so CI on the migration PR can succeed before anything has been merged. Each dep repo is cloned from: 1. github.head_ref (feature/remove-newtonsoft on these PRs) - has the migration right now on every dep 2. sow/2026-Q2 - source of truth after these PRs merge 3. default branch - source of truth after quarter-end merge Co-Authored-By: Claude Opus 4.7 --- .github/workflows/build.yml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 72f4052..5bcea9b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,12 +49,29 @@ jobs: ) foreach ($r in $buildOrder) { - if ($r -eq $repo) { continue } # already checked out + if ($r -eq $repo) { continue } 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 }}' + $candidates = @() + if ($headRef) { $candidates += $headRef } + $candidates += 'sow/2026-Q2' + $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 + } } + - name: Restore + Rebuild in order (safe Platform handling) shell: pwsh run: | From a73c59c346a9e82d0c4ab442bbe43e93458ad14d Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Fri, 15 May 2026 22:39:12 +0200 Subject: [PATCH 04/10] Add SPDX + copyright header to migration-touched files The SPDX-check workflow requires the top 6 lines of every changed .cs file to contain both: // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors (with an en-dash between the years). Migration commits modified existing files without preserving the header. Prepend the two lines now. Co-Authored-By: Claude Opus 4.7 --- SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs b/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs index bbc7c43..9145e5e 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/Classes/ShortDateTime.cs @@ -1,4 +1,6 @@ -using System.Text.Json.Nodes; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors +using System.Text.Json.Nodes; using System; namespace SAM.Core.OpenStudio From 87dc6dbdcb2cfdcf129065a0678f3db7dee3cc69 Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Fri, 15 May 2026 22:51:33 +0200 Subject: [PATCH 05/10] CI: harmonize spdx-check.yml with org-canonical Version A template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the older spdx-check.yml (literal en-dash grep, top 6 lines, PR-only trigger) with the modern template shipped on SAM core: - grep -qE with [-–] char class — accepts both hyphen-minus and en-dash - 20-line lookback (was 6) - BOM and CR stripping - mapfile + diff-filter for cleaner change detection - Adds workflow_dispatch trigger Co-Authored-By: Claude Opus 4.7 --- .github/workflows/spdx-check.yml | 81 +++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/.github/workflows/spdx-check.yml b/.github/workflows/spdx-check.yml index 269d562..e386bd3 100644 --- a/.github/workflows/spdx-check.yml +++ b/.github/workflows/spdx-check.yml @@ -2,44 +2,89 @@ name: SPDX + Copyright header check on: pull_request: + workflow_dispatch: jobs: spdx: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Check header in changed .cs files + shell: bash run: | - set -e - BASE="${{ github.event.pull_request.base.sha }}" - HEAD="${{ github.event.pull_request.head.sha }}" + set -euo pipefail + + if [ "${{ github.event_name }}" = "pull_request" ]; then + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + else + HEAD="${{ github.sha }}" + BASE="$(git rev-parse "${HEAD}^" 2>/dev/null || true)" + fi - FILES=$(git diff --name-only "$BASE" "$HEAD" -- '*.cs' || true) + echo "Base SHA: ${BASE:-}" + echo "Head SHA: $HEAD" + echo - if [ -z "$FILES" ]; then + if [ -z "${BASE:-}" ]; then + mapfile -t files < <(git ls-files '*.cs') + else + mapfile -t files < <(git diff --diff-filter=ACMR --name-only "$BASE" "$HEAD" -- '*.cs' || true) + fi + + if [ "${#files[@]}" -eq 0 ]; then echo "No C# files changed." exit 0 fi - MISSING="" - for f in $FILES; do - HEADBLOCK=$(head -n 6 "$f") + echo "Changed C# files:" + printf ' - %s\n' "${files[@]}" + echo + + missing=() + + for f in "${files[@]}"; do + if [ ! -f "$f" ]; then + echo "Skipping missing file: $f" + continue + fi + + headblock="$(head -n 20 "$f" | sed '1s/^\xEF\xBB\xBF//' | tr -d '\r')" + + echo "Checking: $f" + + if ! grep -q "SPDX-License-Identifier: LGPL-3.0-or-later" <<< "$headblock"; then + echo " Missing SPDX line" + missing+=("$f") + continue + fi + + if ! grep -qE "Copyright \(c\) 2020[-–]2026 Michal Dengusiak & Jakub Ziolkowski and contributors" <<< "$headblock"; then + echo " Missing copyright line" + missing+=("$f") + continue + fi - echo "$HEADBLOCK" | grep -q "// SPDX-License-Identifier: LGPL-3.0-or-later" || MISSING="$MISSING $f" - echo "$HEADBLOCK" | grep -q "// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors" || MISSING="$MISSING $f" + echo " OK" done - if [ -n "$MISSING" ]; then - echo "❌ Missing required header in:" - for f in $MISSING; do echo " - $f"; done - echo "" - echo "Each changed .cs file must start with:" + echo + if [ "${#missing[@]}" -gt 0 ]; then + echo "Missing required header in:" + printf ' - %s\n' "${missing[@]}" + echo + echo "Each checked .cs file must contain within the first 20 lines:" echo "// SPDX-License-Identifier: LGPL-3.0-or-later" - echo "// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors" + echo "// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors" exit 1 fi - echo "✅ SPDX + copyright headers OK." + echo "SPDX + copyright headers OK." \ No newline at end of file From 8208553e987b2c24fbbe95dbbb7c512de11e906f Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Wed, 20 May 2026 09:57:28 +0200 Subject: [PATCH 06/10] Pin System.Text.Json to 8.0.5 Aligns the repo with the SAM-BIM workspace-wide pin to the LTS-aligned System.Text.Json 8.0.5, replacing the previously pinned 10.0.8 preview. --- .../SAM.Analytical.Grasshopper.OpenStudio.csproj | 2 +- .../SAM.Core.Grasshopper.OpenStudio.csproj | 2 +- .../SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj | 2 +- SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj | 2 +- .../SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj index 0dbfa66..59efa23 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj +++ b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj @@ -79,7 +79,7 @@ runtime - + diff --git a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj index ee84797..c9603a5 100644 --- a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj +++ b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj @@ -66,7 +66,7 @@ runtime - + diff --git a/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj b/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj index 2709519..4bd586a 100644 --- a/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj @@ -55,7 +55,7 @@ - + diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj index b8c7477..73ca3a7 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj @@ -43,7 +43,7 @@ - + diff --git a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj index 313fc58..15bc483 100644 --- a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj @@ -43,7 +43,7 @@ - + From b7420996b01cd1ccb332b2c2d49ac55b7e420b01 Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Wed, 20 May 2026 13:35:17 +0200 Subject: [PATCH 07/10] fix: pin AssemblyVersion/FileVersion to 1.0.0.0 (#3) * fix: pin AssemblyVersion/FileVersion to 1.0.0.0 (drop 1.0.* wildcard) Eliminates CS1607 warnings and restores deterministic builds. Aligns with the workspace's existing fixed-version files. Scope: AssemblyInfo.cs + .csproj version attributes only. The // commented-out template example is left intact for documentation. * fix: add SPDX + copyright header to modified AssemblyInfo.cs and refresh .csproj Satisfies the spdx-check workflow which requires every changed .cs file to declare the LGPL-3.0-or-later SPDX identifier and the 2020-2026 attribution in its first 20 lines. Also updates the stale 'Copyright (c) 2020' line in .csproj files to match the SPDX header style. --- .../Properties/AssemblyInfo.cs | 8 +++++--- .../Properties/AssemblyInfo.cs | 8 +++++--- .../SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj | 6 +++--- .../SAM.Geometry.OpenStudio.csproj | 6 +++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs index 015c662..f75b385 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs @@ -1,4 +1,6 @@ -/* +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors +/* * This file is part of the Sustaiable Analytical Model (SAM) * Copyright (c) 2020, the respective contributors. All rights reserved. * @@ -53,5 +55,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs index 7b18ef1..db0dc29 100644 --- a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs +++ b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs @@ -1,4 +1,6 @@ -/* +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors +/* * This file is part of the Sustaiable Analytical Model (SAM) * Copyright (c) 2020, the respective contributors. All rights reserved. * @@ -53,5 +55,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj index 73ca3a7..c742bb0 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj @@ -54,9 +54,9 @@ ::Copy /Y "$(SolutionDir)references\*.dll" "$(SolutionDir)build\*.dll" SAM SAM - Copyright © 2020 - 1.0.%2a - 1.0.%2a + Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + 1.0.0.0 + 1.0.0.0 x64 \ No newline at end of file diff --git a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj index 15bc483..4acdb0e 100644 --- a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj @@ -6,9 +6,9 @@ false SAM SAM - Copyright © 2020 - 1.0.%2a - 1.0.%2a + Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + 1.0.0.0 + 1.0.0.0 AnyCPU;x64 false false From 90d2bf2c47133180a7aea8147ee984883c29f85b Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Wed, 20 May 2026 21:12:10 +0200 Subject: [PATCH 08/10] build: Directory.Build.props for centralised SAMVersion stamping (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build: Directory.Build.props for centralised SAMVersion stamping Mirrors SAM-BIM/SAM#7. Stage 2 of the AssemblyVersion versioning migration. * fix: replace literal u{2013} escape with actual en-dash in SPDX header PowerShell 5.1 doesn't support backtick-u escape sequences; the apply-stage2.ps1 script leaked them as literal text in 'Copyright (c) 2020u{2013}2026'. * fix: relax SAMVersion.g.cs Target condition to != 'true' Codex P1 on SAM_LadybugTools#4: classic (non-SDK) csprojs don't set GenerateAssemblyInfo at all, so the previous '== false' condition skipped them. Switching to '!= true' catches both GenerateAssemblyInfo=false (SDK projects with legacy AssemblyInfo.cs) AND empty (classic projects). * ci: Codex P2 fixes — four-part SAMVersion, prefer head_ref for sow PRs - Append .0 so SAMVersion is 4-part (AssemblyFileVersion expects 4 parts). - Prefer github.head_ref when it matches sow/yyyy-Qx (release-promotion PRs). - Mirrors SAM sow/2026-Q2 6d87d98e. --- .github/workflows/build.yml | 40 ++++++++++++++++++- Directory.Build.props | 39 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 3 -- ...M.Analytical.Grasshopper.OpenStudio.csproj | 1 - .../Kernel/AssemblyInfo.cs | 5 ++- .../Properties/AssemblyInfo.cs | 3 -- .../SAM.Core.Grasshopper.OpenStudio.csproj | 1 - .../Properties/AssemblyInfo.cs | 5 ++- .../SAM.Analytical.OpenStudio.csproj | 1 - .../Properties/AssemblyInfo.cs | 5 ++- .../SAM.Core.OpenStudio.csproj | 3 -- .../Properties/AssemblyInfo.cs | 5 ++- .../SAM.Geometry.OpenStudio.csproj | 3 -- 13 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 Directory.Build.props diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5bcea9b..45e997d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,9 @@ name: Build (Windows) on: push: - branches: [ "master", "main", "sow/2026-Q2" ] + branches: [ "master", "main", "sow/**" ] pull_request: - branches: [ "master", "main", "sow/2026-Q2" ] + branches: [ "master", "main", "sow/**" ] workflow_dispatch: jobs: @@ -32,6 +32,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 @@ -52,8 +82,13 @@ jobs: if ($r -eq $repo) { continue } if (Test-Path $r) { continue } $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' $cloned = $false foreach ($cand in $candidates) { @@ -85,6 +120,7 @@ jobs: '/v:m' '/p:Configuration=Release' '/p:UseSharedCompilation=false' + '/p:SAMVersion=${{ steps.ver.outputs.samversion }}' '/p:RunPostBuildEvent=OnOutputUpdated' $refArg ) diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..9841655 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,39 @@ + + + + + 1.0.0.0 + $(SAMVersion) + $(SAMVersion) + true + + + + + + <_SAMVersionLine Include="// <auto-generated />" /> + <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyVersionAttribute("$(SAMVersion)")]" /> + <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyFileVersionAttribute("$(SAMVersion)")]" /> + + + + + + + + + + diff --git a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs index f75b385..3c9085c 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs @@ -54,6 +54,3 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj index 59efa23..a4f75fa 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj +++ b/Grasshopper/SAM.Analytical.Grasshopper.OpenStudio/SAM.Analytical.Grasshopper.OpenStudio.csproj @@ -10,7 +10,6 @@ false true true - false false false x64 diff --git a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Kernel/AssemblyInfo.cs b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Kernel/AssemblyInfo.cs index d64e096..5cf95ac 100644 --- a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Kernel/AssemblyInfo.cs +++ b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Kernel/AssemblyInfo.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using System; using System.Drawing; diff --git a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs index db0dc29..b2fc33a 100644 --- a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs +++ b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/Properties/AssemblyInfo.cs @@ -54,6 +54,3 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj index c9603a5..31dd303 100644 --- a/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj +++ b/Grasshopper/SAM.Core.Grasshopper.OpenStudio/SAM.Core.Grasshopper.OpenStudio.csproj @@ -10,7 +10,6 @@ false true true - false false false x64 diff --git a/SAM_OpenStudio/SAM.Analytical.OpenStudio/Properties/AssemblyInfo.cs b/SAM_OpenStudio/SAM.Analytical.OpenStudio/Properties/AssemblyInfo.cs index 0e5202e..117ee76 100644 --- a/SAM_OpenStudio/SAM.Analytical.OpenStudio/Properties/AssemblyInfo.cs +++ b/SAM_OpenStudio/SAM.Analytical.OpenStudio/Properties/AssemblyInfo.cs @@ -1,4 +1,7 @@ -/* +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +/* * This file is part of the Sustaiable Analytical Model (SAM) * Copyright (c) 2020, the respective contributors. All rights reserved. * diff --git a/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj b/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj index 4bd586a..aa68f35 100644 --- a/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Analytical.OpenStudio/SAM.Analytical.OpenStudio.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - false false false false diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/Properties/AssemblyInfo.cs b/SAM_OpenStudio/SAM.Core.OpenStudio/Properties/AssemblyInfo.cs index 98164ff..75bf415 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/Properties/AssemblyInfo.cs +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/Properties/AssemblyInfo.cs @@ -1,4 +1,7 @@ -/* +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +/* * This file is part of the Sustaiable Analytical Model (SAM) * Copyright (c) 2020, the respective contributors. All rights reserved. * diff --git a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj index c742bb0..5ad7dc7 100644 --- a/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Core.OpenStudio/SAM.Core.OpenStudio.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - false false false false @@ -55,8 +54,6 @@ SAM SAM Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors - 1.0.0.0 - 1.0.0.0 x64 \ No newline at end of file diff --git a/SAM_OpenStudio/SAM.Geometry.OpenStudio/Properties/AssemblyInfo.cs b/SAM_OpenStudio/SAM.Geometry.OpenStudio/Properties/AssemblyInfo.cs index 98164ff..75bf415 100644 --- a/SAM_OpenStudio/SAM.Geometry.OpenStudio/Properties/AssemblyInfo.cs +++ b/SAM_OpenStudio/SAM.Geometry.OpenStudio/Properties/AssemblyInfo.cs @@ -1,4 +1,7 @@ -/* +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +/* * This file is part of the Sustaiable Analytical Model (SAM) * Copyright (c) 2020, the respective contributors. All rights reserved. * diff --git a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj index 4acdb0e..ebdc921 100644 --- a/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj +++ b/SAM_OpenStudio/SAM.Geometry.OpenStudio/SAM.Geometry.OpenStudio.csproj @@ -2,13 +2,10 @@ netstandard2.0 Library - false false SAM SAM Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors - 1.0.0.0 - 1.0.0.0 AnyCPU;x64 false false From d51a5bb675569c6648caa79f8e751a98b439a964 Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Thu, 21 May 2026 10:19:24 +0200 Subject: [PATCH 09/10] build: emit AssemblyInformationalVersion for non-SDK projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors SAM sow/2026-Q2. Adds AssemblyInformationalVersion attribute generation to Path D's SAMVersion.g.cs Target — covers Grasshopper / Tas-bridge assemblies that have GenerateAssemblyInfo=false, so they also get the CI commit SHA stamp in their ProductVersion field. SDK projects pick up InformationalVersion via PropertyGroup auto-gen as before. Local dev builds unchanged. --- Directory.Build.props | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9841655..b6b921f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,10 +1,17 @@ - + 1.0.0.0 $(SAMVersion) $(SAMVersion) + + $(SAMVersion)+$(SAMSourceRevision) true @@ -23,6 +30,9 @@ <_SAMVersionLine Include="// <auto-generated />" /> <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyVersionAttribute("$(SAMVersion)")]" /> <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyFileVersionAttribute("$(SAMVersion)")]" /> + + <_SAMVersionLine Include="[assembly: System.Reflection.AssemblyInformationalVersionAttribute("$(InformationalVersion)")]" Condition="'$(InformationalVersion)' != ''" /> Date: Thu, 21 May 2026 12:52:09 +0200 Subject: [PATCH 10/10] build: emit AssemblyInformationalVersion for non-SDK projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors SAM sow/2026-Q2. Adds AssemblyInformationalVersion attribute generation to Path D's SAMVersion.g.cs Target — covers Grasshopper / Tas-bridge assemblies that have GenerateAssemblyInfo=false, so they also get the CI commit SHA stamp in their ProductVersion field. SDK projects pick up InformationalVersion via PropertyGroup auto-gen as before. Local dev builds unchanged. --- Directory.Build.props | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index b6b921f..509f4c6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,6 +12,14 @@ that and don't overwrite. Local dev builds leave both empty -> no SHA attribute emitted. --> $(SAMVersion)+$(SAMSourceRevision) + + false true