@@ -3,57 +3,84 @@ name: Publish
33on :
44 push :
55 tags :
6- - ' v*' # Publish on any new tag matching v*, i.e. v1.0, v1.7.2
6+ - ' v*.*.*' # Only publish on 3-segment tags, e.g. v1.0.0, v1.7.2 (not v1.0)
7+ workflow_dispatch :
8+ inputs :
9+ version :
10+ description : ' Version to publish (without v prefix, must be X.Y.Z, e.g. 1.0.0)'
11+ required : true
12+ type : string
713
814jobs :
915 build :
1016
1117 strategy :
1218 matrix :
13- os : [windows -latest]
19+ os : [ubuntu -latest]
1420 dotnet : ['9.0.x']
1521 runs-on : ${{ matrix.os }}
1622
1723 steps :
18- - name : Get version from tag
24+ - name : Get version
1925 id : tag_name
2026 run : |
21- echo ::set-output name=current_version::${GITHUB_REF#refs/tags/v}
27+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
28+ echo "current_version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
29+ else
30+ echo "current_version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
31+ fi
2232 shell : bash
2333 - uses : actions/checkout@v4
34+ - name : Validate version
35+ run : |
36+ VERSION="${{ steps.tag_name.outputs.current_version }}"
37+ # Require at least three numeric segments (X.Y.Z), optionally followed by a pre-release suffix.
38+ # This prevents 2-segment tags like v0.85 (which would publish as 0.85.0 instead of 0.8.5).
39+ if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then
40+ echo "::error::Version '$VERSION' does not match the required X.Y.Z format. Did you mean to add a missing segment (e.g. '0.85' should be '0.8.5')?"
41+ exit 1
42+ fi
43+ # Verify the version matches VersionPrefix in Directory.Build.props so that the tag and
44+ # source code are always in sync.
45+ EXPECTED=$(sed -n 's/.*<VersionPrefix[^>]*>\([^<]*\)<\/VersionPrefix>.*/\1/p' Directory.Build.props | head -1)
46+ if [ "$VERSION" != "$EXPECTED" ] && ! echo "$VERSION" | grep -q "^${EXPECTED}-"; then
47+ echo "::error::Tag version '$VERSION' does not match VersionPrefix '$EXPECTED' in Directory.Build.props. Update Directory.Build.props before tagging."
48+ exit 1
49+ fi
50+ shell : bash
2451 - name : Setup dotnet
2552 uses : actions/setup-dotnet@v4
2653 with :
2754 dotnet-version : ${{ matrix.dotnet }}
2855 include-prerelease : true
2956 - name : Restore tools
3057 run : dotnet tool restore
58+ - name : Restore dependencies
59+ run : dotnet paket restore
3160 - name : Run Test
32- run : dotnet build -c Release -t:Test
33- - name : Run build
34- run : dotnet build -c Release -t:Pack
61+ run : dotnet build build.proj -c Release -t:Test
62+ - name : Run Pack
63+ run : dotnet build build.proj -c Release -t:Pack /p:Version=${{ steps.tag_name.outputs.current_version }}
3564 - name : Get Changelog Entry
3665 id : changelog_reader
66+ if : github.event_name == 'push'
3767 uses : mindsers/changelog-reader-action@v2
3868 with :
3969 version : ${{ steps.tag_name.outputs.current_version }}
4070 path : ./CHANGELOG.md
41- - name : Create Release
42- id : create_release
43- uses : actions/create-release@latest
44- env :
45- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
71+ - name : Create GitHub Release
72+ if : github.event_name == 'push'
73+ uses : softprops/action-gh-release@v2
4674 with :
4775 tag_name : ${{ github.ref }}
48- release_name : ${{ github.ref }}
76+ name : ${{ github.ref_name }}
4977 body : ${{ steps.changelog_reader.outputs.log_entry }}
5078 draft : false
5179 prerelease : false
52- - name : Upload binaries to release
53- uses : svenstaro/upload-release-action@v1-release
54- with :
55- repo_token : ${{ secrets.GITHUB_TOKEN }}
56- file : bin/nupkg/*.nupkg
57- tag : ${{ github.ref }}
58- overwrite : true
59- file_glob : true
80+ files : bin/nupkg/*.nupkg
81+ env :
82+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
83+ - name : Push to NuGet
84+ run : dotnet nuget push bin/nupkg/*.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json --skip-duplicate
85+ env :
86+ NUGET_API_KEY : ${{ secrets.NUGET_API_KEY }}
0 commit comments