Adds sync-beta.yml: triggers on push to master, merges master into
beta using RELEASE_TOKEN (admin — same mechanism auto-tag.yml uses to
push CHANGELOG commits to protected master). Skips gracefully if beta
does not exist yet or is already up to date.
Note: commits with [skip ci] suppress all workflow runs; those commits
are picked up on the next real push to master.
- Add release-beta.yml: triggers on push to beta, creates
v{CARGO}-beta.N pre-release tags with prerelease: true, builds all
four platforms; tag counter resets when Cargo.toml version bumps
- Add beta to test.yml push triggers so CI runs on direct pushes to
beta (pull_request already covers PRs targeting beta)
- Implement update_channel in AppSettings (state.rs) with serde
default "stable"; wire get/set_update_channel commands to AppState
instead of returning hardcoded stubs
- Implement channel-aware check_app_updates: queries /releases?limit=20
and picks first non-draft release matching the active channel
(stable = !prerelease, beta = prerelease), skipping drafts
- Document two-channel strategy in docs/wiki/CICD-Pipeline.md
Manual steps still required in Gitea UI:
1. Create beta branch from master
2. Apply same branch protection rules as master to beta
3. Set repo default PR target branch to beta
- Detect pre-release tags (containing -rc, -alpha, -beta, -pre, -dev)
- Set prerelease: true in Gitea release API call
- Build jobs now respect pre-release status
- Follow anthropics/claude-code code-review workflow precisely
- Add PR_BODY to prompt for author intent context
- Implement 4 parallel analysis agents (2 CLAUDE.md compliance, 2 bug detectors)
- Focus on HIGH SIGNAL issues only (no nitpicks, style, speculative)
- Add validation step to verify findings against codebase
- Consider PR title/description and prior review history
- Check for pre-existing issues and avoid false positives
- Search full codebase to verify functions/variables are properly implemented
Change RENOVATE_ENDPOINT from /api/v3 to /api/v1. Gitea uses v1 for all
API routes; the /api/v3 path returns 404 which Renovate surfaces as an
authentication failure.
- Apply cargo fmt to src-tauri/src/commands/kube.rs (CI was failing)
- Update pr-review.yml to use qwen3-coder-next model via liteLLM
- Add TICKET-kube-ui-feature-parity.md gap analysis for FreeLens parity
Co-Authored-By: TFTSR Engineering <noreply@tftsr.com>
git-cliff's --tag flag sets the display label for unreleased commits;
it does not scope commits to a range. Passing a range string to --tag
caused git-cliff to emit the full cumulative history for every release.
Move the revision range from --tag to a positional argument so only
commits between PREV_TAG and CURRENT_TAG appear in each release body.
CHANGELOG.md generation is unaffected (still full history).
Add a new 'Fetch PR comment history' step that pulls both review posts
and issue comments from the Gitea API before the LLM is called.
The full comment history is injected into the prompt with an explicit
instruction to silently discard any finding already marked as invalid,
acknowledged as intentional, or confirmed fixed in a prior round.
This prevents the reviewer from repeatedly raising refuted findings
across successive push events on the same PR.
The runner environment does not have Node.js in PATH, causing
actions/checkout@v4 and renovatebot/github-action@v41.0.0 (both JS
actions) to fail at startup.
Use renovate/renovate:latest as the job container and invoke the
renovate binary directly via run:, consistent with how all other
workflows in this repo handle checkout and tooling. The Checkout step
was also unnecessary — Renovate manages its own git operations.
Fix for dbus-1 and webkit build errors:
'Package dbus-1 was not found in the pkg-config search path'
**Problem:**
rustlang/rust:nightly is a minimal image with only rustc/cargo.
Tauri requires system libraries: webkit2gtk, dbus, gtk, ssl, etc.
Without these, cargo build fails with missing pkg-config packages.
**Solution:**
Added system dependency installation step to all Rust jobs:
- libwebkit2gtk-4.1-dev (WebView)
- libdbus-1-dev (D-Bus IPC)
- libgtk-3-dev (GTK UI)
- libayatana-appindicator3-dev (System tray)
- librsvg2-dev (SVG rendering)
- libssl-dev (OpenSSL)
- pkg-config (Build tool)
**Changed Jobs:**
- rust-fmt-check: Added system deps before rustfmt
- rust-clippy: Added system deps before clippy
- rust-tests: Added system deps before tests
**Why Each Job Needs Deps:**
All jobs run 'cargo' commands which trigger dependency builds.
Even 'cargo fmt' can trigger builds if dependencies aren't cached.
System libraries must be present for Tauri crates to compile.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix for pxfm-0.1.29 parse error:
'feature `edition2024` is required'
**Problem:**
The pxfm dependency (via moxcms → image processing) requires edition2024,
which is NOT stabilized even in Rust 1.83 stable. Error:
'edition2024 is not stabilized in this version of Cargo (1.83.0)'
**Solution:**
Switched all CI jobs from rust:1.83-bookworm to rustlang/rust:nightly.
Nightly builds include unstable features like edition2024.
**Changed:**
- rust-fmt-check: rust:1.83 → rustlang/rust:nightly
- rust-clippy: rust:1.83 → rustlang/rust:nightly
- rust-tests: rust:1.83 → rustlang/rust:nightly
**Why Nightly:**
Edition2024 is still unstable in Rust 1.83 (released Oct 2024).
Some dependencies in the image processing chain require it.
Nightly is the only option until edition2024 stabilizes.
**Note:**
Local development may use stable Rust if dependency versions are locked.
CI uses nightly to handle bleeding-edge dependencies.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix for Cargo.toml parse error:
'feature `edition2024` is required'
**Problem:**
The toml crate v1.1.2 requires Rust edition2024 feature, which is not
stabilized in Rust 1.82. This causes cargo to fail with:
'feature `edition2024` is required... requires the nightly release'
**Solution:**
Upgraded all workflow jobs from rust:1.82-bookworm to rust:1.83-bookworm.
Rust 1.83 includes the stabilized edition2024 support.
**Changed:**
- rust-fmt-check: rust:1.82 → rust:1.83
- rust-clippy: rust:1.82 → rust:1.83
- rust-tests: rust:1.82 → rust:1.83
**Note:**
Local development uses whatever rustc is installed (currently 1.83+).
CI now matches this requirement.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix for CI failures in rust:1.82-bookworm container:
- 'cargo-clippy' is not installed
- 'cargo-fmt' is not installed
**Solution:**
Added rustup component installation steps:
- rust-fmt-check job: Install rustfmt before format check
- rust-clippy job: Install clippy before linting
**Why Needed:**
The rust:1.82-bookworm Docker image is a minimal Rust installation.
It includes rustc and cargo, but NOT rustfmt or clippy by default.
These must be explicitly installed with 'rustup component add'.
**Verified Locally:**
- ✅ cargo fmt --check passes
- ✅ cargo clippy -- -D warnings passes (0 warnings)
- ✅ cargo test passes (308 tests)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix for CI failure: 'exec: "node": executable file not found in /Users/sarman/.local/bin:/Users/sarman/.bun/bin:/Users/sarman/.codeium/windsurf/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/Users/sarman/.local/bin:/Users/sarman/.opencode/bin:/Users/sarman/.cargo/bin:/opt/homebrew/opt/gnu-sed/libexec/gnubin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/opt/local/bin:/opt/local/sbin:/usr/local/opt/coreutils/libexec/gnubin:/opt/metasploit-framework/bin:/Users/sarman/git/SQL:/Users/sarman/git/mass-scripts:/Users/sarman/gitpersonal:/Users/sarman/git/scripts:/Users/sarman/git/sysadmin-util:/usr/local/mysql/bin:/opt/bin/:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/Applications/iTerm.app/Contents/Resources/utilities:/libexec/bin:/Users/sarman/bin/:/Users/sarman/bin/mass_scripts/:/usr/local/Cellar/mysql/5.7.21/bin:/usr/local/mariadb10/bin:/Users/sarman/bin/scripts:/Users/sarman/bin/SQL/:/Users/sarman/bin/bert_scripts/:/Users/sarman/bin/ecw/:/Users/sarman/bin/mass-scripts/:/Users/sarman/bin/nhudson:/Users/sarman/bin/personal/:/Users/sarman/bin/python_learning/:/Users/sarman/bin/svn/:/Users/sarman/sysadmin-util/:/Users/sarman/was_scripts/:/Users/sarman/.lmstudio/bin:/Users/sarman/.lmstudio/bin:/Users/sarman/.claude/plugins/cache/claude-plugins-official/swift-lsp/1.0.0/bin:/Users/sarman/.claude/plugins/cache/claude-plugins-official/rust-analyzer-lsp/1.0.0/bin:/Users/sarman/.claude/plugins/cache/knowledge-work-plugins/productivity/1.3.0/bin:/Users/sarman/.claude/plugins/cache/knowledge-work-plugins/customer-support/1.3.0/bin:/Users/sarman/.claude/plugins/cache/knowledge-work-plugins/product-management/1.2.0/bin:/Users/sarman/.claude/plugins/cache/knowledge-work-plugins/engineering/1.2.0/bin'
**Problem:**
- actions/cache@v4 requires Node.js to be installed
- rust:1.82-bookworm container doesn't include Node.js
- Installing Node.js in every job just for caching is wasteful
**Solution:**
- Removed all actions/cache@v4 steps from test.yml
- Self-hosted Gitea runners have local disk - caching less critical
- Simplifies workflow and removes Node.js dependency from Rust-only jobs
**Changes:**
- Removed cache step from rust-fmt-check job
- Removed cache step from rust-clippy job
- Removed cache step from rust-tests job
- Kept Node.js install only in rust-fmt-check (needs it for npm/version script)
**Verified Locally:**
- ✅ All format checks pass
- ✅ All clippy checks pass (0 warnings)
- ✅ All 308 Rust tests pass
- ✅ All 92 frontend tests pass
- ✅ TypeScript compiles (0 errors)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical fixes for Gitea compatibility:
1. **Removed .github/ directory completely**
- dependabot.yml (GitHub-only, not supported by Gitea)
- GitHub workflows (replaced by .gitea/workflows)
- CODEOWNERS, AZURE_BOARDS_INTEGRATION.md, COPILOT_SETUP.md
- These files are GitHub-specific and won't work in Gitea
2. **Fixed remaining URLs to use internal IP**
- pr-review.yml: LITELLM_URL gitea.tftsr.com:11434 → 172.0.0.29:11434
- build-images.yml: Updated comments with correct IP
- All CI runners MUST use 172.0.0.29 (internal IP)
3. **Verified branch naming**
- This repo uses 'master' (not 'main')
- All workflows correctly reference 'master'
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace custom CI image with public rust image to fix workflow failures.
Add Node.js installation step for rust-fmt-check job.
The custom image (gitea.tftsr.com:3000/sarman/trcaa-linux-amd64:rust1.88-node22)
needs to be built via build-images workflow first.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Quote shell:: argument to fix YAML parsing error at line 121.
The double colon was being interpreted as a YAML mapping value.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update test workflow with shell module tests.
- Add dedicated shell module test step to .gitea/workflows/test.yml
- Tests run with --test-threads=1 for consistency
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Three issues addressed together:
1. Race condition (was PR #56): changelog job now CREATES the Gitea
release rather than assuming build jobs have already created it.
Build jobs continue to use create-or-skip + upload unchanged.
2. Detached HEAD push: 'git push origin master' fails when HEAD is
detached (no local branch named master). Changed to 'HEAD:master'.
3. git-cliff tag guard: verify tag is present locally before running
git-cliff, to fail fast with a clear message rather than silently
generating a wrong changelog.
4. git commit idiom: replaced 'git commit || echo' (swallows all
non-zero exit codes including real failures) with an explicit
'git diff --staged --quiet' guard so set -euo pipefail is not
undermined.
The changelog job checks out a specific SHA (detached HEAD) then
commits CHANGELOG.md and tries to push with 'git push origin master'.
Since there is no local branch named 'master', git rejects the push
with 'src refspec master does not match any'.
Fix: use 'git push origin HEAD:master' which explicitly maps the
current detached HEAD to the remote master branch regardless of
local branch state.
Addresses the review warning: git rev-parse confirms the tag is
present in the local repo after git fetch --tags before git-cliff
or git tag --sort= runs against it. Fails fast with a clear error
if the tag is missing rather than silently generating an incomplete
changelog.
The changelog and build-* jobs all fan out from autotag in parallel.
Build jobs create the Gitea release with 'curl ... || true', but the
changelog job was trying to GET the release before any build job had
run, reliably failing with 'Could not find release for tag vX.Y.Z'.
Fix: changelog job owns release creation. It creates the release with
the git-cliff body if it does not exist, or patches the body if a
prior run already created it. Build jobs continue using their existing
create-or-skip + upload pattern unchanged.
The 147KB JSON body was being passed as a shell argument to curl,
hitting the kernel ARG_MAX limit. Write it to /tmp/body.json via
jq redirection and use curl --data @/tmp/body.json instead.
bash printf treats format strings starting with '-' as option flags in
some environments. The POSIX-safe idiom is 'printf "%s\n" content'
where the format is always "%s\n" and the content is an argument.
Applied to all prompt printf calls. Also replaced '--' in prompt text
with single '-' to eliminate any remaining double-dash ambiguity.
1. SECRET_PATTERN had [A-Za-z0-9+/_\-!@#] -- backslash-escaped hyphen
is invalid POSIX ERE; grep parsed it as a range with invalid bounds.
Fix: move hyphen to end of class: [A-Za-z0-9+/_!@#-].
2. printf -- '---\n' fails with 'invalid option' in bash because the
builtin does not accept -- as end-of-options. Removed -- from all
four printf calls.
Shell heredocs with unindented bodies (line 1 content) terminate YAML
run: | block scalars. The YAML parser sees the unindented heredoc body
as leaving the block, making the workflow file unparseable -- Gitea
silently stops creating runs for a workflow with invalid YAML.
Replace the single-quoted heredoc prompt with a group of printf + cat
calls. Every line stays properly indented within the YAML block scalar.
Use jq --rawfile instead of --arg to load the prompt from a temp file,
which also eliminates shell escaping hazards for large strings.
Gitea 1.22 cancel-in-progress does not behave like GitHub Actions: when
a new synchronize event arrives while a review is running, instead of
cancelling the running job and starting a new one, it drops the new run
silently. Remove the concurrency block entirely so every commit to a PR
gets its own review run.
The PROMPT string contained backtick-quoted text for the Evidence field
example. Inside a double-quoted bash string, backticks trigger command
substitution, causing 'exact: command not found' at runtime.
Fix: build the prompt using a single-quoted heredoc (no shell expansion
inside) then splice dynamic values via sed and python3 replace() instead
of shell variable interpolation.
Two changes to reduce hallucinations in pr-review:
1. Codebase index (new step "Build codebase index"):
Generates a compact manifest of everything that EXISTS in the project:
- All registered Tauri commands (from lib.rs generate_handler![])
- All TypeScript exports (from tauriCommands.ts)
- All public Rust fn signatures in commands/
- All DB migration names
This index is prepended to the prompt so the model cannot invent
functions like authenticate_sudo or continue_chat_history that are
absent from both the index and the file contents.
2. Full-repo verification (updated "Verify findings" step):
Previously only grepped changed files, which falsely tagged findings
about unchanged-but-real code as UNVERIFIED. Now runs git ls-files
to load all tracked source files, so verification only fails for
code that genuinely does not exist anywhere in the codebase.
If qwen3-coder continues to hallucinate after these changes, swap the
model name on line 184 to bedrock-personal or claude-haiku.
qwen3-coder-next fabricates plausible-looking code in its Evidence
blocks instead of quoting from the actual files provided. This adds a
Python verification step that greps each fenced code block against the
real changed files and tags any finding whose evidence cannot be found
as UNVERIFIED.
This is a safeguard, not a fix — the model is fundamentally unreliable
for grounded code review. The longer-term fix is to replace qwen3-coder
with a model that stays grounded to context (Claude Haiku, devstral,
or deepseek-coder-v2 via the LiteLLM proxy / vLLM at 172.0.1.42).
The previous regex matched any line containing "password", "token", etc.
near certain punctuation characters. This silently removed function
signatures, variable declarations, and test assertions from the context
sent to the LLM — causing it to hallucinate 3 BLOCKERs per review:
- "function signature missing" (the `password: &str` param was scrubbed)
- "filter body empty" (the filter condition containing "password" was scrubbed)
- "password passed unencrypted" (the decrypt_token call line was scrubbed)
Fix: match actual credential VALUES only:
- Well-known token formats (AKIA..., ghp_..., xox...)
- keyword = "long_quoted_literal" (25+ chars, clearly a value not a name)
- Standalone base64 blob lines (60+ chars, PEM-style)
Never scrub a line just because it contains a credential-related word.
Three changes:
- Exclude Cargo.lock/lockfiles from the diff — removes ~163 lines of
hash noise that waste the review budget with no value
- Raise line cap from 500 to 3000 and add a truncation notice when
the diff is cut, so the model knows the diff is incomplete
- Harden prompt: require quoted evidence for every finding; add explicit
self-verification step for missing-identifier claims (search full diff
before raising); tighten no-hallucinate instruction