Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 42 additions & 78 deletions .github/workflows/dotnet-desktop.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,3 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# This workflow will build, test, sign and package a WPF or Windows Forms desktop application
# built on .NET Core.
# To learn how to migrate your existing application to .NET Core,
# refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework
#
# To configure this workflow:
#
# 1. Configure environment variables
# GitHub sets default environment variables for every workflow run.
# Replace the variables relative to your project in the "env" section below.
#
# 2. Signing
# Generate a signing certificate in the Windows Application
# Packaging Project or add an existing signing certificate to the project.
# Next, use PowerShell to encode the .pfx file using Base64 encoding
# by running the following Powershell script to generate the output string:
#
# $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte
# [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'
#
# Open the output file, SigningCertificate_Encoded.txt, and copy the
# string inside. Then, add the string to the repo as a GitHub secret
# and name it "Base64_Encoded_Pfx."
# For more information on how to configure your signing certificate for
# this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing
#
# Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key".
# See "Build the Windows Application Packaging project" below to see how the secret is used.
#
# For more information on GitHub Actions, refer to https://github.com/features/actions
# For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications,
# refer to https://github.com/microsoft/github-actions-for-desktop-apps

name: .NET Core Desktop

on:
Expand All @@ -44,55 +6,57 @@ on:
pull_request:
branches: [ "main" ]

jobs:
env:
Solution_Name: src/StatusLightChecker.sln
Client_Project: src/StatusLightChecker/StatusLightChecker.csproj
Service_Project: src/StatusLightChecker.Service/StatusLightChecker.Service.csproj
Installer_Project: src/StatusLightChecker.Installer/StatusLightChecker.Installer.csproj
Client_Publish_Dir: publish/client
Service_Publish_Dir: publish/service

jobs:
build:

strategy:
matrix:
configuration: [Release]

runs-on: windows-latest # For a list of available runner types, refer to
# https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on

env:
Solution_Name: src/StatusLightChecker.sln # Replace with your solution name, i.e. MyWpfApp.sln.

runs-on: windows-latest
# windows-latest has Inno Setup 6 pre-installed at
# C:\Program Files (x86)\Inno Setup 6\ISCC.exe — no extra install step needed.

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

# Install the .NET Core workload
- name: Install .NET Core
- name: Install .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v2

# Restore the application to populate the obj folder with RuntimeIdentifiers
- name: Restore the application
run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
env:
Configuration: ${{ matrix.configuration }}

- name: Publish Self-contained
run: dotnet publish $env:Solution_Name -c Release -f net8.0-windows -r win-x64 --self-contained True -o ./StatusCheckerSelfContained
env:
Configuration: ${{ matrix.configuration }}

# Create the app package by building and packaging the Windows Application Packaging project
- name: Zip the output zip file
run: |
Compress-Archive -Path ./StatusCheckerSelfContained/* -DestinationPath ./StatusCheckerSelfContained.zip

- name: Upload zip as artifact
uses: actions/upload-artifact@v3
dotnet-version: 10.0.x

- name: Restore solution
run: dotnet restore $env:Solution_Name

# Publish client and service into separate dirs — the installer csproj reads these
# via /p:ClientPublishDir and /p:ServicePublishDir overrides below.
- name: Publish client
run: >
dotnet publish $env:Client_Project
-c Release -f net10.0-windows -r win-x64 --self-contained true
-o $env:Client_Publish_Dir

- name: Publish service
run: >
dotnet publish $env:Service_Project
-c Release -f net10.0-windows -r win-x64 --self-contained true
-o $env:Service_Publish_Dir

- name: Build installer
run: >
dotnet build $env:Installer_Project
-c Release
/p:ClientPublishDir=${{ github.workspace }}\${{ env.Client_Publish_Dir }}\
/p:ServicePublishDir=${{ github.workspace }}\${{ env.Service_Publish_Dir }}\

- name: Upload installer
uses: actions/upload-artifact@v4
with:
name: StatusCheckerSelfContained
path: ./StatusCheckerSelfContained.zip
name: StatusLightCheckerSetup
path: build/bin/StatusLightChecker.Installer/Release/StatusLightCheckerSetup.exe
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
# Mono auto generated files
mono_crash.*

# Centralized build output (BaseOutputPath / BaseIntermediateOutputPath)
/build/

# Build results
[Dd]ebug/
[Dd]ebugPublic/
Expand Down Expand Up @@ -396,3 +399,4 @@ FodyWeavers.xsd

# JetBrains Rider
*.sln.iml
**/.claude
8 changes: 8 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>

<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
</PropertyGroup>

</Project>
18 changes: 18 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project>

<!-- Chain up to the repo-root Directory.Build.props for VersionPrefix -->
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />

<PropertyGroup>
<Company>Jublin.xyz</Company>
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
<FileVersion>$(VersionPrefix)</FileVersion>
</PropertyGroup>

