Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
61 changes: 59 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ jobs:
- name: Build macOS arm64 headless
run: CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -tags=noui -ldflags "-s -w -X 'github.com/device-management-toolkit/console/internal/app.Version=${{ needs.prepare.outputs.version }}'" -trimpath -o dist/darwin/console_mac_arm64_headless ./cmd/app

# Build Windows NSIS Installer
- name: Install NSIS
run: |
sudo apt-get update
sudo apt-get install -y nsis

- name: Build Windows Installers
run: |
makensis -DVERSION=${{ needs.prepare.outputs.version }} -DARCH=x64 -DEDITION=ui "-DBINARY=../dist/windows/console_windows_x64.exe" installer/console.nsi
mv console_${{ needs.prepare.outputs.version }}_windows_x64_setup.exe dist/windows/
makensis -DVERSION=${{ needs.prepare.outputs.version }} -DARCH=x64 -DEDITION=headless "-DBINARY=../dist/windows/console_windows_x64_headless.exe" installer/console.nsi
mv console_${{ needs.prepare.outputs.version }}_windows_x64_headless_setup.exe dist/windows/

# Cache all build artifacts in a single step
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
Expand All @@ -135,11 +148,49 @@ jobs:
dist/windows
key: all-platforms-${{ env.sha_short }}

build-macos-installer:
needs: [prepare, build]
runs-on: macos-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
with:
egress-policy: audit

- name: Checkout Console
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- shell: bash
run: |
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV

# Restore build cache to get macOS binary
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: |
dist/linux
dist/darwin
dist/windows
key: all-platforms-${{ env.sha_short }}

- name: Build macOS PKG Installer
run: |
chmod +x installer/macos/build-pkg.sh
./installer/macos/build-pkg.sh ${{ needs.prepare.outputs.version }} arm64

