Skip to content

Commit f40fd5b

Browse files
committed
🔖 create release pipeline
1 parent e468df8 commit f40fd5b

2 files changed

Lines changed: 250 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
name: release
2+
3+
on:
4+
push:
5+
branches: [dev]
6+
7+
jobs:
8+
build:
9+
name: build
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: checkout code
14+
uses: actions/checkout@v6
15+
16+
- name: setup .net
17+
uses: actions/setup-dotnet@v5
18+
with:
19+
dotnet-version: '10.0.x'
20+
21+
- name: cache nuget packages
22+
uses: actions/cache@v4
23+
with:
24+
path: ~/.nuget/packages
25+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
26+
restore-keys: |
27+
${{ runner.os }}-nuget-
28+
29+
- name: restore dependencies
30+
run: dotnet restore
31+
32+
- name: build
33+
run: dotnet build --no-restore --configuration Release
34+
35+
test:
36+
name: test
37+
runs-on: ubuntu-latest
38+
39+
steps:
40+
- name: checkout code
41+
uses: actions/checkout@v6
42+
43+
- name: setup .net
44+
uses: actions/setup-dotnet@v5
45+
with:
46+
dotnet-version: '10.0.x'
47+
48+
- name: cache nuget packages
49+
uses: actions/cache@v4
50+
with:
51+
path: ~/.nuget/packages
52+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
53+
restore-keys: |
54+
${{ runner.os }}-nuget-
55+
56+
- name: restore dependencies
57+
run: dotnet restore
58+
59+
- name: build
60+
run: dotnet build --no-restore --configuration Release
61+
62+
- name: run tests
63+
run: dotnet test --no-build --configuration Release
64+
65+
release:
66+
name: release
67+
needs: [build, test]
68+
runs-on: windows-latest
69+
permissions:
70+
contents: write
71+
72+
steps:
73+
- name: checkout code
74+
uses: actions/checkout@v6
75+
with:
76+
fetch-depth: 0
77+
78+
- name: setup .net
79+
uses: actions/setup-dotnet@v5
80+
with:
81+
dotnet-version: '10.0.x'
82+
83+
- name: calculate version and generate changelog
84+
id: version
85+
shell: bash
86+
run: |
87+
# Get the latest 5.x.x tag, or default to 5.0.0
88+
LAST_TAG=$(git tag -l '5.*.*' --sort=-v:refname | head -n1)
89+
if [ -z "$LAST_TAG" ]; then
90+
LAST_TAG="5.0.0"
91+
COMPARE_REF="$(git rev-list --max-parents=0 HEAD)"
92+
else
93+
COMPARE_REF="$LAST_TAG"
94+
fi
95+
96+
echo "Last tag: $LAST_TAG"
97+
echo "Comparing from: $COMPARE_REF"
98+
99+
# Parse version components
100+
MAJOR=$(echo "$LAST_TAG" | cut -d. -f1)
101+
MINOR=$(echo "$LAST_TAG" | cut -d. -f2)
102+
PATCH=$(echo "$LAST_TAG" | cut -d. -f3)
103+
104+
# Track the highest semver change and collect commits by type
105+
HIGHEST_CHANGE="none"
106+
MAJOR_COMMITS=""
107+
MINOR_COMMITS=""
108+
PATCH_COMMITS=""
109+
110+
# Get commits since last tag
111+
while IFS= read -r line; do
112+
if [ -z "$line" ]; then
113+
continue
114+
fi
115+
116+
COMMIT_HASH=$(echo "$line" | cut -d' ' -f1)
117+
COMMIT_MSG=$(echo "$line" | cut -d' ' -f2-)
118+
COMMIT_SHORT="${COMMIT_HASH:0:7}"
119+
120+
# Get commit body and look for semver tag
121+
COMMIT_BODY=$(git log -1 --format="%b" "$COMMIT_HASH")
122+
SEMVER_TAG=$(echo "$COMMIT_BODY" | grep -E 'semver:\s*\w+' | sed -E 's/.*semver:\s*(\w+).*/\1/' | head -n1 || true)
123+
124+
case "$SEMVER_TAG" in
125+
major)
126+
if [ "$HIGHEST_CHANGE" != "major" ]; then
127+
HIGHEST_CHANGE="major"
128+
fi
129+
MAJOR_COMMITS="${MAJOR_COMMITS}- ${COMMIT_MSG} (\`${COMMIT_SHORT}\`)\n"
130+
;;
131+
minor)
132+
if [ "$HIGHEST_CHANGE" != "major" ]; then
133+
HIGHEST_CHANGE="minor"
134+
fi
135+
MINOR_COMMITS="${MINOR_COMMITS}- ${COMMIT_MSG} (\`${COMMIT_SHORT}\`)\n"
136+
;;
137+
patch)
138+
if [ "$HIGHEST_CHANGE" = "none" ]; then
139+
HIGHEST_CHANGE="patch"
140+
fi
141+
PATCH_COMMITS="${PATCH_COMMITS}- ${COMMIT_MSG} (\`${COMMIT_SHORT}\`)\n"
142+
;;
143+
esac
144+
done < <(git log "${COMPARE_REF}..HEAD" --format="%H %s" --reverse)
145+
146+
# If no releasable changes, skip
147+
if [ "$HIGHEST_CHANGE" = "none" ]; then
148+
echo "No releasable changes found (no semver: major/minor/patch tags)"
149+
echo "should_release=false" >> $GITHUB_OUTPUT
150+
exit 0
151+
fi
152+
153+
# Calculate new version
154+
case "$HIGHEST_CHANGE" in
155+
major)
156+
MINOR=$((MINOR + 1))
157+
PATCH=0
158+
;;
159+
minor|patch)
160+
PATCH=$((PATCH + 1))
161+
;;
162+
esac
163+
164+
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
165+
echo "New version: $NEW_VERSION"
166+
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
167+
echo "should_release=true" >> $GITHUB_OUTPUT
168+
169+
# Generate changelog
170+
CHANGELOG="## What's Changed in ${NEW_VERSION}\n\n"
171+
172+
if [ -n "$MAJOR_COMMITS" ]; then
173+
CHANGELOG="${CHANGELOG}### Breaking Changes\n${MAJOR_COMMITS}\n"
174+
fi
175+
176+
if [ -n "$MINOR_COMMITS" ]; then
177+
CHANGELOG="${CHANGELOG}### Features\n${MINOR_COMMITS}\n"
178+
fi
179+
180+
if [ -n "$PATCH_COMMITS" ]; then
181+
CHANGELOG="${CHANGELOG}### Bug Fixes\n${PATCH_COMMITS}\n"
182+
fi
183+
184+
# Write changelog to file for later use
185+
echo -e "$CHANGELOG" > changelog.md
186+
187+
# Also output for GitHub Actions
188+
{
189+
echo 'changelog<<EOF'
190+
echo -e "$CHANGELOG"
191+
echo 'EOF'
192+
} >> $GITHUB_OUTPUT
193+
194+
- name: build release
195+
if: steps.version.outputs.should_release == 'true'
196+
run: |
197+
dotnet restore
198+
dotnet build --no-restore --configuration Release /p:Version=${{ steps.version.outputs.version }}
199+
200+
- name: pack nuget
201+
if: steps.version.outputs.should_release == 'true'
202+
run: |
203+
dotnet pack EliteAPI/EliteAPI.csproj --no-build --configuration Release /p:Version=${{ steps.version.outputs.version }} --output ./nupkg
204+
205+
- name: zip net48 release
206+
if: steps.version.outputs.should_release == 'true'
207+
shell: pwsh
208+
run: |
209+
Compress-Archive -Path "EliteVA/bin/Release/net48/*" -DestinationPath "EliteVA-${{ steps.version.outputs.version }}.zip"
210+
211+
- name: create git tag
212+
if: steps.version.outputs.should_release == 'true'
213+
run: |
214+
git config user.name "github-actions[bot]"
215+
git config user.email "github-actions[bot]@users.noreply.github.com"
216+
git tag -a "${{ steps.version.outputs.version }}" -m "Release ${{ steps.version.outputs.version }}"
217+
git push origin "${{ steps.version.outputs.version }}"
218+
219+
- name: create github release
220+
if: steps.version.outputs.should_release == 'true'
221+
uses: softprops/action-gh-release@v2
222+
with:
223+
tag_name: ${{ steps.version.outputs.version }}
224+
name: v${{ steps.version.outputs.version }}
225+
body_path: changelog.md
226+
draft: false
227+
prerelease: false
228+
files: |
229+
EliteVA-${{ steps.version.outputs.version }}.zip
230+
231+
- name: publish to nuget
232+
if: steps.version.outputs.should_release == 'true'
233+
run: |
234+
dotnet nuget push ./nupkg/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate

