Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
7ccbe4d
Add comprehensive Windows service wrapper implementation
claude Nov 19, 2025
6417a03
Fix critical Windows service security issues and add testing infrastr…
bryanchriswhite Nov 22, 2025
82651f0
Migrate installer from WiX 3 to WiX 6
claude Nov 24, 2025
278ad2f
Add quick start guide for WiX 6 installer
claude Nov 24, 2025
0841bce
Add Windows build scripts that don't require make
claude Nov 24, 2025
e98c24b
Fix critical Windows service security issues and add testing infrastr…
claude Nov 24, 2025
4a9cbdb
Add build output directories to .gitignore
claude Nov 24, 2025
c0d9959
Temporarily disable UI components in WiX installer
claude Nov 24, 2025
07b0b0e
Remove UI directory check from WiX 6 build script
claude Nov 25, 2025
092dc46
Add error checking to installer build in build-windows.bat
claude Nov 25, 2025
869dcdb
Fix WiX 4 syntax errors in Package.wxs
claude Nov 25, 2025
0efdf6d
Remove obsolete Product.wxs (WiX 3 format) - using Package.wxs (WiX 6…
claude Nov 25, 2025
6b842e4
Fix WiX 4 syntax errors in Package.wxs
claude Nov 25, 2025
6f81867
Temporarily disable WixToolset.UI.wixext extension to fix multiple en…
claude Nov 25, 2025
7ee7918
Remove all WiX extensions and unused util namespace to fix multiple e…
claude Nov 25, 2025
a560f73
Remove explicit Compile include - WiX 6 SDK auto-globs .wxs files
claude Nov 25, 2025
0a4ece8
Temporarily disable icon references - icon.ico file not yet created
claude Nov 25, 2025
49c8580
Comment out URL shortcut - users will access UI via system tray app
claude Nov 25, 2025
dac85e9
Fix chromedp deadlock by setting dummy VT_TOKEN when SkipVirusTotal i…
claude Nov 25, 2025
cd9f454
Fix Windows service startup failures: PATH, config loading, and FFSki…
claude Nov 26, 2025
e9a4a90
Add /api/health endpoint and increase PinShare startup timeout
claude Nov 26, 2025
7595274
Fix build-windows.bat path handling for installer directory
claude Nov 26, 2025
fdb9cfb
Add Windows architecture docs and fix system tray icon
claude Nov 26, 2025
33d2b5c
Fix WiX 6 installer build: add ConfigDialog and enable WixUI extension
claude Nov 27, 2025
9af36e8
Revert installer to working state: remove ConfigDialog, disable WixUI
claude Nov 27, 2025
43bc78f
Fix build-windows.bat to skip UI build gracefully when pinshare-ui mi…
claude Nov 27, 2025
2f628d2
Restore installer config wizard and add version support
claude Nov 27, 2025
e392925
Fix version detection to require proper semver tags
claude Nov 27, 2025
c87a790
Add TextStyle definitions to ConfigDialog.wxs
claude Nov 27, 2025
58ff694
Fix TextStyle conflicts and add Upload Directory field
claude Nov 27, 2025
4316a44
Use literal path for UPLOAD_DIR default for better UX
claude Nov 27, 2025
fbda8c5
Improve tray app: add Windows message boxes and better status handling
claude Nov 27, 2025
525bcaa
Remove unused fmt import from pinshare-tray/main.go
claude Nov 27, 2025
e9779d6
Improve tray status error handling and show actual error in tooltip
claude Nov 27, 2025
f26d7eb
Add GPLv3 license to installer and improve service robustness
Nov 28, 2025
21116a3
Improve tray app and service process management
Nov 28, 2025
25fb126
chore: update tray
Dec 3, 2025
658d058
revert: PR description
Dec 3, 2025
c88934f
Revert "revert: PR description"
Dec 3, 2025
fdeedce
wip: settings dialog
bryanchriswhite Dec 3, 2025
b95ba72
Improve tray settings and service management
Dec 3, 2025
3a01373
chore: self-review feedback improvements
Dec 3, 2025
1cf4252
chore: address PR #3 review feedback
Dec 4, 2025
81a5701
docs: address additional PR #3 review feedback
Dec 4, 2025
63da675
docs: remove remaining UI references from BUILD.md
Dec 5, 2025
6624921
fix: address remaining PR #3 issues
Dec 6, 2025
f233402
feat: add cross-platform build scripts
Dec 6, 2025
bd05b56
refactor: address PR #3 feedback - code quality improvements
Dec 6, 2025
c85586e
chore: remove unused dependencies from go.mod
Dec 6, 2025
5f07758
chore: update Makefile.windows to remove UI/SQLite references
Dec 6, 2025
42a2b64
fix: check for package.json instead of directory in build-windows.sh
bryanchriswhite Dec 6, 2025
cfdad47
refactor: address PR #3 review feedback - cleanup and consistency
bryanchriswhite Dec 6, 2025
23601ea
refactor: add shared winservice constants package
bryanchriswhite Dec 17, 2025
0f1fe32
build: remove CGO dependency from Windows builds
bryanchriswhite Dec 17, 2025
d365f20
docs: update Windows documentation per PR review
bryanchriswhite Dec 17, 2025
821e290
chore: remove legacy WiX 3.x installer script
bryanchriswhite Dec 17, 2025
4cf0c41
fix: import errors and typos
Dec 20, 2025
bfd4779
docs: address PR #3 review feedback - documentation updates
Dec 12, 2025
e074dd3
refactor: consolidate constants into winservice package
Dec 12, 2025
5af38dc
refactor: extract updateStatus cases to methods, fix path separator
Dec 12, 2025
5d1fb8d
fix: resolve Windows build issues with IPFS download and .NET SDK det…
bryanchriswhite Dec 20, 2025
42f929f
fix: windows 11 start after install
bryanchriswhite Dec 20, 2025
5e1f5dd
refactor: address PR #3 review feedback - round 2
bryanchriswhite Dec 22, 2025
3224409
Merge fork/feat/windows-installer into feat/windows-installer
bryanchriswhite Dec 22, 2025
bfe06df
Merge origin/v0.1.3_g4f into feat/windows-installer
bryanchriswhite Dec 22, 2025
5555cd8
fix: svc restart escalation
bryanchriswhite Dec 22, 2025
9117be6
feat: native Walk settings dialog with proper service restart
bryanchriswhite Dec 23, 2025
354d4d0
fix: use PORT env var for PinShare API port configuration
bryanchriswhite Dec 24, 2025
e10968e
fix: IPFS port configuration sync and View Logs path
bryanchriswhite Dec 24, 2025
f4a455f
chore: cleanup
bryanchriswhite Dec 24, 2025
858da0b
refactor: address PR review comments for code quality
claude Dec 25, 2025
b47cdfe
refactor: address additional PR #3 review comments
bryanchriswhite Dec 26, 2025
fcc0b16
revertme: temporarily run windows installer build action in this PR
bryanchriswhite Dec 26, 2025
190df4d
refactor: address PR #3 review feedback - types and constants
bryanchriswhite Dec 30, 2025
c139f86
Delete PR3_REVIEW_COMMENTS.md
bryanchriswhite Dec 30, 2025
84b725b
feat(tray): add confirmation dialog on exit
bryanchriswhite Jan 2, 2026
10bfe65
refactor: address remaining PR #3 review feedback
bryanchriswhite Jan 2, 2026
ddf6a64
refactor: use Cobra CLI framework for pinsharesvc and remove walk naming
bryanchriswhite Jan 2, 2026
8f342a6
style: prefer new() over composite literal for zero-value struct
bryanchriswhite Jan 2, 2026
b4f2906
refactor: decompose settings dialog into factory functions
bryanchriswhite Jan 2, 2026
1b7458a
refactor: consolidate magic strings into constants.go
bryanchriswhite Jan 2, 2026
870f2e9
refactor: use appName constant in process.go
bryanchriswhite Jan 2, 2026
7b422bb
fix: correct issue 10 URLs to point to origin repo (Episk-pos)
bryanchriswhite Jan 2, 2026
f38e928
refactor: consolidate shared constants into internal/winservice
bryanchriswhite Jan 2, 2026
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
139 changes: 139 additions & 0 deletions .github/workflows/windows-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
name: Build Windows Installer

on:
# TEMP: Enable PR trigger so this workflow runs in the PR that introduces it.
# TODO_IN_THIS_PR(@bryanchriswhite): Remove before merging to avoid running on every PR.
pull_request:

push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to build (e.g., 1.2.3)'
required: false
default: ''

env:
GO_VERSION: '1.21'
DOTNET_VERSION: '8.0'

jobs:
build-windows:
runs-on: windows-latest
permissions:
contents: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for git describe

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}

