Skip to content

Commit a4e879b

Browse files
Rafal Maciagclaude
andcommitted
Add NuGet publishing workflow and release script
- Add GitHub Actions workflow for publishing to nuget.org - Add release.sh script for version tagging - Tag pattern: hdrsplit/X.Y.Z - Multi-targeting net9.0;net10.0 support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent be8a1b6 commit a4e879b

File tree

2 files changed

+283
-0
lines changed

2 files changed

+283
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Publish NuGet Packages
2+
3+
on:
4+
push:
5+
tags:
6+
- 'hdrsplit/*'
7+
workflow_dispatch:
8+
inputs:
9+
version:
10+
description: 'Version to publish (e.g., 1.0.0)'
11+
required: true
12+
type: string
13+
14+
env:
15+
DOTNET_VERSION: '10.0.x'
16+
CONFIGURATION: Release
17+
18+
jobs:
19+
publish:
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- name: Checkout code
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Setup .NET
29+
uses: actions/setup-dotnet@v4
30+
with:
31+
dotnet-version: |
32+
9.0.x
33+
10.0.x
34+
35+
- name: Extract version from tag
36+
id: get_version
37+
run: |
38+
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
39+
VERSION="${{ github.event.inputs.version }}"
40+
else
41+
# Extract version from tag format: hdrsplit/1.0.0
42+
VERSION=${GITHUB_REF#refs/tags/hdrsplit/}
43+
fi
44+
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
45+
echo "Publishing version: $VERSION"
46+
47+
- name: Restore dependencies
48+
run: dotnet restore src/ModelingEvolution.HdrSplitControl/ModelingEvolution.HdrSplitControl.csproj
49+
50+
- name: Build
51+
run: dotnet build src/ModelingEvolution.HdrSplitControl/ModelingEvolution.HdrSplitControl.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:Version=${{ steps.get_version.outputs.VERSION }}
52+
53+
- name: Pack
54+
run: |
55+
dotnet pack src/ModelingEvolution.HdrSplitControl/ModelingEvolution.HdrSplitControl.csproj \
56+
--configuration ${{ env.CONFIGURATION }} \
57+
--no-build \
58+
--output ./artifacts \
59+
/p:PackageVersion=${{ steps.get_version.outputs.VERSION }} \
60+
/p:IncludeSymbols=true \
61+
/p:SymbolPackageFormat=snupkg
62+
63+
- name: List artifacts
64+
run: ls -lh ./artifacts
65+
66+
- name: Publish to NuGet.org
67+
run: |
68+
dotnet nuget push "./artifacts/*.nupkg" \
69+
--api-key ${{ secrets.NUGET_API_KEY }} \
70+
--source https://api.nuget.org/v3/index.json \
71+
--skip-duplicate
72+
73+
- name: Upload artifacts
74+
uses: actions/upload-artifact@v4
75+
with:
76+
name: nuget-packages-${{ steps.get_version.outputs.VERSION }}
77+
path: ./artifacts/*.nupkg
78+
retention-days: 30

release.sh

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#!/bin/bash
2+
3+
# html-split-canvas Release Script
4+
# Automates version tagging and triggering NuGet package publishing
5+
6+
set -e
7+
8+
# Colors for output
9+
RED='\033[0;31m'
10+
GREEN='\033[0;32m'
11+
YELLOW='\033[1;33m'
12+
BLUE='\033[0;34m'
13+
NC='\033[0m' # No Color
14+
15+
# Functions
16+
print_usage() {
17+
echo -e "${BLUE}html-split-canvas Release Script${NC}"
18+
echo
19+
echo "Usage: ./release.sh [VERSION] [OPTIONS]"
20+
echo
21+
echo "Arguments:"
22+
echo " VERSION Semantic version (e.g., 1.0.0, 1.1.0)"
23+
echo " If not provided, script will auto-increment patch"
24+
echo
25+
echo "Options:"
26+
echo " -m, --message TEXT Release notes/message (optional)"
27+
echo " --patch Auto-increment patch version (default)"
28+
echo " --minor Auto-increment minor version"
29+
echo " --major Auto-increment major version"
30+
echo " --dry-run Show what would be done without executing"
31+
echo " -h, --help Show this help message"
32+
echo
33+
echo "Examples:"
34+
echo " ./release.sh 1.0.0 # Release specific version"
35+
echo " ./release.sh 1.0.0 -m \"Bug fixes\" # With release notes"
36+
echo " ./release.sh --patch -m \"New features\" # Auto-increment patch"
37+
echo " ./release.sh --dry-run # Preview next release"
38+
}
39+
40+
print_error() {
41+
echo -e "${RED}Error: $1${NC}" >&2
42+
}
43+
44+
print_success() {
45+
echo -e "${GREEN}$1${NC}"
46+
}
47+
48+
print_info() {
49+
echo -e "${BLUE}$1${NC}"
50+
}
51+
52+
# Get the latest version tag
53+
get_latest_version() {
54+
git tag --sort=-version:refname | grep -E '^hdrsplit/[0-9]+\.[0-9]+\.[0-9]+$' | head -n1 | sed 's/^hdrsplit\///' || echo "1.0.0"
55+
}
56+
57+
# Increment version
58+
increment_version() {
59+
local version=$1
60+
local part=$2
61+
62+
IFS='.' read -r -a parts <<< "$version"
63+
local major=${parts[0]:-1}
64+
local minor=${parts[1]:-0}
65+
local patch=${parts[2]:-0}
66+
67+
case $part in
68+
"major")
69+
major=$((major + 1))
70+
minor=0
71+
patch=0
72+
;;
73+
"minor")
74+
minor=$((minor + 1))
75+
patch=0
76+
;;
77+
"patch")
78+
patch=$((patch + 1))
79+
;;
80+
*)
81+
print_error "Invalid version part: $part"
82+
exit 1
83+
;;
84+
esac
85+
86+
echo "$major.$minor.$patch"
87+
}
88+
89+
# Parse arguments
90+
VERSION=""
91+
MESSAGE=""
92+
INCREMENT="patch"
93+
DRY_RUN=false
94+
95+
while [[ $# -gt 0 ]]; do
96+
case $1 in
97+
-h|--help)
98+
print_usage
99+
exit 0
100+
;;
101+
-m|--message)
102+
MESSAGE="$2"
103+
shift 2
104+
;;
105+
--patch)
106+
INCREMENT="patch"
107+
shift
108+
;;
109+
--minor)
110+
INCREMENT="minor"
111+
shift
112+
;;
113+
--major)
114+
INCREMENT="major"
115+
shift
116+
;;
117+
--dry-run)
118+
DRY_RUN=true
119+
shift
120+
;;
121+
-*)
122+
print_error "Unknown option: $1"
123+
print_usage
124+
exit 1
125+
;;
126+
*)
127+
if [[ -z "$VERSION" ]]; then
128+
VERSION="$1"
129+
else
130+
print_error "Unexpected argument: $1"
131+
print_usage
132+
exit 1
133+
fi
134+
shift
135+
;;
136+
esac
137+
done
138+
139+
# Check if we're in a git repository
140+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
141+
print_error "Not in a git repository"
142+
exit 1
143+
fi
144+
145+
# Check if on master/main branch
146+
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
147+
if [[ "$CURRENT_BRANCH" != "master" && "$CURRENT_BRANCH" != "main" ]]; then
148+
print_error "Not on master/main branch (currently on: $CURRENT_BRANCH)"
149+
exit 1
150+
fi
151+
152+
# Ensure working directory is clean
153+
if [[ -n $(git status --porcelain) ]]; then
154+
print_error "Working directory is not clean. Commit or stash changes first."
155+
exit 1
156+
fi
157+
158+
# Determine version
159+
if [[ -z "$VERSION" ]]; then
160+
LATEST_VERSION=$(get_latest_version)
161+
VERSION=$(increment_version "$LATEST_VERSION" "$INCREMENT")
162+
print_info "Auto-incrementing $INCREMENT: $LATEST_VERSION -> $VERSION"
163+
fi
164+
165+
# Validate version format (X.Y.Z)
166+
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
167+
print_error "Invalid version format: $VERSION (expected X.Y.Z)"
168+
exit 1
169+
fi
170+
171+
TAG="hdrsplit/$VERSION"
172+
173+
# Check if tag already exists
174+
if git rev-parse "$TAG" >/dev/null 2>&1; then
175+
print_error "Tag $TAG already exists"
176+
exit 1
177+
fi
178+
179+
# Show what will be done
180+
print_info "Preparing release:"
181+
print_info " Version: $VERSION"
182+
print_info " Tag: $TAG"
183+
if [[ -n "$MESSAGE" ]]; then
184+
print_info " Message: $MESSAGE"
185+
fi
186+
187+
if $DRY_RUN; then
188+
print_info "\n[DRY RUN] Would create tag and push to origin"
189+
exit 0
190+
fi
191+
192+
# Create and push tag
193+
print_info "\nCreating tag..."
194+
if [[ -n "$MESSAGE" ]]; then
195+
git tag -a "$TAG" -m "$MESSAGE"
196+
else
197+
git tag "$TAG"
198+
fi
199+
200+
print_info "Pushing tag to origin..."
201+
git push origin "$TAG"
202+
203+
print_success "\n✓ Release $VERSION created successfully!"
204+
print_info "GitHub Actions will now build and publish NuGet packages."
205+
print_info "Monitor progress at: https://github.com/modelingevolution/html-split-canvas/actions"

0 commit comments

Comments
 (0)