diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index c89e8b8..5da040a 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -4,6 +4,7 @@ version: 'v0.0.3' workflows: '.github/workflows/build.yml': + - 'actions/attest@v4.2.2' - 'actions/checkout@v7.0.1' - 'actions/download-artifact@v8.0.2' - 'actions/setup-dotnet@v6.1.0' @@ -17,6 +18,11 @@ workflows: '.github/workflows/verify-lockfile.yml': - 'actions/checkout@v7.0.1' dependencies: + 'actions/attest@v4.2.2': + ref: 'v4.2.2' + commit: 'sha1-1e69f48acb82d1966a394da916b4c1698aa569d6' + owner_id: 44036562 + repo_id: 760701061 'actions/checkout@v7.0.1': ref: 'v7.0.1' commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ca9d10..c8945ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,6 +74,22 @@ jobs: - name: テスト run: dotnet test -p:CoreTargetFramework=${{ matrix.core }} + # .editorconfig の書式(インデント・BOM・改行など)に従っているか + format: + needs: changes + if: needs.changes.outputs.code == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-dotnet@v6.1.0 + with: + dotnet-version: 10.0.x + - name: 書式の確認 + # 崩れている場合は、ローカルで dotnet format ZipConvertCustomerBarCode.sln を実行して直す + run: dotnet format ZipConvertCustomerBarCode.sln --verify-no-changes + pack: needs: test # test がスキップされると pack もスキップされる @@ -101,11 +117,11 @@ jobs: name: packages path: artifacts/ - # ルールセットの必須チェック。test・pack のどれかが失敗・キャンセルされたら失敗、 + # ルールセットの必須チェック。test・format・pack のどれかが失敗・キャンセルされたら失敗、 # すべて成功またはスキップ(ドキュメントだけの変更)なら成功する build-result: if: always() - needs: [changes, test, pack] + needs: [changes, test, format, pack] runs-on: ubuntu-latest steps: - name: 結果の確認 @@ -119,12 +135,20 @@ jobs: # release Environment: v* タグのみ・承認後に実行。nuget.org の Trusted Publishing のポリシーもこの Environment に限定している environment: release permissions: - id-token: write # Trusted Publishing の短期間の API キーを取得するため + id-token: write # Trusted Publishing の短期間の API キーの取得と、出所の証明の署名のため + attestations: write # 出所の証明を保存するため + artifact-metadata: write # 出所の証明の対象を記録するため steps: - uses: actions/download-artifact@v8.0.2 with: name: packages path: artifacts + - name: パッケージの出所の証明 + # このワークフローで作ったパッケージであることを証明する(gh attestation verify で確認できる)。 + # nuget.org は公開時にリポジトリ署名を付けてファイルが変わるため、確認には GitHub Release に添付したパッケージを使う + uses: actions/attest@v4.2.2 + with: + subject-path: 'artifacts/*.nupkg' - uses: actions/setup-dotnet@v6.1.0 with: dotnet-version: 10.0.x @@ -137,7 +161,8 @@ jobs: # .snupkg(シンボルパッケージ)は同じフォルダーにあれば一緒に公開される run: dotnet nuget push "artifacts/*.nupkg" --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate - # nuget.org に公開したあと、タグの GitHub Release を作る(リリースノートはマージした PR から自動生成) + # nuget.org に公開したあと、タグの GitHub Release を作り、出所を証明したパッケージを添付する + # (リリースノートはマージした PR から自動生成) # 書き込み権限は、Trusted Publishing を扱う publish ジョブとは分けてこのジョブだけに付ける github-release: needs: publish @@ -145,17 +170,22 @@ jobs: permissions: contents: write steps: + - uses: actions/download-artifact@v8.0.2 + with: + name: packages + path: artifacts - name: GitHub Release の作成 env: GH_TOKEN: ${{ github.token }} shell: bash run: | - # v2.1.0-beta.1 のような - を含むタグはプレリリースにする - prerelease=() - if [[ "$GITHUB_REF_NAME" == *-* ]]; then prerelease=(--prerelease); fi - # 手で先に作った場合や、ジョブを再実行した場合は、作成済みの Release をそのまま使う + # 手で先に作った場合や、ジョブを再実行した場合は、作成済みの Release にパッケージだけ添付する if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" > /dev/null 2>&1; then - echo "Release $GITHUB_REF_NAME は作成済みのため、スキップする" + echo "Release $GITHUB_REF_NAME は作成済みのため、パッケージだけ添付する" + gh release upload "$GITHUB_REF_NAME" artifacts/*.nupkg --repo "$GITHUB_REPOSITORY" --clobber exit 0 fi - gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --verify-tag --generate-notes --title "$GITHUB_REF_NAME" "${prerelease[@]}" + # v2.1.0-beta.1 のような - を含むタグはプレリリースにする + prerelease=() + if [[ "$GITHUB_REF_NAME" == *-* ]]; then prerelease=(--prerelease); fi + gh release create "$GITHUB_REF_NAME" artifacts/*.nupkg --repo "$GITHUB_REPOSITORY" --verify-tag --generate-notes --title "$GITHUB_REF_NAME" "${prerelease[@]}" diff --git a/CLAUDE.md b/CLAUDE.md index 2554f7b..f89127f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,7 +24,7 @@ - `netstandard2.0` の既定 C# は 7.3。`#if NET8_0_OR_GREATER` の外では `record` や null 許容参照型など新しい構文は使わない。 - バージョン・著作権表示・パッケージ情報は `Directory.Build.props` にまとめている。パッケージアイコン `icon.png`(128×128)は、このライブラリで作ったバーコードの先頭4シンボル(スタート + 郵便番号3桁)を縦に伸ばし、紺地に白で描いたもの。`dotnet run tools/GenerateIcon.cs -- icon.png` で生成する(色・拡大率・余白もこのスクリプトにある)。デモサイトのファビコン `ZipConvertCustomerBarCode.Demo/wwwroot/icon.png` も同じ画像なので、作り直したらコピーする。 - 公開メンバーには XML ドキュメントコメントを付ける(`GenerateDocumentationFile` 有効のため、ないと警告になる)。CI(`GITHUB_ACTIONS`)では `TreatWarningsAsErrors` で警告をエラーにしている(依存パッケージの脆弱性の警告 NU1900〜NU1904 は除く)。ローカルで CI と同じ確認をするときは `dotnet build -p:TreatWarningsAsErrors=true` のように付ける。 -- `.cs` ファイルは UTF-8(BOM 付き、`.editorconfig` にも記載)。新規ファイルにも BOM を付ける(`.claude/settings.json` のフックが Write / Edit 後に自動で補う)。改行は `core.autocrlf=true` に従う(Windows の作業ツリーでは CRLF、リポジトリ内は LF)。 +- `.cs` ファイルは UTF-8(BOM 付き、`.editorconfig` にも記載)。新規ファイルにも BOM を付ける(`.claude/settings.json` のフックが Write / Edit 後に自動で補う)。CI の `format` ジョブが `dotnet format --verify-no-changes` で `.editorconfig` に従っているか確認するので、崩れたら `dotnet format ZipConvertCustomerBarCode.sln` で直す。改行は `core.autocrlf=true` に従う(Windows の作業ツリーでは CRLF、リポジトリ内は LF)。 ## テスト @@ -40,16 +40,16 @@ ## CI・リリース - `.github/workflows/build.yml`: push・PR で Ubuntu と Windows × コアの両方のビルドをテストし、パッケージを作る。 -- リリースは `v2.0.0` のようなタグを push すると、タグのバージョンで3パッケージを nuget.org に公開する(Trusted Publishing。ワークフローのファイル名 `build.yml` と Environment 名 `release` を nuget.org に登録しているので、どちらも名前を変えない)。nuget.org 側のポリシーは「新しいバージョンの追加のみ」なので、公開済みのバージョンは出し直せない(修正は次のバージョンで出す)。公開後に `github-release` ジョブがタグの GitHub Release を作る(リリースノートはマージした PR から自動生成、`-` を含むタグはプレリリース)。 +- リリースは `v2.0.0` のようなタグを push すると、タグのバージョンで3パッケージを nuget.org に公開する(Trusted Publishing。ワークフローのファイル名 `build.yml` と Environment 名 `release` を nuget.org に登録しているので、どちらも名前を変えない)。nuget.org 側のポリシーは「新しいバージョンの追加のみ」なので、公開済みのバージョンは出し直せない(修正は次のバージョンで出す)。公開後に `github-release` ジョブがタグの GitHub Release を作る(リリースノートはマージした PR から自動生成、`-` を含むタグはプレリリース)。公開ジョブは `actions/attest` でパッケージの出所を証明し、`github-release` はそのパッケージを Release に添付する(nuget.org は公開時にリポジトリ署名を付けてファイルが変わるため、`gh attestation verify` で確認できるのは Release に添付したもの)。 - 公開ジョブは GitHub の `release` Environment で動く(`v*` タグのみ、cssho の承認後に実行。Secret `NUGET_USER` もこの Environment にある)。`Directory.Build.props` の `VersionPrefix` はローカルと CI のプレリリース版(`2.0.0-ci.N`)用で、公開時はタグのバージョンが優先される。`VersionPrefix` は `PackageValidationBaselineVersion` 以上にしておく(低いとアセンブリのバージョンが基準より低くなり CP0003 エラー)。 - ワークフローのアクションは `.github/workflows/actions.lock`(`gh actions-lock`)でコミットに固定している。`uses:` を追加・変更したら `gh actions-lock` でロックし直し、`gh actions-lock --verify` で確認してから、ロックファイルとワークフローを一緒にコミットする(ワークフローを編集すると、フックが `--verify-local` で漏れを知らせる)。JSON 出力は `--json=valid,findings` のように `=` でつなぐ(空白区切りだとパスとして解釈される)。 -- `.github/workflows/pages.yml`: master への push(コア・デモ・ビルド設定の変更時)と手動実行で、デモサイトを GitHub Pages(https://cssho.github.io/ZipConvertCustomerBarCode/)に配置する。リポジトリ名のパスで公開されるため、配置時に `index.html` の `` を書き換え、`.nojekyll` を置いている。 +- `.github/workflows/pages.yml`: master への push(コア・デモ・ビルド設定の変更時)と手動実行で、デモサイトを GitHub Pages(https://cssho.github.io/ZipConvertCustomerBarCode/)に配置する。リポジトリ名のパスで公開されるため、配置時に `index.html` の `` を書き換え、`.nojekyll` を置いている。`index.html` の OGP タグと `sitemap.xml` は公開 URL を絶対 URL で書いている(`robots.txt` はドメインの直下にしか置けないため置いていない)。 - CI の `verify-lockfile.yml` が PR・push・週1回でロックファイルを検証する。アクションの更新は Dependabot(`.github/dependabot.yml`、既定の cooldown でリリースから3日待つ)が、ロックファイルの作り直しも含めて PR にする。 - パッケージ作成時の検証(`EnablePackageValidation`)で、net8.0 版から netstandard2.0 版の公開 API が欠けているとエラー(CP0002)になる(net8.0 版にだけ API を足すのは検出しない)。 - あわせて、公開済みのバージョン(`Directory.Build.props` の `PackageValidationBaselineVersion`)と比べて公開 API を削除・変更していないかも確認する。新しいバージョンを公開したら、この基準も公開したバージョンに上げる。破壊的変更をするメジャーバージョンアップでは、この基準を外すか更新する。 - NuGet パッケージの更新も Dependabot が PR にする。`SkiaSharp` とテスト用の `SkiaSharp.NativeAssets.Linux.NoDependencies` はバージョンを揃える必要があるので、グループにまとめて一緒に更新する。デモの `Microsoft.AspNetCore.Components.WebAssembly` と `...DevServer` も同様にグループにしている。 - `build.yml` は、ドキュメントなどビルドに関係しないファイル(`*.md`・`LICENSE`・`docs/`・`.claude/`・`.github/dependabot.yml`)だけの変更では test と pack をスキップする(`changes` ジョブで判定)。`paths-ignore` を使うと必須チェックが報告されず PR をマージできなくなるので使わない。 -- master はルールセットで保護している(PR 経由のみ、`build-result`(test・pack の結果をまとめるジョブ)と verify-lockfile の `verify` の成功が必須)。CI のジョブ名を変えるとマージできなくなるので、ルールセットの必須チェックも合わせて変更する。 +- master はルールセットで保護している(PR 経由のみ、`build-result`(test・format・pack の結果をまとめるジョブ)と verify-lockfile の `verify` の成功が必須)。CI のジョブ名を変えるとマージできなくなるので、ルールセットの必須チェックも合わせて変更する。 ## バーコード処理 diff --git a/README.md b/README.md index 2a10bbf..efac767 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ dotnet add package ZipConvertCustomerBarCode.SkiaSharp # SkiaSharp で描画 dotnet add package ZipConvertCustomerBarCode.Drawing # System.Drawing で描画する場合 ``` +2.1.0 より後のバージョンは、[GitHub Release](https://github.com/cssho/ZipConvertCustomerBarCode/releases) に GitHub Actions でビルドしたことを証明したパッケージを添付しています。`gh attestation verify ZipConvertCustomerBarCode.x.y.z.nupkg --repo cssho/ZipConvertCustomerBarCode` で確認できます(nuget.org から取得したものは、nuget.org の署名が付いてファイルが変わるため確認できません)。 + ## 使い方 ### バーコード生成 ```csharp diff --git a/ZipConvertCustomerBarCode.Demo/wwwroot/index.html b/ZipConvertCustomerBarCode.Demo/wwwroot/index.html index 7df9a88..6aefb98 100644 --- a/ZipConvertCustomerBarCode.Demo/wwwroot/index.html +++ b/ZipConvertCustomerBarCode.Demo/wwwroot/index.html @@ -6,6 +6,17 @@ カスタマバーコード デモ | ZipConvertCustomerBarCode + + + + + + + + + + + diff --git a/ZipConvertCustomerBarCode.Demo/wwwroot/sitemap.xml b/ZipConvertCustomerBarCode.Demo/wwwroot/sitemap.xml new file mode 100644 index 0000000..042bfeb --- /dev/null +++ b/ZipConvertCustomerBarCode.Demo/wwwroot/sitemap.xml @@ -0,0 +1,7 @@ + + + + + https://cssho.github.io/ZipConvertCustomerBarCode/ + +