- name: Set up .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Install WiX Toolset
run: dotnet tool install --global wix

- name: Determine version
id: version
shell: pwsh
run: |
if ("${{ github.event.inputs.version }}" -ne "") {
$version = "${{ github.event.inputs.version }}"
} elseif ("${{ github.ref_type }}" -eq "tag") {
$version = "${{ github.ref_name }}" -replace '^v', ''
} else {
$desc = git describe --tags --always 2>$null
if ($desc) {
$version = $desc -replace '^v', ''
# Convert v1.0.0-5-gabcdef to 1.0.0.5
if ($version -match '^(\d+\.\d+\.\d+)-(\d+)-') {
$version = "$($matches[1]).$($matches[2])"
}
} else {
$version = "0.0.0"
}
}
echo "VERSION=$version" >> $env:GITHUB_OUTPUT
echo "Building version: $version"

- name: Create dist directory
run: New-Item -ItemType Directory -Force -Path dist\windows

- name: Build PinShare backend
env:
CGO_ENABLED: 0
GOOS: windows
GOARCH: amd64
run: |
go build -ldflags "-s -w -X main.Version=${{ steps.version.outputs.VERSION }}" -o dist\windows\pinshare.exe .
echo "Built pinshare.exe"

- name: Build Windows service wrapper
env:
CGO_ENABLED: 0
GOOS: windows
GOARCH: amd64
run: |
go build -ldflags "-s -w -X main.Version=${{ steps.version.outputs.VERSION }}" -o dist\windows\pinsharesvc.exe .\cmd\pinsharesvc
echo "Built pinsharesvc.exe"

