Skip to content

Commit fefca52

Browse files
devpossibleclaude
andcommitted
feat: add complete CI/CD pipeline with Release Please
- Add GitHub Actions CI workflow (build, test, lint) - Add Release workflow with Release Please for semantic versioning - Add platform installers (Windows MSIX, Linux DEB/RPM/tar.gz) - Add Dependabot for automated dependency updates - Add PR template with conventional commit guidance - Update README with comprehensive installation instructions - Update package.ps1 with NonInteractive mode for CI The release workflow uses Conventional Commits: - feat: triggers minor version bump - fix: triggers patch version bump - feat!/BREAKING CHANGE: triggers major version bump Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 80298fa commit fefca52

22 files changed

Lines changed: 1248 additions & 170 deletions

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## Description
2+
3+
<!-- Briefly describe what this PR does -->
4+
5+
## Type of Change
6+
7+
<!-- Mark the appropriate option with an 'x' -->
8+
9+
- [ ] `feat:` New feature (minor version bump)
10+
- [ ] `fix:` Bug fix (patch version bump)
11+
- [ ] `docs:` Documentation only
12+
- [ ] `chore:` Maintenance (deps, CI, etc.)
13+
- [ ] `refactor:` Code refactoring (no behavior change)
14+
- [ ] `test:` Adding or updating tests
15+
- [ ] `BREAKING CHANGE:` Breaking change (major version bump)
16+
17+
## Conventional Commit Format
18+
19+
Your PR title and/or commit messages should follow this format:
20+
```
21+
<type>: <description>
22+
23+
[optional body]
24+
25+
[optional footer]
26+
```
27+
28+
Examples:
29+
- `feat: add GPU temperature panel`
30+
- `fix: correct USB timeout handling`
31+
- `feat!: redesign device driver API` (breaking change)
32+
33+
## Testing
34+
35+
<!-- Describe how you tested your changes -->
36+
37+
- [ ] Tested locally on Windows
38+
- [ ] Tested locally on Linux
39+
- [ ] Added/updated unit tests
40+
- [ ] All existing tests pass
41+
42+
## Checklist
43+
44+
- [ ] Code follows project style guidelines
45+
- [ ] Self-review completed
46+
- [ ] Changes are documented (if applicable)
47+
- [ ] No new warnings introduced

.github/dependabot.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
version: 2
2+
updates:
3+
# NuGet packages
4+
- package-ecosystem: "nuget"
5+
directory: "/src"
6+
schedule:
7+
interval: "weekly"
8+
day: "monday"
9+
open-pull-requests-limit: 5
10+
commit-message:
11+
prefix: "chore(deps)"
12+
labels:
13+
- "dependencies"
14+
- "nuget"
15+
groups:
16+
microsoft:
17+
patterns:
18+
- "Microsoft.*"
19+
serilog:
20+
patterns:
21+
- "Serilog*"
22+
testing:
23+
patterns:
24+
- "xunit*"
25+
- "NSubstitute*"
26+
- "Shouldly*"
27+
- "coverlet*"
28+
29+
# GitHub Actions
30+
- package-ecosystem: "github-actions"
31+
directory: "/"
32+
schedule:
33+
interval: "weekly"
34+
day: "monday"
35+
open-pull-requests-limit: 3
36+
commit-message:
37+
prefix: "ci(deps)"
38+
labels:
39+
- "dependencies"
40+
- "github-actions"

.github/release-please-config.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
3+
"packages": {
4+
".": {
5+
"release-type": "simple",
6+
"bump-minor-pre-major": true,
7+
"bump-patch-for-minor-pre-major": true,
8+
"include-component-in-tag": false,
9+
"changelog-path": "CHANGELOG.md",
10+
"extra-files": [
11+
{
12+
"type": "xml",
13+
"path": "Directory.Build.props",
14+
"xpath": "//Project/PropertyGroup/Version"
15+
}
16+
]
17+
}
18+
}
19+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.1.0"
3+
}

.github/workflows/ci.yml

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,71 +6,71 @@ on:
66
pull_request:
77
branches: [main, master]
88

9+
env:
10+
DOTNET_NOLOGO: true
11+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
12+
DOTNET_CLI_TELEMETRY_OPTOUT: true
13+
914
jobs:
10-
build:
15+
build-and-test:
16+
name: Build & Test (${{ matrix.os }})
1117
runs-on: ${{ matrix.os }}
1218
strategy:
19+
fail-fast: false
1320
matrix:
1421
os: [ubuntu-latest, windows-latest]
1522

