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
136 changes: 128 additions & 8 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Verify executable exists
shell: pwsh
run: |
$exePath = "DDCSwitch/bin/Release/net10.0/win-x64/publish/DDCSwitch.exe"
$exePath = "DDCSwitch/bin/Release/net10.0/win-x64/publish/ddcswitch.exe"
if (Test-Path $exePath) {
$size = (Get-Item $exePath).Length / 1MB
Write-Host "✓ Build successful! Executable size: $([math]::Round($size, 2)) MB"
Expand All @@ -52,7 +52,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: DDCSwitch-build-${{ github.sha }}
path: DDCSwitch/bin/Release/net10.0/win-x64/publish/DDCSwitch.exe
path: DDCSwitch/bin/Release/net10.0/win-x64/publish/ddcswitch.exe
retention-days: 7

release:
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path release
Copy-Item artifact/DDCSwitch.exe release/
Copy-Item artifact/ddcswitch.exe release/
Copy-Item README.md release/
Copy-Item LICENSE release/
Copy-Item EXAMPLES.md release/
Expand All @@ -102,7 +102,7 @@ jobs:
shell: pwsh
run: |
$version = "${{ steps.get_version.outputs.version }}"
Compress-Archive -Path release/* -DestinationPath "DDCSwitch-$version-win-x64.zip"
Compress-Archive -Path release/* -DestinationPath "ddcswitch-$version-win-x64.zip"

- name: Generate release notes
id: release_notes
Expand Down Expand Up @@ -150,20 +150,140 @@ jobs:
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.get_version.outputs.tag }}
name: DDCSwitch ${{ steps.get_version.outputs.version }}
name: ddcswitch ${{ steps.get_version.outputs.version }}
body: ${{ steps.release_notes.outputs.notes }}
draft: false
prerelease: false
files: |
DDCSwitch-${{ steps.get_version.outputs.version }}-win-x64.zip
release/DDCSwitch.exe
ddcswitch-${{ steps.get_version.outputs.version }}-win-x64.zip
release/ddcswitch.exe
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: DDCSwitch-${{ steps.get_version.outputs.version }}-win-x64
name: ddcswitch-${{ steps.get_version.outputs.version }}-win-x64
path: release/
retention-days: 30

chocolatey-package:
needs: release
runs-on: windows-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Get version from changelog
id: get_version
shell: pwsh
run: |
$changelog = Get-Content CHANGELOG.md -Raw
if ($changelog -match '\[(\d+\.\d+\.\d+)\]') {
$version = $matches[1]
echo "version=$version" >> $env:GITHUB_OUTPUT
echo "Found version: $version"
} else {
echo "Error: Could not find version in CHANGELOG.md"
exit 1
}

- name: Calculate checksum
id: checksum
shell: pwsh
run: |
$version = "${{ steps.get_version.outputs.version }}"
$url = "https://github.com/markdwags/ddcswitch/releases/download/v$version/ddcswitch-$version-win-x64.zip"
$tempFile = "$env:TEMP\ddcswitch-$version.zip"

Write-Host "Downloading ZIP from: $url"
Start-Sleep -Seconds 2 # Give GitHub a moment to make the release available

# Retry logic for download
$maxRetries = 5
$retryCount = 0
$downloaded = $false

while (-not $downloaded -and $retryCount -lt $maxRetries) {
try {
Invoke-WebRequest -Uri $url -OutFile $tempFile -ErrorAction Stop
$downloaded = $true
} catch {
$retryCount++
Write-Host "Download attempt $retryCount failed. Retrying in 10 seconds..."
Start-Sleep -Seconds 10
}
}

if (-not $downloaded) {
Write-Host "Failed to download after $maxRetries attempts"
exit 1
}

$hash = Get-FileHash $tempFile -Algorithm SHA256
$checksum = $hash.Hash
echo "checksum=$checksum" >> $env:GITHUB_OUTPUT
Write-Host "SHA256 Checksum: $checksum"
Remove-Item $tempFile

- name: Update Chocolatey files with version and checksum
shell: pwsh
run: |
$version = "${{ steps.get_version.outputs.version }}"
$checksum = "${{ steps.checksum.outputs.checksum }}"

# Update version in nuspec (Chocolatey will pass to scripts via $env:chocolateyPackageVersion)
(Get-Content chocolatey\ddcswitch.nuspec -Raw) -replace '__VERSION__', $version | Set-Content chocolatey\ddcswitch.nuspec -NoNewline

# Create CHECKSUM file for install script to read
Set-Content chocolatey\tools\CHECKSUM $checksum -NoNewline

# Update VERIFICATION.txt for moderators
(Get-Content chocolatey\tools\VERIFICATION.txt -Raw) -replace '__VERSION__', $version -replace '__CHECKSUM__', $checksum | Set-Content chocolatey\tools\VERIFICATION.txt -NoNewline

Write-Host "✓ Updated Chocolatey files"
Write-Host " Version: $version (in nuspec, passed via env to scripts)"
Write-Host " Checksum: $checksum (in CHECKSUM file)"

- name: Install Chocolatey
shell: pwsh
run: |
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
Write-Host "Installing Chocolatey..."
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
} else {
Write-Host "Chocolatey is already installed"
}

- name: Create Chocolatey package
shell: pwsh
run: |
cd chocolatey
choco pack
$version = "${{ steps.get_version.outputs.version }}"
if (Test-Path "ddcswitch.$version.nupkg") {
Write-Host "✓ Successfully created ddcswitch.$version.nupkg"
} else {
Write-Host "✗ Failed to create package"
exit 1
}

- name: Upload Chocolatey package
uses: actions/upload-artifact@v4
with:
name: chocolatey-package-${{ steps.get_version.outputs.version }}
path: chocolatey/*.nupkg
retention-days: 90

- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.get_version.outputs.version }}
files: chocolatey/*.nupkg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ artifacts/
# NuGet Packages
*.nupkg
*.snupkg
**/packages/*
**/packages/*

dist/
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Changelog

All notable changes to DDCSwitch will be documented in this file.
All notable changes to ddcswitch will be documented in this file.

## [1.0.2] - 2026-01-07

### Added
- Full support for all DDC/CI compliant monitors
- Improved error handling for unsupported monitors
- Enhanced documentation with additional examples
- Optimized performance for input switching operations
- Better clarity in CLI output messages

## [1.0.1] - 2026-01-07

Expand Down
77 changes: 77 additions & 0 deletions DDCSwitch/Commands/CommandRouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Text.Json;

namespace DDCSwitch.Commands;

internal static class CommandRouter
{
public static int Route(string[] args)
{
if (args.Length == 0)
{
HelpCommand.ShowUsage();
return 1;
}

// Check for --json flag
bool jsonOutput = args.Contains("--json", StringComparer.OrdinalIgnoreCase);
var filteredArgs = args.Where(a => !a.Equals("--json", StringComparison.OrdinalIgnoreCase)).ToArray();

// Check for --verbose flag
bool verboseOutput = filteredArgs.Contains("--verbose", StringComparer.OrdinalIgnoreCase);
filteredArgs = filteredArgs.Where(a => !a.Equals("--verbose", StringComparison.OrdinalIgnoreCase)).ToArray();



if (filteredArgs.Length == 0)
{
HelpCommand.ShowUsage();
return 1;
}

var command = filteredArgs[0].ToLowerInvariant();

try
{
return command switch
{
"list" or "ls" => ListCommand.Execute(jsonOutput, verboseOutput),
"get" => GetCommand.Execute(filteredArgs, jsonOutput),
"set" => SetCommand.Execute(filteredArgs, jsonOutput),
"version" or "-v" or "--version" => HelpCommand.ShowVersion(jsonOutput),
"help" or "-h" or "--help" or "/?" => HelpCommand.ShowUsage(),
_ => InvalidCommand(filteredArgs[0], jsonOutput)
};
}
catch (Exception ex)
{
if (jsonOutput)
{
var error = new ErrorResponse(false, ex.Message);
Console.WriteLine(JsonSerializer.Serialize(error, JsonContext.Default.ErrorResponse));
}
else
{
ConsoleOutputFormatter.WriteError(ex.Message);
}

return 1;
}
}

private static int InvalidCommand(string command, bool jsonOutput)
{
if (jsonOutput)
{
var error = new ErrorResponse(false, $"Unknown command: {command}");
Console.WriteLine(JsonSerializer.Serialize(error, JsonContext.Default.ErrorResponse));
}
else
{
ConsoleOutputFormatter.WriteError($"Unknown command: {command}");
ConsoleOutputFormatter.WriteInfo("Run ddcswitch help for usage information.");
}

return 1;
}
}

42 changes: 42 additions & 0 deletions DDCSwitch/Commands/ConsoleOutputFormatter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Spectre.Console;

namespace DDCSwitch.Commands;

internal static class ConsoleOutputFormatter
{
public static void WriteError(string message)
{
AnsiConsole.MarkupLine($"[bold red]X Error:[/] [red]{message}[/]");
}

public static void WriteInfo(string message)
{
AnsiConsole.MarkupLine($"[cyan]i[/] {message}");
}

public static void WriteSuccess(string message)
{
AnsiConsole.MarkupLine($"[bold green]> Success:[/] [green]{message}[/]");
}

public static void WriteWarning(string message)
{
AnsiConsole.MarkupLine($"[bold yellow]! Warning:[/] [yellow]{message}[/]");
}

public static void WriteHeader(string text)
{
var rule = new Rule($"[bold cyan]{text}[/]")
{
Justification = Justify.Left
};
AnsiConsole.Write(rule);
}

public static void WriteMonitorInfo(string label, string value, bool highlight = false)
{
var color = highlight ? "yellow" : "cyan";
AnsiConsole.MarkupLine($" [bold {color}]{label}:[/] {value}");
}
}

Loading