Commit Graph

16 Commits

Author SHA1 Message Date
viettranx 0c44149fad test: speed up retry/cron/facebook tests, drop coverage ratchet gate
Slow tests were dominating CI feedback time and AI dev loop because they
waited through real exponential backoffs and 1s ticker intervals.
Test-only override pattern keeps production behavior 100% identical.

Speed wins (no-race wall-clock per package):
- internal/vault            16.3s -> 0.6s   (-15.7s)
- internal/cron             11.7s -> 1.5s   (-10.2s)
- internal/channels/facebook 6.3s -> 3.0s   (-3.3s)
- Full -race ./... suite     90s+ -> 51s

Changes:
- vault: new fastBackoffsForTest(t) helper overrides enrichRetryBackoffs
  + enrichRetryTimeouts to 1ms in 3 retry tests; drop 2 duplicate tests
  (FirstAttemptSuccess, MaxRetriesConstant)
- cron: extract runLoopTickInterval as package var (default 1s); test-only
  setFastTick(t) helper shortens to 20ms so 6 scheduler tests no longer
  sleep 1.5s each waiting for a tick
- facebook: extract graphBackoffBase as package var (default 1s); newFakeGraph
  helper shortens to 1ms so HTTP retry tests don't burn 6s of real waits

Coverage ratchet removed:
- Delete scripts/check_coverage.go + scripts/coverage_thresholds.json
- Remove "Coverage ratchet gate" CI step
- Keep coverage profile + go tool cover summary as informational only
- Philosophy: signal over coverage %. Forced tests to bump % were the
  root cause of the slowness this commit unwinds.

Production behavior unchanged. Coverage profile shows isolated package
coverage matches prior thresholds (vault 27.4%, cron 73.7%, facebook 81.9%).
2026-04-11 23:53:07 +07:00
viettranx e3993ee50e fix(ci): check_coverage preserves thresholds in --update mode
The preserve-loop that backfills threshold entries for packages not
present in the current coverage profile was gated on `!*update`, which
meant `go run scripts/check_coverage.go --update` with a narrow
coverprofile silently wiped floors for every package not measured.
Discovered while ratcheting wave C with a package-scoped profile.

Move the preserve-loop out of the gate so it runs in both check and
update modes. Narrow profiles now touch only observed packages and
leave the rest untouched.
2026-04-11 23:14:53 +07:00
viettranx 26f2279b1c build(ci): ratchet bump wave C coverage floors + changelog
- scripts/coverage_thresholds.json: feishu 0 → 63.89, acp 0 → 80.05.
  Minor drift auto-normalized: backup 18.80 → 19.88,
  facebook 81.80 → 81.85, providers 62.15 → 62.53,
  store/pg 3.45 → 3.51, tools 26.61 → 26.59 (precision)
- docs/17-changelog.md: "Deferred Coverage Waves A-C — Resolved" entry
2026-04-11 22:45:13 +07:00
viettranx f2c43c3849 test(facebook,store/pg): wave B coverage push
Phase 03 - facebook 23.1% -> 81.9% (+58.8%, target ≥60%)
  graph_api_test.go: NewGraphClient, VerifyToken, SubscribeApp, GetPost,
  GetComment, GetCommentThread, ReplyToComment, SendMessage, SendTypingOn,
  doRequest retry/backoff matrix (5xx retry, 401 non-retry, 429+Retry-After,
  context cancel during backoff, transport error + retry), 551/subcode 24h
  window non-retry, logRateLimit parse branches.

  handlers_test.go: New required-field validation (4 branches), Factory
  valid+malformed, WebhookHandler single-shot route, handleAPIError health
  state mapping, handleCommentEvent (feature gate, edit/remove drop, page
  routing, self-reply skip, dedup, enriched content path), handleMessagingEvent
  (feature gate, page routing, self skip, receipt drop, text+postback dispatch,
  dedup), Send Messenger+comment paths + missing-metadata error, sendFirstInbox
  one-shot dedup, runDedupCleaner stale eviction, Stop closes deps, webhookRouter
  register/unregister/route-once/ServeHTTP-no-instances, PostFetcher (defaults,
  empty-id, cache hit/miss/expired, error propagation, GetCommentThread
  empty+delegate).

  Minimal refactor: converted package-level graphAPIBase const to var so tests
  can point at httptest server. KISS, zero runtime behavior change.

