Skip to content

[1.1.0] Added icons #136

[1.1.0] Added icons

[1.1.0] Added icons #136

Workflow file for this run

name: Build jb_updater
on:
push:
branches: [ "**" ]
tags: [ "v*.*.*" ]
pull_request:
workflow_dispatch: { }
permissions:
contents: write
# =========================================================
# =============== BUILD JOBS ==========================
# =========================================================
jobs:
linux:
name: Linux x86_64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crystal-lang/install-crystal@v1
with:
crystal: latest
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y libxml2-dev libssl-dev libpcre2-dev libgc-dev liblzma-dev libgtk-3-dev
- name: Install shards
working-directory: jb_updater
run: shards install
- name: Run Ameba linter
working-directory: jb_updater
run: ./bin/lint
- name: Run specs
working-directory: jb_updater
run: crystal spec -v
- name: Build binaries (CLI + GUI)
working-directory: jb_updater
run: |
crystal build src/main.cr --release --no-debug -o jb_updater
crystal build src/gui/main_gui.cr --release --no-debug -o jb_updater_gui
- name: Smoke test — CLI binary loads
working-directory: jb_updater
run: ./jb_updater --help
- name: Package artifacts
run: |
tar -czf jb_updater-cli-linux-x86_64.tar.gz -C jb_updater jb_updater
tar -czf jb_updater-gui-linux-x86_64.tar.gz -C jb_updater jb_updater_gui
mkdir -p jb_updater-bundle
cp jb_updater/jb_updater jb_updater-bundle/
cp jb_updater/jb_updater_gui jb_updater-bundle/
cp jb_updater/assets/jb_updater.svg jb_updater-bundle/
tar -czf jb_updater-bundle-linux-x86_64.tar.gz -C jb_updater-bundle .
- uses: actions/upload-artifact@v4
with:
name: jb_updater-cli-linux-x86_64
path: jb_updater-cli-linux-x86_64.tar.gz
- uses: actions/upload-artifact@v4
with:
name: jb_updater-gui-linux-x86_64
path: jb_updater-gui-linux-x86_64.tar.gz
- uses: actions/upload-artifact@v4
with:
name: jb_updater-bundle-linux-x86_64
path: jb_updater-bundle-linux-x86_64.tar.gz
macos:
name: macOS ${{ matrix.arch }}
strategy:
matrix:
include:
- arch: arm64
runs_on: macos-latest
- arch: x86_64
runs_on: macos-15-intel
runs-on: ${{ matrix.runs_on }}
env:
ARCH: ${{ matrix.arch }}
steps:
- uses: actions/checkout@v4
- uses: crystal-lang/install-crystal@v1
with:
crystal: latest
- name: Install OpenSSL 3
run: brew install openssl@3
- name: Install shards
working-directory: jb_updater
run: shards install
- name: Run Ameba linter
working-directory: jb_updater
run: ./bin/lint
- name: Run specs
working-directory: jb_updater
run: crystal spec -v
- name: Build binaries (CLI + GUI)
working-directory: jb_updater
run: |
brew_prefix=$(brew --prefix openssl@3)
unset PKG_CONFIG_PATH
export PKG_CONFIG_PATH="${brew_prefix}/lib/pkgconfig"
echo "Using OpenSSL from ${brew_prefix}"
crystal build src/main.cr --release --no-debug \
--link-flags "-L${brew_prefix}/lib -I${brew_prefix}/include" \
-o jb_updater
crystal build src/gui/main_gui.cr --release --no-debug \
--link-flags "-L${brew_prefix}/lib -I${brew_prefix}/include" \
-o jb_updater_gui
- name: Bundle OpenSSL runtime dylibs
working-directory: jb_updater
run: |
brew_prefix=$(brew --prefix openssl@3)
for dylib in libcrypto.3.dylib libssl.3.dylib; do
cp "$brew_prefix/lib/$dylib" .
install_name_tool -id "@loader_path/$dylib" "$dylib"
for dep in $(otool -L "$dylib" | grep "/opt/homebrew\|/usr/local" | awk '{print $1}'); do
install_name_tool -change "$dep" "@loader_path/$(basename $dep)" "$dylib"
done
done
for exe in jb_updater jb_updater_gui; do
for dep in $(otool -L "$exe" | grep "/opt/homebrew\|/usr/local" | awk '{print $1}'); do
install_name_tool -change "$dep" "@loader_path/$(basename $dep)" "$exe"
done
done
- name: Smoke test — CLI binary loads
working-directory: jb_updater
run: |
./jb_updater --help
echo "---"
echo "Checking dylib paths..."
# Skip binary name line, filter out system paths and @loader_path refs.
# Any remaining lines are non-system absolute paths → fail.
otool -L jb_updater | tail -n +2 | grep -v -e "/usr/lib" -e "/System" -e "@loader_path" && { echo "::error::Found absolute dylib paths"; exit 1; } || echo "All dylib paths use @loader_path"
- name: Package artifacts
run: |
cd jb_updater
# CLI archive — include bundled dylibs
tar -czf ../jb_updater-cli-macos-${ARCH}.tar.gz jb_updater libcrypto.3.dylib libssl.3.dylib
# Bundle: binaries + dylibs
mkdir -p ../jb_updater-bundle
cp jb_updater jb_updater_gui libcrypto.3.dylib libssl.3.dylib ../jb_updater-bundle/
cd ..
zip -ry jb_updater-bundle-macos-${ARCH}.zip jb_updater-bundle
# .app bundle with dylibs + icon inside
APP_ROOT="JBUpdater.app/Contents"
mkdir -p "$APP_ROOT/MacOS" "$APP_ROOT/Resources"
cp jb_updater/jb_updater_gui "$APP_ROOT/MacOS/"
cp jb_updater/jb_updater "$APP_ROOT/MacOS/"
cp jb_updater/libcrypto.3.dylib "$APP_ROOT/MacOS/"
cp jb_updater/libssl.3.dylib "$APP_ROOT/MacOS/"
cp jb_updater/assets/jb_updater.icns "$APP_ROOT/Resources/"
cat > "$APP_ROOT/Info.plist" <<'PLIST'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>CFBundleName</key><string>JB Updater</string>
<key>CFBundleIdentifier</key><string>com.example.jb-updater</string>
<key>CFBundleVersion</key><string>1.0</string>
<key>CFBundleExecutable</key><string>jb_updater_gui</string>
<key>CFBundleIconFile</key><string>jb_updater</string>
<key>LSMinimumSystemVersion</key><string>11.0</string>
<key>NSHighResolutionCapable</key><true/>
</dict></plist>
PLIST
zip -ry jb_updater-app-macos-${ARCH}.zip JBUpdater.app
- uses: actions/upload-artifact@v4
with:
name: jb_updater-cli-macos-${{ matrix.arch }}
path: jb_updater-cli-macos-${{ matrix.arch }}.tar.gz
- uses: actions/upload-artifact@v4
with:
name: jb_updater-app-macos-${{ matrix.arch }}
path: jb_updater-app-macos-${{ matrix.arch }}.zip
- uses: actions/upload-artifact@v4
with:
name: jb_updater-bundle-macos-${{ matrix.arch }}
path: jb_updater-bundle-macos-${{ matrix.arch }}.zip
windows:
name: Windows x86_64
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: crystal-lang/install-crystal@v1
with:
crystal: latest
# Ensure MSVC build environment is set up (cl, link, mt, etc.)
- name: Set up MSVC Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
- name: Install shards
working-directory: jb_updater
run: shards install
- name: Run Ameba linter
working-directory: jb_updater
run: ./bin/lint
- name: Run specs
working-directory: jb_updater
run: crystal spec -v
- name: Build binaries (CLI + GUI)
working-directory: jb_updater
run: |
crystal build src/main.cr --release --no-debug -o jb_updater.exe
crystal build src/gui/main_gui.cr --release --no-debug --link-flags=/SUBSYSTEM:WINDOWS -o jb_updater_gui.exe
- name: Bundle Crystal runtime DLLs
shell: pwsh
run: |
# Crystal runtime DLLs must ship alongside the EXEs on Windows,
# otherwise the process exits with 0xC0000135 (STATUS_DLL_NOT_FOUND).
$crystalPath = (Get-Command crystal).Source
$crystalRoot = Split-Path (Split-Path $crystalPath -Parent) -Parent
$dllSource = Join-Path $crystalRoot "embedded" "bin"
if (Test-Path $dllSource) {
Copy-Item "$dllSource\*.dll" jb_updater\
Write-Host "Copied DLLs from $dllSource"
Get-ChildItem jb_updater\*.dll | ForEach-Object { Write-Host " → $($_.Name)" }
} else {
Write-Host "::warning::Crystal DLL directory not found at $dllSource"
}
- name: Smoke test — CLI binary loads
working-directory: jb_updater
run: |
# Verify the CLI binary starts (proves all DLLs resolve correctly).
# 0xC0000135 would kill the process before any output.
.\jb_updater.exe --help
shell: cmd
- name: Verify GUI DLLs are present
working-directory: jb_updater
shell: pwsh
run: |
# Can't run the GUI binary on headless CI (no display), but we can
# confirm all DLLs exist alongside the GUI EXE.
$exe = "jb_updater_gui.exe"
$dlls = @(Get-ChildItem *.dll)
if (-not (Test-Path $exe)) {
Write-Host "::error::$exe not found"
exit 1
}
Write-Host "$exe found, $($dlls.Count) DLLs present:"
$dlls | ForEach-Object { Write-Host " → $($_.Name) ($( '{0:N0}' -f $_.Length ) bytes)" }
- name: Package artifacts
run: |
Compress-Archive -Path jb_updater\jb_updater.exe, jb_updater\*.dll -DestinationPath jb_updater-cli-windows-x86_64.zip
Compress-Archive -Path jb_updater\jb_updater_gui.exe, jb_updater\*.dll -DestinationPath jb_updater-gui-windows-x86_64.zip
New-Item -ItemType Directory -Force -Path jb_updater-bundle | Out-Null
Copy-Item jb_updater\*.exe, jb_updater\*.dll jb_updater-bundle\
Compress-Archive -Path jb_updater-bundle\* -DestinationPath jb_updater-bundle-windows-x86_64.zip
- uses: actions/upload-artifact@v4
with:
name: jb_updater-cli-windows-x86_64
path: jb_updater-cli-windows-x86_64.zip
- uses: actions/upload-artifact@v4
with:
name: jb_updater-gui-windows-x86_64
path: jb_updater-gui-windows-x86_64.zip
- uses: actions/upload-artifact@v4
with:
name: jb_updater-bundle-windows-x86_64
path: jb_updater-bundle-windows-x86_64.zip
# =========================================================
# =============== RELEASE JOB =========================
# =========================================================
release:
name: Create GitHub Release
needs: [ linux, macos, windows ]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/')
steps:
- name: Verify branch or tag
run: |
echo "Triggered by $GITHUB_EVENT_NAME for ref $GITHUB_REF"
if [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" && "$GITHUB_REF_NAME" != "master" ]]; then
echo "⚠️ Manual releases are allowed only from master branch."
exit 1
fi
- name: Download all build artifacts
uses: actions/download-artifact@v4
with:
path: ./all-artifacts
- name: Flatten artifacts
run: |
mkdir -p release-assets
find ./all-artifacts -type f -exec mv {} ./release-assets/ \;
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: release-assets/*
generate_release_notes: true