Skip to content
Merged
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
101 changes: 61 additions & 40 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,31 +68,28 @@ jobs:
version: latest
args: --timeout=5m

build:
name: Build
build-desktop:
name: Build Desktop Apps
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
platform: linux/amd64
name: linux-amd64
ext: ""
- os: macos-latest
goos: darwin
goarch: amd64
platform: darwin/amd64
name: darwin-amd64
ext: ""
ext: ".app"
- os: macos-latest
goos: darwin
goarch: arm64
platform: darwin/arm64
name: darwin-arm64
ext: ""
ext: ".app"
- os: windows-latest
goos: windows
goarch: amd64
platform: windows/amd64
name: windows-amd64
ext: ".exe"

Expand All @@ -105,34 +102,58 @@ jobs:
with:
go-version: ${{ env.GO_VERSION }}

- name: Setup Windows build environment
if: matrix.goos == 'windows'
shell: bash
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install Wails
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest

- name: Install Linux dependencies
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.0-dev

- name: Install Windows dependencies
if: matrix.os == 'windows-latest'
run: |
choco install mingw -y
choco install nsis -y

- name: Install frontend dependencies
working-directory: frontend
run: npm ci

- name: Build Wails app
run: |
wails build -platform ${{ matrix.platform }} -clean

- name: Package artifacts (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
# Install MSYS2 for complete build environment
choco install msys2 -y
# Initialize MSYS2 and install required packages
C:/tools/msys64/usr/bin/bash -lc 'pacman --noconfirm -S mingw-w64-x86_64-gcc mingw-w64-x86_64-pkg-config mingw-w64-x86_64-sqlite3'
# Add MSYS2 MinGW64 to PATH
echo "C:\\tools\\msys64\\mingw64\\bin" >> $GITHUB_PATH
# Verify installation
C:/tools/msys64/mingw64/bin/gcc --version || echo "GCC not found"

- name: Build binary
shell: bash
mkdir -p artifacts
cp build/bin/ml-notes artifacts/ml-notes-${{ matrix.name }}
chmod +x artifacts/ml-notes-${{ matrix.name }}

- name: Package artifacts (macOS)
if: matrix.os == 'macos-latest'
run: |
if [ "${{ matrix.goos }}" = "windows" ]; then
# Set up CGO environment for Windows with MSYS2
export CGO_ENABLED=1
export CC=C:/tools/msys64/mingw64/bin/gcc.exe
export CXX=C:/tools/msys64/mingw64/bin/g++.exe
export PKG_CONFIG_PATH="C:/tools/msys64/mingw64/lib/pkgconfig"
export PATH="C:/tools/msys64/mingw64/bin:$PATH"
fi
CGO_ENABLED=1 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build -v -o ml-notes-${{ matrix.name }}${{ matrix.ext }}

- name: Test binary
if: matrix.goarch == 'amd64' # Only test on native architecture
shell: bash
mkdir -p artifacts
cp -r "build/bin/ML Notes.app" "artifacts/ML Notes-${{ matrix.name }}.app"

- name: Package artifacts (Windows)
if: matrix.os == 'windows-latest'
run: |
./ml-notes-${{ matrix.name }}${{ matrix.ext }} --help
mkdir -p artifacts
cp build/bin/ml-notes.exe artifacts/ml-notes-${{ matrix.name }}.exe

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ml-notes-desktop-${{ matrix.name }}
path: artifacts/*
retention-days: 30
130 changes: 102 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Makefile for ML Notes

# Variables
BINARY_NAME := ml-notes
CLI_BINARY_NAME := ml-notes-cli
GUI_BINARY_NAME := ml-notes
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
BUILD_TIME := $(shell date -u '+%Y-%m-%d_%H:%M:%S')
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
Expand All @@ -12,6 +13,19 @@ LDFLAGS := -ldflags "-X main.Version=$(VERSION) -X main.BuildTime=$(BUILD_TIME)
CGO_ENABLED := 1
GOFLAGS := -v

# Go binary paths
GOPATH := $(shell go env GOPATH)
GOBIN := $(shell go env GOBIN)
ifeq ($(GOBIN),)
GOBIN := $(GOPATH)/bin
endif

# Add Go bin to PATH for this Makefile
export PATH := $(PATH):$(GOBIN)

# Check if Wails is available (after adding GOBIN to PATH)
WAILS_AVAILABLE := $(shell command -v wails 2> /dev/null)

# Directories
PREFIX := /usr/local
BINDIR := $(PREFIX)/bin
Expand Down Expand Up @@ -41,37 +55,78 @@ endif

# Default target
.PHONY: all
all: build install
all: build-cli build-gui install

# Build the binary
# Build both CLI and GUI binaries
.PHONY: build
build:
@echo "Building $(BINARY_NAME) $(VERSION) for $(PLATFORM)/$(ARCH)..."
build: build-cli build-gui

# Build the CLI binary
.PHONY: build-cli
build-cli:
@echo "Building $(CLI_BINARY_NAME) $(VERSION) for $(PLATFORM)/$(ARCH)..."
@echo "Go version: $(GO_VERSION)"
@echo "Git commit: $(GIT_COMMIT)"
CGO_ENABLED=$(CGO_ENABLED) go build $(GOFLAGS) $(LDFLAGS) -o $(CLI_BINARY_NAME) ./app/cli
@echo "CLI build complete: ./$(CLI_BINARY_NAME)"

# Build the GUI binary using Wails
.PHONY: build-gui
build-gui:
ifdef WAILS_AVAILABLE
@echo "Building $(GUI_BINARY_NAME) $(VERSION) using Wails..."
@echo "Go version: $(GO_VERSION)"
@echo "Git commit: $(GIT_COMMIT)"
CGO_ENABLED=$(CGO_ENABLED) go build $(GOFLAGS) $(LDFLAGS) -o $(BINARY_NAME) .
@echo "Build complete: ./$(BINARY_NAME)"
wails build -clean -o $(GUI_BINARY_NAME)
@echo "GUI build complete: ./build/bin/$(GUI_BINARY_NAME)"
else
@echo "⚠️ Wails not found. Skipping GUI build."
@echo " Install Wails with: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
endif

# Development build with race detector for CLI
.PHONY: dev-cli
dev-cli:
@echo "Building CLI development version with race detector..."
CGO_ENABLED=1 go build -race $(LDFLAGS) -o $(CLI_BINARY_NAME)-dev ./app/cli
@echo "CLI development build complete: ./$(CLI_BINARY_NAME)-dev"

# Development build for GUI using Wails
.PHONY: dev-gui
dev-gui:
ifdef WAILS_AVAILABLE
@echo "Starting Wails development server..."
wails dev
else
@echo "⚠️ Wails not found. Cannot start development server."
@echo " Install Wails with: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
endif

# Development build with race detector
# Development build for both
.PHONY: dev
dev:
@echo "Building development version with race detector..."
CGO_ENABLED=1 go build -race $(LDFLAGS) -o $(BINARY_NAME)-dev .
@echo "Development build complete: ./$(BINARY_NAME)-dev"
dev: dev-cli dev-gui

# Install the binary to system PATH
# Install binaries to system PATH
.PHONY: install
install: $(BINARY_NAME)
@echo "Installing $(BINARY_NAME) to $(BINDIR)..."
@$(INSTALL_PROGRAM) $(BINARY_NAME) $(BINDIR)/
install: $(CLI_BINARY_NAME) $(GUI_BINARY_NAME)
@echo "Installing $(CLI_BINARY_NAME) to $(BINDIR)..."
@$(INSTALL_PROGRAM) $(CLI_BINARY_NAME) $(BINDIR)/
ifdef WAILS_AVAILABLE
@if [ -f "./build/bin/$(GUI_BINARY_NAME)" ]; then \
echo "Installing $(GUI_BINARY_NAME) to $(BINDIR)..."; \
$(INSTALL_PROGRAM) ./build/bin/$(GUI_BINARY_NAME) $(BINDIR)/; \
fi
endif
@echo "Installation complete!"
@echo "Run 'ml-notes init' to set up your configuration."
@echo "Run '$(CLI_BINARY_NAME) init' to set up your configuration."
@echo "Run '$(GUI_BINARY_NAME)' to start the desktop application."

# Uninstall the binary
# Uninstall the binaries
.PHONY: uninstall
uninstall:
@echo "Removing $(BINARY_NAME) from $(BINDIR)..."
@rm -f $(BINDIR)/$(BINARY_NAME)
@echo "Removing binaries from $(BINDIR)..."
@rm -f $(BINDIR)/$(CLI_BINARY_NAME)
@rm -f $(BINDIR)/$(GUI_BINARY_NAME)
@echo "Uninstall complete."

# Run tests
Expand Down Expand Up @@ -111,7 +166,9 @@ fmt:
.PHONY: clean
clean:
@echo "Cleaning build artifacts..."
@rm -f $(BINARY_NAME) $(BINARY_NAME)-dev
@rm -f $(CLI_BINARY_NAME) $(CLI_BINARY_NAME)-dev
@rm -f $(GUI_BINARY_NAME) $(GUI_BINARY_NAME)-dev
@rm -rf build/
@rm -f coverage.out coverage.html
@rm -rf dist/
@echo "Clean complete."
Expand Down Expand Up @@ -218,7 +275,9 @@ help:
@echo "ML Notes - Makefile targets:"
@echo ""
@echo "🏗️ Build targets:"
@echo " make build - Build the binary for current platform"
@echo " make build - Build both CLI and GUI binaries"
@echo " make build-cli - Build the CLI binary only"
@echo " make build-gui - Build the GUI binary using Wails"
@echo " make build-native - Build for native platform (auto-detect)"
@echo " make build-linux - Build for Linux AMD64"
@echo " make build-darwin - Build for macOS (Intel & Apple Silicon)"
Expand All @@ -229,9 +288,11 @@ help:
@echo " make release - Create release packages for all platforms"
@echo ""
@echo "🛠️ Development targets:"
@echo " make install - Build and install to $(BINDIR)"
@echo " make uninstall - Remove from $(BINDIR)"
@echo " make dev - Build with race detector"
@echo " make install - Build and install both binaries to $(BINDIR)"
@echo " make uninstall - Remove both binaries from $(BINDIR)"
@echo " make dev - Build CLI with race detector"
@echo " make dev-cli - Build CLI with race detector"
@echo " make dev-gui - Start Wails development server"
@echo " make test - Run tests"
@echo " make test-coverage - Run tests with coverage"
@echo " make lint - Run linters"
Expand All @@ -242,16 +303,29 @@ help:
@echo ""
@echo "ℹ️ Information:"
@echo " VERSION=$(VERSION)"
@echo " CLI_BINARY_NAME=$(CLI_BINARY_NAME)"
@echo " GUI_BINARY_NAME=$(GUI_BINARY_NAME)"
@echo " PLATFORM=$(PLATFORM)/$(ARCH)"
@echo " PREFIX=$(PREFIX)"
ifdef WAILS_AVAILABLE
@echo " WAILS=available"
else
@echo " WAILS=not available (GUI builds disabled)"
endif
@echo ""
@echo "📝 Notes:"
@echo " - The CLI binary provides all command-line functionality"
@echo " - The GUI binary is a desktop app built with Wails"
@echo " - Wails is required for GUI builds: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
@echo " - Cross-compilation for macOS/Windows requires appropriate toolchains"
@echo " - For best results, build natively on target platforms"
@echo " - CGO is required for sqlite-vec support"

# Ensure binary exists for install target
$(BINARY_NAME):
@$(MAKE) build
# Ensure binaries exist for install target
$(CLI_BINARY_NAME):
@$(MAKE) build-cli

$(GUI_BINARY_NAME):
@$(MAKE) build-gui

.DEFAULT_GOAL := help
21 changes: 21 additions & 0 deletions app/cli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"fmt"
"os"

"github.com/streed/ml-notes/internal/cli"
)

// Version is set via ldflags during build
var Version = "dev"

func main() {
// Set version for the CLI package
cli.Version = Version

if err := cli.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
8 changes: 8 additions & 0 deletions app/desktop/assets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package main

import (
"embed"
)

//go:embed frontend
var assets embed.FS
Loading
Loading