diff --git a/.claude/skills/release_strix/SKILL.md b/.claude/skills/release_strix/SKILL.md new file mode 100644 index 0000000..27a6c07 --- /dev/null +++ b/.claude/skills/release_strix/SKILL.md @@ -0,0 +1,169 @@ +--- +name: release_strix +description: Full release of Strix -- merge develop to main, tag, build multiarch Docker image, push to Docker Hub, update hassio-strix, create GitHub Release. +disable-model-invocation: true +--- + +# Strix Release + +You are performing a full release of Strix. Follow every step exactly. Do NOT skip steps. Do NOT ask for confirmation except where explicitly noted below. + +## Repositories + +- Strix: `/home/user/Strix` +- hassio-strix: `/home/user/hassio-strix` + +## Step 1: Gather information + +```bash +cd /home/user/Strix +git checkout develop +git pull origin develop +git pull origin main + +# Get last release tag +git tag --sort=-version:refname | head -1 + +# Show all commits since last release +git log main..develop --oneline + +# Show changed files +git diff main..develop --stat +``` + +## Step 2: Ask for version (THE ONLY QUESTION) + +Use AskUserQuestion to ask the user which version to release. + +Show them: +- The last tag +- The list of commits from Step 1 + +Offer options: +- Next patch (e.g. 1.0.9 -> 1.0.10) +- Next minor (e.g. 1.0.9 -> 1.1.0) +- Next major (e.g. 1.0.9 -> 2.0.0) +- Other (user types custom version) + +Wait for answer. Store the chosen version as VERSION (without "v" prefix). + +## Step 3: Verify build + +```bash +cd /home/user/Strix +go test ./... +go build ./... +``` + +If tests or build fail -- STOP and report the error. Do not continue. + +## Step 4: Update CHANGELOG.md + +Read `/home/user/Strix/CHANGELOG.md`. Add a new section at the top (after the header lines), based on the commits from Step 1. Follow the existing format exactly: + +```markdown +## [VERSION] - YYYY-MM-DD + +### Added +- ... + +### Fixed +- ... + +### Changed +- ... +``` + +Use today's date. Categorize commits into Added/Fixed/Changed/Technical sections. Only include sections that have entries. Write clear, user-facing descriptions (not raw commit messages). + +## Step 5: Git -- commit, merge, tag, push + +```bash +cd /home/user/Strix +git add CHANGELOG.md +git commit -m "Release v$VERSION" + +git checkout main +git merge develop --no-ff -m "Merge develop into main for v$VERSION release" +git tag v$VERSION + +git push origin main --tags + +git checkout develop +git merge main +git push origin develop +``` + +## Step 6: Build and push Docker image + +```bash +cd /home/user/Strix +docker buildx build --platform linux/amd64,linux/arm64 \ + --build-arg VERSION=$VERSION \ + -t eduard256/strix:$VERSION \ + -t eduard256/strix:latest \ + -t eduard256/strix:$(echo $VERSION | cut -d. -f1-2) \ + -t eduard256/strix:$(echo $VERSION | cut -d. -f1) \ + --push . +``` + +## Step 7: Verify Docker Hub + +```bash +curl -s "https://hub.docker.com/v2/repositories/eduard256/strix/tags/?page_size=10" | jq '.results[].name' +docker manifest inspect eduard256/strix:$VERSION | jq '.manifests[].platform' +``` + +Verify the new version tag exists and both amd64 and arm64 platforms are present. + +## Step 8: Smoke test + +```bash +docker run --rm -d --name strix-smoke-test -p 14567:4567 eduard256/strix:$VERSION +sleep 5 +curl -s http://localhost:14567/api/v1/health | jq '.version' +docker stop strix-smoke-test +``` + +Verify the health endpoint returns the correct version string. + +## Step 9: Update hassio-strix + +```bash +cd /home/user/hassio-strix +git pull origin main +``` + +Edit `/home/user/hassio-strix/strix/config.json` -- change `"version"` to the new VERSION. + +Edit `/home/user/hassio-strix/strix/CHANGELOG.md` -- add the same CHANGELOG section as in Step 4. + +```bash +cd /home/user/hassio-strix +git add strix/config.json strix/CHANGELOG.md +git commit -m "Release v$VERSION" +git push origin main +``` + +## Step 10: GitHub Release + +```bash +cd /home/user/Strix +PREV_TAG=$(git tag --sort=-version:refname | sed -n '2p') +gh release create v$VERSION \ + --title "v$VERSION" \ + --notes "$(git log --oneline ${PREV_TAG}..v$VERSION)" +``` + +## Step 11: Final report + +Output a summary: + +``` +Release v$VERSION complete: +- Git: tag v$VERSION pushed to main +- Docker Hub: eduard256/strix:$VERSION (amd64 + arm64) +- Health check: version "$VERSION" verified +- hassio-strix: config.json updated to $VERSION, pushed to main +- GitHub Release: +``` diff --git a/.claude/skills/release_strix_dev/SKILL.md b/.claude/skills/release_strix_dev/SKILL.md new file mode 100644 index 0000000..b7b6df9 --- /dev/null +++ b/.claude/skills/release_strix_dev/SKILL.md @@ -0,0 +1,64 @@ +--- +name: release_strix_dev +description: Build and push dev Docker image for Strix, update hassio-strix dev add-on version. +disable-model-invocation: true +--- + +# Strix Dev Build + +You are building and pushing a dev image of Strix. Follow every step exactly. Do NOT ask any questions -- this is fully automated. + +## Repositories + +- Strix: `/home/user/Strix` +- hassio-strix: `/home/user/hassio-strix` + +## Step 1: Get commit hash + +```bash +cd /home/user/Strix +git rev-parse --short HEAD +``` + +Store this as COMMIT_HASH (e.g. `fe93aa3`). + +## Step 2: Build Docker image + +```bash +cd /home/user/Strix +docker build --build-arg VERSION=dev-$COMMIT_HASH -t eduard256/strix:dev -t eduard256/strix:dev-$COMMIT_HASH . +``` + +## Step 3: Push to Docker Hub + +```bash +docker push eduard256/strix:dev +docker push eduard256/strix:dev-$COMMIT_HASH +``` + +## Step 4: Update hassio-strix + +```bash +cd /home/user/hassio-strix +git pull origin main +``` + +Edit `/home/user/hassio-strix/strix-dev/config.json` -- change `"version"` to `dev-$COMMIT_HASH`. + +```bash +cd /home/user/hassio-strix +git add strix-dev/config.json +git commit -m "Dev build dev-$COMMIT_HASH" +git push origin main +``` + +## Step 5: Report + +Output a summary: + +``` +Dev build complete: +- Commit: $COMMIT_HASH +- Docker Hub: eduard256/strix:dev, eduard256/strix:dev-$COMMIT_HASH (amd64) +- hassio-strix: strix-dev version updated to dev-$COMMIT_HASH +``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 3c74083..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - test: - name: Test - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Cache Go modules - uses: actions/cache@v4 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Download dependencies - run: go mod download - - - name: Run tests - run: go test -v -race -coverprofile=coverage.txt -covermode=atomic ./... - - - name: Build - run: make build - - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Run golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - version: latest diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 1c87e3e..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Docker Build and Push - -on: - push: - branches: - - main - tags: - - 'v*' - pull_request: - branches: - - main - -env: - REGISTRY: docker.io - IMAGE_NAME: eduard256/strix - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Docker Hub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value=latest,enable={{is_default_branch}} - - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - build-args: | - VERSION=${{ steps.meta.outputs.version }} - - - name: Docker Hub Description - if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v4 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - repository: ${{ env.IMAGE_NAME }} - readme-filepath: ./README.md - short-description: "Smart IP Camera Stream Discovery System" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index a91af3b..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Release - -on: - push: - tags: - - 'v*' - -permissions: - contents: write - -jobs: - goreleaser: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v6 - with: - distribution: goreleaser - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml deleted file mode 100644 index 4bb62ef..0000000 --- a/.goreleaser.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# GoReleaser configuration for Strix -version: 2 - -before: - hooks: - - go mod tidy - - go mod download - -builds: - - id: strix - main: ./cmd/strix/main.go - binary: strix - env: - - CGO_ENABLED=0 - goos: - - linux - - windows - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - "7" - ignore: - - goos: windows - goarch: arm - - goos: darwin - goarch: arm - ldflags: - - -s -w - - -X main.Version={{.Version}} - - -X main.BuildDate={{.Date}} - - -X main.GitCommit={{.ShortCommit}} - -archives: - - id: strix-archive - format: tar.gz - name_template: >- - {{ .ProjectName }}_ - {{- .Version }}_ - {{- .Os }}_ - {{- if eq .Arch "amd64" }}x86_64 - {{- else if eq .Arch "386" }}i386 - {{- else }}{{ .Arch }}{{ end }} - {{- if .Arm }}v{{ .Arm }}{{ end }} - format_overrides: - - goos: windows - format: zip - files: - - README.md - - LICENSE - - webui/**/* - - cameras/**/* - -checksum: - name_template: 'checksums.txt' - algorithm: sha256 - -changelog: - sort: asc - use: github - filters: - exclude: - - '^docs:' - - '^test:' - - '^chore:' - - typo - groups: - - title: '🚀 Features' - regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$' - order: 0 - - title: '🐛 Bug Fixes' - regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$' - order: 1 - - title: '📝 Documentation' - regexp: '^.*?docs(\([[:word:]]+\))??!?:.+$' - order: 2 - - title: '🔧 Other' - order: 999 - -release: - github: - owner: eduard256 - name: Strix - draft: false - prerelease: auto - name_template: "v{{.Version}}" - header: | - ## 🦉 Strix v{{.Version}} - - Smart IP Camera Stream Discovery System - - ### Installation - - Download the appropriate binary for your platform below and extract it. - - ### Usage - - ```bash - ./strix - ``` - - Then open http://localhost:4567 in your browser. - - footer: | - **Full Changelog**: https://github.com/eduard256/Strix/compare/{{ .PreviousTag }}...{{ .Tag }} - -snapshot: - name_template: "{{ incpatch .Version }}-next" - -dist: dist diff --git a/Dockerfile b/Dockerfile index 0f9c41c..600cd56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,8 @@ # Stage 1: Builder FROM golang:1.24-alpine AS builder +ARG VERSION=dev + WORKDIR /build # Install build dependencies @@ -18,7 +20,7 @@ COPY . . # Build static binary RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \ - -ldflags="-s -w -X main.Version=docker" \ + -ldflags="-s -w -X main.Version=${VERSION}" \ -o strix \ cmd/strix/main.go diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index f2cc777..0000000 --- a/RELEASE.md +++ /dev/null @@ -1,281 +0,0 @@ -# Release Process Documentation - -This document describes the complete release process for Strix and its Home Assistant add-on. - -## Overview - -Strix consists of two repositories: -- **Strix** - Main application (Go binary, Docker image) -- **hassio-strix** - Home Assistant add-on - -Both repositories must be released together to maintain version consistency. - -## Version Files - -### Strix Repository - -| File | Line | Purpose | -|------|------|---------| -| `cmd/strix/main.go` | 23 | Application version constant | -| `webui/package.json` | 3 | Frontend version | -| `CHANGELOG.md` | Top | Release notes | - -### hassio-strix Repository - -| File | Line | Purpose | -|------|------|---------| -| `strix/config.json` | 3 | Home Assistant add-on version | -| `strix/CHANGELOG.md` | Top | Release notes | - -## Release Workflow - -### Prerequisites - -1. Ensure you're on the `develop` branch with all changes committed -2. All tests pass: `go test ./...` -3. Application builds successfully: `go build ./...` - -### Step 1: Update Strix Repository - -```bash -cd /home/user/Strix -git checkout develop - -# 1. Update version in code -# Edit cmd/strix/main.go - line 23 -# Version = "1.0.X" - -# 2. Update frontend version -# Edit webui/package.json - line 3 -# "version": "1.0.X" - -# 3. Update CHANGELOG.md -# Add new section at the top: -# ## [1.0.X] - YYYY-MM-DD -# ### Fixed/Added/Changed -# - Description of changes - -# 4. Commit version bump -git add cmd/strix/main.go webui/package.json CHANGELOG.md -git commit -m "Release v1.0.X: Brief description" - -# 5. Merge to main -git checkout main -git merge develop --no-ff -m "Merge develop into main for v1.0.X release" - -# 6. Create tag -git tag -a v1.0.X -m "Release v1.0.X: Brief description" - -# 7. Push everything -git push origin main --tags -git push origin develop -``` - -### Step 2: Update hassio-strix Repository - -```bash -cd /home/user/hassio-strix - -# 1. Update add-on version -# Edit strix/config.json - line 3 -# "version": "1.0.X" - -# 2. Update CHANGELOG -# Edit strix/CHANGELOG.md - add same section as in Strix - -# 3. Commit and push -git add strix/config.json strix/CHANGELOG.md -git commit -m "Release v1.0.X: Brief description" -git push origin main - -# 4. Create tag -git tag -a v1.0.X -m "Release v1.0.X: Brief description" -git push origin --tags -``` - -### Step 3: Verify GitHub Actions - -After pushing tags, GitHub Actions will automatically: - -**Strix (eduard256/Strix):** -- ✅ `release.yml` - GoReleaser creates GitHub Release with binaries -- ✅ `docker.yml` - Builds and pushes Docker images to Docker Hub - - Tags: `1.0.X`, `1.0`, `1`, `latest` - - Platforms: `linux/amd64`, `linux/arm64` - -**hassio-strix (eduard256/hassio-strix):** -- ✅ `builder.yml` - Builds and pushes HA add-on to GHCR - - Image: `ghcr.io/eduard256/hassio-strix-{arch}` - - Architectures: `amd64`, `aarch64` - -Check status: -```bash -# Check Strix actions -gh run list --repo eduard256/Strix --limit 5 - -# Check hassio-strix actions -gh run list --repo eduard256/hassio-strix --limit 5 -``` - -### Step 4: Verify Release - -1. **GitHub Release**: https://github.com/eduard256/Strix/releases/tag/v1.0.X - - Should have binaries for all platforms - -2. **Docker Hub**: https://hub.docker.com/r/eduard256/strix/tags - - Should show new version tag - -3. **GHCR**: https://github.com/eduard256/hassio-strix/pkgs/container/hassio-strix-amd64 - - Should show new version - -4. **Home Assistant Add-on Store**: - - Users will see update notification automatically - -## Quick Release Script - -For automated release, use this script: - -```bash -#!/bin/bash -# release.sh - Automated release script - -VERSION=$1 - -if [ -z "$VERSION" ]; then - echo "Usage: ./release.sh 1.0.X" - exit 1 -fi - -echo "🚀 Releasing v$VERSION" - -# Strix repo -cd /home/user/Strix -git checkout develop - -# Update versions -sed -i "s/Version = \".*\"/Version = \"$VERSION\"/" cmd/strix/main.go -sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" webui/package.json - -# Update CHANGELOG (manual step reminder) -echo "⚠️ Please update CHANGELOG.md manually" -read -p "Press enter when done..." - -# Commit and merge -git add cmd/strix/main.go webui/package.json CHANGELOG.md -git commit -m "Release v$VERSION" -git checkout main -git merge develop --no-ff -m "Merge develop into main for v$VERSION release" -git tag -a "v$VERSION" -m "Release v$VERSION" -git push origin main --tags -git push origin develop - -# hassio-strix repo -cd /home/user/hassio-strix - -# Update version -sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" strix/config.json - -# Update CHANGELOG (manual step reminder) -echo "⚠️ Please update strix/CHANGELOG.md manually" -read -p "Press enter when done..." - -# Commit and tag -git add strix/config.json strix/CHANGELOG.md -git commit -m "Release v$VERSION" -git push origin main -git tag -a "v$VERSION" -m "Release v$VERSION" -git push origin --tags - -echo "✅ Release v$VERSION complete!" -echo "Check GitHub Actions:" -echo " - https://github.com/eduard256/Strix/actions" -echo " - https://github.com/eduard256/hassio-strix/actions" -``` - -## Troubleshooting - -### Docker Build Fails - -**Symptom**: "Docker Hub Description" step shows `Forbidden` error - -**Cause**: Docker Hub Personal Access Token expired or lacks permissions - -**Solution**: -1. Go to Docker Hub → Account Settings → Security → Personal Access Tokens -2. Create new token with `Read, Write, Delete` scopes -3. Update GitHub secret: https://github.com/eduard256/Strix/settings/secrets/actions -4. Update `DOCKER_TOKEN` secret - -**Note**: This only affects README updates on Docker Hub. Docker images still build successfully. - -### Home Assistant Add-on Build Fails - -**Symptom**: Builder workflow fails - -**Solution**: -1. Check `strix/Dockerfile` for correct Go version -2. Verify `strix/build.yaml` has correct base images -3. Check logs: `gh run view --repo eduard256/hassio-strix --log` - -### Version Mismatch - -**Symptom**: Strix shows different version than add-on - -**Solution**: -1. Verify both `cmd/strix/main.go` and `strix/config.json` have same version -2. Ensure both repositories have matching tags: `git tag -l` -3. If needed, delete wrong tag: `git tag -d v1.0.X && git push origin :refs/tags/v1.0.X` - -## Release Checklist - -Before releasing: -- [ ] All changes merged to `develop` -- [ ] Tests pass: `go test ./...` -- [ ] Build succeeds: `go build ./...` -- [ ] CHANGELOG.md updated in both repos -- [ ] Version numbers match in all files -- [ ] Commit messages don't mention AI/Claude Code - -After releasing: -- [ ] GitHub Release created with binaries -- [ ] Docker images pushed to Docker Hub -- [ ] HA add-on images pushed to GHCR -- [ ] Home Assistant users can see update - -## Version Numbering - -Strix follows [Semantic Versioning](https://semver.org/): - -- **MAJOR.MINOR.PATCH** (e.g., 1.0.9) -- **MAJOR**: Breaking changes -- **MINOR**: New features (backward compatible) -- **PATCH**: Bug fixes - -## GitHub Actions Overview - -### Strix Repository - -**Triggers:** -- `release.yml`: On push tag `v*` -- `docker.yml`: On push tag `v*` or push to `main` -- `ci.yml`: On push to any branch - -**Secrets Required:** -- `GITHUB_TOKEN` (automatic) -- `DOCKER_USERNAME` -- `DOCKER_TOKEN` - -### hassio-strix Repository - -**Triggers:** -- `builder.yml`: On push tag `v*` or manual workflow dispatch - -**Secrets Required:** -- `GITHUB_TOKEN` (automatic) - -## Notes - -- Always release both repositories together -- Keep version numbers synchronized -- Test in Home Assistant Ingress mode before releasing -- Docker/direct mode should work without changes (backward compatibility) diff --git a/cmd/strix/main.go b/cmd/strix/main.go index 248a4a0..f89edc4 100644 --- a/cmd/strix/main.go +++ b/cmd/strix/main.go @@ -18,12 +18,12 @@ import ( "github.com/go-chi/chi/v5" ) -const ( - // Version is the application version - Version = "1.0.9" +// Version is set at build time via ldflags: +// +// go build -ldflags="-X main.Version=1.0.10" ./cmd/strix +var Version = "dev" - // Banner is the application banner - Banner = ` +const Banner = ` ███████╗████████╗██████╗ ██╗██╗ ██╗ ██╔════╝╚══██╔══╝██╔══██╗██║╚██╗██╔╝ ███████╗ ██║ ██████╔╝██║ ╚███╔╝ @@ -34,7 +34,6 @@ const ( Smart IP Camera Stream Discovery System Version: %s ` -) func main() { // Print banner @@ -43,6 +42,7 @@ func main() { // Load configuration cfg := config.Load() + cfg.Version = Version // Setup logger slogger := cfg.SetupLogger() diff --git a/internal/api/routes.go b/internal/api/routes.go index a4e6191..7312079 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -139,7 +139,7 @@ func (s *Server) setupRoutes() { // API routes (mounted at /api/v1 in main.go) // Health check - s.router.Get("/health", handlers.NewHealthHandler("1.0.0", s.logger).ServeHTTP) + s.router.Get("/health", handlers.NewHealthHandler(s.config.Version, s.logger).ServeHTTP) // Camera search s.router.Post("/cameras/search", handlers.NewSearchHandler(s.searchEngine, s.logger).ServeHTTP) diff --git a/internal/config/config.go b/internal/config/config.go index 7c0cb58..0bdef72 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,6 +1,7 @@ package config import ( + "encoding/json" "fmt" "log/slog" "os" @@ -14,6 +15,7 @@ import ( // Config holds application configuration type Config struct { + Version string // Application version, set by caller after Load() Server ServerConfig Database DatabaseConfig Scanner ScannerConfig @@ -104,8 +106,14 @@ func Load() *Config { }, } - // Load from strix.yaml if exists + // Load from Home Assistant options.json if running as HA add-on + // Priority: defaults < HA options < strix.yaml < ENV configSource := "default" + if err := loadHAOptions(cfg); err == nil { + configSource = "/data/options.json (Home Assistant)" + } + + // Load from strix.yaml if exists (overrides HA options) if err := loadYAML(cfg); err == nil { configSource = "strix.yaml" } @@ -150,6 +158,42 @@ func loadYAML(cfg *Config) error { return nil } +// haOptions represents the structure of Home Assistant /data/options.json. +// When Strix runs as a Home Assistant add-on, HA creates this file from the +// add-on configuration UI. Fields are optional -- zero values are ignored. +type haOptions struct { + LogLevel string `json:"log_level"` + Port int `json:"port"` +} + +// loadHAOptions loads configuration from Home Assistant's /data/options.json. +// This file only exists when running inside the HA add-on environment. +// Returns an error if the file doesn't exist or can't be parsed (callers +// should treat errors as "not running in HA" and silently continue). +func loadHAOptions(cfg *Config) error { + data, err := os.ReadFile("/data/options.json") + if err != nil { + return err + } + + var opts haOptions + if err := json.Unmarshal(data, &opts); err != nil { + return fmt.Errorf("failed to parse /data/options.json: %w", err) + } + + if opts.LogLevel != "" { + cfg.Logger.Level = opts.LogLevel + } + if opts.Port > 0 { + cfg.Server.Listen = fmt.Sprintf(":%d", opts.Port) + } + + // Home Assistant add-on always uses JSON logging for the HA log viewer + cfg.Logger.Format = "json" + + return nil +} + // validateListen validates the listen address format and port range func validateListen(listen string) error { if listen == "" { diff --git a/webui/package.json b/webui/package.json index a1e8b57..2caef8f 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "webui", - "version": "1.0.9", + "version": "0.0.0", "type": "module", "description": "", "main": "index.js", diff --git a/webui/web/js/main.js b/webui/web/js/main.js index 14978c8..fbe9abf 100644 --- a/webui/web/js/main.js +++ b/webui/web/js/main.js @@ -87,6 +87,12 @@ class StrixApp { // Screen 2: Configuration form document.getElementById('btn-back-to-address').addEventListener('click', () => { + // Clear probe-filled fields so stale data doesn't persist + document.getElementById('camera-model').value = ''; + document.getElementById('camera-model').disabled = false; + document.getElementById('camera-model').placeholder = 'Start typing...'; + document.getElementById('model-disabled-hint').classList.add('hidden'); + this.probeResult = null; this.showScreen('address'); });