Skip to content

Bump version to 1.22.0 #75

Bump version to 1.22.0

Bump version to 1.22.0 #75

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag_name:
description: Existing v* tag to release
required: true
type: string
permissions:
contents: read
env:
DOCFX_VERSION: 2.78.5
DOTNET_ILDASM_VERSION: 0.12.2
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
# On workflow_dispatch, force refs/tags/<tag_name> so a branch name
# (e.g. "main") fails checkout instead of falling through to the
# tag-assumed downstream steps.
# workflow_dispatch では refs/tags/<tag_name> に固定し、"main" 等の
# ブランチ名が指定された場合にタグ前提の後続ステップへ進む前に
# checkout 段階で失敗させます。
ref: ${{ inputs.tag_name && format('refs/tags/{0}', inputs.tag_name) || github.ref }}
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
- name: Cache NuGet packages
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Restore dependencies
run: dotnet restore FolderDiffIL4DotNet.sln
- name: Build
run: dotnet build FolderDiffIL4DotNet.sln --configuration Release --no-restore
- name: Install DocFX
run: dotnet tool update --global docfx --version "$DOCFX_VERSION"
- name: Generate documentation site
run: |
export PATH="$PATH:$HOME/.dotnet/tools"
docfx metadata docfx.json
docfx build docfx.json
- name: Install real disassembler for E2E tests
if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }}
run: |
dotnet tool install --global dotnet-ildasm --version "$DOTNET_ILDASM_VERSION"
echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH"
DOTNET_ROLL_FORWARD=Major "$HOME/.dotnet/tools/dotnet-ildasm" --version
- name: Test with coverage
if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }}
env:
DOTNET_ROLL_FORWARD: Major
FOLDERDIFF_RUN_E2E: true
run: dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj --configuration Release --no-build --nologo --settings coverlet.runsettings --logger "trx;LogFileName=test_results.trx" --collect:"XPlat Code Coverage" --results-directory ./TestResults
- name: Enforce coverage thresholds
if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }}
run: |
python3 - <<'PY'
import glob
import sys
import xml.etree.ElementTree as ET
line_threshold = 80.0
branch_threshold = 75.0
matches = glob.glob("TestResults/**/coverage.cobertura.xml", recursive=True)
if not matches:
print("coverage.cobertura.xml was not found.", file=sys.stderr)
sys.exit(1)
root = ET.parse(matches[0]).getroot()
line_rate = float(root.attrib["line-rate"]) * 100.0
branch_rate = float(root.attrib["branch-rate"]) * 100.0
print(f"Total line coverage : {line_rate:.2f}% (threshold {line_threshold:.2f}%)")
print(f"Total branch coverage: {branch_rate:.2f}% (threshold {branch_threshold:.2f}%)")
failures = []
if line_rate < line_threshold:
failures.append(f"line coverage {line_rate:.2f}% < {line_threshold:.2f}%")
if branch_rate < branch_threshold:
failures.append(f"branch coverage {branch_rate:.2f}% < {branch_threshold:.2f}%")
if failures:
print("Coverage threshold check failed:", file=sys.stderr)
for failure in failures:
print(f" - {failure}", file=sys.stderr)
sys.exit(1)
PY
- name: Publish
run: dotnet publish FolderDiffIL4DotNet.csproj --configuration Release --no-build --output publish
- name: Remove debugging symbols
run: find publish -name '*.pdb' -delete
- name: Archive release artifacts
env:
TAG_NAME: ${{ inputs.tag_name || github.ref_name }}
run: |
mkdir -p artifacts
tag_name="${TAG_NAME}"
zip -rq "artifacts/FolderDiffIL4DotNet-${tag_name}.zip" publish
zip -rq "artifacts/DocumentationSite-${tag_name}.zip" _site
sha256sum artifacts/*.zip > "artifacts/sha256-${tag_name}.txt"
- name: Upload release artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ReleaseArtifacts
path: artifacts/**
- name: Write release notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ inputs.tag_name || github.ref_name }}
run: |
set -euo pipefail
if [[ ! "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "Release tag must be a v-prefixed SemVer version, got: ${TAG_NAME}" >&2
exit 1
fi
previous_tag="$(
gh api --paginate --slurp \
"/repos/${GITHUB_REPOSITORY}/releases?per_page=100" \
| jq -r --arg current "${TAG_NAME}" '
flatten
| map(
select(
.draft == false
and .prerelease == false
and .published_at != null
and .tag_name != $current
and (.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))
)
)
| max_by(.published_at).tag_name // empty
'
)"
if [ -z "${previous_tag}" ]; then
echo "No previous non-draft, non-prerelease GitHub release was found before ${TAG_NAME}." >&2
exit 1
fi
if [[ ! "${previous_tag}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Latest GitHub release tag is not a stable v-prefixed SemVer version: ${previous_tag}" >&2
exit 1
fi
cat > release-notes.md <<EOF
## What's Changed
Full Changelog: https://github.com/${GITHUB_REPOSITORY}/compare/${previous_tag}...${TAG_NAME}
## Install or update
NuGet:
\`\`\`bash
dotnet tool install -g nildiff
dotnet tool update -g nildiff
\`\`\`
EOF
- name: Create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ inputs.tag_name || github.ref_name }}
run: |
gh release create "${TAG_NAME}" \
artifacts/*.zip \
artifacts/*.txt \
--verify-tag \
--notes-file release-notes.md
nuget-publish:
runs-on: ubuntu-latest
needs: release
if: ${{ success() }}
permissions:
contents: read
packages: write
env:
GITHUB_PACKAGES_SOURCE: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
# See release job for rationale.
# release ジョブの注記を参照してください。
ref: ${{ inputs.tag_name && format('refs/tags/{0}', inputs.tag_name) || github.ref }}
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
- name: Cache NuGet packages
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Check if Core has changes since previous tag
id: core-diff
run: |
# Resolve the previous v* tag on the current first-parent release line.
# 現在の first-parent リリース系列上にある直前の v* タグを解決します。
CURRENT_TAG=$(git describe --tags --exact-match HEAD --match 'v*')
PREV_TAG=$(git describe --first-parent --tags --abbrev=0 HEAD^ --match 'v*' 2>/dev/null || true)
if [ -z "$PREV_TAG" ]; then
echo "No previous tag found — treating Core as changed"
echo "changed=true" >> "$GITHUB_OUTPUT"
elif git diff --quiet "${PREV_TAG}..HEAD" -- FolderDiffIL4DotNet.Core/; then
echo "No changes in FolderDiffIL4DotNet.Core/ since ${PREV_TAG} — skipping NuGet publish"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "Core has changes since ${PREV_TAG}"
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Check if Plugin.Abstractions has changes since previous tag
id: plugin-diff
run: |
CURRENT_TAG=$(git describe --tags --exact-match HEAD --match 'v*')
PREV_TAG=$(git describe --first-parent --tags --abbrev=0 HEAD^ --match 'v*' 2>/dev/null || true)
if [ -z "$PREV_TAG" ]; then
echo "No previous tag found — treating Plugin.Abstractions as changed"
echo "changed=true" >> "$GITHUB_OUTPUT"
elif git diff --quiet "${PREV_TAG}..HEAD" -- FolderDiffIL4DotNet.Plugin.Abstractions/; then
echo "No changes in FolderDiffIL4DotNet.Plugin.Abstractions/ since ${PREV_TAG} — skipping NuGet publish"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "Plugin.Abstractions has changes since ${PREV_TAG}"
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Restore Core dependencies
if: steps.core-diff.outputs.changed == 'true'
run: dotnet restore FolderDiffIL4DotNet.Core/FolderDiffIL4DotNet.Core.csproj
- name: Pack Core NuGet package
if: steps.core-diff.outputs.changed == 'true'
run: dotnet pack FolderDiffIL4DotNet.Core/FolderDiffIL4DotNet.Core.csproj --configuration Release --no-restore --output nupkgs
- name: Publish Core to nuget.org
if: steps.core-diff.outputs.changed == 'true'
run: dotnet nuget push "nupkgs/FolderDiffIL4DotNet.Core.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
- name: Skip Core nuget.org publish (no changes)
if: steps.core-diff.outputs.changed != 'true'
run: echo "NuGet publish skipped — FolderDiffIL4DotNet.Core/ has no changes since the previous tag"
- name: Restore Plugin.Abstractions dependencies
if: steps.plugin-diff.outputs.changed == 'true'
run: dotnet restore FolderDiffIL4DotNet.Plugin.Abstractions/FolderDiffIL4DotNet.Plugin.Abstractions.csproj
- name: Pack Plugin.Abstractions NuGet package
if: steps.plugin-diff.outputs.changed == 'true'
run: dotnet pack FolderDiffIL4DotNet.Plugin.Abstractions/FolderDiffIL4DotNet.Plugin.Abstractions.csproj --configuration Release --no-restore --output nupkgs
- name: Publish Plugin.Abstractions to nuget.org
if: steps.plugin-diff.outputs.changed == 'true'
run: dotnet nuget push "nupkgs/FolderDiffIL4DotNet.Plugin.Abstractions.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
- name: Skip Plugin.Abstractions nuget.org publish (no changes)
if: steps.plugin-diff.outputs.changed != 'true'
run: echo "NuGet publish skipped — FolderDiffIL4DotNet.Plugin.Abstractions/ has no changes since the previous tag"
- name: Restore global tool dependencies
run: dotnet restore FolderDiffIL4DotNet.csproj
- name: Pack global tool NuGet package
run: dotnet pack FolderDiffIL4DotNet.csproj --configuration Release --no-restore --output nupkgs
- name: Publish global tool to nuget.org
run: dotnet nuget push "nupkgs/nildiff.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
- name: Authenticate GitHub Packages source
id: github-auth
continue-on-error: true
run: |
dotnet nuget remove source github >/dev/null 2>&1 || true
dotnet nuget add source "${{ env.GITHUB_PACKAGES_SOURCE }}" \
--name github \
--username "${{ github.actor }}" \
--password "${{ secrets.GITHUB_TOKEN }}" \
--store-password-in-clear-text
- name: Warn if GitHub Packages auth failed
if: steps.github-auth.outcome == 'failure'
run: |
echo "Warning: GitHub Packages mirror auth failed after nuget.org publication; investigate the mirror channel separately." >> "$GITHUB_STEP_SUMMARY"
- name: Publish Core to GitHub Packages
id: core-gpr-publish
if: steps.core-diff.outputs.changed == 'true' && steps.github-auth.outcome == 'success'
continue-on-error: true
run: dotnet nuget push "nupkgs/FolderDiffIL4DotNet.Core.*.nupkg" --source github --skip-duplicate
- name: Warn if Core GitHub Packages mirror failed
if: steps.core-gpr-publish.outcome == 'failure'
run: |
echo "Warning: Core GitHub Packages mirror failed after nuget.org publication; investigate the mirror channel separately." >> "$GITHUB_STEP_SUMMARY"
- name: Publish Plugin.Abstractions to GitHub Packages
id: plugin-gpr-publish
if: steps.plugin-diff.outputs.changed == 'true' && steps.github-auth.outcome == 'success'
continue-on-error: true
run: dotnet nuget push "nupkgs/FolderDiffIL4DotNet.Plugin.Abstractions.*.nupkg" --source github --skip-duplicate
- name: Warn if Plugin.Abstractions GitHub Packages mirror failed
if: steps.plugin-gpr-publish.outcome == 'failure'
run: |
echo "Warning: Plugin.Abstractions GitHub Packages mirror failed after nuget.org publication; investigate the mirror channel separately." >> "$GITHUB_STEP_SUMMARY"
- name: Publish global tool to GitHub Packages
id: tool-gpr-publish
if: steps.github-auth.outcome == 'success'
continue-on-error: true
run: dotnet nuget push "nupkgs/nildiff.*.nupkg" --source github --skip-duplicate
- name: Warn if global tool GitHub Packages mirror failed
if: steps.tool-gpr-publish.outcome == 'failure'
run: |
echo "Warning: nildiff GitHub Packages mirror failed after nuget.org publication; investigate the mirror channel separately." >> "$GITHUB_STEP_SUMMARY"