- name: Build system tray application
env:
CGO_ENABLED: 0
GOOS: windows
GOARCH: amd64
run: |
go build -ldflags "-s -w -H windowsgui -X main.Version=${{ steps.version.outputs.VERSION }}" -o dist\windows\pinshare-tray.exe .\cmd\pinshare-tray
echo "Built pinshare-tray.exe"

- name: Download IPFS Kubo
shell: pwsh
run: |
$kuboVersion = "v0.31.0"
$url = "https://dist.ipfs.tech/kubo/$kuboVersion/kubo_${kuboVersion}_windows-amd64.zip"
Invoke-WebRequest -Uri $url -OutFile kubo.zip
Expand-Archive -Path kubo.zip -DestinationPath kubo-temp -Force
Copy-Item kubo-temp\kubo\ipfs.exe dist\windows\ipfs.exe
Remove-Item kubo.zip
Remove-Item kubo-temp -Recurse
echo "Downloaded IPFS Kubo $kuboVersion"

- name: List built binaries
run: Get-ChildItem -Path dist\windows\*.exe | Format-Table Name, Length

- name: Build MSI installer
working-directory: installer
run: |
dotnet build PinShare.wixproj -c Release -p:ProductVersion=${{ steps.version.outputs.VERSION }}
echo "Built MSI installer"

- name: Rename installer with version
shell: pwsh
run: |
$version = "${{ steps.version.outputs.VERSION }}"
Copy-Item "installer\bin\Release\PinShare-Setup.msi" "installer\bin\Release\PinShare-$version-Setup.msi"

- name: Upload MSI artifact
uses: actions/upload-artifact@v4
with:
name: PinShare-${{ steps.version.outputs.VERSION }}-Setup
path: installer/bin/Release/PinShare-${{ steps.version.outputs.VERSION }}-Setup.msi

- name: Upload to Release
if: github.ref_type == 'tag'
uses: softprops/action-gh-release@v1
with:
files: |
installer/bin/Release/PinShare-${{ steps.version.outputs.VERSION }}-Setup.msi
fail_on_unmatched_files: true
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,21 @@ pinshare
*/test/node*
/test/node*

# Build outputs
dist/
bin/
*.msi

# WiX installer build artifacts
installer/bin/
installer/obj/
installer/nul
*.wixpdb
*.log

# Node.js
node_modules/
package-lock.json

# Claude Code
.claude/
207 changes: 207 additions & 0 deletions Makefile.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
# Makefile for building PinShare Windows distribution
# This Makefile is cross-platform: it can be run from Linux/macOS (with cross-compilation)
# or from Windows (using Git Bash or similar POSIX shell)

.PHONY: all clean windows-backend windows-service windows-tray copy-resources download-ipfs windows-all installer help check-deps install-deps dev-service dev-tray test-windows check-platform

# Platform detection
UNAME_S := $(shell uname -s 2>/dev/null || echo Windows)

# Platform check target - prints info about the current platform
check-platform:
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
@echo "Platform: Windows (Git Bash/MinGW)"
else ifeq ($(findstring MSYS,$(UNAME_S)),MSYS)
@echo "Platform: Windows (MSYS)"
else ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN)
@echo "Platform: Windows (Cygwin)"
else ifeq ($(UNAME_S),Linux)
@echo "Platform: Linux (cross-compiling for Windows)"
else ifeq ($(UNAME_S),Darwin)
@echo "Platform: macOS (cross-compiling for Windows)"
else
@echo "Platform: Unknown ($(UNAME_S))"
endif