<PropertyGroup>
<RepoRoot>$([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)../'))</RepoRoot>
<BaseIntermediateOutputPath>$(RepoRoot)build\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
<BaseOutputPath>$(RepoRoot)build\bin\$(MSBuildProjectName)\</BaseOutputPath>
</PropertyGroup>

</Project>
50 changes: 50 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup Label="FlaUI">
<PackageVersion Include="FlaUI.Core" Version="5.0.0" />
<PackageVersion Include="FlaUI.UIA3" Version="5.0.0" />
<PackageVersion Include="Tools.InnoSetup" Version="6.4.3" />
</ItemGroup>
<ItemGroup Label="gRPC">
<PackageVersion Include="Google.Protobuf" Version="3.34.1" />
<PackageVersion Include="Grpc.AspNetCore" Version="2.76.0" />
<PackageVersion Include="Grpc.AspNetCore.Server" Version="2.76.0" />
<PackageVersion Include="Grpc.Net.Client" Version="2.76.0" />
<PackageVersion Include="Grpc.Tools" Version="2.80.0" />
</ItemGroup>
<ItemGroup Label="MaterialDesign">
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageVersion Include="MaterialDesignColors" Version="5.3.1" />
<PackageVersion Include="MaterialDesignThemes" Version="5.3.1" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.142" />
</ItemGroup>
<ItemGroup Label="Microsoft.Extensions">
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.6" />
</ItemGroup>
<ItemGroup Label="Serilog">
<PackageVersion Include="Serilog" Version="4.3.1" />
<PackageVersion Include="Serilog.Extensions.Hosting" Version="10.0.0" />
<PackageVersion Include="Serilog.Extensions.Logging" Version="10.0.0" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageVersion Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
</ItemGroup>
<ItemGroup Label="System">
<PackageVersion Include="System.IO.Ports" Version="10.0.6" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.6" />
</ItemGroup>

</Project>
48 changes: 48 additions & 0 deletions src/StatusLightChecker.Contracts/Protos/settings.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
syntax = "proto3";

option csharp_namespace = "StatusLightChecker.Contracts";

package settings;

service SettingsService {
// Get current color configuration
rpc GetColorConfig (ColorConfigRequest) returns (ColorConfigResponse);

// Update color configuration
rpc UpdateColorConfig (UpdateColorConfigRequest) returns (ColorConfigResponse);

// Subscribe to color config changes
rpc StreamColorConfigUpdates (ColorConfigRequest) returns (stream ColorConfigResponse);
}

message ColorConfigRequest {
string clientId = 1;
}

message UpdateColorConfigRequest {
string clientId = 1;
ColorConfiguration config = 2;
}

message ColorConfiguration {
StatusColor available = 1;
StatusColor busy = 2;
StatusColor doNotDisturb = 3;
StatusColor away = 4;
StatusColor offline = 5;
StatusColor unknown = 6;
}

message StatusColor {
int32 statusLevel = 1;
string name = 2;
string hexColor = 3;
bool isBlinking = 4;
}

message ColorConfigResponse {
ColorConfiguration config = 1;
int64 lastUpdatedUnixMs = 2;
bool success = 3;
string errorMessage = 4;
}
51 changes: 51 additions & 0 deletions src/StatusLightChecker.Contracts/Protos/status_service.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
syntax = "proto3";

option csharp_namespace = "StatusLightChecker.Contracts";

package statusservice;

service StatusService {
// Stream status updates from service to client
rpc StreamStatusUpdates (StatusRequest) returns (stream StatusUpdate);

// Get current status immediately
rpc GetCurrentStatus (StatusRequest) returns (StatusUpdate);

// Get service health
rpc GetServiceHealth (HealthRequest) returns (HealthResponse);
}

message StatusRequest {
string clientId = 1;
}

message HealthRequest {
// Empty request
}

message StatusUpdate {
string statusId = 1;
string applicationName = 2;
string statusValue = 3;
string statusLabel = 4;
int32 statusLevel = 5; // 0=Unknown, 1=Available, 2=Busy, 3=DoNotDisturb, 4=Away, 5=Offline
string colorHex = 6;
int64 timestampUnixMs = 7;
string details = 8;
}

message HealthResponse {
ServiceState state = 1;
string version = 2;
int64 uptimeSeconds = 3;
string message = 4;
}

enum ServiceState {
UNKNOWN = 0;
RUNNING = 1;
STOPPED = 2;
PAUSED = 3;
STARTING = 4;
STOPPING = 5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Google.Protobuf" />
<PackageReference Include="Grpc.Net.Client" />
<PackageReference Include="Grpc.AspNetCore.Server" />
<PackageReference Include="Grpc.Tools">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<Protobuf Include="Protos\status_service.proto" GrpcServices="Both" />
<Protobuf Include="Protos\settings.proto" GrpcServices="Both" />
</ItemGroup>

</Project>
Loading
Loading