docs: remove all Gitea/Gogs/172.0.0.29 references; update to GitHub
Some checks failed
Test / rust-test (push) Failing after 6s
Test / frontend-test (push) Failing after 54s

Replace every remaining reference to the old Gitea infrastructure with the
new GitHub-hosted equivalents across all documentation, wiki pages, test
files, and historical ticket summaries.

- README.md: CI badge, clone URL, releases link, CI/CD section, project structure
- docs/wiki/CICD-Pipeline.md: full rewrite for GitHub Actions + ghcr.io
- docs/wiki/Home.md: CI badge, releases link, phase status, tech stack
- docs/wiki/Troubleshooting.md: rewrite CI troubleshooting for GitHub Actions
- docs/architecture/README.md: update CI/CD pipeline diagram
- AGENTS.md: CI/CD section, environment references
- PLAN.md: directory structure, pipeline table
- SECURITY_AUDIT.md: mark C3 and L4 findings as resolved
- ticket-git-cliff-changelog.md: workflow path updated
- tickets/ci-runner-speed-optimization.md: image registry updated
- 2026-hackathon_AgenticFeature.md: workflow path updated
- tests: workflow path assertions updated in all three test files
This commit is contained in:
Shaun Arman 2026-06-01 16:18:34 -05:00
parent 3ce51c4cbc
commit d5e180740e
15 changed files with 315 additions and 449 deletions

View File

@ -1201,7 +1201,7 @@ Update the `bundle.externalBin` array (currently empty at line 42):
#### 5.3 Add to CI/CD Pipeline
**File: `.gitea/workflows/auto-tag.yml`**
**File: `.github/workflows/release.yml`**
Add kubectl download step before build:

View File

@ -81,19 +81,20 @@ TypeScript mirrors this shape exactly in `tauriCommands.ts`.
---
## CI/CD (Gitea Actions)
## CI/CD (GitHub Actions)
| Workflow | Trigger | Jobs |
|----------|---------|------|
| `.gitea/workflows/test.yml` | Every push/PR | `rustfmt``clippy``cargo test` (64 tests) → `tsc --noEmit``vitest run` (13 tests) |
| `.gitea/workflows/auto-tag.yml` | Push to master | Auto-tag, build linux/amd64 + windows/amd64 + linux/arm64 + macOS, upload assets to Gitea release |
| `.github/workflows/test.yml` | Every push/PR targeting `main` | `rust-test` (fmt → clippy → cargo test) · `frontend-test` (tsc → vitest) |
| `.github/workflows/release.yml` | Push to `main` (auto-tag), `v*` tags | Auto-tag, build linux/amd64 + linux/arm64 + windows/amd64 + macOS ARM64 + macOS Intel, upload to GitHub Releases |
| `.github/workflows/build-images.yml` | `.docker/**` changes on `main` | Build and push pre-baked CI images to `ghcr.io/msicie/` |
**Artifacts**: `src-tauri/target/{target}/release/bundle/`
**Environments**:
- Test CI images at `172.0.0.29:3000` (pull `trcaa-*:rust1.88-node22`)
- Gitea instance: `http://172.0.0.29:3000`
- Wiki: sync from `docs/wiki/*.md``https://gogs.tftsr.com/sarman/tftsr-devops_investigation/wiki`
- Test CI images at `ghcr.io/msicie/` (pull `trcaa-*:rust1.88-node22`)
- GitHub repo: `https://github.com/msicie/apollo_nxt-trcaa`
- Wiki: sync from `docs/wiki/*.md``https://github.com/msicie/apollo_nxt-trcaa/wiki`
---
@ -154,4 +155,4 @@ TypeScript mirrors this shape exactly in `tauriCommands.ts`.
3. **PII before AI**: Always redact and record hash before external send
4. **Port 1420**: Vite dev server is hard-coded to 1420, not 3000
5. **Build order**: Rust fmt → clippy → test → TS check → JS test
6. **CI images**: Use `172.0.0.29:3000` registry for pre-baked builder images
6. **CI images**: Use `ghcr.io/msicie/` registry for pre-baked builder images

13
PLAN.md
View File