Phase 04 - store/pg 1.3% -> 3.5% (+2.2%, unit-test-only)
  scan_rows_test.go: pure-logic transformation tests for agentShareRow,
  userInstanceRow, documentInfoRow, documentDetailRow, chunkInfoRow,
  scoredChunkRow, episodicSummaryRow, episodicScoredRow, sessionListRow,
  sessionPagedRow, sessionRichRow, entityRow, entityTemporalRow, relationRow,
  relationExportRow, traversalRow, dedupCandidateRow, mcpAccessRequestRow,
  cronRunLogRow, skillInfoRow+skillInfoRowWithFrontmatter, customSkillExportRow,
  parseDepsColumn, parseFrontmatterAuthor, marshalFrontmatter, buildSkillInfo,
  mergeEpisodicScores, hybridMerge.

  pure_logic_test.go: matchWildcard pattern matching, evalPermRows priority
  resolution (individual deny > individual allow > group deny > group allow),
  contactResolveCache get/set/expired/negative cache.

  Finding: 30% target not reachable with unit tests alone. Store/pg is
  fundamentally DB-bound (~6000 LOC of SQL code vs ~200 LOC pure logic).
  Reaching 30% requires running integration tests with TEST_DATABASE_URL and
  -coverpkg=./internal/store/pg/ — which the current CI ratchet does NOT
  do. Confirmed: integration tests yield 32% coverage on store/pg, but that
  requires a wired-up test database in CI. Deferred as infrastructure change
  outside Phase 04 scope.

Ratchet bumps (scripts/coverage_thresholds.json):
- internal/channels/facebook: 23.08 -> 81.80
- internal/store/pg: 1.28 -> 3.45

Race clean, dual build (default + -tags sqliteonly) clean.
2026-04-11 21:47:22 +07:00
viettranx abc6d62c95 test(providers,zalo): wave A coverage push
Push two deferred packages above their coverage floors:
- internal/providers 57.0% -> 62.2% (+5.2%, target ≥60%)
  Targeted pure-logic adapter transformation code: registry,
  openai/dashscope/codex ToRequest/FromResponse/FromStreamChunk,
  Azure header branch, token source propagation, function_call +
  incomplete + reasoning parse branches.

- internal/channels/zalo 7.2% -> 65.3% (+58.1%, target ≥20%)
  Factory table-driven creds/config cases, New() defaults, callAPI
  success/error/malformed, getMe/getUpdates, sendMessage/sendPhoto,
  Send routing + photo extraction, Stop signal, processUpdate
  dispatch, handleTextMessage empty-sender drop, downloadMedia four
  branches (png/jpg fallback/404/empty).

Minimal refactor: converted package-level apiBase const to var in
internal/channels/zalo/zalo.go so tests can point at httptest server.
Zero runtime behavior change; tests restore the original value via
t.Cleanup.

Ratchet bumps (scripts/coverage_thresholds.json):
- internal/providers: 57.00 -> 62.15
- internal/channels/zalo: 7.20 -> 65.25

Race clean, dual build (default + -tags sqliteonly) clean,
personal/ sub-packages untouched.
2026-04-11 21:29:32 +07:00
viettranx 27c9415193 build(ci): add coverage ratchet gate with per-package floors
Add automated coverage floor validation:
- scripts/check_coverage.go: parses coverage.out, compares to per-package
  thresholds, supports --update to lock current floors