# Configuration
GOOS := windows
GOARCH := amd64
CGO_ENABLED := 0

# Directories
DIST_DIR := dist/windows
INSTALLER_DIR := installer

# IPFS version
IPFS_VERSION := v0.31.0
IPFS_ARCHIVE := kubo_$(IPFS_VERSION)_windows-amd64.zip
IPFS_URL := https://dist.ipfs.tech/kubo/$(IPFS_VERSION)/$(IPFS_ARCHIVE)

# Build flags
LDFLAGS := -s -w
BUILD_DATE := $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
VERSION := 1.0.0

# All targets
all: help

help:
@echo "PinShare Windows Build System"
@echo "============================="
@echo ""
@echo "Available targets:"
@echo " windows-all Build all Windows components"
@echo " windows-backend Build PinShare backend for Windows"
@echo " windows-service Build Windows service wrapper"
@echo " windows-tray Build Windows system tray application"
@echo " download-ipfs Download IPFS Kubo binary for Windows"
@echo " installer Build Windows MSI installer (requires WiX)"
@echo " check-deps Check build dependencies"
@echo " clean Clean build artifacts"
@echo ""
@echo "Example: make -f Makefile.windows windows-all"
@echo ""

# Create distribution directory
$(DIST_DIR):
@echo "Creating distribution directory..."
@mkdir -p $(DIST_DIR)

# Build PinShare backend for Windows
windows-backend: $(DIST_DIR)
@echo "Building PinShare backend for Windows..."
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) \
go build -ldflags "$(LDFLAGS) -X main.Version=$(VERSION) -X main.GitCommit=$(GIT_COMMIT) -X main.BuildDate=$(BUILD_DATE)" \
-o $(DIST_DIR)/pinshare.exe .
@echo "✓ Built: $(DIST_DIR)/pinshare.exe"

# Build Windows service wrapper
windows-service: $(DIST_DIR)
@echo "Building Windows service wrapper..."
GOOS=$(GOOS) GOARCH=$(GOARCH) \
go build -ldflags "$(LDFLAGS)" \
-o $(DIST_DIR)/pinsharesvc.exe ./cmd/pinsharesvc
@echo "✓ Built: $(DIST_DIR)/pinsharesvc.exe"

# Build Windows system tray application
windows-tray: $(DIST_DIR)
@echo "Building Windows system tray application..."
@echo "Generating resource file from manifest..."
@cd cmd/pinshare-tray && go run github.com/akavel/rsrc@latest -manifest pinshare-tray.manifest -o rsrc.syso 2>/dev/null || true
GOOS=$(GOOS) GOARCH=$(GOARCH) \
go build -ldflags "$(LDFLAGS) -H windowsgui" \
-o $(DIST_DIR)/pinshare-tray.exe ./cmd/pinshare-tray
@echo "✓ Built: $(DIST_DIR)/pinshare-tray.exe"

# Download IPFS Kubo binary
download-ipfs: $(DIST_DIR)
@echo "Downloading IPFS Kubo $(IPFS_VERSION) for Windows..."
@if [ ! -f "$(DIST_DIR)/ipfs.exe" ]; then \
echo "Fetching from $(IPFS_URL)..."; \
curl -L -o /tmp/$(IPFS_ARCHIVE) $(IPFS_URL); \
unzip -j /tmp/$(IPFS_ARCHIVE) "kubo/ipfs.exe" -d $(DIST_DIR)/; \
rm /tmp/$(IPFS_ARCHIVE); \
echo "✓ Downloaded: $(DIST_DIR)/ipfs.exe"; \
else \
echo "✓ IPFS already downloaded: $(DIST_DIR)/ipfs.exe"; \
fi