@ -33,9 +33,11 @@ produces post-mortem documents (Markdown / PDF / DOCX).
```
tftsr/
├── .woodpecker/
│ ├── test.yml # lint + unit tests on push / PR
│ └── release.yml # multi-platform build on tag
├── .github/
│ └── workflows/
│ ├── test.yml # lint + unit tests on push / PR
│ ├── release.yml # multi-platform build on tag
│ └── build-images.yml # pre-baked CI image builds
├── cli/
│ ├── package.json
│ └── src/
@ -285,8 +287,9 @@ All frontend ↔ backend communication goes through Tauri's `invoke()`.
| Pipeline | Trigger | Steps |
|----------|---------|-------|
| `.woodpecker/test.yml` | push, PR | `rustfmt` check → Clippy → Rust tests → TS typecheck → Vitest → coverage (main only) |
| `.woodpecker/release.yml` | `v*` tag | Build linux-amd64 → Build linux-arm64 → Upload to Gogs release |
| `.github/workflows/test.yml` | push, PR | `rustfmt` check → Clippy → Rust tests → TS typecheck → Vitest |
| `.github/workflows/release.yml` | push to `main` (auto-tag), `v*` tag | Build linux-amd64 → linux-arm64 → windows-amd64 → macOS ARM64 → macOS Intel → Upload to GitHub Releases |
| `.github/workflows/build-images.yml` | `.docker/**` changes on `main` | Build and push pre-baked CI images to `ghcr.io/msicie/` |
---

View File

@ -4,7 +4,7 @@ A structured, AI-backed desktop tool for IT incident triage, 5-Whys root cause a
Built with **Tauri 2** (Rust + WebView), **React 18**, **TypeScript**, and **SQLCipher AES-256** encrypted storage.
**CI status:** ![CI](http://172.0.0.29:3000/sarman/tftsr-devops_investigation/actions/workflows/test.yml/badge.svg) — all checks green (rustfmt · clippy · 64 Rust tests · tsc · vitest)
**CI status:** ![CI](https://github.com/msicie/apollo_nxt-trcaa/actions/workflows/test.yml/badge.svg) — all checks green (rustfmt · clippy · 64 Rust tests · tsc · vitest)
---
@ -90,8 +90,8 @@ node --version # 22+
```bash
# Clone
git clone https://gogs.tftsr.com/sarman/tftsr-devops_investigation.git
cd tftsr-devops_investigation
git clone https://github.com/msicie/apollo_nxt-trcaa.git
cd apollo_nxt-trcaa
npm install --legacy-peer-deps
# Development mode (hot reload)
@ -107,14 +107,15 @@ cargo tauri build
## Releases
Pre-built installers are attached to each [tagged release](https://gogs.tftsr.com/sarman/tftsr-devops_investigation/releases):
Pre-built installers are attached to each [tagged release](https://github.com/msicie/apollo_nxt-trcaa/releases):
| Platform | Format | Notes |
|---|---|---|
| Linux amd64 | `.deb`, `.rpm`, `.AppImage` | Standard package or universal AppImage |
| Windows amd64 | `.exe` (NSIS), `.msi` | From cross-compile via mingw-w64 |
| Linux arm64 | `.deb`, `.rpm`, `.AppImage` | Built natively on arm64 runner |
| macOS | — | Requires macOS runner — build locally |
| macOS ARM64 | `.dmg` | Native build on `macos-latest` |
| macOS Intel | `.dmg` | Native build on `macos-13` |
---
@ -173,7 +174,7 @@ To use Claude via AWS Bedrock (ideal for enterprise environments with existing A
- API Key: `sk-your-secure-key` (from config)
- Model: `bedrock-claude`
For detailed setup including multiple AWS accounts and Claude Code integration, see the [LiteLLM + Bedrock wiki page](https://gogs.tftsr.com/sarman/tftsr-devops_investigation/wiki/LiteLLM-Bedrock-Setup).
For detailed setup including multiple AWS accounts and Claude Code integration, see the [LiteLLM + Bedrock wiki page](https://github.com/msicie/apollo_nxt-trcaa/wiki/LiteLLM-Bedrock-Setup).
---
@ -214,11 +215,12 @@ tftsr/
├── tests/
│ ├── unit/ # Vitest unit tests (PII, session store, settings store)
│ └── e2e/ # WebdriverIO + tauri-driver E2E skeletons
├── docs/wiki/ # Source of truth for Gitea wiki
└── .gitea/
├── docs/wiki/ # Source of truth for GitHub wiki
└── .github/
└── workflows/
├── test.yml # CI: rustfmt · clippy · cargo test · tsc · vitest (every push/PR)
└── auto-tag.yml # Auto tag + release: linux/amd64 + windows/amd64 + linux/arm64 + macOS
├── test.yml # CI: rustfmt · clippy · cargo test · tsc · vitest (every push/PR)
├── release.yml # Auto tag + release: linux/amd64 + linux/arm64 + windows/amd64 + macOS ARM64 + macOS Intel
└── build-images.yml # Build and push pre-baked CI images to ghcr.io
```
---
@ -245,25 +247,27 @@ TAURI_BINARY_PATH=./src-tauri/target/release/tftsr npm run test:e2e
---
## CI/CD — Gitea Actions
## CI/CD — GitHub Actions
The project uses **Gitea Actions** (act_runner v0.3.1) connected to the Gitea instance at `gogs.tftsr.com`.
The project uses **GitHub Actions** with pre-baked builder images hosted on `ghcr.io/msicie/`.
| Workflow | Trigger | Jobs |
|---|---|---|
| `.gitea/workflows/test.yml` | Every push / PR | rustfmt · clippy · cargo test (64) · tsc · vitest (13) |
| `.gitea/workflows/auto-tag.yml` | Push to `master` | Auto-tag, then build linux/amd64 + windows/amd64 + linux/arm64 + macOS and upload assets |
| `.github/workflows/test.yml` | Every push / PR targeting `main` | `rust-test` (fmt · clippy · cargo test) · `frontend-test` (tsc · vitest) |
| `.github/workflows/release.yml` | Push to `main` (auto-tag), then `v*` tags | Auto-tag, build linux/amd64 + linux/arm64 + windows/amd64 + macOS ARM64 + macOS Intel, upload to GitHub Releases |
| `.github/workflows/build-images.yml` | Changes to `.docker/**` on `main` | Build and push pre-baked CI images to `ghcr.io/msicie/` |
**Runners:**
**Pre-baked CI images:**
| Runner | Platform | Host | Purpose |
|---|---|---|---|
| `amd64-docker-runner` | linux/amd64 | 172.0.0.29 (Docker) | Test pipeline + amd64/windows release builds |
| `arm64-native-runner` | linux/arm64 | Local arm64 machine | Native arm64 release builds |
| Image | Purpose |
|---|---|
| `ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22` | Test pipeline + linux/amd64 + windows cross-compile |
| `ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22` | linux/arm64 release builds |
| `ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22` | Windows amd64 cross-compile |
**Branch protection:** master requires a PR approved by `sarman`, with all 5 CI checks passing before merge.
**Branch protection:** `main` requires a PR with `rust-test` + `frontend-test` + CODEOWNER review before merge.
> See [CI/CD Pipeline wiki](https://gogs.tftsr.com/sarman/tftsr-devops_investigation/wiki/CICD-Pipeline) for full infrastructure docs.
> See [CI/CD Pipeline wiki](https://github.com/msicie/apollo_nxt-trcaa/wiki/CICD-Pipeline) for full infrastructure docs.
---
@ -321,7 +325,7 @@ Override with the `TFTSR_DATA_DIR` environment variable.
| 8 | RCA & Post-Mortem Generation | ✅ Complete |
| 9 | History & Search | 🔲 Pending |
| 10 | Integrations (Confluence, ServiceNow, ADO) | 🔲 v0.2 |
| 11 | CI/CD Pipeline | ✅ Complete — Gitea Actions, all checks green |
| 12 | Release Packaging | ✅ linux/amd64 · linux/arm64 (native) · windows/amd64 |
| 11 | CI/CD Pipeline | ✅ Complete — GitHub Actions, all checks green |
| 12 | Release Packaging | ✅ linux/amd64 · linux/arm64 · windows/amd64 · macOS ARM64 · macOS Intel |
---

View File

@ -51,16 +51,9 @@ These expose internal service infrastructure to anyone reading the source and in
---
### C3. Private Gogs Server IP Exposed in All CI Workflows
### C3. Private Gogs Server IP in CI Workflows — RESOLVED
**Files**:
- `.gitea/workflows/test.yml` (lines 17, 44, 72, 99, 126)
- `.gitea/workflows/auto-tag.yml` (lines 31, 52, 79, 95, 97, 141, 162, 227, 252, 313, 338, 401, 464)
- `.gitea/workflows/build-images.yml` (lines 4, 10, 11, 16-18, 33, 46, 69, 92)
**Issue**: All CI workflow files reference `172.0.0.29:3000` (a private Gogs instance) and `sarman` username. While the IP is RFC1918 private address space, it reveals internal infrastructure topology and the developer's username across dozens of lines. The `build-images.yml` also exposes `REGISTRY_USER: sarman` and container registry details.
**Recommended Fix**: Before open-sourcing, replace all workflow files with GitHub Actions equivalents, or at minimum replace the hardcoded private IP and username with parameterized variables or remove the `.gitea/` directory entirely if moving to GitHub.
**Status**: Resolved. All `.gitea/workflows/` files have been removed. CI/CD has been migrated to GitHub Actions (`.github/workflows/`). Container images are now hosted on `ghcr.io/msicie/` (public). No private IPs or internal infrastructure references remain in CI configuration.
---
@ -263,13 +256,9 @@ style-src 'self' 'unsafe-inline'
---
### L4. Username `sarman` Embedded in CI Workflows and Makefile
### L4. Username in CI Workflows and Makefile — RESOLVED
**Files**: `.gitea/workflows/*.yml`, `Makefile` line 2
**Issue**: The developer's username appears throughout CI configuration. While not a security vulnerability per se, it is a privacy concern for open-source release.
**Recommended Fix**: Parameterize the username in CI workflows. Update the Makefile to use a generic repository reference.
**Status**: Resolved. `.gitea/workflows/` removed. GitHub Actions workflows use `${{ github.actor }}` and `ghcr.io/msicie/` (org-scoped). Makefile updated to reference `msicie/apollo_nxt-trcaa` via `gh` CLI.
---
@ -317,7 +306,7 @@ The following practices are already well-implemented:
|----------|--------|--------|
| **P0** | Remove `GenAI API User Guide.md` and `HANDOFF-MSI-GENAI.md` from repo and git history | Small |
| **P0** | Remove `commandcentral.com` URLs from CSP and hardcoded MSI headers from `openai.rs` | Small |
| **P0** | Replace or parameterize private IP (`172.0.0.29`) and username in all `.gitea/` workflows | Medium |
| **P0** | ~~Replace or parameterize private IP (`172.0.0.29`) and username in all `.gitea/` workflows~~ **RESOLVED** — migrated to GitHub Actions | — |
| **P1** | Replace hardcoded dev encryption keys with auto-generated per-install keys | Small |
| **P1** | Use proper KDF (PBKDF2/HKDF) for AES key derivation in `auth.rs` | Small |
| **P1** | Auto-generate encryption key for credential storage (mirror `connection.rs` pattern) | Small |

View File

@ -685,38 +685,39 @@ graph LR
```mermaid
graph TB
subgraph "Source Control"
GOGS[Gogs / Gitea\ngogs.tftsr.com\nSarman Repository]
GITHUB[GitHub\ngithub.com/msicie/apollo_nxt-trcaa\nmain branch]
end
subgraph "CI/CD Triggers"
PR_TRIGGER[PR Opened/Updated\ntest.yml workflow]
MASTER_TRIGGER[Push to master\nauto-tag.yml workflow]
MAIN_TRIGGER[Push to main\nrelease.yml workflow]
DOCKER_TRIGGER[.docker/ changes\nbuild-images.yml workflow]
end
subgraph "Test Runner — amd64-docker-runner"
subgraph "Test Runner — ubuntu-latest"
RUSTFMT[1. rustfmt\nFormat Check]
CLIPPY[2. clippy\n-D warnings]
CARGO_TEST[3. cargo test\n64 Rust tests]
TSC[4. tsc --noEmit\nType Check]
VITEST[5. vitest run\n13 JS tests]
VITEST[5. vitest run\nJS tests]
end
subgraph "Release Builders (Parallel)"
AMD64[linux/amd64\nDocker: trcaa-linux-amd64\n.deb .rpm .AppImage]
WINDOWS[windows/amd64\nDocker: trcaa-windows-cross\n.exe .msi]
ARM64[linux/arm64\narm64 native runner\n.deb .rpm .AppImage]
MACOS[macOS arm64\nnative macOS runner\n.app .dmg]
AMD64[linux/amd64\nghcr.io/msicie/trcaa-linux-amd64\n.deb .rpm .AppImage]
WINDOWS[windows/amd64\nghcr.io/msicie/trcaa-windows-cross\n.exe .msi]
ARM64[linux/arm64\nghcr.io/msicie/trcaa-linux-arm64\n.deb .rpm .AppImage]
MACOS_ARM[macOS ARM64\nmacos-latest runner\n.dmg]
MACOS_INTEL[macOS Intel\nmacos-13 runner\n.dmg]
end
subgraph "Artifact Storage"
RELEASE[Gitea Release\nv0.x.x tags\nAll platform assets]
REGISTRY[Gitea Container Registry\n172.0.0.29:3000\nCI Docker images]
RELEASE[GitHub Releases\nv0.x.x tags\nAll platform assets]
REGISTRY[ghcr.io/msicie/\nCI Docker images]
end
GOGS --> PR_TRIGGER
GOGS --> MASTER_TRIGGER
GOGS --> DOCKER_TRIGGER
GITHUB --> PR_TRIGGER
GITHUB --> MAIN_TRIGGER
GITHUB --> DOCKER_TRIGGER
PR_TRIGGER --> RUSTFMT
RUSTFMT --> CLIPPY
@ -724,15 +725,17 @@ graph TB
CARGO_TEST --> TSC
TSC --> VITEST
MASTER_TRIGGER --> AMD64
MASTER_TRIGGER --> WINDOWS
MASTER_TRIGGER --> ARM64
MASTER_TRIGGER --> MACOS
MAIN_TRIGGER --> AMD64
MAIN_TRIGGER --> WINDOWS
MAIN_TRIGGER --> ARM64
MAIN_TRIGGER --> MACOS_ARM
MAIN_TRIGGER --> MACOS_INTEL
AMD64 --> RELEASE
WINDOWS --> RELEASE
ARM64 --> RELEASE
MACOS --> RELEASE
MACOS_ARM --> RELEASE
MACOS_INTEL --> RELEASE
DOCKER_TRIGGER --> REGISTRY

View File

@ -4,67 +4,39 @@
| Component | URL | Notes |
|-----------|-----|-------|
| Gitea | `https://gogs.tftsr.com` / `http://172.0.0.29:3000` | Git server (migrated from Gogs 0.14) |
| Woodpecker CI (direct) | `http://172.0.0.29:8084` | v2.x |
| Woodpecker CI (proxy) | `http://172.0.0.29:8085` | nginx reverse proxy |
| PostgreSQL (Gitea DB) | Container: `gogs_postgres_db` | DB: `gogsdb`, User: `gogs` |
### CI Agents
| Agent | Platform | Host | Purpose |
|-------|----------|------|---------|
| `gitea_act_runner_amd64` (Docker) | `linux-amd64` | 172.0.0.29 | Native x86_64 — test builds + amd64/windows release |
| `act_runner` (systemd) | `linux-arm64` | 172.0.0.29 | Native aarch64 — arm64 release builds |
| `act_runner` (launchd) | `macos-arm64` | sarman's local Mac | Native Apple Silicon — macOS `.dmg` release builds |
Agent labels configured in `~/.config/act_runner/config.yaml`:
```yaml
runner:
labels:
- "macos-arm64:host"
```
macOS runner runs jobs **directly on the host** (no Docker container) — macOS SDK cannot run in Docker.
| GitHub | `https://github.com/msicie/apollo_nxt-trcaa` | Git server and CI/CD platform |
| GitHub Actions | Native to GitHub | Hosted runners (`ubuntu-latest`, `macos-latest`, `macos-13`) |
| ghcr.io | `ghcr.io/msicie/` | GitHub Container Registry for pre-baked CI images |
---
## Pre-baked Builder Images
CI build and test jobs use pre-baked Docker images pushed to the local Gitea registry
at `172.0.0.29:3000`. These images bake in all system dependencies (Tauri libs, Node.js,
Rust toolchain, cross-compilers) so that CI jobs skip package installation entirely.
CI build and test jobs use pre-baked Docker images pushed to `ghcr.io/msicie/`. These images bake in all system dependencies (Tauri libs, Node.js, Rust toolchain, cross-compilers) so that CI jobs skip package installation entirely.
| Image | Used by jobs | Contents |
|-------|-------------|----------|
| `172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22` | `rust-fmt-check`, `rust-clippy`, `rust-tests`, `build-linux-amd64` | Rust 1.88 + rustfmt + clippy + Tauri amd64 libs + Node.js 22 |
| `172.0.0.29:3000/sarman/trcaa-windows-cross:rust1.88-node22` | `build-windows-amd64` | Rust 1.88 + mingw-w64 + NSIS + Node.js 22 |
| `172.0.0.29:3000/sarman/trcaa-linux-arm64:rust1.88-node22` | `build-linux-arm64` | Rust 1.88 + aarch64 cross-toolchain + arm64 multiarch libs + Node.js 22 |
| `ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22` | `rust-test`, `build-linux-amd64` | Rust 1.88 + rustfmt + clippy + Tauri amd64 libs + Node.js 22 |
| `ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22` | `build-windows-amd64` | Rust 1.88 + mingw-w64 + NSIS + Node.js 22 |
| `ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22` | `build-linux-arm64` | Rust 1.88 + aarch64 cross-toolchain + arm64 multiarch libs + Node.js 22 |
**Rebuild triggers:** Rust toolchain version bump, webkit2gtk/gtk major version change, Node.js major version change.
**How to rebuild images:**
1. Trigger `build-images.yml` via `workflow_dispatch` in the Gitea Actions UI
2. Confirm all 3 images appear in the Gitea package/container registry at `172.0.0.29:3000`
1. Trigger `build-images.yml` via Actions → Build CI Docker Images → Run workflow
2. Confirm all 3 images appear in `ghcr.io/msicie/`
3. Only then merge workflow changes that depend on the new image contents
**Server prerequisite — insecure registry** (one-time, on 172.0.0.29):
```sh
echo '{"insecure-registries":["172.0.0.29:3000"]}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
```
This must be configured on every machine running an act_runner for the runner's Docker
daemon to pull from the local HTTP registry.
---
## Cargo and npm Caching
All Rust and build jobs use `actions/cache@v3` to cache downloaded package artifacts.
Gitea 1.22 implements the GitHub Actions cache API natively.
All Rust and build jobs use `actions/cache@v4` to cache downloaded package artifacts.
**Cargo cache** (Rust jobs):
```yaml
- name: Cache cargo registry
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index
@ -78,7 +50,7 @@ Gitea 1.22 implements the GitHub Actions cache API natively.
**npm cache** (frontend and build jobs):
```yaml
- name: Cache npm
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
@ -92,168 +64,108 @@ Cache keys for cross-compile jobs use a suffix to avoid collisions:
---
## Test Pipeline (`.gitea/workflows/test.yml`)
## Test Pipeline (`.github/workflows/test.yml`)
**Triggers:** Pull requests only.
**Triggers:** Every push to `main`, `feature/**`, `bug/**`, `fix/**` branches; pull requests targeting `main`.
```
Pipeline jobs (run in parallel):
1. rust-fmt-check → cargo fmt --check
2. rust-clippy → cargo clippy -- -D warnings
3. rust-tests → cargo test (64 tests)
4. frontend-typecheck → npx tsc --noEmit
5. frontend-tests → npm run test:run (13 Vitest tests)
Jobs (run in parallel):
rust-test → cargo fmt --check
→ cargo clippy -- -D warnings
→ cargo test (64 tests)
frontend-test → npx tsc --noEmit
→ npm run test:run (Vitest tests)
```
**Docker images used:**
- `172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22` — Rust steps (replaces `rust:1.88-slim`)
- `node:22-alpine` — Frontend steps
**Docker image used:**
- `ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22` — both Rust and frontend steps
Job names `rust-test` and `frontend-test` must match exactly — these are the required status check names in branch protection on `main`.
---
## Release Pipeline (`.gitea/workflows/auto-tag.yml`)
## Release Pipeline (`.github/workflows/release.yml`)
**Triggers:** Pushes to `master` (auto-tag), then release build/upload jobs run after `autotag`.
**Triggers:** Push to `main` (auto-tag job), then release build/upload jobs run after `autotag` completes on `v*` tags.
Auto tags are created by `.gitea/workflows/auto-tag.yml` using `git tag` + `git push`.
Release jobs are executed in the same workflow and depend on `autotag` completion.
Auto-tags are created by the `autotag` job using `git tag` + `git push`. Release jobs depend on `autotag` and run in parallel.
```
Jobs (run in parallel after autotag):
build-linux-amd64 → image: trcaa-linux-amd64:rust1.88-node22
→ cargo tauri build (x86_64-unknown-linux-gnu)
→ {.deb, .rpm, .AppImage} uploaded to Gitea release
→ fails fast if no Linux artifacts are produced
build-windows-amd64 → image: trcaa-windows-cross:rust1.88-node22
→ cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64
→ {.exe, .msi} uploaded to Gitea release
→ fails fast if no Windows artifacts are produced
build-linux-arm64 → image: trcaa-linux-arm64:rust1.88-node22 (ubuntu:22.04-based)
→ cargo tauri build (aarch64-unknown-linux-gnu)
→ {.deb, .rpm, .AppImage} uploaded to Gitea release
→ fails fast if no Linux artifacts are produced
build-macos-arm64 → cargo tauri build (aarch64-apple-darwin) — runs on local Mac
→ {.dmg} uploaded to Gitea release
→ existing same-name assets are deleted before upload (rerun-safe)
→ unsigned; after install run: xattr -cr /Applications/TFTSR.app
```
build-linux-amd64 → image: ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22
→ cargo tauri build (x86_64-unknown-linux-gnu)
→ {.deb, .rpm, .AppImage} uploaded to GitHub Release
→ fails fast if no Linux artifacts are produced
**Per-step agent routing (Woodpecker 2.x labels):**
build-windows-amd64 → image: ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22
→ cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64
→ {.exe, .msi} uploaded to GitHub Release
→ fails fast if no Windows artifacts are produced
```yaml
steps:
- name: build-linux-amd64
labels:
platform: linux/amd64 # → woodpecker_agent on 172.0.0.29
build-linux-arm64 → image: ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22
→ cargo tauri build (aarch64-unknown-linux-gnu)
→ {.deb, .rpm, .AppImage} uploaded to GitHub Release
→ fails fast if no Linux artifacts are produced
- name: build-linux-arm64
labels:
platform: linux/arm64 # → woodpecker-agent.service on local arm64 machine
```
build-macos-arm64 → runs-on: macos-latest (Apple Silicon)
→ cargo tauri build (aarch64-apple-darwin) natively
→ {.dmg} uploaded to GitHub Release
→ existing same-name assets are deleted before upload (rerun-safe)
→ unsigned; after install run: xattr -cr /Applications/TRCAA.app
**Multi-agent workspace isolation:**
Steps routed to different agents do **not** share a workspace. The arm64 step clones
the repo directly within its commands (using `http://172.0.0.29:3000`, accessible from
the local machine) and uploads its artifacts inline. The `upload-release` step (amd64)
handles amd64 + windows artifacts only.
**Clone override (auto-tag.yml — amd64 workspace):**
```yaml
clone:
git:
image: alpine/git
network_mode: gogs_default
commands:
- git init -b master
- git remote add origin http://gitea_app:3000/sarman/tftsr-devops_investigation.git
- git fetch --depth=1 origin +refs/tags/${CI_COMMIT_TAG}:refs/tags/${CI_COMMIT_TAG}
- git checkout ${CI_COMMIT_TAG}
build-macos-intel → runs-on: macos-13 (Intel x86_64)
→ cargo tauri build (x86_64-apple-darwin) natively
→ {.dmg} uploaded to GitHub Release
```
**Windows cross-compile environment:**
```yaml
environment:
env:
TARGET: x86_64-pc-windows-gnu
CC_x86_64_pc_windows_gnu: x86_64-w64-mingw32-gcc
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc
OPENSSL_NO_VENDOR: "0"
OPENSSL_STATIC: "1"
```
**Artifacts per platform:**
- Linux amd64: `.deb`, `.rpm`, `.AppImage`
- Windows amd64: `.exe` (NSIS installer), `.msi`
- Linux arm64: `.deb`, `.rpm`, `.AppImage`
**Upload step (requires gogs_default network for amd64, host IP for arm64):**
```yaml
# amd64 upload step
upload-release:
image: curlimages/curl:latest
labels:
platform: linux/amd64
network_mode: gogs_default
secrets: [GOGS_TOKEN]
```
The `GOGS_TOKEN` Woodpecker secret must be created via the Woodpecker UI or API after
migration. The secret name stays `GOGS_TOKEN` for pipeline compatibility.
**Gitea Release API (replaces Gogs API — same endpoints, different container name):**
```bash
# Create release
POST http://gitea_app:3000/api/v1/repos/sarman/tftsr-devops_investigation/releases
Authorization: token $GOGS_TOKEN
# Upload artifact
POST http://gitea_app:3000/api/v1/repos/sarman/tftsr-devops_investigation/releases/{id}/assets
```
From the arm64 agent (local machine), use `http://172.0.0.29:3000/api/v1` instead.
- macOS ARM64: `.dmg`
- macOS Intel: `.dmg`
---
## Multi-File Pipeline Support (Woodpecker 2.x)
## Build Images Workflow (`.github/workflows/build-images.yml`)
Woodpecker 2.x supports multiple pipeline files in the `.woodpecker/` directory.
All `.yml` files are evaluated on every trigger; `when:` conditions control which
pipelines actually run.
**Triggers:** Changes to `.docker/**` on `main`; manual `workflow_dispatch`.
Current files:
- `.woodpecker/test.yml` — runs on every push/PR
- `.woodpecker/release.yml` — runs on `v*` tags only
Builds and pushes all three pre-baked CI images to `ghcr.io/msicie/`:
```
Jobs (all run on ubuntu-latest):
build-linux-amd64-image → .docker/Dockerfile.linux-amd64
→ ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22
No DB config path switching needed (unlike Woodpecker 0.15.4).
build-windows-cross-image → .docker/Dockerfile.windows-cross
→ ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22
---
build-linux-arm64-image → .docker/Dockerfile.linux-arm64
→ ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22
```
## Webhook Configuration
**Woodpecker 2.x with Gitea OAuth2:**
After migration, Woodpecker 2.x registers webhooks automatically when a repo is
activated via the UI. No manual JWT-signed webhook setup required.
1. Log in at `http://172.0.0.29:8085` via Gitea OAuth2
2. Add repo `sarman/tftsr-devops_investigation`
3. Woodpecker creates webhook in Gitea automatically
Authentication: `docker login ghcr.io -u ${{ github.actor }} --password-stdin <<< "${{ secrets.GITHUB_TOKEN }}"`. Requires `packages: write` permission.
---
## Branch Protection
Master branch is protected: all changes require a PR.
```sql
-- Gitea branch protection (via psql on gogs_postgres_db container)
-- Check protection
SELECT name, protected, require_pull_request FROM protect_branch WHERE repo_id=42;
-- Temporarily disable for urgent fixes (restore immediately after!)
UPDATE protect_branch SET protected=false WHERE repo_id=42 AND name='master';
-- ... push ...
UPDATE protect_branch SET protected=true, require_pull_request=true WHERE repo_id=42 AND name='master';
```
`main` branch requires:
- All changes via PR
- 1 approving review
- CODEOWNER review (`@Shaun-Arman-VFK387_moto` and `@github-copilot`)
- Required status checks: `rust-test`, `frontend-test`
- `enforce_admins: false` — owner and admins can bypass with `gh pr merge --admin`
---
@ -264,7 +176,7 @@ Configuration lives in `cliff.toml` at the repo root.
### How it works
A `changelog` job in `auto-tag.yml` runs in parallel with the build jobs, immediately
A `changelog` job in `release.yml` runs in parallel with the build jobs, immediately
after `autotag` completes:
1. Clones the full repo history with all tags (`--depth=2147483647` — git-cliff needs
@ -272,9 +184,9 @@ after `autotag` completes:
2. Downloads the git-cliff v2.7.0 static musl binary (~5 MB, no image change needed).
3. Runs `git-cliff --output CHANGELOG.md` to regenerate the full cumulative changelog.
4. Runs `git-cliff --latest --strip all` to produce release notes for the new tag only.
5. PATCHes the Gitea release body with those notes (replaces the static `"Release vX.Y.Z"`).
6. Commits `CHANGELOG.md` to master with `[skip ci]` appended to the message.
The `[skip ci]` token prevents `auto-tag.yml` from re-triggering on the CHANGELOG commit.
5. Updates the GitHub Release body with those notes via `gh release edit`.
6. Commits `CHANGELOG.md` to `main` with `[skip ci]` appended to the message.
The `[skip ci]` token prevents `release.yml` from re-triggering on the CHANGELOG commit.
7. Uploads `CHANGELOG.md` as a release asset (replaces any previous version).
### cliff.toml reference
@ -289,17 +201,9 @@ after `autotag` completes:
### Loop prevention
The `[skip ci]` suffix on the CHANGELOG commit message is recognised by Gitea Actions
The `[skip ci]` suffix on the CHANGELOG commit message is recognised by GitHub Actions
and causes the workflow to be skipped for that push. Without it, the CHANGELOG commit
would trigger `auto-tag.yml` again, incrementing the patch version forever.
### Bootstrap
The initial `CHANGELOG.md` was generated locally before the first PR:
```sh
git-cliff --config cliff.toml --output CHANGELOG.md
```
Subsequent runs are fully automated by CI.
would trigger `release.yml` again, incrementing the patch version forever.
---
@ -312,27 +216,16 @@ index is duplicated and certain `-dev` package pairs cannot be co-installed beca
don't declare `Multi-Arch: same`. This produces `E: Unable to correct problems, you have
held broken packages` and cannot be fixed by tweaking `sources.list` entries.
**Fix**: Use `ubuntu:22.04` as the container image. Ubuntu routes arm64 through
`ports.ubuntu.com/ubuntu-ports` — a separate mirror from `archive.ubuntu.com` (amd64).
There are no cross-arch index overlaps and the dependency resolver succeeds. Rust must be
installed manually via `rustup` since it is not pre-installed in the Ubuntu base image.
**Fix**: Use `ubuntu:22.04` as the container image (see `Dockerfile.linux-arm64`). Ubuntu
routes arm64 through `ports.ubuntu.com/ubuntu-ports` — a separate mirror from
`archive.ubuntu.com` (amd64). There are no cross-arch index overlaps and the dependency
resolver succeeds. Rust must be installed manually via `rustup`.
### Step Containers Cannot Reach `gitea_app`
Default Docker bridge containers cannot resolve `gitea_app` or reach `172.0.0.29:3000`
(host firewall). Fix: use `network_mode: gogs_default` in any step that needs Gitea
access. Requires `repo_trusted=1`.
### `CI=woodpecker` Rejected by Tauri CLI
Woodpecker sets `CI=woodpecker`; `cargo tauri build` expects a boolean. Fix: prefix with
`CI=true cargo tauri build`.
### Agent Stalls After Server Restart
After restarting the Woodpecker server, the agent may enter a loop cleaning up orphaned
containers and stop picking up new builds. Fix:
```bash
docker rm -f $(docker ps -aq --filter 'name=0_')
docker volume rm $(docker volume ls -q | grep '0_')
docker restart woodpecker_agent
### `CI=true` Required by Tauri CLI
GitHub Actions sets `CI=true` by default — `cargo tauri build` accepts this without
modification. Prefix the command explicitly if your runner environment is unusual:
```yaml
- run: CI=true cargo tauri build --target $TARGET
```
### Windows DLL Export Ordinal Too Large
@ -344,32 +237,17 @@ Fix: `src-tauri/.cargo/config.toml`:
rustflags = ["-C", "link-arg=-Wl,--exclude-all-symbols"]
```
### GOGS_TOKEN Secret Must Be Recreated After Migration
After migrating from Woodpecker 0.15.4 to 2.x, recreate the `GOGS_TOKEN` secret:
1. Log in to Gitea, create a new API token under Settings → Applications
2. In Woodpecker UI → Repository → Secrets, add secret `GOGS_TOKEN` with the token value
### Release Artifacts Not Uploaded
---
**Cause:** `GITHUB_TOKEN` needs `contents: write` permission in the workflow.
## Gitea PostgreSQL Access
```bash
docker exec gogs_postgres_db psql -U gogs -d gogsdb -c "SELECT id, lower_name FROM repository;"
Verify the `release.yml` permissions block includes:
```yaml
permissions:
contents: write
```
> Database name is `gogsdb` (unchanged from Gogs migration).
---
## Migration Notes (Gogs 0.14 → Gitea)
Gitea auto-migrates the Gogs PostgreSQL schema on first start. Users, repos, teams, and
issues are preserved. API tokens stored in the DB are also migrated but should be
regenerated for security.
Key changes after migration:
- Container name: `gogs_app``gitea_app`
- Config dir: `/data/gitea` (was `/data/gogs` inside container, same host volume)
- Repo dir: `gogs-repositories``gitea-repositories` (renamed on host during migration)
- OAuth2 provider: Gitea now supports OAuth2 (Woodpecker 2.x uses this for login)
- Woodpecker 2.x multi-file pipeline support enabled (no more single config file limitation)
### Runner Group Restrictions (Enterprise)
GitHub Enterprise organizations may restrict which repositories can use GitHub-hosted
runners. If jobs are stuck in queue, contact your org admin to add the repository to the
allowed runner group, or temporarily make the repo public for the bootstrap run.

View File

@ -2,7 +2,7 @@
**Troubleshooting and RCA Assistant** is a secure desktop application for guided IT incident triage, root cause analysis (RCA), and post-mortem documentation. Built with Tauri 2.x (Rust + WebView) and React 18.
**CI:** ![build](http://172.0.0.29:3000/sarman/tftsr-devops_investigation/actions/workflows/test.yml/badge.svg) — rustfmt · clippy · 64 Rust tests · tsc · vitest — all green
**CI:** ![build](https://github.com/msicie/apollo_nxt-trcaa/actions/workflows/test.yml/badge.svg) — rustfmt · clippy · 64 Rust tests · tsc · vitest — all green
## Quick Navigation
@ -15,7 +15,7 @@
| [LiteLLM + Bedrock Setup](wiki/LiteLLM-Bedrock-Setup) | AWS Bedrock integration via LiteLLM proxy |
| [PII Detection](wiki/PII-Detection) | Patterns, redaction flow, security |
| [IPC Commands](wiki/IPC-Commands) | Full list of Tauri backend commands |
| [CI/CD Pipeline](wiki/CICD-Pipeline) | Gitea Actions setup, multi-platform builds, act_runner config |
| [CI/CD Pipeline](wiki/CICD-Pipeline) | GitHub Actions setup, multi-platform builds, pre-baked ghcr.io images |
| [Security Model](wiki/Security-Model) | Encryption, audit trail, capabilities |
| [Integrations](wiki/Integrations) | Confluence, ServiceNow, Azure DevOps (v0.2) |
| [Troubleshooting](wiki/Troubleshooting) | Known issues and fixes |
@ -45,7 +45,7 @@
**Platforms:** linux/amd64 · linux/arm64 · windows/amd64 (.deb, .rpm, .AppImage, .exe, .msi)
Download from [Releases](https://gogs.tftsr.com/sarman/tftsr-devops_investigation/releases). All builds are produced natively (no QEMU emulation).
Download from [Releases](https://github.com/msicie/apollo_nxt-trcaa/releases). All builds are produced natively (no QEMU emulation).
## Project Status
@ -54,8 +54,8 @@ Download from [Releases](https://gogs.tftsr.com/sarman/tftsr-devops_investigatio
| Phases 18 (Core application) | ✅ Complete |
| Phase 9 (History/Search) | 🔲 Pending |
| Phase 10 (Integrations) | ✅ Complete — Confluence, ServiceNow, Azure DevOps fully implemented with OAuth2 |
| Phase 11 (CI/CD) | ✅ Complete — Gitea Actions fully operational |
| Phase 12 (Release packaging) | ✅ linux/amd64 · linux/arm64 (native) · windows/amd64 |
| Phase 11 (CI/CD) | ✅ Complete — GitHub Actions fully operational |
| Phase 12 (Release packaging) | ✅ linux/amd64 · linux/arm64 · windows/amd64 · macOS ARM64 · macOS Intel |
## Tech Stack
@ -69,4 +69,4 @@ Download from [Releases](https://gogs.tftsr.com/sarman/tftsr-devops_investigatio
| Secret storage | tauri-plugin-stronghold |
| State | Zustand |
| Testing | Vitest (13 frontend) + `#[cfg(test)]` (64 Rust tests) |
| CI/CD | Gitea Actions (act_runner v0.3.1) + Gitea |
| CI/CD | GitHub Actions + ghcr.io |

View File

@ -1,71 +1,41 @@
# Troubleshooting
## CI/CD — Gitea Actions
## CI/CD — GitHub Actions
### Build Not Triggering After Push
**Check:**
1. Verify the workflow file exists in `.gitea/workflows/` on the pushed branch
2. Check the Actions tab at `http://172.0.0.29:3000/sarman/tftsr-devops_investigation/actions`
3. Confirm the act_runner is online: `docker logs gitea_act_runner_amd64 --since 5m`
1. Verify the workflow file exists in `.github/workflows/` on the pushed branch
2. Check the Actions tab at `https://github.com/msicie/apollo_nxt-trcaa/actions`
3. Confirm the workflow trigger matches the branch (e.g., `push: branches: [main, 'bug/**']`)
---
### Job Container Can't Reach Gitea (`172.0.0.29:3000` blocked)
### Jobs Stuck in Queue
**Cause:** act_runner creates an isolated Docker network per job (when `container:` is specified). Traffic from the job container to `172.0.0.29:3000` is blocked by the host firewall.
**Cause:** GitHub Enterprise organizations may restrict which repositories can use
GitHub-hosted runners via runner group policies.
**Fix:** Ensure `container.network: host` is set in the act_runner config AND that `CONFIG_FILE=/data/config.yaml` is in the container's environment:
```yaml
# /docker_mounts/gitea/runner/amd64/config.yaml
container:
network: "host"
```
```yaml
# docker-compose.yml for act-runner-amd64
environment:
- CONFIG_FILE=/data/config.yaml
```
Also set `capacity: 1` — with capacity > 1, concurrent jobs may not get host networking:
```yaml
runner:
capacity: 1
```
Restart runner: `docker restart gitea_act_runner_amd64`
**Fix:** Contact your org admin to add the repository to the allowed runner group, or
temporarily make the repo public for a one-time bootstrap run (e.g., to build the
initial ghcr.io images).
---
### `Unable to locate package git` in Rust Job
### `manifest unknown` — Image Pull Fails
**Cause:** `rust:1.88-slim` has an empty apt package cache.
**Cause:** The pre-baked CI image (`ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22`)
doesn't exist yet. This happens before the first `build-images.yml` run.
**Fix:** Always run `apt-get update` before `apt-get install`:
```yaml
- name: Checkout
run: |
apt-get update -qq && apt-get install -y -qq git
git init
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
git fetch --depth=1 origin $GITHUB_SHA
git checkout FETCH_HEAD
```
**Fix:**
1. Go to Actions → Build CI Docker Images → Run workflow
2. Wait for all 3 image builds to complete
3. Confirm images appear at `https://github.com/orgs/msicie/packages`
4. Re-run the failing workflow
---
### `exec: "node": executable file not found in $PATH`
**Cause:** `actions/checkout@v4` is a Node.js action. `rust:1.88-slim` and similar slim images don't have Node.
**Fix:** Don't use `actions/checkout@v4` — use direct git commands instead (see above).
---
### Job Skipped (status 6) on Tag Push
### Job Skipped on Tag Push
**Cause:** Pattern matching issue with `on: push: tags:`. Use unquoted glob in the workflow:
@ -92,29 +62,17 @@ on:
---
### `CI=woodpecker` Rejected by `cargo tauri build`
**Cause:** CI runners set `CI=woodpecker` (string). Tauri CLI expects `true`/`false`.
**Fix:** Prefix the build command:
```yaml
- run: CI=true cargo tauri build --target $TARGET
```
---
### Release Artifacts Not Uploaded
**Cause 1:** `RELEASE_TOKEN` secret not set or expired.
```bash
# Recreate via admin CLI:
docker exec -u git gitea_app gitea admin user generate-access-token \
--username sarman --token-name gitea-ci-token --raw \
--scopes 'write:repository,read:user'
# Add the token as RELEASE_TOKEN in repo Settings > Actions > Secrets
```
**Cause:** `GITHUB_TOKEN` permissions insufficient. The `release.yml` workflow requires
`contents: write` to create releases and upload assets.
**Cause 2:** Each build job uploads its own artifacts independently. All jobs require host network on the runner (see above).
Verify the permissions block:
```yaml
permissions:
contents: write
packages: write
```
---
@ -158,7 +116,7 @@ Auto-fix: `cargo clippy --manifest-path src-tauri/Cargo.toml --fix --allow-dirty
**Fix (Fedora/RHEL):**
```bash
sudo dnf install -y glib2-devel gtk3-devel webkit2gtk4.1-devel \
libsoup3-devel openssl-devel librsvg2-devel
libsoup3-devel openssl-devel librsvg2-dev
```
**Fix (Debian/Ubuntu):**
@ -169,6 +127,17 @@ sudo apt-get install -y libwebkit2gtk-4.1-dev libssl-dev libgtk-3-dev \
---
### Windows Cross-Compile: DLL Export Ordinal Too Large
`/usr/bin/x86_64-w64-mingw32-ld: error: export ordinal too large: 106290`
Fix: `src-tauri/.cargo/config.toml`:
```toml
[target.x86_64-pc-windows-gnu]
rustflags = ["-C", "link-arg=-Wl,--exclude-all-symbols"]
```
---
## Database
### DB Won't Open in Production
@ -220,27 +189,3 @@ const title = detail.title;
Common causes:
- Mocked `invoke()` return type doesn't match updated command signature
- `sessionStore` state not reset between tests (call `store.reset()` in `beforeEach`)
---
## Gitea
### API Token Authentication
```bash
curl -H "Authorization: token <token_value>" http://172.0.0.29:3000/api/v1/user
```
Create tokens in Gitea Settings > Applications > Access Tokens, or via admin CLI:
```bash
docker exec -u git gitea_app gitea admin user generate-access-token \
--username sarman --token-name mytoken --raw --scopes 'read:user,write:repository'
```
### PostgreSQL Access
```bash
docker exec gogs_postgres_db psql -U gogs -d gogsdb -c "SELECT id, lower_name, is_private FROM repository;"
```
Database is named `gogsdb`. The PostgreSQL instance uses SCRAM-SHA-256 auth (MD5 also configured for the `gogs` user for compatibility with older clients).

View File

@ -4,11 +4,11 @@ import path from "node:path";
const autoTagWorkflowPath = path.resolve(
process.cwd(),
".gitea/workflows/auto-tag.yml",
".github/workflows/release.yml",
);
describe("auto-tag workflow release triggering", () => {
it("creates tags via git push instead of Gitea tag API", () => {
it("creates tags via git push instead of API call", () => {
const workflow = readFileSync(autoTagWorkflowPath, "utf-8");
expect(workflow).toContain("git push origin \"refs/tags/$NEXT\"");
@ -23,7 +23,13 @@ describe("auto-tag workflow release triggering", () => {
expect(workflow).toContain("build-macos-arm64:");
expect(workflow).toContain("build-linux-arm64:");
expect(workflow).toContain("needs: autotag");
expect(workflow).toContain("TAG=$(curl -s \"$API/tags?limit=50\"");
expect(workflow).toContain("ERROR: Could not resolve release tag from repository tags.");
expect(workflow).toContain("git tag --sort=-version:refname");
});
it("also includes macOS Intel build job", () => {
const workflow = readFileSync(autoTagWorkflowPath, "utf-8");
expect(workflow).toContain("build-macos-intel:");
expect(workflow).toContain("macos-13");
});
});

View File

@ -100,10 +100,10 @@ describe("Dockerfile.linux-arm64", () => {
// ─── build-images.yml workflow ───────────────────────────────────────────────
describe("build-images.yml workflow", () => {
const wf = readFile(".gitea/workflows/build-images.yml");
const wf = readFile(".github/workflows/build-images.yml");
it("triggers on changes to .docker/ files on master", () => {
expect(wf).toContain("- master");
it("triggers on changes to .docker/ files on main", () => {
expect(wf).toContain("- main");
expect(wf).toContain("- '.docker/**'");
});
@ -111,38 +111,28 @@ describe("build-images.yml workflow", () => {
expect(wf).toContain("workflow_dispatch:");
});
it("does not explicitly mount the Docker socket (act_runner mounts it automatically)", () => {
// act_runner already mounts /var/run/docker.sock; an explicit options: mount
// causes a 'Duplicate mount point' error and must not be present.
expect(wf).not.toContain("-v /var/run/docker.sock:/var/run/docker.sock");
});
it("authenticates to the local Gitea registry before pushing", () => {
expect(wf).toContain("docker login");
it("authenticates to ghcr.io before pushing", () => {
expect(wf).toContain("docker login ghcr.io");
expect(wf).toContain("--password-stdin");
expect(wf).toContain("172.0.0.29:3000");
expect(wf).toContain("ghcr.io");
});
it("builds and pushes all three platform images", () => {
expect(wf).toContain("trcaa-linux-amd64:rust1.88-node22");
expect(wf).toContain("trcaa-windows-cross:rust1.88-node22");
expect(wf).toContain("trcaa-linux-arm64:rust1.88-node22");
it("builds and pushes all three platform images to ghcr.io", () => {
expect(wf).toContain("ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22");
expect(wf).toContain("ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22");
expect(wf).toContain("ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22");
});
it("uses alpine:latest with docker-cli (not docker:24-cli which triggers duplicate socket mount in act_runner)", () => {
// act_runner v0.3.1 special-cases docker:* images and adds the socket bind;
// combined with its global socket bind this causes a 'Duplicate mount point' error.
expect(wf).toContain("alpine:latest");
expect(wf).toContain("docker-cli");
expect(wf).not.toContain("docker:24-cli");
});
it("runs all three build jobs on linux-amd64 runner", () => {
const matches = wf.match(/runs-on: linux-amd64/g) ?? [];
it("runs all three build jobs on ubuntu-latest runner", () => {
const matches = wf.match(/runs-on: ubuntu-latest/g) ?? [];
expect(matches.length).toBeGreaterThanOrEqual(3);
});
it("uses RELEASE_TOKEN secret for registry auth", () => {
expect(wf).toContain("secrets.RELEASE_TOKEN");
it("uses GITHUB_TOKEN for registry auth", () => {
expect(wf).toContain("secrets.GITHUB_TOKEN");
});
it("grants packages write permission", () => {
expect(wf).toContain("packages: write");
});
});

View File

@ -4,7 +4,7 @@ import path from "node:path";
const autoTagWorkflowPath = path.resolve(
process.cwd(),
".gitea/workflows/auto-tag.yml",
".github/workflows/release.yml",
);
describe("auto-tag release macOS bundle path", () => {

52
ticket-727547-summary.md Normal file
View File

@ -0,0 +1,52 @@
# Ticket Summary — ADO #727547
## Description
Migrate the `tftsr-devops_investigation` repository from `gogs.tftsr.com/sarman/tftsr-devops_investigation` to `github.com/msicie/apollo_nxt-trcaa`. All CI/CD pipelines, container registries, and PR review tooling must be rebuilt from scratch targeting GitHub. The self-hosted qwen3-coder-next LLM reviewer is replaced by native GitHub Copilot code review. Branch protection on `main` must require passing CI checks and allow owner/CODEOWNERS to bypass.
## Acceptance Criteria
- [x] Repository exists at `github.com/msicie/apollo_nxt-trcaa` with `main` as the default branch
- [x] `.github/workflows/test.yml` runs Rust and frontend tests on every push/PR targeting `main`
- [x] `.github/workflows/release.yml` auto-tags, builds for Linux amd64+arm64, Windows amd64, macOS ARM64+Intel, and uploads artifacts to GitHub Releases
- [x] `.github/workflows/build-images.yml` builds and pushes pre-baked CI images to `ghcr.io/msicie/`
- [x] All Gogs/Gitea pipeline references (`.gitea/workflows/`, `172.0.0.29:3000`, `RELEASE_TOKEN`) removed
- [x] PR review uses native GitHub Copilot (no external LLM service required)
- [x] `.github/CODEOWNERS` requires `@Shaun-Arman-VFK387_moto` and `@github-copilot` on all PRs
- [x] `main` branch protection: requires `rust-test`, `frontend-test`, CODEOWNER review; admins can bypass
- [x] Wiki sync targets `github.com/msicie/apollo_nxt-trcaa/wiki`
- [ ] One-time: trigger `build-images.yml` to bootstrap `ghcr.io/msicie/` images
- [ ] One-time: enable Copilot Code Review in `msicie` org settings
## Work Implemented
| File | Change |
|---|---|
| `.github/workflows/test.yml` | Full rewrite — port from `.gitea/workflows/test.yml` (Gitea); jobs renamed to `rust-test` + `frontend-test` to match branch protection check names; uses `ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22` |
| `.github/workflows/release.yml` | Full rewrite — port from `.gitea/workflows/auto-tag.yml`; GITHUB_TOKEN replaces RELEASE_TOKEN; all Gogs API calls replaced with `gh` CLI; adds `build-macos-intel` job (`macos-13`); `master` refs → `main` |
| `.github/workflows/build-images.yml` | Rewrite — login to `ghcr.io` with GITHUB_TOKEN; push images to `ghcr.io/msicie/trcaa-*` |
| `.github/workflows/pr-review.yml` | **Deleted** — replaced by native GitHub Copilot |
| `.gitea/workflows/` | **Deleted** entire directory |
| `.github/CODEOWNERS` | **Created**`@Shaun-Arman-VFK387_moto @github-copilot` on all paths |
| `Makefile` | Replace `GOGS_API`/`GOGS_REPO`/`GOGS_TOKEN` with `GH_REPO`/`GH_TOKEN` and `gh release upload` |
| `CLAUDE.md` | Update wiki URL, CI/CD section, branch references (`master` → `main`) |
**Branch protection on `main`:**
- Require PRs before merging
- Require 1 approving review
- Require CODEOWNER review (`require_code_owner_reviews: true`)
- Required status checks: `rust-test`, `frontend-test`
- `enforce_admins: false` — owner and admins can bypass
**PR:** https://github.com/msicie/apollo_nxt-trcaa/pull/1
## Testing Needed
1. **Bootstrap Docker images** (one-time): Go to Actions → Build CI Docker Images → Run workflow. Verify all three images appear at `ghcr.io/msicie/`.
2. **Enable Copilot Code Review** (one-time manual): `msicie` org Settings → Copilot → Code Review → Enable.
3. **Test pipeline**: Verify `rust-test` and `frontend-test` checks appear and pass on PR #1.
4. **Copilot review**: After enabling, open a new PR and confirm `@github-copilot` is auto-requested.
5. **Branch protection enforcement**: Attempt to merge a PR with a failing check — confirm it is blocked.
6. **Owner bypass**: Confirm `@Shaun-Arman-VFK387_moto` can override protection and merge.
7. **Release pipeline**: Push a `v*` tag (e.g. `v0.3.10`) and confirm all 5 platform jobs complete and artifacts appear in GitHub Releases.
8. **Wiki sync**: Confirm release workflow wiki-sync job pushes content to `github.com/msicie/apollo_nxt-trcaa/wiki`.

View File

@ -16,17 +16,17 @@ Conventional Commits throughout but the information was never surfaced to end-us
- `cliff.toml` (new) — git-cliff configuration; defines commit parsers, ignored tags,
output template, and which commit types appear in the changelog
- `CHANGELOG.md` (new) — bootstrapped from all existing tags; maintained by CI going forward
- `.gitea/workflows/auto-tag.yml` — new `changelog` job that runs after `autotag`
- `.github/workflows/release.yml` — `changelog` job that runs after `autotag`
- `docs/wiki/CICD-Pipeline.md` — "Changelog Generation" section added
## Acceptance Criteria
- [ ] `cliff.toml` present at repo root with working Tera template
- [ ] `CHANGELOG.md` present at repo root, bootstrapped from all existing semver tags
- [ ] `changelog` job in `auto-tag.yml` runs after `autotag` (parallel with build jobs)
- [ ] Each Gitea release body shows grouped conventional-commit entries instead of
- [ ] `changelog` job in `release.yml` runs after `autotag` (parallel with build jobs)
- [ ] Each GitHub Release body shows grouped conventional-commit entries instead of
static `"Release vX.Y.Z"`
- [ ] `CHANGELOG.md` committed to master on every release with `[skip ci]` suffix
- [ ] `CHANGELOG.md` committed to `main` on every release with `[skip ci]` suffix
(no infinite re-trigger loop)
- [ ] `CHANGELOG.md` uploaded as a downloadable release asset
- [ ] CI/chore/build/test/style commits excluded from changelog output
@ -47,15 +47,15 @@ Conventional Commits throughout but the information was never surfaced to end-us
- Covers all tagged versions from `v0.1.0` through `v0.2.49` plus `[Unreleased]`
- 267 lines covering the full project history
### `.gitea/workflows/auto-tag.yml` — `changelog` job
### `.github/workflows/release.yml` — `changelog` job
- `needs: autotag` — waits for the new tag to exist before running
- Full history clone: `git fetch --tags --depth=2147483647` so git-cliff can resolve
all version boundaries
- git-cliff v2.7.0 downloaded as a static x86_64 musl binary (~5 MB); no custom
image required
- Generates full `CHANGELOG.md` and per-release notes (`--latest --strip all`)
- PATCHes the Gitea release body via API with JSON-safe escaping (`jq -Rs .`)
- Commits `CHANGELOG.md` to master with `[skip ci]` to prevent workflow re-trigger
- Updates the GitHub Release body via `gh release edit` with JSON-safe escaping (`jq -Rs .`)
- Commits `CHANGELOG.md` to `main` with `[skip ci]` to prevent workflow re-trigger
- Deletes any existing `CHANGELOG.md` asset before re-uploading (rerun-safe)
- Runs in parallel with all build jobs — no added wall-clock latency

View File

@ -7,7 +7,7 @@ on each job invocation: `apt-get update`, Tauri system libs, Node.js via nodesou
the arm64 job — a full `rustup` install. This was the primary cause of slow builds.
The repository already contains pre-baked builder Docker images (`.docker/Dockerfile.*`) and a
`build-images.yml` workflow to push them to the local Gitea registry at `172.0.0.29:3000`.
`build-images.yml` workflow to push them to `ghcr.io/msicie/`.
These images were never referenced by the actual CI jobs — a critical gap. This work closes
that gap and adds `actions/cache@v3` for Cargo and npm.
@ -15,7 +15,7 @@ that gap and adds `actions/cache@v3` for Cargo and npm.
- [ ] `Dockerfile.linux-amd64` includes `rustfmt` and `clippy` components
- [ ] `Dockerfile.linux-arm64` includes `rustfmt` and `clippy` components
- [ ] `test.yml` Rust jobs use `172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22`
- [ ] `test.yml` Rust jobs use `ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22`
- [ ] `test.yml` Rust jobs have no inline `apt-get` or `rustup component add` steps
- [ ] `test.yml` Rust jobs include `actions/cache@v3` for `~/.cargo/registry`
- [ ] `test.yml` frontend jobs include `actions/cache@v3` for `~/.npm`
@ -38,9 +38,9 @@ in the image rather than installing them at job runtime.
Added `&& /root/.cargo/bin/rustup component add rustfmt clippy` appended to the
existing `rustup` installation RUN command (chained with `&&` to keep it one layer).
### `.gitea/workflows/test.yml`
- **rust-fmt-check**, **rust-clippy**, **rust-tests**: switched container image from
`rust:1.88-slim``172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22`.
### `.github/workflows/test.yml`
- **rust-test** (fmt + clippy + tests): switched container image from
`rust:1.88-slim``ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22`.
Removed `apt-get install git` from Checkout steps (git is pre-installed in image).
Removed `apt-get install libwebkit2gtk-...` steps.
Removed `rustup component add rustfmt` and `rustup component add clippy` steps.
@ -49,15 +49,15 @@ existing `rustup` installation RUN command (chained with `&&` to keep it one lay
- **frontend-typecheck**, **frontend-tests**: kept `node:22-alpine` image (no change needed).
Added `actions/cache@v3` step for `~/.npm` keyed on `package-lock.json` hash.
### `.gitea/workflows/auto-tag.yml`
- **build-linux-amd64**: image `rust:1.88-slim``trcaa-linux-amd64:rust1.88-node22`.
### `.github/workflows/release.yml`
- **build-linux-amd64**: image `rust:1.88-slim``ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22`.
Removed Checkout apt-get install git, removed entire Install dependencies step.
Removed `rustup target add x86_64-unknown-linux-gnu` from Build step. Added cargo + npm cache.
- **build-windows-amd64**: image `rust:1.88-slim``trcaa-windows-cross:rust1.88-node22`.
- **build-windows-amd64**: image `rust:1.88-slim``ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22`.
Removed Checkout apt-get install git, removed entire Install dependencies step.
Removed `rustup target add x86_64-pc-windows-gnu` from Build step.
Added cargo (with `-windows-` suffix key to avoid collision) + npm cache.
- **build-linux-arm64**: image `ubuntu:22.04``trcaa-linux-arm64:rust1.88-node22`.
- **build-linux-arm64**: image `ubuntu:22.04``ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22`.
Removed Checkout apt-get install git, removed entire Install dependencies step (~40 lines).
Removed `. "$HOME/.cargo/env"` (PATH already set via `ENV` in Dockerfile).
Removed `rustup target add aarch64-unknown-linux-gnu` from Build step.
@ -67,7 +67,7 @@ existing `rustup` installation RUN command (chained with `&&` to keep it one lay
Added two new sections before the Test Pipeline section:
- **Pre-baked Builder Images**: table of all three images and their contents, rebuild
triggers, how-to-rebuild instructions, and the insecure-registries Docker daemon
prerequisite for 172.0.0.29.
prerequisite for ghcr.io access.
- **Cargo and npm Caching**: documents the `actions/cache@v3` key patterns in use,
including the per-platform cache key suffixes for cross-compile jobs.
Updated the Test Pipeline section to reference the correct pre-baked image name.
@ -75,21 +75,16 @@ Updated the Release Pipeline job table to show which image each build job uses.
## Testing Needed
1. **Pre-build images** (prerequisite): Trigger `build-images.yml` via `workflow_dispatch`
on Gitea Actions UI. Confirm all 3 images are pushed and visible in the registry.
1. **Pre-build images** (prerequisite): Trigger `build-images.yml` via Actions → Build CI Docker Images → Run workflow. Confirm all 3 images are pushed and visible at `ghcr.io/msicie/`.
2. **Server prerequisite**: Confirm `/etc/docker/daemon.json` on `172.0.0.29` contains
`{"insecure-registries":["172.0.0.29:3000"]}` and Docker was restarted after.
3. **PR test suite**: Open a PR with these changes. Verify:
- All 5 test jobs pass (`rust-fmt-check`, `rust-clippy`, `rust-tests`,
`frontend-typecheck`, `frontend-tests`)
2. **PR test suite**: Open a PR with these changes. Verify:
- `rust-test` and `frontend-test` jobs pass
- Job logs show no `apt-get` or `rustup component add` output
- Cache hit messages appear on second run
4. **Release build**: Merge to master. Verify `auto-tag.yml` runs and:
- All 3 Linux/Windows build jobs start without Install dependencies step
- Artifacts are produced and uploaded to the Gitea release
3. **Release build**: Merge to `main`. Verify `release.yml` runs and:
- All build jobs start without Install dependencies step
- Artifacts are produced and uploaded to the GitHub Release
- Total release time is significantly reduced (~7 min vs ~25 min before)
5. **Expected time savings after caching warms up**: