Document service account choices for AD-aware hooks #1

Merged
justin merged 17 commits from claude/pensive-easley-4abcbe into main 2026-05-08 10:05:12 -04:00
4 changed files with 245 additions and 0 deletions
Showing only changes of commit 9e6abeef74 - Show all commits
+27
View File
@@ -0,0 +1,27 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Restore
run: dotnet restore WebhookServer.sln
- name: Build
run: dotnet build WebhookServer.sln -c Release --no-restore
- name: Test
run: dotnet test WebhookServer.sln -c Release --no-build --verbosity normal
+71
View File
@@ -0,0 +1,71 @@
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to build (e.g. 0.1.0). Defaults to Directory.Build.props.'
required: false
jobs:
build-installer:
runs-on: windows-latest
permissions:
contents: write # needed to create releases / upload assets
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Resolve version
id: ver
shell: pwsh
run: |
if ('${{ github.event_name }}' -eq 'push') {
$v = '${{ github.ref_name }}'.TrimStart('v')
} elseif ('${{ inputs.version }}') {
$v = '${{ inputs.version }}'
} else {
[xml]$p = Get-Content Directory.Build.props
$v = $p.Project.PropertyGroup.Version
}
"version=$v" | Out-File $env:GITHUB_OUTPUT -Append
Write-Host "Building version $v"
- name: Restore + test
run: |
dotnet restore WebhookServer.sln
dotnet test WebhookServer.sln -c Release
- name: Install Inno Setup
shell: pwsh
run: |
choco install innosetup --no-progress -y
Write-Host "ISCC at: $((Get-Command iscc).Path)"
- name: Build installer
shell: pwsh
run: ./scripts/build-installer.ps1 -VersionOverride ${{ steps.ver.outputs.version }}
- name: Upload installer artifact
uses: actions/upload-artifact@v4
with:
name: WebhookServer-Setup-${{ steps.ver.outputs.version }}
path: dist/WebhookServer-Setup-*.exe
- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
name: Webhook Server ${{ steps.ver.outputs.version }}
tag_name: ${{ github.ref_name }}
draft: false
prerelease: ${{ startsWith(steps.ver.outputs.version, '0.') }}
files: dist/WebhookServer-Setup-*.exe
generate_release_notes: true
+79
View File
@@ -0,0 +1,79 @@
; Inno Setup script for Webhook Server.
;
; Build: iscc /DAppVersion=0.1.0 webhook-server.iss
; Output: ..\dist\WebhookServer-Setup-{AppVersion}.exe
;
; The installer copies published binaries to {pf}\WebhookServer, installs the
; Windows Service via install-service.ps1 post-install, and removes the service
; via uninstall-service.ps1 pre-uninstall. Start Menu gets a single GUI shortcut.
#ifndef AppVersion
#define AppVersion "0.1.0"
#endif
#define AppName "Webhook Server"
#define AppPublisher "Justin Paul"
#define AppURL "https://jpaul.me"
#define AppExeName "WebhookServer.Gui.exe"
#define ServiceExeName "WebhookServer.Service.exe"
#define ServiceName "WebhookServer"
#define RepoRoot "..\"
[Setup]
AppId={{6E3B3C1A-9C20-4F50-B6A8-2B6D6D7E2F11}
AppName={#AppName}
AppVersion={#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL=https://github.com/recklessop/webhook-server
AppUpdatesURL=https://github.com/recklessop/webhook-server/releases
DefaultDirName={autopf}\WebhookServer
DefaultGroupName={#AppName}
DisableProgramGroupPage=yes
OutputBaseFilename=WebhookServer-Setup-{#AppVersion}
OutputDir={#RepoRoot}dist
SetupIconFile={#RepoRoot}resources\webhook-server.ico
UninstallDisplayIcon={app}\{#AppExeName}
PrivilegesRequired=admin
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
Compression=lzma2/max
SolidCompression=yes
WizardStyle=modern
VersionInfoVersion={#AppVersion}.0
VersionInfoCompany={#AppPublisher}
VersionInfoProductName={#AppName}
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "Create a &desktop shortcut"; GroupDescription: "Additional shortcuts:"; Flags: unchecked
[Files]
Source: "{#RepoRoot}publish\service\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#RepoRoot}publish\gui\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#RepoRoot}scripts\install-service.ps1"; DestDir: "{app}\scripts"; Flags: ignoreversion
Source: "{#RepoRoot}scripts\uninstall-service.ps1"; DestDir: "{app}\scripts"; Flags: ignoreversion
Source: "{#RepoRoot}README.md"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#RepoRoot}resources\webhook-server.ico"; DestDir: "{app}"; Flags: ignoreversion
[Icons]
Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\webhook-server.ico"
Name: "{group}\Uninstall {#AppName}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\webhook-server.ico"; Tasks: desktopicon
[Run]
Filename: "powershell.exe"; \
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\install-service.ps1"" -BinaryPath ""{app}\{#ServiceExeName}"""; \
StatusMsg: "Installing Windows Service..."; \
Flags: runhidden
Filename: "{app}\{#AppExeName}"; \
Description: "Launch {#AppName}"; \
Flags: postinstall nowait skipifsilent
[UninstallRun]
Filename: "powershell.exe"; \
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\uninstall-service.ps1"""; \
Flags: runhidden; \
RunOnceId: "RemoveWebhookService"
+68
View File
@@ -0,0 +1,68 @@
<#
.SYNOPSIS
End-to-end installer build: publish service + GUI, then run Inno Setup
to produce dist/WebhookServer-Setup-{version}.exe.
.DESCRIPTION
Reads the version from Directory.Build.props. Requires Inno Setup 6 (ISCC.exe)
on PATH or in the standard install location. CI runs this same script after
setup-dotnet + winget install Inno Setup.
#>
[CmdletBinding()]
param(
[string]$Configuration = 'Release',
[string]$VersionOverride
)
$ErrorActionPreference = 'Stop'
$repoRoot = Split-Path -Parent $PSScriptRoot
function Get-RepoVersion {
$propsPath = Join-Path $repoRoot 'Directory.Build.props'
[xml]$props = Get-Content $propsPath
return $props.Project.PropertyGroup.Version
}
function Find-InnoCompiler {
$candidates = @(
'ISCC.exe', # on PATH
'C:\Program Files (x86)\Inno Setup 6\ISCC.exe',
'C:\Program Files\Inno Setup 6\ISCC.exe'
)
foreach ($c in $candidates) {
$cmd = Get-Command $c -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Path }
if (Test-Path $c) { return $c }
}
throw "Inno Setup compiler not found. Install with: winget install JRSoftware.InnoSetup"
}
$version = if ($VersionOverride) { $VersionOverride } else { Get-RepoVersion }
Write-Host "Building Webhook Server installer v$version" -ForegroundColor Cyan
# 1. Publish both projects.
$publishSvc = Join-Path $repoRoot 'publish\service'
$publishGui = Join-Path $repoRoot 'publish\gui'
Remove-Item -Recurse -Force $publishSvc, $publishGui -ErrorAction SilentlyContinue
& dotnet publish (Join-Path $repoRoot 'src\WebhookServer.Service\WebhookServer.Service.csproj') `
-c $Configuration -r win-x64 --self-contained false -o $publishSvc | Out-Host
if ($LASTEXITCODE -ne 0) { throw 'service publish failed' }
& dotnet publish (Join-Path $repoRoot 'src\WebhookServer.Gui\WebhookServer.Gui.csproj') `
-c $Configuration -r win-x64 --self-contained false -o $publishGui | Out-Host
if ($LASTEXITCODE -ne 0) { throw 'GUI publish failed' }
# 2. Compile installer.
$iscc = Find-InnoCompiler
$iss = Join-Path $repoRoot 'installer\webhook-server.iss'
$dist = Join-Path $repoRoot 'dist'
New-Item -ItemType Directory -Path $dist -Force | Out-Null
Write-Host "Compiling installer with $iscc"
& $iscc "/DAppVersion=$version" $iss
if ($LASTEXITCODE -ne 0) { throw 'Inno Setup compile failed' }
$out = Get-Item (Join-Path $dist "WebhookServer-Setup-$version.exe")
Write-Host ""
Write-Host ("Built: {0} ({1:n0} bytes)" -f $out.FullName, $out.Length) -ForegroundColor Green