Skip to content

Commit 8f8dd15

Browse files
committed
Add release workflow for automated multi-platform builds
Introduces release.yml GitHub Actions workflow to automate VectraCtl releases. Supports manual version input, validates version format, builds and packages binaries for Linux, Windows, and macOS (various architectures), uploads artifacts, generates checksums, creates detailed release notes from commit history, and publishes GitHub releases with assets and notes. #10
1 parent 77bd0d8 commit 8f8dd15

1 file changed

Lines changed: 220 additions & 0 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
name: vectractl
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
rel_version:
7+
description: 'Release version (examples: 1.9.0-rc.1, 1.9.1)'
8+
required: true
9+
type: string
10+
release_summary:
11+
description: 'Short summary shown at the top of the release notes (optional)'
12+
required: false
13+
type: string
14+
default: ''
15+
prerelease:
16+
description: 'Mark this as a pre-release'
17+
required: false
18+
type: boolean
19+
default: false
20+
21+
permissions:
22+
contents: write
23+
packages: read
24+
25+
jobs:
26+
validate:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Validate version format
30+
run: |
31+
if ! echo "${{ inputs.rel_version }}" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
32+
echo "Invalid version format: ${{ inputs.rel_version }}"
33+
exit 1
34+
fi
35+
36+
build:
37+
needs: validate
38+
strategy:
39+
matrix:
40+
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
41+
os_arch: [x64, arm, arm64]
42+
include:
43+
- os: ubuntu-latest
44+
kind: linux
45+
title: linux
46+
- os: windows-latest
47+
kind: win
48+
title: windows
49+
- os: macos-latest
50+
kind: osx
51+
title: osx
52+
exclude:
53+
- os: windows-latest
54+
os_arch: arm
55+
- os: macos-latest
56+
os_arch: arm
57+
runs-on: ${{ matrix.os }}
58+
59+
steps:
60+
- uses: actions/checkout@v4
61+
with:
62+
fetch-depth: 0
63+
64+
- name: Setup .NET
65+
uses: actions/setup-dotnet@v4
66+
with:
67+
dotnet-version: 10.0.x
68+
69+
- name: Publish
70+
shell: bash
71+
run: |
72+
release_name="vectractl-${{ matrix.title }}-${{ matrix.os_arch }}"
73+
dotnet publish src/FlowCtl/FlowCtl.csproj \
74+
/property:PublishSingleFile=true \
75+
/property:PublishReadyToRun=true \
76+
--runtime "${{ matrix.kind }}-${{ matrix.os_arch }}" \
77+
-c Release \
78+
--self-contained true \
79+
/property:Version="${{ inputs.rel_version }}" \
80+
-o "${{ github.workspace }}/${release_name}"
81+
82+
mkdir -p "${{ github.workspace }}/dist"
83+
cd "${{ github.workspace }}/${release_name}"
84+
if [ "${{ matrix.kind }}" == "win" ]; then
85+
7z a -tzip "${{ github.workspace }}/dist/${release_name}.zip" *
86+
else
87+
tar czvf "${{ github.workspace }}/dist/${release_name}.tar.gz" *
88+
fi
89+
90+
- name: Upload binaries
91+
uses: actions/upload-artifact@v4
92+
with:
93+
name: vectractl-${{ matrix.title }}-${{ matrix.os_arch }}
94+
path: "${{ github.workspace }}/dist"
95+
96+
release:
97+
runs-on: ubuntu-latest
98+
needs: build
99+
if: github.ref == 'refs/heads/main'
100+
env:
101+
ARTIFACT_DIR: ./release
102+
steps:
103+
- name: Checkout repository
104+
uses: actions/checkout@v4
105+
with:
106+
fetch-depth: 0
107+
108+
- name: Download artifacts
109+
uses: actions/download-artifact@v4
110+
with:
111+
pattern: vectractl-*
112+
path: ${{ env.ARTIFACT_DIR }}
113+
merge-multiple: true
114+
115+
- name: Generate checksum files
116+
run: |
117+
cd ${{ env.ARTIFACT_DIR }}
118+
for i in *.zip *.tar.gz; do
119+
[ -f "$i" ] && sha256sum -b "$i" > "$i.sha256"
120+
done
121+
122+
- name: Build release notes
123+
id: notes
124+
shell: bash
125+
run: |
126+
VERSION="v${{ inputs.rel_version }}"
127+
SUMMARY="${{ inputs.release_summary }}"
128+
129+
# Find previous tag to diff against; fall back to first commit
130+
PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${VERSION}$" | head -n1)
131+
if [ -z "$PREV_TAG" ]; then
132+
RANGE="HEAD"
133+
PREV_LABEL="initial commit"
134+
else
135+
RANGE="${PREV_TAG}..HEAD"
136+
PREV_LABEL="${PREV_TAG}"
137+
fi
138+
139+
COMMIT_COUNT=$(git rev-list $RANGE --count)
140+
141+
# Collect commits grouped by conventional-commit prefix
142+
BREAKING=$(git log "$RANGE" --pretty="format:%s|%h|%an" | grep -iE "^[a-z]+(\(.+\))?!:" || true)
143+
FEATURES=$(git log "$RANGE" --pretty="format:%s|%h|%an" | grep -iE "^feat(\(.+\))?:" || true)
144+
FIXES=$(git log "$RANGE" --pretty="format:%s|%h|%an" | grep -iE "^fix(\(.+\))?:" || true)
145+
PERF=$(git log "$RANGE" --pretty="format:%s|%h|%an" | grep -iE "^perf(\(.+\))?:" || true)
146+
OTHERS=$(git log "$RANGE" --pretty="format:%s|%h|%an" \
147+
| grep -viE "^(feat|fix|perf|chore|ci|docs|style|refactor|test|build)(\(.+\))?[!:]?" || true)
148+
149+
format_section() {
150+
local title="$1"
151+
local items="$2"
152+
if [ -n "$items" ]; then
153+
echo "### ${title}"
154+
echo ""
155+
while IFS='|' read -r subject hash author; do
156+
echo "- ${subject} (\`${hash}\`) — @${author}"
157+
done <<< "$items"
158+
echo ""
159+
fi
160+
}
161+
162+
{
163+
echo "## What's in VectraCtl ${VERSION}"
164+
echo ""
165+
if [ -n "$SUMMARY" ]; then
166+
echo "> ${SUMMARY}"
167+
echo ""
168+
fi
169+
echo "| | |"
170+
echo "|---|---|"
171+
echo "| **Released** | $(date -u +'%B %d, %Y') |"
172+
echo "| **Commits** | ${COMMIT_COUNT} since \`${PREV_LABEL}\` |"
173+
echo "| **Full diff** | [${{ github.repository }}](https://github.com/${{ github.repository }}/compare/${PREV_LABEL}...${VERSION}) |"
174+
echo ""
175+
echo "---"
176+
echo ""
177+
178+
if [ -n "$BREAKING" ]; then
179+
echo "### ⚠️ Breaking Changes"
180+
echo ""
181+
while IFS='|' read -r subject hash author; do
182+
echo "- ${subject} (\`${hash}\`) — @${author}"
183+
done <<< "$BREAKING"
184+
echo ""
185+
fi
186+
187+
format_section "✨ New Features" "$FEATURES"
188+
format_section "🐛 Bug Fixes" "$FIXES"
189+
format_section "⚡ Performance" "$PERF"
190+
format_section "🔀 Other Changes" "$OTHERS"
191+
192+
echo "---"
193+
echo ""
194+
echo "### 📦 Installation"
195+
echo ""
196+
echo "Download the archive for your platform from the assets below,"
197+
echo "verify its checksum, then extract."
198+
echo ""
199+
echo '```bash'
200+
echo "# Linux / macOS"
201+
echo "sha256sum -c vectractl-<platform>-<arch>.tar.gz.sha256"
202+
echo "tar -xzf vectractl-<platform>-<arch>.tar.gz"
203+
echo '```'
204+
echo ""
205+
echo '```powershell'
206+
echo "# Windows (PowerShell)"
207+
echo "Get-FileHash vectractl-windows-x64.zip -Algorithm SHA256"
208+
echo "Expand-Archive vectractl-windows-x64.zip"
209+
echo '```'
210+
} > release_notes.md
211+
212+
- name: Create Release
213+
uses: ncipollo/release-action@v1
214+
with:
215+
tag: v${{ inputs.rel_version }}
216+
name: VectraCtl v${{ inputs.rel_version }}
217+
bodyFile: release_notes.md
218+
prerelease: ${{ inputs.prerelease }}
219+
artifacts: "${{ env.ARTIFACT_DIR }}/*"
220+
token: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)