Skip to content

Commit cac9616

Browse files
authored
feat(ci): update workflows for build and release process (#82)
1 parent fd0094c commit cac9616

4 files changed

Lines changed: 277 additions & 128 deletions

File tree

.github/release-drafter.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Release Drafter Configuration
2+
# Documentation: https://github.com/release-drafter/release-drafter
3+
4+
name-template: 'Version $RESOLVED_VERSION'
5+
tag-template: 'v$RESOLVED_VERSION'
6+
7+
# Categories for organizing release notes
8+
categories:
9+
- title: '🚀 Features'
10+
labels:
11+
- 'feature'
12+
- 'enhancement'
13+
- title: '🐛 Bug Fixes'
14+
labels:
15+
- 'bug'
16+
- 'fix'
17+
- title: '🔧 Maintenance'
18+
labels:
19+
- 'maintenance'
20+
- 'chore'
21+
- 'refactor'
22+
- 'dependencies'
23+
- title: '📚 Documentation'
24+
labels:
25+
- 'documentation'
26+
- 'docs'
27+
- title: '⚡ Performance'
28+
labels:
29+
- 'performance'
30+
- title: '🔒 Security'
31+
labels:
32+
- 'security'
33+
34+
# Exclude certain labels from release notes
35+
exclude-labels:
36+
- 'skip-changelog'
37+
- 'wip'
38+
39+
# Change template (how each PR is listed)
40+
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
41+
change-title-escapes: '\<*_&' # Escape special markdown characters
42+
43+
# Template for the release body
44+
template: |
45+
## What's Changed
46+
47+
$CHANGES
48+
49+
## 📦 NuGet Packages
50+
51+
The following packages are included in this release:
52+
53+
- `MyCSharp.HttpUserAgentParser`
54+
- `MyCSharp.HttpUserAgentParser.AspNetCore`
55+
- `MyCSharp.HttpUserAgentParser.MemoryCache`
56+
57+
### Installation
58+
59+
```bash
60+
dotnet add package MyCSharp.HttpUserAgentParser
61+
dotnet add package MyCSharp.HttpUserAgentParser.AspNetCore
62+
dotnet add package MyCSharp.HttpUserAgentParser.MemoryCache
63+
```
64+
65+
## Contributors
66+
67+
$CONTRIBUTORS
68+
69+
---
70+
71+
**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
72+
73+
# Automatically label PRs based on modified files
74+
autolabeler:
75+
- label: 'documentation'
76+
files:
77+
- '*.md'
78+
- 'docs/**/*'
79+
- label: 'bug'
80+
branch:
81+
- '/fix\/.+/'
82+
title:
83+
- '/fix/i'
84+
- label: 'feature'
85+
branch:
86+
- '/feature\/.+/'
87+
title:
88+
- '/feature/i'
89+
- label: 'dependencies'
90+
files:
91+
- '**/packages.lock.json'
92+
- '**/*.csproj'
93+
- 'Directory.Packages.props'
94+
- 'Directory.Build.props'
95+
- label: 'github-actions'
96+
files:
97+
- '.github/workflows/**/*'
98+
- label: 'tests'
99+
files:
100+
- 'tests/**/*'
101+
- '**/*Tests.cs'
102+
- '**/*Test.cs'
103+
- label: 'performance'
104+
files:
105+
- 'perf/**/*'
106+
- '**/*Benchmark*.cs'
107+
108+
# Version resolver (uses version from workflow input)
109+
version-resolver:
110+
default: patch
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
name: Build and Test (Reusable)
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
dotnet-version:
7+
description: '.NET version to use (can be multi-line for multiple versions)'
8+
required: false
9+
type: string
10+
default: |
11+
8.0.x
12+
9.0.x
13+
10.0.x
14+
configuration:
15+
description: 'Build configuration'
16+
required: false
17+
type: string
18+
default: 'Release'
19+
upload-test-results:
20+
description: 'Whether to upload test results as artifacts'
21+
required: false
22+
type: boolean
23+
default: false
24+
create-pack:
25+
description: 'Whether to pack NuGet packages'
26+
required: false
27+
type: boolean
28+
default: false
29+
outputs:
30+
version:
31+
description: 'The calculated version from NBGV'
32+
value: ${{ jobs.build.outputs.version }}
33+
34+
jobs:
35+
build:
36+
name: Build and Test
37+
runs-on: ubuntu-latest
38+
outputs:
39+
version: ${{ steps.nbgv.outputs.version }}
40+
41+
steps:
42+
- name: Checkout code
43+
uses: actions/checkout@v4
44+
with:
45+
fetch-depth: 0 # Required for GitVersion
46+
47+
- name: Setup .NET
48+
uses: actions/setup-dotnet@v4
49+
with:
50+
dotnet-version: ${{ inputs.dotnet-version }}
51+
52+
- name: Install Nerdbank.GitVersioning
53+
run: dotnet tool install -g nbgv
54+
55+
- name: Set version with NBGV
56+
id: nbgv
57+
run: |
58+
nbgv get-version --format json > version.json
59+
VERSION=$(nbgv get-version -v NuGetPackageVersion)
60+
echo "version=$VERSION" >> $GITHUB_OUTPUT
61+
echo "Calculated version: $VERSION"
62+
63+
- name: Restore dependencies
64+
run: dotnet restore
65+
66+
- name: Build
67+
run: dotnet build --configuration ${{ inputs.configuration }} --no-restore
68+
69+
- name: Test
70+
run: dotnet test --configuration ${{ inputs.configuration }} --no-build --verbosity normal --logger "trx;LogFileName=test-results.trx"
71+
72+
- name: Upload test results
73+
if: always() && inputs.upload-test-results
74+
uses: actions/upload-artifact@v4
75+
with:
76+
name: test-results-${{ inputs.dotnet-version }}
77+
path: '**/TestResults/**/*.trx'
78+
79+
- name: Pack NuGet packages
80+
if: inputs.create-pack
81+
run: dotnet pack --configuration ${{ inputs.configuration }} --no-build --output ./artifacts
82+
83+
- name: Upload NuGet packages
84+
if: inputs.create-pack
85+
uses: actions/upload-artifact@v4
86+
with:
87+
name: nuget-packages
88+
path: ./artifacts/*.nupkg
89+
retention-days: 30

.github/workflows/main-build.yml

Lines changed: 58 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,118 +10,82 @@ permissions:
1010
packages: write
1111

1212
jobs:
13-
build-and-pack:
14-
name: Build, Pack and Create Draft Release
13+
build-and-test:
14+
name: Build, Test and Pack
15+
uses: ./.github/workflows/build-and-test.yml
16+
with:
17+
create-pack: true
18+
19+
create-draft-release:
20+
name: Create Draft Release
21+
needs: build-and-test
1522
runs-on: ubuntu-latest
23+
permissions:
24+
contents: write
1625

1726
steps:
1827
- name: Checkout code
1928
uses: actions/checkout@v4
20-
with:
21-
fetch-depth: 0 # Required for GitVersion
2229

23-
- name: Setup .NET
24-
uses: actions/setup-dotnet@v4
30+
- name: Download NuGet packages
31+
uses: actions/download-artifact@v4
2532
with:
26-
dotnet-version: |
27-
8.0.x
28-
9.0.x
29-
10.0.x
30-
31-
- name: Restore dependencies
32-
run: dotnet restore
33-
34-
- name: Build
35-
run: dotnet build --configuration Release --no-restore
36-
37-
- name: Test
38-
run: dotnet test --configuration Release --no-build --verbosity normal
39-
40-
- name: Pack NuGet packages
41-
run: dotnet pack --configuration Release --no-build --output ./artifacts
33+
name: nuget-packages
34+
path: ./artifacts
4235

43-
- name: Get version from packages
44-
id: get-version
36+
- name: Check if tag exists
37+
id: check-tag
4538
run: |
46-
# Extract version from the first package
47-
VERSION=$(ls ./artifacts/*.nupkg | head -1 | sed -n 's/.*\.MyCSharp\.HttpUserAgentParser\.\([0-9]\+\.[0-9]\+\.[0-9]\+.*\)\.nupkg/\1/p')
48-
echo "version=$VERSION" >> $GITHUB_OUTPUT
49-
echo "Version: $VERSION"
50-
51-
- name: Check for existing draft release
52-
id: check-draft
53-
env:
54-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55-
run: |
56-
DRAFT_RELEASE=$(gh release list --limit 100 --json isDraft,name,tagName | jq -r '.[] | select(.isDraft == true) | .tagName' | head -1)
57-
if [ -n "$DRAFT_RELEASE" ]; then
39+
TAG="v${{ needs.build-and-test.outputs.version }}"
40+
if git rev-parse "$TAG" >/dev/null 2>&1; then
5841
echo "exists=true" >> $GITHUB_OUTPUT
59-
echo "tag=$DRAFT_RELEASE" >> $GITHUB_OUTPUT
60-
echo "Found existing draft release: $DRAFT_RELEASE"
42+
echo "⚠️ Tag $TAG already exists"
6143
else
6244
echo "exists=false" >> $GITHUB_OUTPUT
63-
echo "No existing draft release found"
45+
echo "✅ Tag $TAG does not exist yet"
6446
fi
6547
66-
- name: Delete existing draft release
67-
if: steps.check-draft.outputs.exists == 'true'
48+
- name: Create/Update Draft Release
49+
if: steps.check-tag.outputs.exists == 'false'
50+
uses: release-drafter/release-drafter@v6
6851
env:
69-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
70-
run: |
71-
echo "Deleting existing draft release: ${{ steps.check-draft.outputs.tag }}"
72-
gh release delete ${{ steps.check-draft.outputs.tag }} --yes --cleanup-tag || true
73-
74-
- name: Create draft release
52+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53+
with:
54+
config-name: release-drafter.yml
55+
version: v${{ needs.build-and-test.outputs.version }}
56+
tag: v${{ needs.build-and-test.outputs.version }}
57+
name: Version ${{ needs.build-and-test.outputs.version }}
58+
publish: false
59+
prerelease: false
60+
61+
- name: Upload packages to draft release
62+
if: steps.check-tag.outputs.exists == 'false'
7563
env:
7664
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7765
run: |
78-
VERSION="${{ steps.get-version.outputs.version }}"
79-
TAG="v${VERSION}"
80-
81-
# Create release notes
82-
cat > release-notes.md << 'EOF'
83-
## What's Changed
84-
85-
This is an automated draft release created from the main branch.
86-
87-
### Packages
88-
89-
The following NuGet packages are included in this release:
90-
91-
EOF
92-
93-
# List all packages
66+
TAG="v${{ needs.build-and-test.outputs.version }}"
67+
# Wait a moment for the release to be created
68+
sleep 2
69+
# Upload artifacts to the draft release
9470
for file in ./artifacts/*.nupkg; do
95-
filename=$(basename "$file")
96-
echo "- \`$filename\`" >> release-notes.md
71+
gh release upload "$TAG" "$file" --clobber
9772
done
73+
echo "✅ Uploaded NuGet packages to draft release"
9874
99-
cat >> release-notes.md << 'EOF'
100-
101-
### Installation
102-
103-
```bash
104-
dotnet add package MyCSharp.HttpUserAgentParser
105-
dotnet add package MyCSharp.HttpUserAgentParser.AspNetCore
106-
dotnet add package MyCSharp.HttpUserAgentParser.MemoryCache
107-
```
108-
109-
**Full Changelog**: https://github.com/${{ github.repository }}/commits/${{ github.sha }}
110-
EOF
111-
112-
# Create draft release
113-
gh release create "$TAG" \
114-
./artifacts/*.nupkg \
115-
--draft \
116-
--title "Release $VERSION" \
117-
--notes-file release-notes.md \
118-
--target ${{ github.sha }}
119-
120-
echo "Created draft release: $TAG"
121-
122-
- name: Upload artifacts
123-
uses: actions/upload-artifact@v4
124-
with:
125-
name: nuget-packages
126-
path: ./artifacts/*.nupkg
127-
retention-days: 30
75+
- name: Summary
76+
if: steps.check-tag.outputs.exists == 'false'
77+
run: |
78+
echo "✅ Draft release created/updated" >> $GITHUB_STEP_SUMMARY
79+
echo "Version: v${{ needs.build-and-test.outputs.version }}" >> $GITHUB_STEP_SUMMARY
80+
echo "" >> $GITHUB_STEP_SUMMARY
81+
echo "### Next steps:" >> $GITHUB_STEP_SUMMARY
82+
echo "1. Go to [Releases](../../releases)" >> $GITHUB_STEP_SUMMARY
83+
echo "2. Review the draft release" >> $GITHUB_STEP_SUMMARY
84+
echo "3. Edit release notes if needed" >> $GITHUB_STEP_SUMMARY
85+
echo "4. Publish release to trigger production deployment" >> $GITHUB_STEP_SUMMARY
86+
87+
- name: Release already exists
88+
if: steps.check-tag.outputs.exists == 'true'
89+
run: |
90+
echo "ℹ️ Release v${{ needs.build-and-test.outputs.version }} already exists" >> $GITHUB_STEP_SUMMARY
91+
echo "No action taken" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)