- scripts/coverage_thresholds.json: 61 packages, initial floors from Phase 1
- .github/workflows/ci.yaml: new 'Coverage ratchet gate' step in CI
- internal/testutil/: test utilities (context builders, TestDB, doc.go)
2026-04-11 21:22:23 +07:00
Viet Tran 52c67d6d92 feat(build): embed web UI in backend binary + simplify Docker variants (#620)
- Add internal/webui/ package with //go:build embedui tag for optional
  SPA embedding (handler.go serves static files with SPA fallback)
- Add internal/version/ shared semver comparison (DRY: extracted from
  gateway/update_check.go and updater/updater.go)
- Enhance UpdateChecker: release notes, ETag caching, filter lite-v* tags
- Add web UI build stage to Dockerfile with ENABLE_EMBEDUI build arg
- Simplify CI: 7 Docker variants → 4 (base, latest, full, otel)
- Add SHA256 checksums job to release workflow
- Add Makefile build-full target (embeds web UI in Go binary)
- Default make up now embeds web UI (no separate nginx needed)
- Add WITH_WEB_NGINX=1 flag for optional nginx reverse proxy
- Update README + 30 translated READMEs: make up, port 18790
- Update docker-compose comments and prepare-env.sh
- About dialog: show release notes with markdown rendering
- Health card: amber badge for available updates

BREAKING: Default Docker setup no longer requires selfservice overlay.
Web dashboard served at :18790 (same port as API).
2026-04-01 15:25:59 +07:00
Kai (Tam Nhu) Tran 4c60dd021e fix: clarify container-scoped runtime warnings for minimal images (#395)
* fix(ui): clarify container-scoped runtime warnings

* docs(runtime): clarify docker image variant expectations

* test(tools): align media path expectations with workspace policy

* docs(tests): narrow message media path contract wording
2026-03-30 21:44:53 +07:00
viettranx b373561f72 fix(desktop): fetch up to 100 releases to find lite-v* tags
GitHub API returns 30 releases by default. With 30+ v2.x releases,
lite-v* tags were pushed out of page 1 causing "No desktop release
found" error.
2026-03-27 23:44:59 +07:00
viettranx e1b8217e45 fix(desktop): keep PowerShell window open on install errors
Add Exit-WithPause helper that waits for keypress before closing the
window, so users can read error messages when fetch/download fails.
2026-03-27 23:37:06 +07:00
viettranx 4102d4f321 fix(scripts): auto-launch app after install on macOS and Windows 2026-03-27 12:23:29 +07:00
viettranx c2cb37afcf fix(desktop): improve Windows install script error handling
- SilentlyContinue progress preference (10x faster download)
- try/catch on API + download calls with colored error messages
- Non-fatal shortcut creation (works without admin)
- Colored output for better UX
2026-03-27 10:32:10 +07:00
viettranx e5175a044a fix(desktop): install script pipefail on missing release
grep returns exit 1 when no lite-v* tags exist yet, which
pipefail propagates before the -z check. Add || true.
2026-03-27 10:31:03 +07:00
viettranx b9c1731e31 feat(desktop): packaging, auto-update, CI/CD, and install scripts
- GitHub Actions: release-desktop.yaml builds macOS (arm64+amd64) + Windows
  on lite-v* tag push, creates DMG + tar.gz + zip GitHub Release assets
- Install scripts: install-lite.sh (macOS curl) + install-lite.ps1 (Windows PowerShell)
- Auto-update: internal/updater checks GitHub Releases, downloads + atomic
  app swap with path traversal guards, size limits, symlink handling
- UpdateBanner: thin notification bar with download progress + restart
- Wails bindings: CheckForUpdate, ApplyUpdate (server-cached, no URL from JS),
  RestartApp (graceful gateway shutdown before exit)
- AboutTab: dynamic version from backend via GetVersion()
- Windows build assets: icon.ico, info.json, wails.exe.manifest
- Makefile: desktop-dev, desktop-build, desktop-dmg targets
- README: Desktop Edition section with install commands + feature comparison
- .gitignore: desktop packaging artifacts, SQLite DB files, update backups

Security: HTTPS-only downloads, io.LimitReader on all extractions,
zip/tar path traversal validation, symlink target guard, no untrusted
URL from frontend (ApplyUpdate uses server-cached info).
2026-03-27 10:15:15 +07:00
Thieu Nguyen 7f19db14f5 fix(install): bundle migrations in release tarball and install script (#249)
The install script only copied the binary, so `goclaw migrate up` and
`goclaw onboard` failed when run from the installed location because the
migrations directory was missing.

- Include migrations/ in the release tarball
- Install migrations to /usr/local/share/goclaw/migrations
- Guide users to export GOCLAW_MIGRATIONS_DIR before onboard
- Align next-steps output with onboard's own instructions
2026-03-18 07:32:53 +07:00
Goon 9429a7c844 ci: publish Docker images to GHCR and Docker Hub (#237)
* feat(ci): add node/python/full runtime variants to Docker publish

Add runtime image variants alongside existing build-tag variants:
- :node (pre-installed Node.js)
- :python (pre-installed Python)
- :full (Node.js + Python + all skill deps)

* feat(ci): add install scripts, release binaries, and Discord notifications

- scripts/install.sh: one-liner binary installer from GitHub Releases
- scripts/setup-docker.sh: interactive Docker setup with variant selection
  (alpine/node/python/full), auto-generates .env + docker-compose.yaml
  with persistent volumes for data, skills, workspace, storage
- release.yaml: build cross-platform binaries (linux/darwin × amd64/arm64)
  and attach to GitHub Release, notify Discord on new releases
- .gitignore: ignore Apple Double (._*) files from external volumes

* docs(docker): add pre-built image references and update docker-compose workflows

- Add `image:` directives to docker-compose.yml, docker-compose.selfservice.yml, and docker-compose.upgrade.yml pointing to ghcr.io/nextlevelbuilder/goclaw pre-built images
- Add Docker Hub mirror references (digitop/goclaw) for public access
- Document available image tags (latest, node, python, full, otel, tsnet, redis) with descriptions
- Update README with pre-built image pull instructions and semver tag examples
- Clarify deployment workflows: use pre-built images by default (no --build), add --build only when building from source
- Update upgrade workflow to pull pre-built images instead of rebuild
- Add note about build args requirement for otel/tsnet/redis overlays
- Update .dockerignore to exclude macOS temp files (._*)

* fix(ci): use claude_code_oauth_token instead of anthropic_api_key
2026-03-17 12:44:18 +07:00