Skip to content

Commit 596cdfd

Browse files
authored
Merge pull request #1 from aubynsamuel/test
Added workflows to automate test and releases
2 parents 515578e + b91a2ab commit 596cdfd

7 files changed

Lines changed: 582 additions & 1 deletion

File tree

.github/workflows/build.yml

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
branches: [ main, develop, test ]
6+
tags: [ 'v*' ]
7+
pull_request:
8+
branches: [ main ]
9+
10+
env:
11+
DOTNET_VERSION: '9.0.x'
12+
PROJECT_FILE: 'ClipSyncWindows.csproj'
13+
RUNTIME: 'win-x64'
14+
15+
jobs:
16+
build:
17+
runs-on: windows-latest
18+
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Setup .NET
24+
uses: actions/setup-dotnet@v4
25+
with:
26+
dotnet-version: ${{ env.DOTNET_VERSION }}
27+
28+
- name: Cache NuGet packages
29+
uses: actions/cache@v4
30+
with:
31+
path: ~/.nuget/packages
32+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
33+
restore-keys: |
34+
${{ runner.os }}-nuget-
35+
36+
- name: Restore dependencies
37+
run: dotnet restore ${{ env.PROJECT_FILE }}
38+
39+
- name: Build
40+
run: dotnet build ${{ env.PROJECT_FILE }} --configuration Release --no-restore
41+
42+
- name: Test
43+
run: dotnet test ${{ env.PROJECT_FILE }} --no-build --verbosity normal --configuration Release
44+
45+
- name: Publish application
46+
run: dotnet publish ${{ env.PROJECT_FILE }} --configuration Release --output ./publish --self-contained true --runtime ${{ env.RUNTIME }}
47+
48+
- name: Upload build artifacts
49+
uses: actions/upload-artifact@v4
50+
with:
51+
name: ClipSync-Windows-${{ github.sha }}
52+
path: ./publish/
53+
retention-days: 30
54+
55+
prepare-installer:
56+
needs: build
57+
runs-on: windows-latest
58+
if: github.ref == 'refs/heads/test' || startsWith(github.ref, 'refs/tags/v')
59+
60+
outputs:
61+
is-release: ${{ steps.check-release.outputs.is-release }}
62+
version: ${{ steps.get-version.outputs.version }}
63+
64+
steps:
65+
- name: Checkout code
66+
uses: actions/checkout@v4
67+
68+
- name: Download build artifacts
69+
uses: actions/download-artifact@v4
70+
with:
71+
name: ClipSync-Windows-${{ github.sha }}
72+
path: ./publish/
73+
74+
- name: Check if this is a release
75+
id: check-release
76+
run: |
77+
if ("${{ github.ref }}" -like "refs/tags/v*") {
78+
echo "is-release=true" >> $env:GITHUB_OUTPUT
79+
} else {
80+
echo "is-release=false" >> $env:GITHUB_OUTPUT
81+
}
82+
83+
- name: Get version
84+
id: get-version
85+
run: |
86+
if ("${{ github.ref }}" -like "refs/tags/v*") {
87+
$version = "${{ github.ref_name }}"
88+
echo "version=$version" >> $env:GITHUB_OUTPUT
89+
} else {
90+
echo "version=test-${{ github.sha }}" >> $env:GITHUB_OUTPUT
91+
}
92+
93+
- name: Setup Inno Setup
94+
run: |
95+
try {
96+
choco install innosetup -y --no-progress
97+
Write-Host "Inno Setup installed successfully"
98+
} catch {
99+
Write-Error "Failed to install Inno Setup: $_"
100+
exit 1
101+
}
102+
103+
- name: Verify Inno Setup installation
104+
run: |
105+
$innoPath = Get-Command "iscc.exe" -ErrorAction SilentlyContinue
106+
if (-not $innoPath) {
107+
Write-Error "Inno Setup not found in PATH"
108+
exit 1
109+
}
110+
Write-Host "Inno Setup found at: $($innoPath.Source)"
111+
112+
- name: Verify installer script exists
113+
run: |
114+
if (-not (Test-Path "InnoInstaller.iss")) {
115+
Write-Error "InnoInstaller.iss not found in repository"
116+
exit 1
117+
}
118+
Write-Host "Installer script found"
119+
120+
- name: Update Inno Setup script
121+
run: |
122+
try {
123+
$content = Get-Content "InnoInstaller.iss" -Raw -ErrorAction Stop
124+
125+
# Update source path
126+
$content = $content -replace 'Source: "publish\\\*"', 'Source: "publish\*"'
127+
$content = $content -replace 'Source: "publish\\([^"]+)"', 'Source: "publish\$1"'
128+
129+
# Update icon path if it exists
130+
if ($content -match 'SetupIconFile=') {
131+
$content = $content -replace 'SetupIconFile=publish\\([^"]*)', 'SetupIconFile=publish\$1'
132+
}
133+
134+
# Update version and filename for releases
135+
if ("${{ steps.check-release.outputs.is-release }}" -eq "true") {
136+
$version = "${{ steps.get-version.outputs.version }}"
137+
$content = $content -replace '#define MyAppVersion "[^"]*"', "#define MyAppVersion `"$version`""
138+
$content = $content -replace 'OutputBaseFilename=ClipSync_Setup', "OutputBaseFilename=ClipSync-Windows-$version-Setup"
139+
} else {
140+
# For test builds
141+
$content = $content -replace 'OutputBaseFilename=ClipSync_Setup', 'OutputBaseFilename=ClipSync-Test-Setup'
142+
}
143+
144+
Set-Content "InnoInstaller.iss" $content -ErrorAction Stop
145+
Write-Host "Installer script updated successfully"
146+
147+
# Show the changes for debugging
148+
Write-Host "Updated installer script content (first 10 lines):"
149+
Get-Content "InnoInstaller.iss" | Select-Object -First 10 | ForEach-Object { Write-Host " $_" }
150+
151+
} catch {
152+
Write-Error "Failed to update installer script: $_"
153+
exit 1
154+
}
155+
156+
- name: Build installer
157+
run: |
158+
try {
159+
iscc "InnoInstaller.iss"
160+
Write-Host "Installer built successfully"
161+
162+
# List generated files
163+
Write-Host "Generated files:"
164+
Get-ChildItem -Filter "*.exe" | ForEach-Object { Write-Host " $($_.Name)" }
165+
166+
} catch {
167+
Write-Error "Failed to build installer: $_"
168+
exit 1
169+
}
170+
171+
- name: Upload installer artifact
172+
uses: actions/upload-artifact@v4
173+
with:
174+
name: ClipSync-Installer-${{ steps.get-version.outputs.version }}
175+
path: "*.exe"
176+
retention-days: 30
177+
178+
test-release:
179+
needs: prepare-installer
180+
runs-on: windows-latest
181+
if: github.ref == 'refs/heads/test'
182+
183+
steps:
184+
- name: Download installer
185+
uses: actions/download-artifact@v4
186+
with:
187+
name: ClipSync-Installer-${{ needs.prepare-installer.outputs.version }}
188+
path: ./
189+
190+
- name: Download build artifacts
191+
uses: actions/download-artifact@v4
192+
with:
193+
name: ClipSync-Windows-${{ github.sha }}
194+
path: ./publish/
195+
196+
- name: Upload test release artifacts
197+
uses: actions/upload-artifact@v4
198+
with:
199+
name: ClipSync-Test-Release-${{ github.sha }}
200+
path: |
201+
*.exe
202+
./publish/
203+
retention-days: 7
204+
205+
release:
206+
needs: prepare-installer
207+
runs-on: windows-latest
208+
if: startsWith(github.ref, 'refs/tags/v')
209+
210+
steps:
211+
- name: Download installer
212+
uses: actions/download-artifact@v4
213+
with:
214+
name: ClipSync-Installer-${{ needs.prepare-installer.outputs.version }}
215+
path: ./
216+
217+
- name: Download build artifacts
218+
uses: actions/download-artifact@v4
219+
with:
220+
name: ClipSync-Windows-${{ github.sha }}
221+
path: ./publish/
222+
223+
- name: Create release archive
224+
run: |
225+
try {
226+
Compress-Archive -Path ./publish/* -DestinationPath "ClipSync-Windows-${{ needs.prepare-installer.outputs.version }}.zip" -ErrorAction Stop
227+
Write-Host "Release archive created successfully"
228+
} catch {
229+
Write-Error "Failed to create release archive: $_"
230+
exit 1
231+
}
232+
233+
- name: Verify release files
234+
run: |
235+
Write-Host "Release files:"
236+
Get-ChildItem -Filter "ClipSync-Windows-*" | ForEach-Object {
237+
Write-Host " $($_.Name) ($([math]::Round($_.Length / 1MB, 2)) MB)"
238+
}
239+
240+
- name: Create GitHub Release
241+
uses: softprops/action-gh-release@v2
242+
with:
243+
name: ClipSync Windows ${{ needs.prepare-installer.outputs.version }}
244+
body: |
245+
## ClipSync Windows ${{ needs.prepare-installer.outputs.version }}
246+
247+
### Installation Options
248+
249+
**Option 1: Installer (Recommended)**
250+
1. Download `ClipSync-Windows-${{ needs.prepare-installer.outputs.version }}-Setup.exe`
251+
2. Run the installer and follow the setup wizard
252+
253+
**Option 2: Portable**
254+
1. Download `ClipSync-Windows-${{ needs.prepare-installer.outputs.version }}.zip`
255+
2. Extract to your desired location
256+
3. Run `ClipSyncWindows.exe`
257+
258+
### System Requirements
259+
260+
- Windows 10 version 1903+ or Windows 11
261+
- .NET 9.0 Runtime (included in self-contained build)
262+
- Bluetooth adapter (for device synchronization)
263+
264+
### What's New
265+
266+
Please see the [CHANGELOG](CHANGELOG.md) for detailed information about changes in this release.
267+
files: |
268+
ClipSync-Windows-${{ needs.prepare-installer.outputs.version }}.zip
269+
ClipSync-Windows-${{ needs.prepare-installer.outputs.version }}-Setup.exe
270+
draft: false
271+
prerelease: false
272+
generate_release_notes: true
273+
env:
274+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Changelog
2+
3+
All notable changes to ClipSync Windows will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [1.0.0]
9+
10+
### Added
11+
12+
- Cross-platform clipboard sharing between Windows and Android devices
13+
- Bluetooth connectivity for secure local device communication
14+
- Modern WPF interface with dark/light theme support
15+
- Real-time clipboard synchronization
16+
- Service-based background listening for incoming connections
17+
- JSON protocol for reliable data exchange
18+
- Self-contained deployment (no .NET runtime installation required)
19+
- Professional installer with Inno Setup
20+
- Automatic GitHub Actions CI/CD pipeline
21+
22+
### Technical Details
23+
24+
- Built with .NET 9.0 and WPF
25+
- Uses InTheHand.Net.Bluetooth 4.2.0 for Bluetooth connectivity
26+
- Uses Newtonsoft.Json 13.0.1 for data serialization
27+
- Supports Windows 10 version 1903+ and Windows 11
28+
- Self-contained win-x64 runtime included

ClipSyncWindows.csproj

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<OutputType>WinExe</OutputType>
@@ -7,6 +7,29 @@
77
<ImplicitUsings>enable</ImplicitUsings>
88
<UseWPF>true</UseWPF>
99
<ApplicationIcon>app.ico</ApplicationIcon>
10+
11+
<!-- Version Information -->
12+
<AssemblyVersion>1.0.0.0</AssemblyVersion>
13+
<FileVersion>1.0.0.0</FileVersion>
14+
<Version>1.0.0</Version>
15+
16+
<!-- Assembly Metadata -->
17+
<AssemblyTitle>ClipSync Windows</AssemblyTitle>
18+
<AssemblyDescription>Cross-platform clipboard sharing application for Windows and Android devices via Bluetooth</AssemblyDescription>
19+
<AssemblyCompany>ClipSync</AssemblyCompany>
20+
<AssemblyProduct>ClipSync Windows</AssemblyProduct>
21+
<AssemblyCopyright>Copyright 2024 ClipSync. All rights reserved.</AssemblyCopyright>
22+
<AssemblyTrademark>ClipSync</AssemblyTrademark>
23+
24+
<!-- Application Properties -->
25+
<ApplicationManifest>app.manifest</ApplicationManifest>
26+
<Win32Resource />
27+
<StartupObject />
28+
29+
<!-- Build Configuration -->
30+
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
31+
<Deterministic>true</Deterministic>
32+
<PathMap>$(MSBuildProjectDirectory)=C:\</PathMap>
1033
</PropertyGroup>
1134

1235
<ItemGroup>

InnoInstaller.iss

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
; Script for ClipSync Installer
2+
#define MyAppName "ClipSync"
3+
#define MyAppVersion "1.0.0"
4+
#define MyAppPublisher "Samuel Aubyn"
5+
#define MyAppExeName "ClipSyncWindows.exe"
6+
7+
[Setup]
8+
; NOTE: The value of AppId uniquely identifies this application
9+
AppId={{156DCBB3-4DFE-44ED-AA91-736BABE00F9D}}
10+
AppName={#MyAppName}
11+
AppVersion={#MyAppVersion}
12+
AppPublisher={#MyAppPublisher}
13+
DefaultDirName={autopf}\{#MyAppName}
14+
UninstallDisplayIcon={app}\{#MyAppExeName}
15+
; Architecture settings
16+
ArchitecturesAllowed=x64compatible
17+
ArchitecturesInstallIn64BitMode=x64compatible
18+
; Output settings
19+
OutputDir=.
20+
OutputBaseFilename=ClipSync_Setup
21+
SetupIconFile=publish\app.ico
22+
Compression=lzma
23+
SolidCompression=yes
24+
WizardStyle=modern
25+
; Add Windows startup option
26+
DisableProgramGroupPage=yes
27+
28+
[Languages]
29+
Name: "english"; MessagesFile: "compiler:Default.isl"
30+
31+
[Tasks]
32+
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
33+
Name: "startupicon"; Description: "Start ClipSync when Windows starts"; GroupDescription: "Startup options:"; Flags: unchecked
34+
35+
[Files]
36+
; Include ALL files from the publish directory
37+
Source: "publish\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
38+
39+
[Icons]
40+
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico"
41+
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon;IconFilename: "{app}\app.ico"
42+
Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startupicon; IconFilename: "{app}\app.ico"
43+
44+
[Run]
45+
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

0 commit comments

Comments
 (0)