# Cache the installer separately
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: dist/darwin/*.pkg
key: macos-installer-${{ env.sha_short }}

release:
permissions:
contents: write # for Git to git push
runs-on: ubuntu-latest
needs: build
needs: [build, build-macos-installer]
steps:
- name: Harden Runner
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
Expand All @@ -163,7 +214,13 @@ jobs:
dist/darwin
dist/windows
key: all-platforms-${{ env.sha_short }}


# Restore macOS installer cache
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: dist/darwin/*.pkg
key: macos-installer-${{ env.sha_short }}

# Generate licenses.zip
- name: Use Node.js 22.x
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ vendor/
# ...but keep the folder
!**/ui/.gitkeep
# Documentation files
doc/openapi.json
doc/openapi.json
dist
28 changes: 22 additions & 6 deletions .releaserc.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,35 @@
"assets": [
{
"path": "console_linux_x64.tar.gz",
"label": "Linux x64 Console (Full)"
"label": "Linux x64 Installer (Full)"
},
{
"path": "console_linux_x64_headless.tar.gz",
"label": "Linux x64 Console Headless (No UI)"
"label": "Linux x64 Installer Headless (No UI)"
},
{
"path": "console_linux_arm64.tar.gz",
"label": "Linux ARM64 Console (Full)"
"label": "Linux ARM64 Installer (Full)"
},
{
"path": "console_linux_arm64_headless.tar.gz",
"label": "Linux ARM64 Console Headless (No UI)"
"label": "Linux ARM64 Installer Headless (No UI)"
},
{
"path": "dist/windows/console_windows_x64.exe",
"label": "Windows x64 Console (Full)"
"label": "Windows x64 Binary (Full)"
},
{
"path": "dist/windows/console_windows_x64_headless.exe",
"label": "Windows x64 Console Headless (No UI)"
"label": "Windows x64 Binary Headless (No UI)"
},
{
"path": "dist/windows/console_*_windows_x64_setup.exe",
"label": "Windows x64 Installer (Full)"
},
{
"path": "dist/windows/console_*_windows_x64_headless_setup.exe",
"label": "Windows x64 Installer Headless (No UI)"
},
{
"path": "console_mac_arm64.tar.gz",
Expand All @@ -58,6 +66,14 @@
"path": "console_mac_arm64_headless.tar.gz",
"label": "macOS ARM64 Console Headless (No UI)"
},
{
"path": "dist/darwin/console_*_macos_arm64.pkg",
"label": "macOS ARM64 Installer (Full PKG)"
},
{
"path": "dist/darwin/console_*_macos_arm64_headless.pkg",
"label": "macOS ARM64 Installer Headless (PKG)"
},
{
"path": "licenses.zip",
"label": "Third-Party Licenses"
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/app/",
"program": "${workspaceFolder}/cmd/app",
"envFile": "${workspaceFolder}/.env",
"cwd": "${workspaceFolder}"
}
Expand Down
58 changes: 58 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ build-noui: ### build app without UI
CGO_ENABLED=0 go build -tags=noui -o ./bin/console-noui ./cmd/app
.PHONY: build-noui

build-tray: ### build app with system tray support (requires CGO, native build only)
CGO_ENABLED=1 go build -tags=tray -o ./bin/console-tray ./cmd/app
.PHONY: build-tray

build-all-platforms: ### cross-compile for all platforms (Linux, Windows, macOS)
@echo "Building for all platforms using cross-compilation (CGO_ENABLED=0)..."
@mkdir -p dist/linux dist/windows dist/darwin
Expand Down Expand Up @@ -144,3 +148,57 @@ migrate-up: ### migration up
bin-deps:
GOBIN=$(LOCAL_BIN) go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
GOBIN=$(LOCAL_BIN) go install go.uber.org/mock/mockgen@latest

# Installers (requires NSIS for Windows, macOS for PKG)
VERSION ?= 3.0.0-dev

# Build Windows binaries (full and headless)
build-windows-binaries: ### build Windows binaries (full and headless)
@echo "Building Windows binaries..."
@mkdir -p dist/windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o dist/windows/console_windows_x64.exe ./cmd/app
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -tags=noui -ldflags "-s -w" -trimpath -o dist/windows/console_windows_x64_headless.exe ./cmd/app
@echo "Windows binaries built successfully!"
.PHONY: build-windows-binaries

build-windows-installer: build-windows-binaries ### build Windows NSIS installers (full + headless)
@echo "Building Windows installers with NSIS..."
@command -v makensis >/dev/null 2>&1 || { echo "NSIS is not installed. Install with: brew install nsis (macOS) or apt-get install nsis (Linux)"; exit 1; }
$(eval VI_VERSION := $(shell echo '$(VERSION)' | sed 's/-.*//' ).0)
makensis -DVERSION=$(VERSION) -DVI_VERSION=$(VI_VERSION) -DARCH=x64 -DEDITION=ui -DBINARY="../dist/windows/console_windows_x64.exe" installer/console.nsi
@mv installer/console_$(VERSION)_windows_x64_setup.exe dist/windows/
makensis -DVERSION=$(VERSION) -DVI_VERSION=$(VI_VERSION) -DARCH=x64 -DEDITION=headless -DBINARY="../dist/windows/console_windows_x64_headless.exe" installer/console.nsi
@mv installer/console_$(VERSION)_windows_x64_headless_setup.exe dist/windows/
@echo "Windows installers created in dist/windows/"
.PHONY: build-windows-installer

# Build macOS binaries (full and headless)
build-macos-binaries: ### build macOS binaries (full and headless)
@echo "Building macOS binaries..."
@mkdir -p dist/darwin
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w" -trimpath -o dist/darwin/console_mac_arm64 ./cmd/app
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -tags=noui -ldflags "-s -w" -trimpath -o dist/darwin/console_mac_arm64_headless ./cmd/app
@echo "macOS binaries built successfully!"
.PHONY: build-macos-binaries

build-macos-installer: build-macos-binaries ### build macOS PKG installer (macOS only)
@echo "Building macOS PKG installer..."
@if [ "$$(uname)" != "Darwin" ]; then echo "Error: macOS PKG can only be built on macOS"; exit 1; fi
chmod +x installer/macos/build-pkg.sh
./installer/macos/build-pkg.sh $(VERSION) arm64
@echo "macOS installer created: dist/darwin/console_$(VERSION)_macos_arm64.pkg"
.PHONY: build-macos-installer

build-linux-installer: ### build Linux installer archives (full + headless)
@echo "Building Linux installer archives..."
@mkdir -p dist/linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o dist/linux/console_linux_x64 ./cmd/app
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -tags=noui -ldflags "-s -w" -trimpath -o dist/linux/console_linux_x64_headless ./cmd/app
chmod +x installer/linux/build-packages.sh
./installer/linux/build-packages.sh $(VERSION) amd64
@echo "Linux installer archives created in dist/linux/"
.PHONY: build-linux-installer

build-all-with-installers: build-all-platforms build-windows-installer build-macos-installer build-linux-installer ### build all platforms plus all installers
@echo "All platforms and installers built successfully!"
.PHONY: build-all-with-installers
39 changes: 34 additions & 5 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,40 @@ chmod +x dist/linux/console_linux_arm64_headless
chmod +x dist/darwin/console_mac_arm64
chmod +x dist/darwin/console_mac_arm64_headless

# Package Linux variants
tar cvfpz console_linux_x64.tar.gz dist/linux/console_linux_x64
tar cvfpz console_linux_x64_headless.tar.gz dist/linux/console_linux_x64_headless
tar cvfpz console_linux_arm64.tar.gz dist/linux/console_linux_arm64
tar cvfpz console_linux_arm64_headless.tar.gz dist/linux/console_linux_arm64_headless
# Prepare Linux installer scripts with version replacement
LINUX_INSTALLER_DIR="installer/linux"
STAGING_DIR=$(mktemp -d)

for script in configure.sh install.sh uninstall.sh dmt-console.service; do
cp "$LINUX_INSTALLER_DIR/$script" "$STAGING_DIR/$script"
sed -i "s/VERSION_PLACEHOLDER/$version/g" "$STAGING_DIR/$script"
done

# Package Linux variants (binary + installer scripts)
package_linux() {
local binary=$1
local output=$2
local pkg_dir
pkg_dir=$(mktemp -d)

cp "$binary" "$pkg_dir/console"
chmod +x "$pkg_dir/console"
cp "$STAGING_DIR/configure.sh" "$pkg_dir/"
cp "$STAGING_DIR/install.sh" "$pkg_dir/"
cp "$STAGING_DIR/uninstall.sh" "$pkg_dir/"
cp "$STAGING_DIR/dmt-console.service" "$pkg_dir/"
chmod +x "$pkg_dir/configure.sh" "$pkg_dir/install.sh" "$pkg_dir/uninstall.sh"

tar cvfpz "$output" -C "$pkg_dir" .
rm -rf "$pkg_dir"
}

package_linux dist/linux/console_linux_x64 console_linux_x64.tar.gz
package_linux dist/linux/console_linux_x64_headless console_linux_x64_headless.tar.gz
package_linux dist/linux/console_linux_arm64 console_linux_arm64.tar.gz
package_linux dist/linux/console_linux_arm64_headless console_linux_arm64_headless.tar.gz

rm -rf "$STAGING_DIR"

# Package macOS variants
tar cvfpz console_mac_arm64.tar.gz dist/darwin/console_mac_arm64
Expand Down
5 changes: 5 additions & 0 deletions cmd/app/edition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !noui

package main

var isHeadlessBuild = false //nolint:unused // used in tray.go (tray build tag)
5 changes: 5 additions & 0 deletions cmd/app/edition_noui.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build noui

package main

var isHeadlessBuild = true //nolint:unused // used in tray.go (tray build tag)
29 changes: 27 additions & 2 deletions cmd/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ var (
)

func main() {
// Detect Windows service mode early, before any interactive prompts
serviceMode = isServiceMode()

cfg, err := initializeConfigFunc()
if err != nil {
log.Fatalf("Config error: %s", err)
Expand All @@ -65,8 +68,23 @@ func main() {
l := logger.New(cfg.Level)

handleEncryptionKey(cfg)
handleDebugMode(cfg, l)
runAppFunc(cfg, l)

// Run as a Windows service if started by the SCM (no-op on non-Windows)
if serviceMode {
if err := runAsService(cfg, l); err != nil {
log.Fatalf("Windows service error: %s", err)
}

return
}

// Run with system tray (if built with tray tag and --tray flag) or standard mode
if trayBuildEnabled && config.TrayMode {
runWithTray(cfg, l)
} else {
handleDebugMode(cfg, l)
runAppFunc(cfg, l)
}
}

func setupCIRACertificates(cfg *config.Config, secretsClient security.Storager) error {
Expand Down Expand Up @@ -269,6 +287,13 @@ func saveEncryptionKey(key string, remoteStorage, localStorage security.Storager
}

func handleKeyNotFound(toolkitCrypto security.Crypto, _, _ security.Storager) string {
// When running as a Windows service there is no stdin — auto-generate the key
if serviceMode {
log.Println("No encryption key found — generating new key (service mode)")

return toolkitCrypto.GenerateKey()
}

log.Print("\033[31mWarning: Key Not Found, Generate new key? -- This will prevent access to existing data? Y/N: \033[0m")

var response string
Expand Down
18 changes: 18 additions & 0 deletions cmd/app/service_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build !windows

package main

import (
"github.com/device-management-toolkit/console/config"
"github.com/device-management-toolkit/console/pkg/logger"
)

var serviceMode bool

func isServiceMode() bool {
return false
}

func runAsService(_ *config.Config, _ logger.Interface) error {
return nil
}
Loading
Loading