diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e37ea2..d16b29a 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/**" ] 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' + $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" ) 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 diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..509f4c6 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,57 @@ + + + + + 1.0.0.0 + $(SAMVersion) + $(SAMVersion) + + $(SAMVersion)+$(SAMSourceRevision) + + false + true + + + + + + <_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)' != ''" /> + + + + + + + + + + diff --git a/Grasshopper/SAM.Analytical.Grasshopper.TMP/Kernel/AssemblyInfo.cs b/Grasshopper/SAM.Analytical.Grasshopper.TMP/Kernel/AssemblyInfo.cs index 4d59577..177e4f8 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.TMP/Kernel/AssemblyInfo.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.TMP/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.Analytical.Grasshopper.TMP/Properties/AssemblyInfo.cs b/Grasshopper/SAM.Analytical.Grasshopper.TMP/Properties/AssemblyInfo.cs index 39cc8b3..6fc7b87 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.TMP/Properties/AssemblyInfo.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.TMP/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,6 +55,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.*")] -[assembly: AssemblyFileVersion("1.0.*")] diff --git a/Grasshopper/SAM.Analytical.Grasshopper.TMP/SAM.Analytical.Grasshopper.TMP.csproj b/Grasshopper/SAM.Analytical.Grasshopper.TMP/SAM.Analytical.Grasshopper.TMP.csproj index 72d88e0..98cf142 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.TMP/SAM.Analytical.Grasshopper.TMP.csproj +++ b/Grasshopper/SAM.Analytical.Grasshopper.TMP/SAM.Analytical.Grasshopper.TMP.csproj @@ -10,7 +10,6 @@ false true true - false false false @@ -54,9 +53,7 @@ 2.5.0 - - 13.0.3 - + diff --git a/Grasshopper/SAM.Core.Grasshopper.TMP/Kernel/AssemblyInfo.cs b/Grasshopper/SAM.Core.Grasshopper.TMP/Kernel/AssemblyInfo.cs index d64e096..5cf95ac 100644 --- a/Grasshopper/SAM.Core.Grasshopper.TMP/Kernel/AssemblyInfo.cs +++ b/Grasshopper/SAM.Core.Grasshopper.TMP/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.TMP/Properties/AssemblyInfo.cs b/Grasshopper/SAM.Core.Grasshopper.TMP/Properties/AssemblyInfo.cs index 2544fa5..874d4fa 100644 --- a/Grasshopper/SAM.Core.Grasshopper.TMP/Properties/AssemblyInfo.cs +++ b/Grasshopper/SAM.Core.Grasshopper.TMP/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,6 +55,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.*")] -[assembly: AssemblyFileVersion("1.0.*")] diff --git a/Grasshopper/SAM.Core.Grasshopper.TMP/SAM.Core.Grasshopper.TMP.csproj b/Grasshopper/SAM.Core.Grasshopper.TMP/SAM.Core.Grasshopper.TMP.csproj index 55706c4..715d271 100644 --- a/Grasshopper/SAM.Core.Grasshopper.TMP/SAM.Core.Grasshopper.TMP.csproj +++ b/Grasshopper/SAM.Core.Grasshopper.TMP/SAM.Core.Grasshopper.TMP.csproj @@ -11,7 +11,6 @@ true true C:\Program Files\Rhino 8\System\Rhino.exe - false false false True @@ -30,7 +29,7 @@ - + diff --git a/SAM_TMP/SAM.Analytical.TMP/Properties/AssemblyInfo.cs b/SAM_TMP/SAM.Analytical.TMP/Properties/AssemblyInfo.cs index e46b4e2..fc1a18b 100644 --- a/SAM_TMP/SAM.Analytical.TMP/Properties/AssemblyInfo.cs +++ b/SAM_TMP/SAM.Analytical.TMP/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_TMP/SAM.Analytical.TMP/SAM.Analytical.TMP.csproj b/SAM_TMP/SAM.Analytical.TMP/SAM.Analytical.TMP.csproj index 52d2b7e..7de9420 100644 --- a/SAM_TMP/SAM.Analytical.TMP/SAM.Analytical.TMP.csproj +++ b/SAM_TMP/SAM.Analytical.TMP/SAM.Analytical.TMP.csproj @@ -2,13 +2,10 @@ netstandard2.0 Library - false false SAM.Analytical SAM.Analytical - Copyright © 2020 - 1.0.%2a - 1.0.%2a + Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors false false @@ -42,7 +39,7 @@ 2.5.0 - + diff --git a/SAM_TMP/SAM.Core.TMP/Properties/AssemblyInfo.cs b/SAM_TMP/SAM.Core.TMP/Properties/AssemblyInfo.cs index cf1e05d..2fa9aca 100644 --- a/SAM_TMP/SAM.Core.TMP/Properties/AssemblyInfo.cs +++ b/SAM_TMP/SAM.Core.TMP/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_TMP/SAM.Core.TMP/SAM.Core.TMP.csproj b/SAM_TMP/SAM.Core.TMP/SAM.Core.TMP.csproj index ffadfc7..53fa88d 100644 --- a/SAM_TMP/SAM.Core.TMP/SAM.Core.TMP.csproj +++ b/SAM_TMP/SAM.Core.TMP/SAM.Core.TMP.csproj @@ -2,13 +2,10 @@ netstandard2.0 Library - false false SAM SAM - Copyright © 2020 - 1.0.%2a - 1.0.%2a + Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors false false @@ -22,6 +19,6 @@ - + \ No newline at end of file diff --git a/SAM_TMP/SAM.Geometry.TMP/Properties/AssemblyInfo.cs b/SAM_TMP/SAM.Geometry.TMP/Properties/AssemblyInfo.cs index cf1e05d..2fa9aca 100644 --- a/SAM_TMP/SAM.Geometry.TMP/Properties/AssemblyInfo.cs +++ b/SAM_TMP/SAM.Geometry.TMP/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_TMP/SAM.Geometry.TMP/SAM.Geometry.TMP.csproj b/SAM_TMP/SAM.Geometry.TMP/SAM.Geometry.TMP.csproj index 327c5de..de3eb0f 100644 --- a/SAM_TMP/SAM.Geometry.TMP/SAM.Geometry.TMP.csproj +++ b/SAM_TMP/SAM.Geometry.TMP/SAM.Geometry.TMP.csproj @@ -2,13 +2,10 @@ netstandard2.0 Library - false false SAM SAM - Copyright © 2020 - 1.0.%2a - 1.0.%2a + Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors false false @@ -46,6 +43,6 @@ - + \ No newline at end of file