Skip to content

Add comprehensive CI/CD: GitHub Actions for ghcr.io builds, release script, and Windows installer #9

@bryanchriswhite

Description

@bryanchriswhite

Summary

Implement a comprehensive CI/CD pipeline using GitHub Actions that includes:

  1. Automated Docker image builds and push to ghcr.io for all components
  2. A release script for semantic versioning with GPG-signed tags
  3. Windows installer build and release asset attachment

Background

Currently, CI/CD is minimal:

  • main.yml - Manual trigger only, builds backend image
  • oauth-broker.yml - Automated on main branch push, but no version tagging

Missing capabilities:

  • No automated builds for pinshare-ui Docker image
  • No semantic versioning or release automation
  • No Windows installer builds
  • No multi-architecture support (arm64)
  • No automated testing in CI

Deliverables

1. Enhanced GitHub Actions Workflows

A. build-backend.yml - Backend Docker Image Build

Triggers:

  • Push to main branch (paths: *.go, go.*, internal/**, Dockerfile)
  • Release published (for version-tagged images)
  • Manual workflow_dispatch

Features:

  • Multi-platform builds: linux/amd64, linux/arm64
  • Push to ghcr.io/episk-pos/pinshare-backend
  • Tags: latest (main), sha-<commit>, v<version> (releases)
  • Build cache for faster iterations
  • Build args for version injection

Example tags produced:

ghcr.io/episk-pos/pinshare-backend:latest
ghcr.io/episk-pos/pinshare-backend:main-abc1234
ghcr.io/episk-pos/pinshare-backend:v1.0.0

B. build-ui.yml - Frontend Docker Image Build

Triggers:

  • Push to main branch (paths: pinshare-ui/**)
  • Release published
  • Manual workflow_dispatch

Features:

  • Multi-stage Dockerfile (dev → builder → production nginx)
  • Push to ghcr.io/episk-pos/pinshare-ui
  • Same tagging strategy as backend
  • Artifact upload of dist/ folder for release assets

C. build-oauth.yml - OAuth Broker Build (enhance existing)

Enhancements:

  • Add multi-platform support (linux/amd64, linux/arm64)
  • Add version tagging on releases
  • Update action versions to latest

D. release.yml - Release Build Workflow

Triggers:

  • Release published on GitHub

Jobs:

  1. build-binaries - Cross-platform Go binaries

    • Matrix: linux/amd64, linux/arm64, windows/amd64, darwin/amd64, darwin/arm64
    • Outputs: pinshare-linux-amd64, pinshare-linux-arm64, pinshare-windows-amd64.exe, pinshare-darwin-amd64, pinshare-darwin-arm64
    • Upload as release assets
  2. build-windows-installer - Windows NSIS Installer

    • Build Windows binary
    • Package with NSIS (or WiX for MSI)
    • Include: executable, default config, README
    • Output: PinShare-Setup-v<version>.exe
    • Upload to release assets
  3. build-docker-images - Build and push all Docker images with version tags

    • Backend, UI, OAuth broker
    • Tag with release version

E. test.yml - Automated Testing

Triggers:

  • Pull requests to any branch
  • Push to main

Jobs:

  1. go-tests - Backend unit tests

    • go test ./...
    • Coverage report
  2. ui-tests - Frontend tests

    • npm run lint
    • Playwright E2E tests (optional, browser matrix)
  3. integration-tests - Docker compose integration tests

    • Spin up services with docker-compose
    • Run API smoke tests

2. Release Script (scripts/release.sh)

Adapt the lenr.academy release script for PinShare:

Features:

  • Semantic versioning: patch, minor, major, prerelease
  • Prerelease identifiers: alpha, beta, rc
  • GPG-signed annotated tags (required)
  • Clean working directory check
  • Branch validation (warn if not on main)
  • Version source of truth: git tags
  • Automatic GitHub pre-release creation
  • Version bump in relevant files (go.mod annotation, package.json in UI)

Usage:

./scripts/release.sh patch                    # 0.0.1 → 0.0.2
./scripts/release.sh minor                    # 0.0.1 → 0.1.0
./scripts/release.sh major                    # 0.0.1 → 1.0.0
./scripts/release.sh prerelease               # 0.0.1 → 0.0.2-alpha.0
./scripts/release.sh prerelease beta          # 0.0.1 → 0.0.2-beta.0

Release Flow:

Developer runs ./scripts/release.sh patch
        ↓
Script validates clean working directory
        ↓
Bumps version, creates GPG-signed tag
        ↓
Pushes to GitHub, creates pre-release
        ↓
GitHub Actions triggered (release.yml)
        ├─→ Build all binaries (Linux, Windows, macOS)
        ├─→ Build Windows installer
        ├─→ Build Docker images with version tags
        └─→ Attach all artifacts to release
        ↓
Manual QA on pre-release
        ↓
Uncheck "pre-release" to promote to stable

3. Windows Installer Build

Technology Options:

  1. NSIS (Nullsoft Scriptable Install System) - Recommended

    • Free, well-documented
    • Creates .exe installer
    • Supports custom install paths, shortcuts, uninstaller
    • GitHub Action: joncloud/makensis-action
  2. WiX Toolset - Alternative

    • Creates .msi installer
    • More complex but enterprise-friendly
    • GitHub Action: coderpatros/wix-toolset-action

Installer Contents:

  • pinshare.exe - Main executable
  • config.example.yaml - Example configuration
  • README.txt - Quick start guide
  • Start menu shortcuts
  • Uninstaller

NSIS Script Structure (scripts/installer.nsi):

!include "MUI2.nsh"

Name "PinShare"
OutFile "PinShare-Setup-${VERSION}.exe"
InstallDir "$PROGRAMFILES\PinShare"

Section "Install"
    SetOutPath $INSTDIR
    File "pinshare.exe"
    File "config.example.yaml"
    File "README.txt"
    
    CreateDirectory "$SMPROGRAMS\PinShare"
    CreateShortcut "$SMPROGRAMS\PinShare\PinShare.lnk" "$INSTDIR\pinshare.exe"
    CreateShortcut "$SMPROGRAMS\PinShare\Uninstall.lnk" "$INSTDIR\uninstall.exe"
    
    WriteUninstaller "$INSTDIR\uninstall.exe"
SectionEnd

Section "Uninstall"
    Delete "$INSTDIR\*.*"
    RMDir "$INSTDIR"
    Delete "$SMPROGRAMS\PinShare\*.*"
    RMDir "$SMPROGRAMS\PinShare"
SectionEnd

Implementation Tasks

Phase 1: Core CI/CD

  • Create build-backend.yml workflow with multi-arch support
  • Create build-ui.yml workflow
  • Enhance oauth-broker.yml with version tagging
  • Create test.yml for automated testing

Phase 2: Release Automation

  • Create scripts/release.sh adapted from lenr.academy
  • Create release.yml workflow for release builds
  • Add version injection to Go builds (ldflags)
  • Document release process in RELEASE.md

Phase 3: Windows Installer

  • Create NSIS installer script (scripts/installer.nsi)
  • Add Windows installer job to release.yml
  • Test installer on Windows
  • Sign installer (optional, requires code signing cert)

Phase 4: Documentation & Polish

  • Create DEPLOYMENT.md documenting CI/CD pipeline
  • Add badges to README (build status, latest release)
  • Create CONTRIBUTING.md with release guidelines

Required GitHub Secrets

Secret Purpose
GITHUB_TOKEN Auto-provided, used for ghcr.io and releases

Note: GITHUB_TOKEN is automatically available and has permissions for ghcr.io pushes within the same organization.

Optional secrets for enhanced features:

Secret Purpose
CODE_SIGNING_CERT Windows installer code signing (optional)
CODE_SIGNING_PASSWORD Certificate password (optional)

Workflow Permissions Required

Add to each workflow:

permissions:
  contents: write      # For release asset uploads
  packages: write      # For ghcr.io pushes
  actions: read        # For workflow status

Acceptance Criteria

  • Pushing to main triggers automated Docker builds for all components
  • Docker images are properly tagged with branch, SHA, and version
  • release.sh script creates semantic version tags with GPG signing
  • Publishing a release triggers binary builds for all platforms
  • Windows installer is automatically built and attached to releases
  • All workflows have proper caching for faster builds
  • Documentation exists for the release process

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions