diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 09200a181..6d7b4aac2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,15 @@ on: push: tags: ['v*'] workflow_dispatch: + inputs: + version: + description: "Version string for package names (e.g. 0.2.0). Blank = derive from ref." + required: false + default: "" + coins: + description: "JSON array of coins to build (e.g. [\"ltc\"]). Blank = all five." + required: false + default: "" concurrency: group: release-${{ github.ref }} @@ -50,14 +59,16 @@ jobs: strategy: fail-fast: false matrix: - coin: [btc, ltc, dgb, dash, bch] + coin: ${{ fromJSON(github.event.inputs.coins || '["btc","ltc","dgb","dash","bch"]') }} steps: - uses: actions/checkout@v6 - name: Resolve version id: ver run: | - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + if [ -n "${{ github.event.inputs.version }}" ]; then + echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT" + elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" else echo "version=0.0.0-${GITHUB_SHA:0:8}" >> "$GITHUB_OUTPUT" @@ -178,7 +189,7 @@ jobs: strategy: fail-fast: false matrix: - coin: [btc, ltc, dgb, dash, bch] + coin: ${{ fromJSON(github.event.inputs.coins || '["btc","ltc","dgb","dash","bch"]') }} arch: [arm64, x86_64] include: - arch: arm64 @@ -191,7 +202,9 @@ jobs: - name: Resolve version id: ver run: | - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + if [ -n "${{ github.event.inputs.version }}" ]; then + echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT" + elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" else echo "version=0.0.0-${GITHUB_SHA:0:8}" >> "$GITHUB_OUTPUT" @@ -291,14 +304,16 @@ jobs: strategy: fail-fast: false matrix: - coin: [btc, ltc, dgb, dash, bch] + coin: ${{ fromJSON(github.event.inputs.coins || '["btc","ltc","dgb","dash","bch"]') }} steps: - uses: actions/checkout@v6 - name: Resolve version id: ver run: | - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + if [ -n "${{ github.event.inputs.version }}" ]; then + echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT" + elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" else echo "version=0.0.0-${GITHUB_SHA:0:8}" >> "$GITHUB_OUTPUT" @@ -366,6 +381,24 @@ jobs: name: pkg-macos-${{ matrix.coin }} path: c2pool-*-macos-universal.zip + - name: Build DMG installer + if: steps.presence.outputs.exists == '1' + run: | + VERSION="${{ steps.ver.outputs.version }}" + COIN="${{ matrix.coin }}" + bash installer/macos/create-dmg.sh \ + --staged "c2pool-${COIN}-${VERSION}-macos-universal" \ + --name "c2pool-${COIN}" \ + --version "${VERSION}" \ + --arch universal + + - name: Upload DMG installer + if: steps.presence.outputs.exists == '1' + uses: actions/upload-artifact@v7 + with: + name: pkg-macos-dmg-${{ matrix.coin }} + path: c2pool-*-macos-universal.dmg + # ════════════════════════════════════════════════════════════════════════════ # Windows x86_64 (MSVC 2022, Conan) # ════════════════════════════════════════════════════════════════════════════ @@ -375,7 +408,7 @@ jobs: strategy: fail-fast: false matrix: - coin: [btc, ltc, dgb, dash, bch] + coin: ${{ fromJSON(github.event.inputs.coins || '["btc","ltc","dgb","dash","bch"]') }} steps: - uses: actions/checkout@v6 @@ -383,7 +416,9 @@ jobs: id: ver shell: bash run: | - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + if [ -n "${{ github.event.inputs.version }}" ]; then + echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT" + elif [[ "${GITHUB_REF}" == refs/tags/v* ]]; then echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" else echo "version=0.0.0-${GITHUB_SHA:0:8}" >> "$GITHUB_OUTPUT" @@ -482,6 +517,29 @@ jobs: name: pkg-windows-${{ matrix.coin }} path: c2pool-*-windows-x86_64.zip + - name: Build setup.exe installer (Inno Setup) + if: steps.presence.outputs.exists == '1' + shell: cmd + run: | + choco install innosetup -y --no-progress + set "PKG=c2pool-${{ matrix.coin }}-${{ steps.ver.outputs.version }}-windows-x86_64" + for /f "delims=" %%i in ('powershell -NoProfile -Command "(Get-ChildItem -Path 'C:\Program Files\Microsoft Visual Studio\2022' -Recurse -Filter vc_redist.x64.exe -ErrorAction SilentlyContinue | Select-Object -First 1).FullName"') do set "VCREDIST=%%i" + "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" installer\windows\c2pool-setup.iss ^ + /DPACKAGE_DIR="%CD%\%PKG%" ^ + /DVCREDIST_PATH="%VCREDIST%" ^ + /DMyAppName=c2pool-${{ matrix.coin }} ^ + /DMyAppVersion=${{ steps.ver.outputs.version }} ^ + /DMyAppExeName=c2pool-${{ matrix.coin }}.exe ^ + /DOutputBase=%PKG%-setup + copy "installer\windows\Output\%PKG%-setup.exe" . + + - name: Upload setup.exe installer + if: steps.presence.outputs.exists == '1' + uses: actions/upload-artifact@v7 + with: + name: pkg-windows-setup-${{ matrix.coin }} + path: c2pool-*-windows-x86_64-setup.exe + # ════════════════════════════════════════════════════════════════════════════ # Aggregate: single SHA256SUMS over every produced package; on tags, # attach everything to a DRAFT release (operator publishes manually). diff --git a/installer/macos/create-dmg.sh b/installer/macos/create-dmg.sh index 424226476..aaef451a7 100755 --- a/installer/macos/create-dmg.sh +++ b/installer/macos/create-dmg.sh @@ -1,27 +1,71 @@ #!/bin/bash # c2pool macOS DMG builder # -# Usage: -# ./create-dmg.sh +# Two modes: # -# Examples: -# ./create-dmg.sh ~/c2pool-build/build/src/c2pool/c2pool x86_64 -# ./create-dmg.sh ~/c2pool-build/build-arm64/src/c2pool/c2pool arm64 +# 1. Staged mode (used by release.yml — wraps an already-assembled universal +# package directory into a .dmg): +# ./create-dmg.sh --staged --name c2pool-ltc --version 0.2.0 --arch universal +# must already contain the binary, lib/, web-static/, config/, +# start.sh — i.e. the exact tree the release matrix stages/lipo-merges. +# No asset copying or dylib rewriting is done here; the staged tree +# (which already has @executable_path-fixed dylibs) is shipped verbatim. +# Output: --macos-.dmg # -# The script expects web-static/, explorer/, config/, start.sh in the -# repo root (same level as src/). Output: c2pool-VERSION-macos-ARCH.dmg +# 2. Legacy single-binary mode (per-arch, alpha compatible): +# ./create-dmg.sh set -e -BINARY="$1" -ARCH="${2:-$(uname -m)}" -VERSION="0.1.1-alpha" +STAGED="" +NAME="" +VERSION="" +ARCH="" +BINARY="" + +# Flag parsing (staged mode) with positional fallback (legacy mode) +while [ $# -gt 0 ]; do + case "$1" in + --staged) STAGED="$2"; shift 2 ;; + --name) NAME="$2"; shift 2 ;; + --version) VERSION="$2"; shift 2 ;; + --arch) ARCH="$2"; shift 2 ;; + *) + if [ -z "$BINARY" ]; then BINARY="$1"; else ARCH="$1"; fi + shift ;; + esac +done + +# ── Staged mode ───────────────────────────────────────────────────────────── +if [ -n "$STAGED" ]; then + [ -n "$NAME" ] || { echo "ERROR: --name required with --staged"; exit 1; } + [ -n "$VERSION" ] || { echo "ERROR: --version required with --staged"; exit 1; } + ARCH="${ARCH:-universal}" + [ -d "$STAGED" ] || { echo "ERROR: staged dir not found: $STAGED"; exit 1; } + VOLNAME="${NAME}-${VERSION}" + DMG_NAME="${NAME}-${VERSION}-macos-${ARCH}.dmg" + echo "Building $DMG_NAME from staged tree $STAGED" + rm -f "$DMG_NAME" + hdiutil create -volname "$VOLNAME" \ + -srcfolder "$STAGED" \ + -ov -format UDZO \ + "$DMG_NAME" + echo "" + echo "Created: $DMG_NAME" + echo "Size: $(du -h "$DMG_NAME" | cut -f1)" + echo "SHA256: $(shasum -a 256 "$DMG_NAME" | cut -d' ' -f1)" + exit 0 +fi + +# ── Legacy single-binary mode (unchanged alpha behaviour) ─────────────────── +ARCH="${ARCH:-$(uname -m)}" +VERSION="${VERSION:-0.1.1-alpha}" VOLNAME="c2pool-${VERSION}" DMG_NAME="c2pool-${VERSION}-macos-${ARCH}.dmg" if [ -z "$BINARY" ] || [ ! -f "$BINARY" ]; then echo "Usage: $0 [arch]" - echo " arch: x86_64 or arm64 (default: native)" + echo " or: $0 --staged --name --version [--arch ]" exit 1 fi @@ -83,8 +127,6 @@ STARTEOF fi # Copy secp256k1 dylib and fix load path -# Detect the actual linked path from the binary (Homebrew may use Cellar paths -# like /usr/local/opt/secp256k1/lib/ instead of /usr/local/lib/) LINKED_SECP=$(otool -L "$APP_DIR/c2pool" | grep secp256k1 | awk '{print $1}') if [ -n "$LINKED_SECP" ] && [ -f "$LINKED_SECP" ]; then SECP_REAL=$(realpath "$LINKED_SECP") @@ -93,7 +135,6 @@ if [ -n "$LINKED_SECP" ] && [ -f "$LINKED_SECP" ]; then install_name_tool -change "$LINKED_SECP" "@executable_path/lib/libsecp256k1.6.dylib" "$APP_DIR/c2pool" echo " secp256k1: $LINKED_SECP -> @executable_path/lib/libsecp256k1.6.dylib" else - # Fallback: try known paths if [ "$ARCH" = "arm64" ]; then SECP_SEARCH="/Users/user0/arm64-deps/lib /opt/homebrew/lib" else @@ -103,7 +144,6 @@ else if [ -f "$DIR/libsecp256k1.6.dylib" ]; then cp "$DIR/libsecp256k1.6.dylib" "$APP_DIR/lib/libsecp256k1.6.dylib" ln -sf libsecp256k1.6.dylib "$APP_DIR/lib/libsecp256k1.dylib" - # Try all possible linked names for CANDIDATE in "$DIR/libsecp256k1.dylib" "$DIR/libsecp256k1.6.dylib"; do install_name_tool -change "$CANDIDATE" "@executable_path/lib/libsecp256k1.6.dylib" "$APP_DIR/c2pool" 2>/dev/null || true done diff --git a/installer/windows/c2pool-setup.iss b/installer/windows/c2pool-setup.iss index 3ed0438b5..53cbe62cd 100644 --- a/installer/windows/c2pool-setup.iss +++ b/installer/windows/c2pool-setup.iss @@ -1,12 +1,17 @@ ; c2pool Windows Installer — Inno Setup Script ; ; Usage: -; 1. Build c2pool.exe and prepare the package directory (see PACKAGE_DIR below) -; 2. Set PACKAGE_DIR and VCREDIST_PATH below to match your build environment -; 3. Compile: "C:\...\Inno Setup 6\ISCC.exe" c2pool-setup.iss +; 1. Build c2pool-.exe and prepare the package directory (PACKAGE_DIR) +; 2. Compile, overriding the per-package defines on the ISCC command line: +; ISCC.exe c2pool-setup.iss ^ +; /DPACKAGE_DIR=C:\path\to\c2pool-ltc-0.2.0-windows-x86_64 ^ +; /DVCREDIST_PATH=C:\...\vc_redist.x64.exe ^ +; /DMyAppName=c2pool-ltc /DMyAppVersion=0.2.0 ^ +; /DMyAppExeName=c2pool-ltc.exe ^ +; /DOutputBase=c2pool-ltc-0.2.0-windows-x86_64-setup ; ; The package directory should contain: -; c2pool.exe, start.bat, lib\*, web-static\*, explorer\*, config\* +; , start.bat, lib\*, web-static\*, explorer\*, config\* ; ── Configurable paths ────────────────────────────────────────────────────── ; Override on ISCC command line: /DPACKAGE_DIR=C:\path\to\package @@ -17,12 +22,21 @@ #define VCREDIST_PATH "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\v143\vc_redist.x64.exe" #endif -; ── App metadata ──────────────────────────────────────────────────────────── -#define MyAppName "c2pool" -#define MyAppVersion "0.1.1-alpha" +; ── App metadata (all overridable via /D for per-coin packages) ───────────── +#ifndef MyAppName + #define MyAppName "c2pool" +#endif +#ifndef MyAppVersion + #define MyAppVersion "0.1.1-alpha" +#endif +#ifndef MyAppExeName + #define MyAppExeName "c2pool.exe" +#endif +#ifndef OutputBase + #define OutputBase "c2pool-" + MyAppVersion + "-windows-x86_64-setup" +#endif #define MyAppPublisher "frstrtr" #define MyAppURL "https://github.com/frstrtr/c2pool" -#define MyAppExeName "c2pool.exe" [Setup] AppId={{C2POOL-MINING-POOL} @@ -30,9 +44,9 @@ AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} -DefaultDirName={autopf}\c2pool -DefaultGroupName=c2pool -OutputBaseFilename=c2pool-{#MyAppVersion}-windows-x86_64-setup +DefaultDirName={autopf}\{#MyAppName} +DefaultGroupName={#MyAppName} +OutputBaseFilename={#OutputBase} Compression=lzma2 SolidCompression=yes WizardStyle=modern @@ -44,8 +58,8 @@ Name: "english"; MessagesFile: "compiler:Default.isl" [Files] ; Main binary -Source: "{#PACKAGE_DIR}\c2pool.exe"; DestDir: "{app}"; Flags: ignoreversion -; DLLs (secp256k1, etc.) — must be next to c2pool.exe for Windows DLL search +Source: "{#PACKAGE_DIR}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +; DLLs (secp256k1, etc.) — must be next to the exe for Windows DLL search Source: "{#PACKAGE_DIR}\lib\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs ; Web dashboard Source: "{#PACKAGE_DIR}\web-static\*"; DestDir: "{app}\web-static"; Flags: ignoreversion recursesubdirs createallsubdirs @@ -58,19 +72,19 @@ Source: "{#PACKAGE_DIR}\start.bat"; DestDir: "{app}"; Flags: ignoreversion ; Transition message blobs (authority-signed V36 upgrade signal) Source: "{#PACKAGE_DIR}\transition_messages\*"; DestDir: "{app}\transition_messages"; Flags: ignoreversion recursesubdirs createallsubdirs skipifsourcedoesntexist ; VC++ Redistributable (installed silently, deleted after) -Source: "{#VCREDIST_PATH}"; DestDir: "{tmp}"; Flags: deleteafterinstall +Source: "{#VCREDIST_PATH}"; DestDir: "{tmp}"; Flags: deleteafterinstall skipifsourcedoesntexist [Icons] -Name: "{group}\c2pool"; Filename: "{app}\c2pool.exe"; Parameters: "--integrated --net litecoin --dashboard-dir ""{app}\web-static"""; WorkingDir: "{app}" -Name: "{group}\c2pool (start.bat)"; Filename: "{app}\start.bat"; WorkingDir: "{app}" -Name: "{group}\Uninstall c2pool"; Filename: "{uninstallexe}" -Name: "{commondesktop}\c2pool"; Filename: "{app}\c2pool.exe"; Parameters: "--integrated --net litecoin --dashboard-dir ""{app}\web-static"""; WorkingDir: "{app}" +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Parameters: "--integrated --net litecoin --dashboard-dir ""{app}\web-static"""; WorkingDir: "{app}" +Name: "{group}\{#MyAppName} (start.bat)"; Filename: "{app}\start.bat"; WorkingDir: "{app}" +Name: "{group}\Uninstall {#MyAppName}"; Filename: "{uninstallexe}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Parameters: "--integrated --net litecoin --dashboard-dir ""{app}\web-static"""; WorkingDir: "{app}" [Run] ; Install VC++ Runtime (skip if already present) -Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installing Visual C++ Runtime..."; Flags: waituntilterminated +Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installing Visual C++ Runtime..."; Flags: waituntilterminated skipifdoesntexist ; Offer to launch after install -Filename: "{app}\c2pool.exe"; Description: "Launch c2pool"; Flags: nowait postinstall skipifsilent; Parameters: "--integrated --net litecoin --dashboard-dir ""{app}\web-static""" +Filename: "{app}\{#MyAppExeName}"; Description: "Launch {#MyAppName}"; Flags: nowait postinstall skipifsilent; Parameters: "--integrated --net litecoin --dashboard-dir ""{app}\web-static""" [Code] var