EliteAPI/EliteAPI.csproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,24 @@
44
<Nullable>enable</Nullable>
55
<LangVersion>latest</LangVersion>
66
<TargetFramework>netstandard2.0</TargetFramework>
7+
8+
<!-- NuGet Package Metadata -->
9+
<PackageId>EliteAPI</PackageId>
10+
<Version>5.0.0</Version>
11+
<Authors>Somfic</Authors>
12+
<Description>A .NET library for interacting with Elite Dangerous game data</Description>
13+
<PackageProjectUrl>https://github.com/Somfic/EliteAPI</PackageProjectUrl>
14+
<RepositoryUrl>https://github.com/Somfic/EliteAPI</RepositoryUrl>
15+
<RepositoryType>git</RepositoryType>
16+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
17+
<PackageReadmeFile>README.md</PackageReadmeFile>
18+
<PackageTags>elite;dangerous;api;game;space</PackageTags>
719
</PropertyGroup>
820

21+
<ItemGroup>
22+
<None Include="../README.md" Pack="true" PackagePath="/" />
23+
</ItemGroup>
24+
925
<ItemGroup>
1026
<PackageReference Include="IsExternalInit" Version="1.0.3">
1127
<PrivateAssets>all</PrivateAssets>

0 commit comments

Comments
 (0)