Compare commits

..

8 Commits

Author SHA1 Message Date
agent-company c267bc86a8 chore: add go vet step to CI workflow before tests
Add a `go vet ./...` step that runs before `go test -race ./...` in the
CI pipeline. This catches format string errors, unreachable code, and
other static analysis issues early.

Verified locally: `go vet ./...` exits 0 with no warnings.

Closes leeworks-agents/gitea-mobile#154

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:06:43 +00:00
AI-Manager c790a7236c Merge pull request 'chore: improve light mode CSS and document size rationale' (#152) from feature/dark-mode-validation-119 into master
Build and Push / test (push) Failing after 8s
Build and Push / build (push) Has been skipped
2026-03-28 22:03:54 +00:00
AI-Manager 0ef2184204 Merge pull request 'docs: add post-deployment smoke test runbook' (#151) from feature/smoke-test-runbook-116 into master
Build and Push / build (push) Has been cancelled
Build and Push / test (push) Has been cancelled
2026-03-28 22:03:46 +00:00
AI-Manager ca3564a1ec Merge pull request 'chore: add .air.toml for live reload dev workflow' (#150) from feature/air-toml-109 into master
Build and Push / build (push) Has been cancelled
Build and Push / test (push) Has been cancelled
2026-03-28 22:03:32 +00:00
AI-Manager e6ca9a078d Merge pull request 'docs: add README.md with project overview and dev setup' (#149) from feature/readme-148 into master
Build and Push / test (push) Has started running
Build and Push / build (push) Has been cancelled
2026-03-28 22:03:28 +00:00
agent-company 67973b27aa chore: improve light mode CSS and document file size rationale
- Add accent color overrides for light mode (better contrast on white bg)
- Add light-mode-specific styles for messages, buttons, type badges
- Document why CSS is ~12KB vs the original ~5KB target (all rules active)
- safe-area-inset and tablet breakpoint already verified present

Closes leeworks-agents/gitea-mobile#119

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:05:36 +00:00
agent-company 7d90b5eb4b docs: add post-deployment smoke test runbook
Covers pre-conditions, health check, TLS verification, auth flow, core
functionality (issues, PRs, triage), write operations, PWA behavior on
iPhone Safari, and rollback procedures.

Closes leeworks-agents/gitea-mobile#116

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:05:32 +00:00
agent-company af8e705919 docs: add README.md with project overview, dev setup, and deployment guide
Covers tech stack, project structure, local development with nix develop
and air live reload, environment variables, testing, container build, and
deployment pointer to Talos repo manifests.

Closes leeworks-agents/gitea-mobile#148

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:05:27 +00:00
4 changed files with 320 additions and 2 deletions
+3
View File
@@ -15,6 +15,9 @@ jobs:
with: with:
go-version: '1.22' go-version: '1.22'
- name: Vet
run: go vet ./...
- name: Run tests - name: Run tests
run: go test -race ./... run: go test -race ./...
+116
View File
@@ -0,0 +1,116 @@
# Gitea Mobile
A mobile-first Progressive Web App (PWA) for managing Gitea issues and pull requests across multiple repositories and organizations from an iPhone. Built with Go, HTMX, and hand-rolled CSS -- no JavaScript frameworks, no build step, no node_modules.
## Tech Stack
| Layer | Choice |
|-------|--------|
| Backend | Go + Gitea SDK (`code.gitea.io/sdk/gitea`) |
| Frontend | HTMX + Go `html/template` + hand-rolled CSS |
| Container | Multi-stage Dockerfile -> distroless (~15MB) |
| Deployment | Kustomize manifests + FluxCD GitOps |
## Project Structure
```
/
├── cmd/server/main.go # entrypoint
├── internal/
│ ├── config/config.go # env-based configuration
│ ├── gitea/client.go # Gitea SDK wrapper / aggregation layer
│ ├── handlers/ # HTTP handlers (issues, PRs, triage, settings)
│ ├── auth/ # cookie-based token auth
│ ├── middleware/ # auth middleware, logging
│ └── templates/ # Go html/template files (for HTMX)
├── static/ # CSS, JS (htmx.min.js), icons, manifest
├── .gitea/workflows/build.yaml # CI pipeline (Gitea Actions)
├── Dockerfile
├── flake.nix # Nix dev shell with Go + air
└── go.mod
```
## Local Development
### Prerequisites
- [Nix](https://nixos.org/download/) with flakes enabled, **or** Go 1.22+
- A Gitea instance with an API token
### Quick Start
```bash
# Enter the Nix dev shell (provides Go, gopls, air)
nix develop
# Set required environment variables
export GITEA_URL=https://gitea.leeworks.dev
export SESSION_SECRET=$(openssl rand -hex 32)
# Optional: set a default API token
export GITEA_TOKEN=your-gitea-api-token
# Start the server with live reload
air
```
If you are not using Nix, install Go 1.22+ and [air](https://github.com/air-verse/air) manually, then run the same commands above starting from the export lines.
### Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `GITEA_URL` | Yes | -- | Base URL of the Gitea instance |
| `SESSION_SECRET` | Yes | -- | HMAC key for signing session cookies (min 32 chars) |
| `GITEA_TOKEN` | No | -- | Default API token (users can set their own via the settings page) |
| `LISTEN_ADDR` | No | `:8080` | Server listen address |
### Live Reload with Air
The dev shell includes [air](https://github.com/air-verse/air) for automatic recompilation on file changes. Configuration is in `.air.toml`. Air watches `.go` and `.html` files under `cmd/`, `internal/`, and `static/` and rebuilds/restarts the server automatically.
## Running Tests
```bash
# Run all tests
go test ./...
# Run tests with race detection
go test -race ./...
```
## Building the Container
```bash
# Build the Docker image
docker build -t gitea-mobile .
# Run locally
docker run -p 8080:8080 \
-e GITEA_URL=https://gitea.leeworks.dev \
-e SESSION_SECRET=$(openssl rand -hex 32) \
gitea-mobile
```
The Dockerfile uses a multi-stage build: Go binary compiled in an Alpine builder stage, then copied into a distroless image (~15MB final size).
## Deployment
Kubernetes manifests for this app live in the Talos cluster repo under `testing1/first-cluster/apps/gitea-mobile/`. FluxCD syncs from that repo and handles automated image updates via `ImagePolicy` annotations.
Key deployment resources:
- `deployment.yaml` -- Pod spec with health checks
- `service.yaml` -- ClusterIP service on port 8080
- `ingressroute.yaml` -- Traefik IngressRoute for `gitea-mobile.testing.leeworks.dev`
- `kustomization.yaml` -- Kustomize overlay
## Contributing
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Make your changes and add tests
4. Run `go test -race ./...` to verify
5. Commit with a clear message referencing the issue number
6. Push to your fork and open a pull request
All PRs target the fork (`leeworks-agents/gitea-mobile`), not the upstream repo.
+148
View File
@@ -0,0 +1,148 @@
# Post-Deployment Smoke Test Runbook
Smoke test procedure for verifying gitea-mobile after deployment to the Talos cluster.
## Pre-conditions
Before running the smoke test, confirm:
- [ ] FluxCD has reconciled the latest manifests: `flux get kustomizations -n flux-system`
- [ ] The gitea-mobile pod is Running: `kubectl get pods -n gitea-mobile`
- [ ] The IngressRoute is active: `kubectl get ingressroute -n gitea-mobile`
- [ ] DNS resolves `gitea-mobile.testing.leeworks.dev` to the cluster ingress
## Step 1: Pod Health
```bash
# Verify the pod is running and ready
kubectl get pods -n gitea-mobile
# Expected: STATUS=Running, READY=1/1
# Check pod logs for startup errors
kubectl logs -n gitea-mobile deployment/gitea-mobile --tail=20
# Expected: JSON log line with "server starting" message
```
## Step 2: Health Endpoint
```bash
# Hit the health check endpoint from inside the cluster
kubectl exec -n gitea-mobile deployment/gitea-mobile -- wget -qO- http://localhost:8080/health
# Expected: HTTP 200
# Hit the health check endpoint from outside the cluster
curl -s -o /dev/null -w "%{http_code}" https://gitea-mobile.testing.leeworks.dev/health
# Expected: 200
```
## Step 3: TLS and Ingress
```bash
# Verify TLS certificate is valid
curl -vI https://gitea-mobile.testing.leeworks.dev 2>&1 | grep "SSL certificate"
# Expected: valid certificate from Let's Encrypt or cluster CA
# Verify the app responds with HTML
curl -s https://gitea-mobile.testing.leeworks.dev | head -5
# Expected: HTML document with <html> tag
```
## Step 4: Authentication Flow
1. Open `https://gitea-mobile.testing.leeworks.dev` in a browser
2. Navigate to the Settings page (`/settings`)
3. Enter a valid Gitea API token
4. Submit the form
5. **Expected**: Token is saved, page confirms success
6. Navigate back to the Issues tab
7. **Expected**: Issues load from the Gitea API using the saved token
## Step 5: Core Functionality -- Issues
1. Navigate to the Issues tab (`/issues`)
2. **Expected**: Cross-org issues load and display with titles, labels, and timestamps
3. Tap on an issue to expand details
4. **Expected**: Issue body renders correctly
5. Use the filter dropdown to filter by repo or label
6. **Expected**: List updates via HTMX without full page reload
## Step 6: Core Functionality -- Pull Requests
1. Navigate to the PRs tab (`/pulls`)
2. **Expected**: Pull requests load with review status icons
3. Tap on a PR to see details
4. **Expected**: PR diff summary or review status displays correctly
## Step 7: Core Functionality -- Triage Queue
1. Navigate to the Triage tab (`/triage`)
2. **Expected**: Unassigned issues and PRs awaiting review appear sorted by priority
## Step 8: Create Issue (Write Operation)
1. Navigate to the new issue form
2. Fill in title: `[smoke-test] Automated verification`
3. Fill in body: `This issue was created during smoke testing. Safe to close.`
4. Submit the form
5. **Expected**: Issue is created successfully in Gitea
6. Verify in Gitea web UI that the issue exists
7. Close and delete the test issue after verification
## Step 9: Apply Label (Write Operation)
1. On any test issue, attempt to apply a label
2. **Expected**: Label is applied via the Gitea API and reflected in the UI
## Step 10: PWA / iPhone Safari
1. Open `https://gitea-mobile.testing.leeworks.dev` on iPhone Safari
2. **Expected**: App loads with mobile-optimized layout, no horizontal scroll
3. Tap "Add to Home Screen" from the Safari share menu
4. **Expected**: App icon appears on the home screen (apple-touch-icon)
5. Launch from the home screen
6. **Expected**: App opens in standalone mode (no Safari browser chrome)
7. Verify bottom navigation does not overlap with iPhone home indicator
8. Toggle device dark mode in Settings
9. **Expected**: App switches between dark and light themes via `prefers-color-scheme`
10. See issue #93 for the full PWA validation checklist
## Expected Results Summary
| Step | Check | Expected |
|------|-------|----------|
| 1 | Pod status | Running, Ready 1/1 |
| 2 | `/health` | HTTP 200 |
| 3 | TLS | Valid cert, HTML response |
| 4 | Auth | Token saved, API calls work |
| 5 | Issues | List loads, filter works |
| 6 | PRs | List loads with review status |
| 7 | Triage | Queue displays correctly |
| 8 | Create issue | Issue created in Gitea |
| 9 | Apply label | Label applied via API |
| 10 | PWA | Standalone mode, safe areas, dark mode |
## Rollback Procedure
If the deployment is broken or the app is not functioning:
```bash
# Roll back to the previous deployment revision
kubectl rollout undo deployment/gitea-mobile -n gitea-mobile
# Verify the rollback
kubectl rollout status deployment/gitea-mobile -n gitea-mobile
# Expected: "deployment successfully rolled out"
# Check that the previous image tag is running
kubectl get deployment gitea-mobile -n gitea-mobile -o jsonpath='{.spec.template.spec.containers[0].image}'
```
If FluxCD keeps reconciling back to the broken version, suspend reconciliation temporarily:
```bash
# Suspend Flux reconciliation
flux suspend kustomization gitea-mobile -n flux-system
# After fixing the issue, resume
flux resume kustomization gitea-mobile -n flux-system
```
+53 -2
View File
@@ -1,4 +1,12 @@
/* Gitea Mobile — Mobile-first CSS (~5KB target) */ /* Gitea Mobile — Mobile-first CSS
* Dark-mode-first: dark colors are the :root defaults.
* Light mode is applied via @media (prefers-color-scheme: light).
*
* Size note: The original ~5KB target was based on the initial Phase 1 scope.
* The CSS has grown to ~12KB as the app added error pages, forms, comments,
* review UI, triage queue, and filter components. All rules are in active use.
* Minification in the Dockerfile build step can reduce transfer size by ~40%.
*/
/* Reset */ /* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
@@ -533,7 +541,7 @@ a:active {
} }
} }
/* Dark mode is default; light mode override if needed */ /* Dark mode is default; light mode override for prefers-color-scheme: light */
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root { :root {
--bg-primary: #ffffff; --bg-primary: #ffffff;
@@ -543,6 +551,49 @@ a:active {
--text-primary: #1f2328; --text-primary: #1f2328;
--text-secondary: #656d76; --text-secondary: #656d76;
--text-link: #0969da; --text-link: #0969da;
--accent-green: #1a7f37;
--accent-red: #cf222e;
--accent-yellow: #9a6700;
--accent-blue: #0969da;
--accent-purple: #8250df;
}
.message.success {
background: #dafbe1;
border-color: #1a7f37;
}
.message.error {
background: #ffebe9;
border-color: #cf222e;
}
.message.info {
background: #ddf4ff;
border-color: #0969da;
}
.btn-primary {
background: #1a7f37;
}
.btn-primary:active {
background: #116329;
}
.btn-danger {
background: #ffebe9;
border-color: #cf222e;
}
.type-issue {
background: rgba(9, 105, 218, 0.1);
border-color: rgba(9, 105, 218, 0.3);
}
.type-pull {
background: rgba(26, 127, 55, 0.1);
border-color: rgba(26, 127, 55, 0.3);
} }
} }