1623
steps:
17-
- uses: actions/checkout@v4
24+
- name: Checkout
25+
uses: actions/checkout@v4
1826

1927
- name: Setup .NET
2028
uses: actions/setup-dotnet@v4
2129
with:
2230
dotnet-version: '10.0.x'
2331
dotnet-quality: 'preview'
2432

33+
- name: Cache NuGet packages
34+
uses: actions/cache@v4
35+
with:
36+
path: ~/.nuget/packages
37+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Build.props') }}
38+
restore-keys: |
39+
${{ runner.os }}-nuget-
40+
2541
- name: Restore dependencies
2642
run: dotnet restore src/LCDPossible.sln
2743

2844
- name: Build
2945
run: dotnet build src/LCDPossible.sln --configuration Release --no-restore
3046

3147
- name: Test
32-
run: dotnet test src/LCDPossible.sln --configuration Release --no-build --verbosity normal
48+
run: dotnet test src/LCDPossible.sln --configuration Release --no-build --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage
3349

34-
publish:
35-
needs: build
50+
- name: Upload coverage
51+
if: matrix.os == 'ubuntu-latest'
52+
uses: actions/upload-artifact@v4
53+
with:
54+
name: coverage-report
55+
path: ./coverage/**/coverage.cobertura.xml
56+
retention-days: 7
57+
58+
lint:
59+
name: Code Format Check
3660
runs-on: ubuntu-latest
37-
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
3861

3962
steps:
40-
- uses: actions/checkout@v4
63+
- name: Checkout
64+
uses: actions/checkout@v4
4165

4266
- name: Setup .NET
4367
uses: actions/setup-dotnet@v4
4468
with:
4569
dotnet-version: '10.0.x'
4670
dotnet-quality: 'preview'
4771

48-
- name: Publish Linux x64
49-
run: |
50-
dotnet publish src/LCDPossible.Service/LCDPossible.Service.csproj \
51-
--configuration Release \
52-
--runtime linux-x64 \
53-
--self-contained true \
54-
-p:PublishSingleFile=true \
55-
--output .build/publish/linux-x64
56-
57-
- name: Publish Windows x64
58-
run: |
59-
dotnet publish src/LCDPossible.Service/LCDPossible.Service.csproj \
60-
--configuration Release \
61-
--runtime win-x64 \
62-
--self-contained true \
63-
-p:PublishSingleFile=true \
64-
--output .build/publish/win-x64
65-
66-
- name: Upload Linux artifact
67-
uses: actions/upload-artifact@v4
68-
with:
69-
name: lcdpossible-linux-x64
70-
path: .build/publish/linux-x64/
72+
- name: Restore dependencies
73+
run: dotnet restore src/LCDPossible.sln
7174

72-
- name: Upload Windows artifact
73-
uses: actions/upload-artifact@v4
74-
with:
75-
name: lcdpossible-win-x64
76-
path: .build/publish/win-x64/
75+
- name: Check formatting
76+
run: dotnet format src/LCDPossible.sln --verify-no-changes --verbosity diagnostic

