Stop publishing SHA256SUMS checksum files with releases #49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 260405Cl Version.cs の History 先頭行が変わったら自動でインストーラをビルド・リリースする | |
| # 260602Cl portable ZIP も同じリリースに添付。MSI を主配布のまま (管理 PC 向けの代替として self-contained ZIP を追加) | |
| name: Build And Release Installer And Portable ZIP | |
| on: | |
| push: | |
| branches: [master] | |
| paths: | |
| - "ReciPro/Version.cs" | |
| # 260530Cl force input を廃止: v* tag 削除禁止 ruleset と非整合で、既存 release を壊す危険があるため。 | |
| # 手動再実行は引数なし workflow_dispatch で可能 (ビルド失敗時の再試行用)。 | |
| # 旧: | |
| # workflow_dispatch: | |
| # inputs: | |
| # force: | |
| # description: "既存リリースを削除してリビルドする" | |
| # type: boolean | |
| # default: false | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| runs-on: windows-2025-vs2026 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Parse version and check if release needed | |
| id: version | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| $content = Get-Content "ReciPro\Version.cs" -Raw | |
| if ($content -notmatch 'ver(\d+\.\d+)\(') { | |
| throw "Could not parse version from Version.cs History." | |
| } | |
| $ver = $Matches[1] | |
| $tag = "v.$ver" | |
| # 同じバージョンのリリースが既にあれば常にスキップ | |
| # 260530Cl force モードを廃止: v* tag 削除禁止 ruleset と非整合で、 | |
| # 既存 release を消した後にタグを再作成できず壊すため。 | |
| # リリースに失敗したら Version.cs を進めて新しい tag で出し直す運用とする。 | |
| gh release view $tag 2>&1 | Out-Null | |
| $releaseExists = ($LASTEXITCODE -eq 0) | |
| $global:LASTEXITCODE = 0 | |
| if ($releaseExists) { | |
| Write-Host "Release $tag already exists. Skipping." | |
| "needed=false" >> $env:GITHUB_OUTPUT | |
| return | |
| } | |
| # 旧 force 処理 (260530Cl 廃止): | |
| # if ($releaseExists) { | |
| # if ("(inputs.force)" -eq "true") { # 260530Cl 旧コードでは inputs.force を式参照していた | |
| # Write-Host "Force mode: deleting existing release $tag..." | |
| # gh release delete $tag --yes | |
| # git push origin :refs/tags/$tag 2>&1 | Out-Null | |
| # $global:LASTEXITCODE = 0 | |
| # } else { | |
| # Write-Host "Release $tag already exists. Skipping." | |
| # "needed=false" >> $env:GITHUB_OUTPUT | |
| # return | |
| # } | |
| # } | |
| # History の先頭行をリリースノートに使う | |
| $historyLine = ([regex]::Match($content, 'ver[^\r\n"]+').Value).Trim() | |
| $notesPath = Join-Path $env:RUNNER_TEMP "release-notes.txt" | |
| # $historyLine | Set-Content -Path $notesPath -Encoding UTF8 # 260602Cl 旧: 変更履歴 1 行のみ | |
| @( # 260602Cl MSI を第一候補、portable ZIP を管理 PC 向け代替として release notes に明記 | |
| # 260613Cl SHA256SUMS.txt の行を削除 (checksum 公開廃止: 同一チャネル配布では改竄対策にならず、初心者を惑わすため) | |
| $historyLine | |
| "" | |
| "Assets:" | |
| "- ReciProSetup.msi: recommended installer." | |
| "- ReciPro-v.$ver-x64.zip: no-install, self-contained portable alternative for managed Windows PCs." | |
| ) | Set-Content -Path $notesPath -Encoding UTF8 | |
| # AssemblyVersion / FileVersion 用のタイムスタンプ (yyyy.M.d.HHmm UTC) | |
| $now = [System.DateTime]::UtcNow | |
| $assemblyVer = "$($now.Year).$($now.Month).$($now.Day).$($now.ToString('HHmm'))" | |
| Write-Host "New version detected: $ver (tag: $tag, assembly: $assemblyVer)" | |
| "needed=true" >> $env:GITHUB_OUTPUT | |
| "version=$ver" >> $env:GITHUB_OUTPUT | |
| "tag=$tag" >> $env:GITHUB_OUTPUT | |
| "product_version=0.$ver" >> $env:GITHUB_OUTPUT | |
| "notes_path=$notesPath" >> $env:GITHUB_OUTPUT | |
| "assembly_version=$assemblyVer" >> $env:GITHUB_OUTPUT | |
| # ---- 以降、新バージョンが検出されたときのみ実行 ---- | |
| - name: Setup .NET 10 | |
| if: steps.version.outputs.needed == 'true' | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.0.x" | |
| - name: Restore managed dependencies | |
| if: steps.version.outputs.needed == 'true' | |
| shell: pwsh | |
| run: dotnet restore ReciPro\ReciPro.csproj | |
| - name: Find devenv.com | |
| if: steps.version.outputs.needed == 'true' | |
| id: devenv | |
| shell: pwsh | |
| run: | | |
| $devenvExe = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property productPath).Trim() | |
| if (-not $devenvExe) { throw "Visual Studio was not found." } | |
| $cli = [System.IO.Path]::ChangeExtension($devenvExe, ".com") | |
| if (-not (Test-Path $cli)) { throw "devenv.com was not found." } | |
| Write-Host "devenv.com: $cli" | |
| "cli=$cli" >> $env:GITHUB_OUTPUT | |
| - name: Build native runtime binaries | |
| if: steps.version.outputs.needed == 'true' | |
| shell: pwsh | |
| run: | | |
| $log = Join-Path $env:RUNNER_TEMP "devenv-native.log" | |
| & "${{ steps.devenv.outputs.cli }}" "ReciPro.sln" /Build "Release|x64" /Project "Crystallography.Native" /Out $log | |
| if (Test-Path $log) { Get-Content $log } | |
| if ($LASTEXITCODE -ne 0) { throw "Crystallography.Native build failed (exit $LASTEXITCODE)." } | |
| # 260613Cl vdproj→WiX 移行 (Phase B、計画書 .project-guidance/ReciPro_WiX移行計画.md): | |
| # 旧「Build managed application」(dotnet build → bin\Release を vdproj が直接参照) を、 | |
| # MSI 専用 staging への framework-dependent publish に置換。bin\Release 共有による | |
| # 「publish は MSI 後」順序制約はこれで解消 (vdproj の SourcePath 参照が消えたため)。 | |
| # ★FileVersion 注入は必須: 欠くと csproj 静的値が旧 release より古くなり、MSI の | |
| # ファイルバージョン規則で自前アセンブリの FileCopy が costing 段階で省略され、 | |
| # アップグレード時に REP 削除後ファイル欠落する (validate-wix-msi.yml run 27405216245 で実証)。 | |
| - name: Stage MSI payload (framework-dependent publish) | |
| if: steps.version.outputs.needed == 'true' | |
| shell: pwsh | |
| run: | | |
| $s = "artifacts\staging-msi-x64" | |
| dotnet publish ReciPro\ReciPro.csproj -c Release -p:Platform=x64 --self-contained false -o $s --no-restore ` | |
| -p:AssemblyVersion=${{ steps.version.outputs.assembly_version }} -p:FileVersion=${{ steps.version.outputs.assembly_version }} | |
| if ($LASTEXITCODE -ne 0) { throw "x64 publish failed." } | |
| # Crystallography.Native 3 flavor は publish グラフ外 (vcxproj が bin\Release へ後置き) → 明示コピー | |
| $native = Get-ChildItem "ReciPro\bin\Release" -Filter "Crystallography.Native*.dll" -File | |
| if ($native.Count -ne 3) { throw "native DLL count != 3: $($native.Count)" } | |
| $native | Copy-Item -Destination $s | |
| Copy-Item ReciProSetup\LICENSE.rtf, ReciProSetup\REQUIREMENT.rtf $s | |
| # 旧 vdproj MSI と内容を揃える: 参照プロジェクトの分離 pdb は同梱しない (portable ZIP と同方針) | |
| Get-ChildItem $s -Filter *.pdb | Remove-Item | |
| # 出荷前検査 (計画書 §3 D3) | |
| if (Test-Path "$s\README-PORTABLE.txt") { throw "README-PORTABLE.txt leaked (portable marker must not be in MSI)" } | |
| if (Test-Path "$s\coreclr.dll") { throw "self-contained runtime leaked into framework-dependent staging" } | |
| if (-not (Test-Path "$s\ReciPro.exe")) { throw "ReciPro.exe missing from staging" } | |
| Write-Host "MSI staging OK: $((Get-ChildItem $s -Recurse -File).Count) files" | |
| # 260613Cl vdproj→WiX 移行 (Phase B) で以下 4 ステップを廃止 (本文は git 履歴 b6340c74 以前を参照): | |
| # - Update installer version in vdproj (regex で ProductVersion/ProductCode/PackageCode 書換) | |
| # → WiX では -p:ProductVersion 注入 + ProductCode 自動生成で代替 (UpgradeCode は Package.wxs に固定) | |
| # - Disable out-of-proc setup project build (HKCU レジストリハック) → 不要 | |
| # - Create installer-only solution (ReciProSetup.CI.sln 動的生成) → 不要 | |
| # - Build installer with Visual Studio (devenv.com) → dotnet build (WixToolset.Sdk) に置換 | |
| # devenv.com は Crystallography.Native (vcxproj) ビルドのため引き続き必要。 | |
| # vdproj 一式 (ReciProSetup\) は WiX 版リリース 1 回成功後に削除予定 (計画書 §6 Phase B-3)。 | |
| - name: Build installer with WiX | |
| id: build_installer | |
| if: steps.version.outputs.needed == 'true' | |
| timeout-minutes: 10 | |
| shell: pwsh | |
| run: | | |
| dotnet build ReciProSetup.Wix\ReciProSetup.wixproj -c Release -p:InstallerPlatform=x64 ` | |
| -p:ProductVersion=${{ steps.version.outputs.product_version }} ` | |
| -p:StagingDir="$PWD\artifacts\staging-msi-x64" | |
| if ($LASTEXITCODE -ne 0) { throw "WiX build failed (exit $LASTEXITCODE)." } | |
| # MSI の存在確認 (出力名 ReciProSetup.msi は自動更新の固定 URL なので不変) | |
| $msi = Get-Item "ReciProSetup.Wix\bin\Release\ReciProSetup.msi" -ErrorAction SilentlyContinue | |
| if (-not $msi) { throw "ReciProSetup.msi was not found." } | |
| Write-Host "MSI built: $($msi.FullName) ($($msi.Length) bytes)" | |
| "msi_path=$($msi.FullName)" >> $env:GITHUB_OUTPUT | |
| - name: Publish portable ZIP | |
| if: steps.version.outputs.needed == 'true' | |
| id: portable | |
| shell: pwsh | |
| run: | | |
| # 260602Cl 管理された Windows PC 向けの代替配布。MSI が第一候補、ZIP は管理者権限や .NET Runtime 導入が難しい環境用。 | |
| # 260602Cl このステップは installer (MSI) ビルドより後に置く。self-contained publish は bin\Release を | |
| # ランタイム同梱の内容で汚染し (AppendRuntimeIdentifierToOutputPath=false で publish と build が | |
| # bin\Release を共有するため)、MSI ビルドより前に走らせると framework-dependent であるべき MSI に | |
| # ランタイムが紛れ込む。詳細は .project-guidance\ReciPro_MSI+PortableZip構築方針.md §4。 | |
| # 260613Cl ↑の順序制約は WiX 移行で解消済み (MSI は専用 staging から作り bin\Release を参照しない)。 | |
| # 位置は当面維持 (変更を最小にするため)。 | |
| $publishDir = Join-Path $env:RUNNER_TEMP "ReciPro-portable\ReciPro" | |
| # 260613Cl 作者指示で命名簡素化 (旧: ReciPro-v.X-win-x64-portable.zip)。自動更新は MSI 固定 URL のみで ZIP 名に依存しない | |
| $zipPath = Join-Path (Get-Location) "ReciPro-v.${{ steps.version.outputs.version }}-x64.zip" | |
| if (Test-Path $publishDir) { Remove-Item -LiteralPath $publishDir -Recurse -Force } | |
| if (Test-Path $zipPath) { Remove-Item -LiteralPath $zipPath -Force } | |
| # 260602Cl DebugType は csproj の既定 (ReciPro 本体は embedded) を使うため、PDIndexer のような | |
| # 別 pdb 欠落による MSI ビルド失敗 (方針 §4-a) は起こらない。参照ライブラリ | |
| # (Crystallography 等) は分離 pdb を出すので、配布前に publish 出力から除去する (後述)。 | |
| # 260611Cl SatelliteResourceLanguages=ja: self-contained publish が同梱する .NET ランタイムの | |
| # ローカライズ 13 言語 (~18MB) を、アプリが提供する neutral(en)+ja に合わせて ja のみに絞る。 | |
| # publish 引数に留める (csproj に入れない) ことで MSI ビルド経路には影響させない。 | |
| # 260611Cl PublishSingleFile=true: フラット ~290 ファイルでは ReciPro.exe が探しにくいという作者要望 | |
| # (arm64 Surface 検証) を受け、ランタイム・managed DLL・ja サテライト・libxrl を exe に埋め込む。 | |
| # Crystallography.Native*.dll (3 flavors) は従来どおり後コピーで exe 横に外置き | |
| # (NativeWrapper の BaseDirectory 解決と CPU 判定 flavor 選択をそのまま使うため)。 | |
| # ビルド出力 (bin\Release) や MSI には影響しない (PublishSingleFile は publish 専用)。 | |
| dotnet publish ReciPro\ReciPro.csproj ` | |
| -c Release ` | |
| -r win-x64 ` | |
| --self-contained true ` | |
| -p:Platform=x64 ` | |
| -p:AssemblyVersion=${{ steps.version.outputs.assembly_version }} ` | |
| -p:FileVersion=${{ steps.version.outputs.assembly_version }} ` | |
| -p:PublishSingleFile=true ` | |
| -p:PublishTrimmed=false ` | |
| -p:SatelliteResourceLanguages=ja ` | |
| -o $publishDir | |
| # 260602Cl ★ReciPro 固有: Crystallography.Native*.dll は ProjectReference でも Content でも PackageReference でもなく、 | |
| # vcxproj の OutDir 経由で ReciPro\bin\Release に置かれるだけなので publish 出力には含まれない。 | |
| # generic / avx2 / avx512 の 3 種を明示コピーする (NativeWrapper が起動時に CPU 判定で選択する)。 | |
| $nativeDir = "ReciPro\bin\Release" | |
| $natives = Get-ChildItem -Path $nativeDir -Filter "Crystallography.Native*.dll" -ErrorAction SilentlyContinue | |
| if (-not $natives) { throw "Native DLLs (Crystallography.Native*.dll) were not found in $nativeDir." } | |
| foreach ($n in $natives) { Copy-Item $n.FullName $publishDir -Force; Write-Host "Bundled native: $($n.Name)" } | |
| Copy-Item "LICENSE.md" $publishDir -Force | |
| Copy-Item "README-PORTABLE.txt" $publishDir -Force | |
| # 260602Cl 参照ライブラリの分離 pdb を配布物から除去 (ReciPro 本体は embedded のため元々 pdb なし)。 | |
| Get-ChildItem $publishDir -Filter "*.pdb" | Remove-Item -Force | |
| Compress-Archive -Path (Join-Path (Split-Path $publishDir -Parent) "ReciPro") -DestinationPath $zipPath -Force | |
| Write-Host "Portable ZIP built: $zipPath" | |
| "zip_path=$zipPath" >> $env:GITHUB_OUTPUT | |
| # 260613Cl 「Generate release checksums」ステップを廃止 (SHA256SUMS.txt の公開をやめる)。 | |
| # 理由: 同一チャネル (同じ release ページ) に置く checksum は改竄対策にならず、 | |
| # リリースページで初心者を惑わす悪影響の方が大きい (作者決定)。真正性保証は SignPath 署名 (Phase D) で行う。 | |
| # 本文は git 履歴 b3c35d22 以前を参照。 | |
| - name: Upload workflow artifacts | |
| if: steps.version.outputs.needed == 'true' | |
| # 260425Cl Node.js 20 廃止対応 (v6 で Node.js 24 がデフォルト) | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: ReciPro-release-v.${{ steps.version.outputs.version }} | |
| path: | | |
| ${{ steps.build_installer.outputs.msi_path }} | |
| ${{ steps.portable.outputs.zip_path }} | |
| - name: Create tag and GitHub Release | |
| if: steps.version.outputs.needed == 'true' | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| $tag = "${{ steps.version.outputs.tag }}" | |
| # 260530Cl タグとリリースを gh release create で原子的に作成 (--target で対象コミットを固定) | |
| # 旧実装は git tag -a + git push の2段階で、push 成功後に release 作成が失敗すると | |
| # タグだけ remote に残り、v* tag 削除禁止 ruleset により同一バージョンで復旧不能だった。 | |
| # gh release create は tag 未存在時に --target のコミットへ lightweight tag を作成し、 | |
| # release と一括で作るため orphan tag が発生せず、失敗時も同一バージョンで再試行できる。 | |
| # 旧コード: | |
| # git config user.name "github-actions[bot]" | |
| # git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| # git tag -a $tag -m "ReciPro ${{ steps.version.outputs.version }}" | |
| # git push origin $tag | |
| # 260602Cl 第一候補の MSI に加え、portable ZIP も添付する。 | |
| # 260613Cl SHA256SUMS.txt の添付を廃止 (checksum 公開廃止)。 | |
| gh release create $tag ` | |
| "${{ steps.build_installer.outputs.msi_path }}" ` | |
| "${{ steps.portable.outputs.zip_path }}" ` | |
| --target $env:GITHUB_SHA ` | |
| --title "ReciPro $tag" ` | |
| --notes-file "${{ steps.version.outputs.notes_path }}" |