diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3266fa1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,48 @@ +name: CI + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.21' + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + pkg-config \ + libasound2-dev \ + libpulse-dev \ + libpipewire-0.3-dev + + - name: Download dependencies + run: go mod download + + - name: Run tests + run: go test -v ./... + + - name: Build binary + env: + CGO_ENABLED: 1 + run: go build -o hyprvoice ./cmd/hyprvoice + + - name: Test binary help + run: ./hyprvoice --help + + - name: Test configure command + run: ./hyprvoice configure --help diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..519e7bf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,112 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + build: + name: Build and Release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.21' + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + pkg-config \ + libasound2-dev \ + libpulse-dev \ + libpipewire-0.3-dev + + - name: Extract version from tag + id: version + run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + + - name: Build binary + env: + CGO_ENABLED: 1 + GOOS: linux + GOARCH: amd64 + run: | + go mod download + go build -ldflags="-s -w" -o hyprvoice-linux-x86_64 ./cmd/hyprvoice + chmod +x hyprvoice-linux-x86_64 + + - name: Run tests + run: go test ./... + + - name: Create release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ steps.version.outputs.VERSION }} + body: | + ## Hyprvoice v${{ steps.version.outputs.VERSION }} + + ### Installation + + **From AUR (Recommended):** + ```bash + yay -S hyprvoice-bin + hyprvoice configure + systemctl --user enable --now hyprvoice.service + ``` + + **Manual installation:** + ```bash + wget https://github.com/leonardotrapani/hyprvoice/releases/download/v${{ steps.version.outputs.VERSION }}/hyprvoice-linux-x86_64 + chmod +x hyprvoice-linux-x86_64 + mv hyprvoice-linux-x86_64 ~/.local/bin/hyprvoice + ``` + + ### What's Changed + - See commit history for detailed changes + + ### Requirements + - Wayland desktop environment + - PipeWire audio system + - OpenAI API key for transcription + + **Full Changelog**: https://github.com/leonardotrapani/hyprvoice/commits/v${{ steps.version.outputs.VERSION }} + draft: false + prerelease: false + + - name: Upload binary + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./hyprvoice-linux-x86_64 + asset_name: hyprvoice-linux-x86_64 + asset_content_type: application/octet-stream + + - name: Upload checksums + run: | + sha256sum hyprvoice-linux-x86_64 > hyprvoice-linux-x86_64.sha256 + echo "Binary SHA256:" + cat hyprvoice-linux-x86_64.sha256 + + - name: Upload checksum file + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./hyprvoice-linux-x86_64.sha256 + asset_name: hyprvoice-linux-x86_64.sha256 + asset_content_type: text/plain \ No newline at end of file diff --git a/README.md b/README.md index 4272e9e..91bfb89 100644 --- a/README.md +++ b/README.md @@ -15,24 +15,23 @@ Press a toggle key, speak, and get instant text input. Built natively for Waylan ## Installation -### From AUR (Arch Linux) +### From AUR (Arch Linux) - Recommended ```bash -# Using your preferred AUR helper +# Install hyprvoice and all dependencies automatically yay -S hyprvoice-bin # or paru -S hyprvoice-bin - -# Enable user service -systemctl --user enable --now hyprvoice.service ``` -### Download Binary +The AUR package automatically installs all dependencies (`pipewire`, `wl-clipboard`, `wtype`, etc.) and sets up the systemd service. Follow the post-install instructions to complete setup. -1. Download from [GitHub Releases](https://github.com/leonardotrapani/hyprvoice/releases) -2. Install: +### Alternative: Download Binary + +For non-Arch users or testing: ```bash +# Download and install binary wget https://github.com/leonardotrapani/hyprvoice/releases/latest/download/hyprvoice-linux-x86_64 mkdir -p ~/.local/bin mv hyprvoice-linux-x86_64 ~/.local/bin/hyprvoice @@ -40,6 +39,9 @@ chmod +x ~/.local/bin/hyprvoice # Add to PATH (add to ~/.bashrc or ~/.zshrc) export PATH="$HOME/.local/bin:$PATH" + +# You'll need to manually install dependencies and create systemd service +# See Requirements section above ``` ### Build from Source @@ -47,83 +49,67 @@ export PATH="$HOME/.local/bin:$PATH" ```bash git clone https://github.com/leonardotrapani/hyprvoice.git cd hyprvoice - -# Install Go dependencies go mod download - -# Build the binary go build -o hyprvoice ./cmd/hyprvoice -# Install locally (optional) -sudo cp hyprvoice /usr/local/bin/ - -# Or install to user directory +# Install locally mkdir -p ~/.local/bin cp hyprvoice ~/.local/bin/ -export PATH="$HOME/.local/bin:$PATH" # Add to ~/.bashrc or ~/.zshrc +export PATH="$HOME/.local/bin:$PATH" ``` ## Requirements - **Wayland desktop** (Hyprland, Niri, GNOME, KDE, etc.) - **PipeWire audio system** with tools -- **System packages**: +- **OpenAI API key** (for transcription) + +**System packages** (automatically installed with AUR package): + +- `pipewire`, `pipewire-pulse`, `pipewire-audio` - Audio capture +- `wl-clipboard` - Clipboard integration +- `wtype` - Text typing +- `libnotify` - Desktop notifications +- `systemd` - User service management + +For manual installation on other distros: ```bash -# Arch Linux -sudo pacman -S pipewire pipewire-pulse pw-record wl-clipboard - # Ubuntu/Debian -sudo apt install pipewire-pulse pipewire-bin wl-clipboard +sudo apt install pipewire-pulse pipewire-bin wl-clipboard wtype libnotify-bin # Fedora -sudo dnf install pipewire-utils wl-clipboard +sudo dnf install pipewire-utils wl-clipboard wtype libnotify ``` -**For text injection:** - -```bash -# Arch Linux -sudo pacman -S wtype - -# Ubuntu/Debian -sudo apt install wtype - -# Alternative: ydotool (if wtype unavailable) -# Follow ydotool setup for user permissions -``` - -**Optional:** - -- `notify-send` (desktop notifications) -- `systemd --user` (daemon service) - ## Quick Start -1. **Setup daemon service:** +After installing via AUR: +1. **Configure hyprvoice interactively:** ```bash -# Enable and start the user service (reccomended) -systemctl --user enable --now hyprvoice.service +hyprvoice configure +``` +This wizard will guide you through setting up your OpenAI API key, audio preferences, and other settings. -# Or run manually in background -hyprvoice serve & +2. **Enable and start the service:** +```bash +systemctl --user enable --now hyprvoice.service ``` -2. **Configure Hyprland keybind:** - +3. **Add keybinding to your window manager:** ```bash -# Add to ~/.config/hypr/hyprland.conf +# For Hyprland, add to ~/.config/hypr/hyprland.conf bind = SUPER, R, exec, hyprvoice toggle ``` -3. **Test voice input:** +4. **Test voice input:** ```bash # Check daemon status hyprvoice status -# Toggle recording (or use Super+R) +# Toggle recording (or use your keybind) hyprvoice toggle # Speak something... hyprvoice toggle # Stop and transcribe @@ -134,6 +120,9 @@ hyprvoice toggle # Stop and transcribe ### Common Commands ```bash +# Interactive configuration wizard +hyprvoice configure + # Start the daemon hyprvoice serve @@ -198,7 +187,21 @@ hyprvoice status ## Configuration -Configuration is automatically loaded from `~/.config/hyprvoice/config.toml`. The daemon creates this file with sensible defaults and helpful comments on first run. Changes to the config file are applied immediately without restarting the daemon. +Use the interactive configuration wizard: + +```bash +hyprvoice configure +``` + +This will guide you through setting up: + +- OpenAI API key for transcription +- Language preferences (auto-detect or specific language) +- Text injection method (clipboard/typing/fallback) +- Notification settings +- Recording timeout + +Configuration is stored in `~/.config/hyprvoice/config.toml` and can also be edited manually. Changes are applied immediately without restarting the daemon. ### Transcription Providers @@ -326,33 +329,24 @@ The daemon automatically watches the config file for changes and applies them im - **Recording/Transcription settings**: Applied to new recording sessions - **Invalid configs**: Rejected with error notification, daemon continues with previous config -### Service Configuration +### Service Management -#### Systemd Service - -The daemon runs as a user service: +The systemd user service is automatically installed with the AUR package: ```bash -# Create service file -mkdir -p ~/.config/systemd/user -cat > ~/.config/systemd/user/hyprvoice.service << 'EOF' -[Unit] -Description=Hyprvoice voice-to-text daemon -After=pipewire.service +# Check service status +systemctl --user status hyprvoice.service -[Service] -Type=simple -ExecStart=/usr/local/bin/hyprvoice serve -Restart=on-failure -RestartSec=5 +# Start/stop service +systemctl --user start hyprvoice.service +systemctl --user stop hyprvoice.service -[Install] -WantedBy=default.target -EOF +# Enable/disable autostart +systemctl --user enable hyprvoice.service +systemctl --user disable hyprvoice.service -# Enable and start -systemctl --user daemon-reload -systemctl --user enable --now hyprvoice.service +# View logs +journalctl --user -u hyprvoice.service -f ``` ### File Locations @@ -372,8 +366,10 @@ systemctl --user enable --now hyprvoice.service | OpenAI transcription | ✅ | HTTP API integration | | Text injection | ✅ | Clipboard + wtype with fallback | | Configuration system | ✅ | TOML-based user settings with hot-reload | +| Interactive setup | ✅ | `hyprvoice configure` wizard for easy setup | | Unit test coverage | ✅ | Comprehensive test suite (100% pass) | -| Installation (AUR etc) | ⏳ | Installation via AUR and easy setup | +| CI/CD Pipeline | ✅ | Automated builds and releases via GitHub Actions | +| Installation (AUR etc) | ✅ | AUR package with automated dependency installation | | Light dictation models | ⏳ | Alternatives to whispers for light and fast dictation | | whisper.cpp support | ⏳ | Local model inference | @@ -563,18 +559,26 @@ hyprvoice status ```bash git clone https://github.com/leonardotrapani/hyprvoice.git cd hyprvoice - -# Install Go dependencies go mod download - -# Build -CGO_ENABLED=1 go build -o hyprvoice ./cmd/hyprvoice - -# Run tests -go test ./... +go build -o hyprvoice ./cmd/hyprvoice # Install locally -sudo cp hyprvoice /usr/local/bin/ +mkdir -p ~/.local/bin +cp hyprvoice ~/.local/bin/ +export PATH="$HOME/.local/bin:$PATH" +``` + +## For Maintainers + +### Publishing to AUR + +See [`packaging/RELEASE.md`](packaging/RELEASE.md) for complete release process including AUR deployment. + +Quick start for AUR: +```bash +# After creating your first GitHub release +cd packaging/ +./setup-aur.sh # One-time AUR repository setup ``` ### Project Structure diff --git a/cmd/hyprvoice/main.go b/cmd/hyprvoice/main.go index d8418ce..505c553 100644 --- a/cmd/hyprvoice/main.go +++ b/cmd/hyprvoice/main.go @@ -1,9 +1,15 @@ package main import ( + "bufio" "fmt" + "os" + "strconv" + "strings" + "time" "github.com/leonardotrapani/hyprvoice/internal/bus" + "github.com/leonardotrapani/hyprvoice/internal/config" "github.com/leonardotrapani/hyprvoice/internal/daemon" "github.com/spf13/cobra" ) @@ -24,6 +30,7 @@ func init() { statusCmd(), versionCmd(), stopCmd(), + configureCmd(), ) } @@ -100,3 +107,223 @@ func stopCmd() *cobra.Command { }, } } + +func configureCmd() *cobra.Command { + return &cobra.Command{ + Use: "configure", + Short: "Interactive configuration setup", + Long: `Interactive configuration wizard for hyprvoice. +This will guide you through setting up: +- OpenAI API key for transcription +- Audio and text injection preferences +- Notification settings`, + RunE: func(cmd *cobra.Command, args []string) error { + return runInteractiveConfig() + }, + } +} + +func runInteractiveConfig() error { + fmt.Println("🎤 Hyprvoice Configuration Wizard") + fmt.Println("==================================") + fmt.Println() + + // Load existing config or create default + cfg, err := config.Load() + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + scanner := bufio.NewScanner(os.Stdin) + + // Configure transcription + fmt.Println("📝 Transcription Configuration") + fmt.Println("------------------------------") + + // OpenAI API Key + fmt.Printf("OpenAI API Key (current: %s): ", maskAPIKey(cfg.Transcription.APIKey)) + if scanner.Scan() { + input := strings.TrimSpace(scanner.Text()) + if input != "" { + cfg.Transcription.APIKey = input + } + } + + // Language + fmt.Printf("Language (empty for auto-detect, current: %s): ", cfg.Transcription.Language) + if scanner.Scan() { + input := strings.TrimSpace(scanner.Text()) + cfg.Transcription.Language = input + } + + fmt.Println() + + // Configure injection + fmt.Println("⌨️ Text Injection Configuration") + fmt.Println("--------------------------------") + fmt.Printf("Injection mode [clipboard/type/fallback] (current: %s): ", cfg.Injection.Mode) + if scanner.Scan() { + input := strings.TrimSpace(scanner.Text()) + if input != "" && (input == "clipboard" || input == "type" || input == "fallback") { + cfg.Injection.Mode = input + } + } + + fmt.Printf("Restore clipboard after injection [y/n] (current: %v): ", cfg.Injection.RestoreClipboard) + if scanner.Scan() { + switch strings.TrimSpace(strings.ToLower(scanner.Text())) { + case "y", "yes": + cfg.Injection.RestoreClipboard = true + case "n", "no": + cfg.Injection.RestoreClipboard = false + } + } + + fmt.Println() + + // Configure notifications + fmt.Println("🔔 Notification Configuration") + fmt.Println("-----------------------------") + fmt.Printf("Enable notifications [y/n] (current: %v): ", cfg.Notifications.Enabled) + if scanner.Scan() { + switch strings.TrimSpace(strings.ToLower(scanner.Text())) { + case "y", "yes": + cfg.Notifications.Enabled = true + case "n", "no": + cfg.Notifications.Enabled = false + } + } + + fmt.Println() + + // Configure recording timeout + fmt.Println("⏱️ Recording Configuration") + fmt.Println("---------------------------") + fmt.Printf("Recording timeout in minutes (current: %.0f): ", cfg.Recording.Timeout.Minutes()) + if scanner.Scan() { + input := strings.TrimSpace(scanner.Text()) + if input != "" { + if minutes, err := strconv.Atoi(input); err == nil && minutes > 0 { + cfg.Recording.Timeout = time.Duration(minutes) * time.Minute + } + } + } + + fmt.Println() + + // Validate configuration + if err := cfg.Validate(); err != nil { + fmt.Printf("❌ Configuration validation failed: %v\n", err) + fmt.Println("Please check your inputs and try again.") + return err + } + + // Save configuration + fmt.Println("💾 Saving configuration...") + if err := saveConfig(cfg); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + + fmt.Println("✅ Configuration saved successfully!") + fmt.Println() + + // Show next steps + fmt.Println("🚀 Next Steps:") + fmt.Println("1. Start/restart the daemon: systemctl --user restart hyprvoice.service") + fmt.Println("2. Test voice input: hyprvoice toggle") + fmt.Println() + + configPath, _ := config.GetConfigPath() + fmt.Printf("📁 Config file location: %s\n", configPath) + + return nil +} + +func maskAPIKey(key string) string { + if key == "" { + return "" + } + if len(key) <= 8 { + return "****" + } + return key[:4] + "****" + key[len(key)-4:] +} + +func saveConfig(cfg *config.Config) error { + configPath, err := config.GetConfigPath() + if err != nil { + return err + } + + file, err := os.Create(configPath) + if err != nil { + return fmt.Errorf("failed to create config file: %w", err) + } + defer file.Close() + + configContent := fmt.Sprintf(`# Hyprvoice Configuration +# This file is automatically generated with defaults. +# Edit values as needed - changes are applied immediately without daemon restart. + +# Audio Recording Configuration +[recording] + sample_rate = %d # Audio sample rate in Hz (16000 recommended for speech) + channels = %d # Number of audio channels (1 = mono, 2 = stereo) + format = "%s" # Audio format (s16 = 16-bit signed integers) + buffer_size = %d # Internal buffer size in bytes (larger = less CPU, more latency) + device = "%s" # PipeWire audio device (empty = use default microphone) + channel_buffer_size = %d # Audio frame buffer size (frames to buffer) + timeout = "%s" # Maximum recording duration (e.g., "30s", "2m", "5m") + +# Speech Transcription Configuration +[transcription] + provider = "%s" # Transcription service ("openai" only currently supported) + api_key = "%s" # OpenAI API key (or set OPENAI_API_KEY environment variable) + language = "%s" # Language code (empty for auto-detect, "en", "it", "es", "fr", etc.) + model = "%s" # OpenAI model name ("whisper-1" recommended) + +# Text Injection Configuration +[injection] + mode = "%s" # Injection method ("clipboard", "type", "fallback") + restore_clipboard = %v # Restore original clipboard after injection + wtype_timeout = "%s" # Timeout for direct typing via wtype + clipboard_timeout = "%s" # Timeout for clipboard operations + +# Desktop Notification Configuration +[notifications] + enabled = %v # Enable desktop notifications + type = "%s" # Notification type ("desktop", "log", "none") + +# Mode explanations: +# - "clipboard": Copy text to clipboard only +# - "type": Direct typing via wtype only +# - "fallback": Try typing first, fallback to clipboard if it fails +# +# Language codes: Use empty string ("") for automatic detection, or specific codes like: +# "en" (English), "it" (Italian), "es" (Spanish), "fr" (French), "de" (German), etc. +`, + cfg.Recording.SampleRate, + cfg.Recording.Channels, + cfg.Recording.Format, + cfg.Recording.BufferSize, + cfg.Recording.Device, + cfg.Recording.ChannelBufferSize, + cfg.Recording.Timeout, + cfg.Transcription.Provider, + cfg.Transcription.APIKey, + cfg.Transcription.Language, + cfg.Transcription.Model, + cfg.Injection.Mode, + cfg.Injection.RestoreClipboard, + cfg.Injection.WtypeTimeout, + cfg.Injection.ClipboardTimeout, + cfg.Notifications.Enabled, + cfg.Notifications.Type, + ) + + if _, err := file.WriteString(configContent); err != nil { + return fmt.Errorf("failed to write config content: %w", err) + } + + return nil +} diff --git a/packaging/PKGBUILD b/packaging/PKGBUILD new file mode 100644 index 0000000..853e299 --- /dev/null +++ b/packaging/PKGBUILD @@ -0,0 +1,38 @@ +# Maintainer: Leonardo Trapani +pkgname=hyprvoice-bin +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Voice-powered typing for Wayland/Hyprland" +arch=('x86_64') +url="https://github.com/leonardotrapani/hyprvoice" +license=('MIT') +depends=( + 'pipewire' + 'pipewire-pulse' + 'pipewire-audio' + 'wl-clipboard' + 'wtype' + 'libnotify' + 'systemd' +) +optdepends=( + 'hyprland: For Hyprland window manager integration' + 'sway: For Sway window manager integration' +) +provides=('hyprvoice') +conflicts=('hyprvoice') +source=( + "hyprvoice-${pkgver}::https://github.com/leonardotrapani/hyprvoice/releases/download/v${pkgver}/hyprvoice-linux-x86_64" + "hyprvoice.service" +) +sha256sums=('SKIP' # Update this with: updpkgsums after first release + 'SKIP') # Update this with: sha256sum hyprvoice.service +install=hyprvoice.install + +package() { + # Install binary + install -Dm755 "hyprvoice-${pkgver}" "${pkgdir}/usr/bin/hyprvoice" + + # Install systemd service file + install -Dm644 hyprvoice.service "${pkgdir}/usr/lib/systemd/user/hyprvoice.service" +} diff --git a/packaging/RELEASE.md b/packaging/RELEASE.md new file mode 100644 index 0000000..4b6e654 --- /dev/null +++ b/packaging/RELEASE.md @@ -0,0 +1,110 @@ +# Release Process + +This document describes how to create a new release of hyprvoice. + +## Automated Release Process + +### 1. Create a Release Tag + +```bash +# Make sure you're on main branch with latest changes +git checkout main +git pull origin main + +# Create and push a version tag +git tag v0.1.0 +git push origin v0.1.0 +``` + +### 2. GitHub Actions Automatically: + +- ✅ Builds the binary with CGO for Linux x86_64 +- ✅ Runs all tests +- ✅ Creates a GitHub release with changelog +- ✅ Uploads `hyprvoice-linux-x86_64` binary +- ✅ Generates and uploads SHA256 checksums + +### 3. Update AUR Package + +```bash +cd packaging/ +./update-aur.sh 0.1.0 +``` + +That's it! The script handles everything: +- Updates PKGBUILD version and checksums +- Copies files to AUR repository +- Generates .SRCINFO +- Tests the build +- Commits and pushes to AUR (with confirmation) + +## Manual Release (if needed) + +### Build Binary + +```bash +CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o hyprvoice-linux-x86_64 ./cmd/hyprvoice +``` + +### Create Release + +1. Go to GitHub Releases +2. Click "Create a new release" +3. Tag: `v0.1.0` +4. Release title: `Release 0.1.0` +5. Upload `hyprvoice-linux-x86_64` +6. Publish release + +## Version Scheme + +- **Major.Minor.Patch** (e.g., `0.1.0`) +- **Major**: Breaking changes +- **Minor**: New features, backwards compatible +- **Patch**: Bug fixes, small improvements + +## Complete Release Checklist + +### Pre-release +- [ ] All tests pass: `go test ./...` +- [ ] Binary builds: `go build ./cmd/hyprvoice` +- [ ] Configure command works: `./hyprvoice configure --help` +- [ ] Version bumped in any relevant files +- [ ] Changes documented + +### GitHub Release +- [ ] Create and push version tag: `git tag v0.1.0 && git push origin v0.1.0` +- [ ] Verify GitHub Actions completed successfully +- [ ] Verify binary uploaded to GitHub releases +- [ ] Verify checksums generated + +### AUR Package Update (if AUR package exists) +- [ ] Run complete AUR update: `./packaging/update-aur.sh 0.1.0` +- [ ] Verify AUR package page updated + +### Post-release Verification +- [ ] Test AUR installation: `yay -S hyprvoice-bin` +- [ ] Test configure command: `hyprvoice configure` +- [ ] Test service: `systemctl --user status hyprvoice.service` +- [ ] Update project README if needed + +## Files Updated in Release + +- `packaging/PKGBUILD` - Version and checksums +- GitHub Release - Binary and checksums +- AUR repository - Updated package + +## Troubleshooting + +### Build Fails +- Check that all CGO dependencies are installed +- Ensure Go version matches workflow (1.21+) + +### AUR Package Issues +- Run `makepkg -si` to test locally +- Check checksums match: `updpkgsums` +- Verify binary downloads correctly + +### GitHub Actions Issues +- Check workflow logs in Actions tab +- Ensure tag follows `v*` pattern +- Verify GITHUB_TOKEN has necessary permissions diff --git a/packaging/hyprvoice.install b/packaging/hyprvoice.install new file mode 100644 index 0000000..956f464 --- /dev/null +++ b/packaging/hyprvoice.install @@ -0,0 +1,43 @@ +post_install() { + echo "==> Hyprvoice installation complete!" + echo "" + echo " 📋 Next steps (in order):" + echo " 1. Configure hyprvoice: hyprvoice configure" + echo " 2. Enable the service: systemctl --user enable --now hyprvoice.service" + echo " 3. Add keybinding to your window manager config" + echo "" + echo " 🔑 For Hyprland, add to ~/.config/hypr/hyprland.conf:" + echo " bind = SUPER, R, exec, hyprvoice toggle" + echo "" + echo " 💡 The configure step will guide you through API key setup and preferences." + echo "" +} + +post_upgrade() { + echo "==> Hyprvoice has been upgraded." + echo "" + echo " 📋 Next steps:" + echo " 1. Restart the service: systemctl --user restart hyprvoice.service" + echo " 2. Check for new options: hyprvoice configure" + echo "" +} + +pre_remove() { + # Stop and disable service if running + if systemctl --user is-active --quiet hyprvoice.service 2>/dev/null; then + echo "==> Stopping hyprvoice service..." + systemctl --user stop hyprvoice.service 2>/dev/null || true + fi + + if systemctl --user is-enabled --quiet hyprvoice.service 2>/dev/null; then + echo "==> Disabling hyprvoice service..." + systemctl --user disable hyprvoice.service 2>/dev/null || true + fi +} + +post_remove() { + echo "==> Hyprvoice has been removed." + echo " Configuration files remain in ~/.config/hyprvoice/" + echo " Cache files remain in ~/.cache/hyprvoice/" + echo " Remove them manually if desired." +} diff --git a/packaging/hyprvoice.service b/packaging/hyprvoice.service new file mode 100644 index 0000000..0deb979 --- /dev/null +++ b/packaging/hyprvoice.service @@ -0,0 +1,15 @@ +[Unit] +Description=Hyprvoice voice-to-text daemon +Documentation=https://github.com/leonardotrapani/hyprvoice +After=pipewire.service +Wants=pipewire.service + +[Service] +Type=simple +ExecStart=/usr/bin/hyprvoice serve +Restart=on-failure +RestartSec=5 +Environment=XDG_RUNTIME_DIR=/run/user/%i + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/packaging/update-aur.sh b/packaging/update-aur.sh new file mode 100755 index 0000000..b948439 --- /dev/null +++ b/packaging/update-aur.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# Complete script to update AUR package after a new release + +set -e + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 0.1.0" + exit 1 +fi + +VERSION=$1 +AUR_DIR="../hyprvoice-bin" + +echo "🚀 Updating AUR package for version $VERSION..." +echo "" + +# Check if we're in the packaging directory +if [ ! -f "PKGBUILD" ]; then + echo "❌ Error: PKGBUILD not found. Run this from the packaging/ directory." + exit 1 +fi + +# Check if AUR directory exists +if [ ! -d "$AUR_DIR" ]; then + echo "❌ Error: AUR directory not found at $AUR_DIR" + echo " Expected structure:" + echo " ├── hyprvoice/ # Main repo" + echo " │ └── packaging/ # You are here" + echo " └── hyprvoice-bin/ # AUR repo" + echo "" + echo " Run the initial AUR setup first." + exit 1 +fi + +# Update version in PKGBUILD +echo "📝 Updating version to $VERSION..." +sed -i "s/pkgver=.*/pkgver=${VERSION}/" PKGBUILD + +# Update checksums +echo "🔐 Updating checksums..." +if ! updpkgsums; then + echo "❌ Error: Failed to update checksums." + echo " Make sure GitHub release v$VERSION exists and is accessible." + exit 1 +fi + +# Copy files to AUR repo +echo "📋 Copying files to AUR repository..." +cp PKGBUILD "$AUR_DIR/" +cp hyprvoice.service "$AUR_DIR/" +cp hyprvoice.install "$AUR_DIR/" + +# Switch to AUR directory +cd "$AUR_DIR" + +# Generate .SRCINFO +echo "📄 Generating .SRCINFO..." +makepkg --printsrcinfo > .SRCINFO + +# Test build +echo "🔨 Testing package build..." +if ! makepkg --noextract --nodeps; then + echo "❌ Error: Package build failed." + exit 1 +fi + +echo "✅ Package build successful!" +echo "" + +# Show git status +echo "📊 AUR repository status:" +git status --short + +echo "" +echo "🚀 Ready to publish to AUR:" +echo " git add ." +echo " git commit -m \"Update to version $VERSION\"" +echo " git push origin master" +echo "" + +read -p "Push to AUR now? (y/N): " push_confirm +if [[ $push_confirm == [yY] ]]; then + git add . + git commit -m "Update to version $VERSION" + git push origin master + echo "" + echo "🎉 Successfully updated AUR package to v$VERSION!" + echo " AUR page: https://aur.archlinux.org/packages/hyprvoice-bin" +else + echo "📝 To push later:" + echo " cd $AUR_DIR" + echo " git add . && git commit -m \"Update to version $VERSION\" && git push" +fi + +echo "" +echo "✅ AUR update complete!" \ No newline at end of file diff --git a/packaging/update-pkgbuild.sh b/packaging/update-pkgbuild.sh new file mode 100755 index 0000000..e1dcd4c --- /dev/null +++ b/packaging/update-pkgbuild.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Helper script to update PKGBUILD after a new release + +set -e + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 0.1.0" + exit 1 +fi + +VERSION=$1 +echo "Updating PKGBUILD for version $VERSION..." + +# Update version in PKGBUILD +sed -i "s/pkgver=.*/pkgver=${VERSION}/" PKGBUILD + +# Update checksums +echo "Updating checksums..." +updpkgsums + +echo "✅ PKGBUILD updated for version $VERSION" +echo "" +echo "Next steps:" +echo "1. Review the changes: git diff" +echo "2. Test the package: makepkg -si" +echo "3. Commit and push to AUR" \ No newline at end of file