.github/workflows/release.yml

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
env:
13+
DOTNET_NOLOGO: true
14+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
15+
DOTNET_CLI_TELEMETRY_OPTOUT: true
16+
17+
jobs:
18+
release-please:
19+
name: Release Please
20+
runs-on: ubuntu-latest
21+
outputs:
22+
release_created: ${{ steps.release.outputs.release_created }}
23+
tag_name: ${{ steps.release.outputs.tag_name }}
24+
version: ${{ steps.release.outputs.version }}
25+
26+
steps:
27+
- name: Release Please
28+
id: release
29+
uses: google-github-actions/release-please-action@v4
30+
with:
31+
token: ${{ secrets.GITHUB_TOKEN }}
32+
config-file: .github/release-please-config.json
33+
manifest-file: .github/release-please-manifest.json
34+
35+
build-artifacts:
36+
name: Build (${{ matrix.runtime }})
37+
needs: release-please
38+
if: needs.release-please.outputs.release_created == 'true'
39+
runs-on: ${{ matrix.os }}
40+
strategy:
41+
fail-fast: false
42+
matrix:
43+
include:
44+
- runtime: win-x64
45+
os: windows-latest
46+
artifact_ext: .zip
47+
- runtime: linux-x64
48+
os: ubuntu-latest
49+
artifact_ext: .tar.gz
50+
- runtime: linux-arm64
51+
os: ubuntu-latest
52+
artifact_ext: .tar.gz
53+
- runtime: osx-x64
54+
os: macos-latest
55+
artifact_ext: .tar.gz
56+
57+
steps:
58+
- name: Checkout
59+
uses: actions/checkout@v4
60+
61+
- name: Setup .NET
62+
uses: actions/setup-dotnet@v4
63+
with:
64+
dotnet-version: '10.0.x'
65+
dotnet-quality: 'preview'
66+
67+
- name: Publish
68+
run: |
69+
dotnet publish src/LCDPossible/LCDPossible.csproj \
70+
--configuration Release \
71+
--runtime ${{ matrix.runtime }} \
72+
--self-contained true \
73+
-p:PublishSingleFile=true \
74+
-p:IncludeNativeLibrariesForSelfExtract=true \
75+
-p:Version=${{ needs.release-please.outputs.version }} \
76+
--output ./publish
77+
78+
- name: Create archive (Windows)
79+
if: matrix.os == 'windows-latest'
80+
shell: pwsh
81+
run: |
82+
Compress-Archive -Path ./publish/* -DestinationPath ./lcdpossible-${{ needs.release-please.outputs.version }}-${{ matrix.runtime }}.zip
83+
84+
- name: Create archive (Linux/macOS)
85+
if: matrix.os != 'windows-latest'
86+
run: |
87+
tar -czvf ./lcdpossible-${{ needs.release-please.outputs.version }}-${{ matrix.runtime }}.tar.gz -C ./publish .
88+
89+
- name: Upload artifact
90+
uses: actions/upload-artifact@v4
91+
with:
92+
name: lcdpossible-${{ matrix.runtime }}
93+
path: ./lcdpossible-${{ needs.release-please.outputs.version }}-${{ matrix.runtime }}${{ matrix.artifact_ext }}
94+
95+
build-installers:
96+
name: Build Installers
97+
needs: [release-please, build-artifacts]
98+
if: needs.release-please.outputs.release_created == 'true'
99+
runs-on: ubuntu-latest
100+
101+
steps:
102+
- name: Checkout
103+
uses: actions/checkout@v4
104+
105+
- name: Download all artifacts
106+
uses: actions/download-artifact@v4
107+
with:
108+
path: ./artifacts
109+
110+
- name: Setup .NET
111+
uses: actions/setup-dotnet@v4
112+
with:
113+
dotnet-version: '10.0.x'
114+
dotnet-quality: 'preview'
115+
116+
- name: Build DEB package
117+
run: |
118+
chmod +x ./installer/linux/debian/build-deb.sh
119+
./installer/linux/debian/build-deb.sh ${{ needs.release-please.outputs.version }}
120+
121+
- name: Build RPM package
122+
run: |
123+
chmod +x ./installer/linux/rpm/build-rpm.sh
124+
./installer/linux/rpm/build-rpm.sh ${{ needs.release-please.outputs.version }}
125+
126+
- name: Upload DEB package
127+
uses: actions/upload-artifact@v4
128+
with:
129+
name: lcdpossible-deb
130+
path: ./installer/linux/debian/*.deb
131+
132+
- name: Upload RPM package
133+
uses: actions/upload-artifact@v4
134+
with:
135+
name: lcdpossible-rpm
136+
path: ./installer/linux/rpm/*.rpm
137+
138+
upload-to-release:
139+
name: Upload to Release
140+
needs: [release-please, build-artifacts, build-installers]
141+
if: needs.release-please.outputs.release_created == 'true'
142+
runs-on: ubuntu-latest
143+
144+
steps:
145+
- name: Download all artifacts
146+
uses: actions/download-artifact@v4
147+
with:
148+
path: ./artifacts
149+
150+
- name: Display structure of downloaded files
151+
run: ls -R ./artifacts
152+
153+
- name: Upload to GitHub Release
154+
uses: softprops/action-gh-release@v2
155+
with:
156+
tag_name: ${{ needs.release-please.outputs.tag_name }}
157+
files: |
158+
./artifacts/lcdpossible-win-x64/*
159+
./artifacts/lcdpossible-linux-x64/*
160+
./artifacts/lcdpossible-linux-arm64/*
161+
./artifacts/lcdpossible-osx-x64/*
162+
./artifacts/lcdpossible-deb/*
163+
./artifacts/lcdpossible-rpm/*

0 commit comments

Comments
 (0)