# Copy tray resources
copy-resources: $(DIST_DIR)
@echo "Copying tray application resources..."
@mkdir -p $(DIST_DIR)/resources
@cp -r cmd/pinshare-tray/resources/* $(DIST_DIR)/resources/ 2>/dev/null || true
@echo "✓ Copied: $(DIST_DIR)/resources/"

# Build all Windows components
windows-all: windows-backend windows-service windows-tray copy-resources download-ipfs
@echo ""
@echo "=========================================="
@echo "All Windows components built successfully!"
@echo "=========================================="
@echo ""
@echo "Distribution files:"
@ls -lh $(DIST_DIR)/*.exe
@echo ""
@echo "Next step: Build installer with 'make -f Makefile.windows installer'"
@echo ""

# Build Windows MSI installer (requires WiX 6 via .NET tool)
installer: windows-all
@echo "Building Windows installer..."
@if command -v wix >/dev/null 2>&1 || command -v wix.exe >/dev/null 2>&1; then \
echo "WiX 6 detected, building MSI..."; \
cd $(INSTALLER_DIR) && cmd.exe //c build-wix6.bat; \
elif command -v dotnet >/dev/null 2>&1 || command -v dotnet.exe >/dev/null 2>&1; then \
echo ".NET detected, WiX will be installed if needed..."; \
cd $(INSTALLER_DIR) && cmd.exe //c build-wix6.bat; \
else \
echo ""; \
echo "ERROR: .NET SDK not found!"; \
echo ""; \
echo "To build the installer:"; \
echo "1. Install .NET SDK 6+ from https://dotnet.microsoft.com/download"; \
echo "2. WiX 6 will be installed automatically via: dotnet tool install --global wix"; \
echo "3. On Windows, run: cd installer && build-wix6.bat"; \
echo ""; \
exit 1; \
fi

# Clean build artifacts
clean:
@echo "Cleaning build artifacts..."
@rm -rf $(DIST_DIR)
@rm -rf $(INSTALLER_DIR)/bin
@rm -rf $(INSTALLER_DIR)/obj
@rm -f $(INSTALLER_DIR)/*.wixobj
@rm -f $(INSTALLER_DIR)/*.wixpdb
@rm -f dist/PinShare-Setup.msi
@echo "✓ Cleaned"

# Test Windows binaries (requires Wine on Linux)
test-windows: windows-all
@echo "Testing Windows binaries..."
@if command -v wine64 >/dev/null 2>&1; then \
echo "Testing with Wine..."; \
wine64 $(DIST_DIR)/pinsharesvc.exe 2>&1 | head -5; \
else \
echo "Wine not found, skipping tests"; \
echo "To test on Linux, install Wine: sudo apt-get install wine64"; \
fi

# Development: Build service only (faster iteration)
dev-service: windows-service
@echo "Development build complete: $(DIST_DIR)/pinsharesvc.exe"

# Development: Build tray only (faster iteration)
dev-tray: windows-tray
@echo "Development build complete: $(DIST_DIR)/pinshare-tray.exe"

# Check dependencies
check-deps:
@echo "Checking build dependencies..."
@echo ""
@echo "Go version:"
@go version || echo "ERROR: Go not found"
@echo ""
@echo "Build tools:"
@which unzip >/dev/null 2>&1 && echo "✓ unzip found" || echo "⚠ unzip not found"
@which curl >/dev/null 2>&1 && echo "✓ curl found" || echo "⚠ curl not found"
@echo ""

# Install build dependencies (Linux only)
install-deps:
@echo "Installing build dependencies for Windows cross-compilation..."
@if [ "$(shell uname -s)" = "Linux" ]; then \
echo "Detected Linux, installing packages..."; \
sudo apt-get update; \
sudo apt-get install -y gcc-mingw-w64-x86-64 wine64 unzip curl; \
echo "✓ Dependencies installed"; \
else \
echo "This target is for Linux only"; \
echo "On Windows, install:"; \
echo " - Go: https://golang.org/dl/"; \
echo " - Git (includes Git Bash): https://git-scm.com/"; \
echo " - WiX Toolset (for installer): https://wixtoolset.org/"; \
fi
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ The service exposes a RESTful API for management and queries. The API is defined
- **API Specification**: See `docs/spec/basemetadata.openapi.spec.yaml` for the full contract.
- The API server starts automatically when you run the main application.

## Windows Installation

PinShare includes a native Windows service with system tray integration for easy management.

### Quick Start

Download and run `PinShare-Setup.msi` from the [releases page](https://github.com/Cypherpunk-Labs/PinShare/releases).

### Documentation

- **[Quick Start Guide](docs/windows/QUICKSTART.md)** - Get up and running quickly
- **[Installation & Usage](docs/windows/README.md)** - Complete Windows installation guide
- **[Windows Service](docs/windows/SERVICE.md)** - Service wrapper architecture and management
- **[Building from Source](docs/windows/BUILD.md)** - Build Windows binaries and installer
- **[Testing Guide](docs/windows/TESTING.md)** - Testing procedures for Windows

## Security Considerations

The integration with VirusTotal currently relies on **web scraping** using `chromedp`. This approach is inherently fragile and may break if VirusTotal changes its website's HTML structure or selectors. This is a known risk and a more robust API-based integration is a future goal.
Loading
Loading