Commit Graph
10 Commits
Author SHA1 Message Date
sneak 5101abd407 Reject path traversal in deploy log download handler (closes #177)
Check / check (pull_request) Skipped
gosec flagged G703 (path traversal via taint analysis) on the log
download handler because the served path derives from a URL parameter.
Open the log file through an os.Root confined to the deploy log
directory instead of passing the path to http.ServeFile; Root.Open
rejects any path that escapes the root, so traversal attempts return
404. Serve the opened file with http.ServeContent. Adds GetLogDir on
the deploy service.

The traversal regression test plants a sentinel file at the location a
traversal-shaped app name resolves to (outside the log directory) and
asserts the handler returns 404 without leaking the sentinel, so it
fails if the os.Root guard is removed. Keeps the legitimate-download
test.

Model: opus-4-8
2026-09-22 08:09:04 +00:00
clawbot 1d38585431 Add .prettierignore for vendored minified JS (closes #185)
script/fmt ran prettier over static/js/*.js, which rewrote the vendored
minified static/js/alpine.min.js. A root .prettierignore with *.min.js
excludes vendored bundles: make fmt on a clean tree now yields no changes
and alpine.min.js stays byte-identical, while first-party JS still formats.

Model: opus-4-8
2026-09-22 10:00:50 +02:00
sneak cdcf527b25 Fix four deployability blockers found by QA (closes #189, closes #190, closes #191, closes #192)
Check / check (pull_request) Failing after 13s
- CSRF over plain HTTP (#189): gorilla/csrf assumed https for its
  same-origin check, so setup and every POST returned 403 over plain
  HTTP. Gate csrf.PlaintextHTTPRequest on a new UPAAS_PLAINTEXT_HTTP
  config value; the default keeps https, correct for a TLS-terminating
  reverse proxy. The README plain-HTTP recipe now sets it.
- git image never pulled (#190): ensureImage pulls alpine/git (pinned
  digest unchanged) when absent, before the clone container is created.
- port-mapping 500 (#192): the ports delete form used {{ .CSRFField }}
  inside {{range .Ports}}, where the dot is a *models.Port; use
  {{ $.CSRFField }} like the labels and volumes blocks.
- env-var 403 (#191): the editor read the CSRF token from $el (the
  submitting form, which has none) instead of $root, sending an empty
  token; read from $root.

Model: opus-4-8
2026-09-09 14:12:09 +00:00
clawbotandsneak 7a34fc999c Update golangci-lint to v2.12.2 with canonical config (#187)
Check / check (push) Successful in 4s
Bumps golangci-lint from v2.10.1 to v2.12.2 everywhere it is pinned and installs the canonical `.golangci.yml`, then fixes every finding the new linter surfaces so `make check` is green.

## Version pins

- `Dockerfile` lint stage: `golangci/golangci-lint:v2.12.2` (Debian-based), tag plus digest pin
- `script/bootstrap`: `GOLANGCI_LINT_VERSION=2.12.2` with updated `linux-amd64`/`linux-arm64` release-archive sha256 pins

## Config

`.golangci.yml` replaced with the canonical config. Material change: the old file declared `version: "2"` but kept settings under the legacy top-level `linters-settings` key, which golangci-lint v2 ignores — so the intended thresholds (`lll` 88, `funlen` 80/50, `cyclop` 15, `dupl` 100) were not being applied. The canonical file moves them under `linters.settings` and drops `issues.exclude-use-default`.

## Lint fixes (216 findings)

- `lll` (96): wrapped lines to the 88-column limit
- `noctx` (46): `httptest.NewRequestWithContext` with `t.Context()` throughout the tests
- `goconst` (24): shared constants for template/JSON keys in `internal/handlers` and repeated test literals
- `gosec` (23): app-page redirects now go through a `redirectToApp` helper that path-escapes the app ID (G710 open redirect); `http.ServeFile` of the internally derived deployment log path annotated like the adjacent `os.Stat` (G703)
- `dupl` (22): extracted a generic `findAllByAppID` in `internal/models`, a `deleteAppResource` helper in `internal/handlers`, a shared `parsePush` in `internal/service/webhook`, and table-driven/helper-based dedup in tests
- `nolintlint` (5): removed `//nolint:funlen` directives made obsolete by the new limits (plus one more that became obsolete after refactoring)
- `nilerr` (3, surfaced during fixing): resource-delete lookups now propagate the find error to the caller

No behavior changes intended; all tests pass and `make check` is green.

Note: golangci-lint v2.12 warns that `gomodguard` is deprecated in favor of `gomodguard_v2` — a future canonical-config update should address this centrally.
Co-authored-by: sneak <sneak@sneak.berlin>
Reviewed-on: #187
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-08-07 22:21:42 +02:00
sneak 291f85f3ed scripts-to-rule-them-all (#174)
Check / check (push) Successful in 4s
Reviewed-on: #174
Co-authored-by: sneak <sneak@sneak.berlin>
Co-committed-by: sneak <sneak@sneak.berlin>
2026-07-07 02:15:20 +02:00
sneak bee933ce8e TODO (#173)
Check / check (push) Successful in 4s
Reviewed-on: #173
2026-07-06 21:36:27 +02:00
user e09cf11c06 chore: remove TODO.md — all items tracked as Gitea issues
All unchecked items now have corresponding issues:
- #67 Edit env vars/labels/volumes (merged)
- #68 GitHub/GitLab webhook support
- #69 JSON API (PR #74 open)
- #72 CPU/memory resource limits
- #79 Backup/restore
- #80 Private Docker registry auth
- #81 Custom health checks
- #82 Multi-user support with roles
- #83 Scheduled deployments
- #84 Observability (logging, metrics, audit)
- #85 Webhook event history UI
- #86 Settings page

Completed items: #66 (cancel endpoint), #67 (edit entities),
#71 (rollback), plus all Phase 1-2 items already done.
2026-02-16 00:35:23 -08:00
clawbot 6696db957d Update TODO.md: check off deployment cancellation 2026-02-16 09:12:08 +01:00
sneak c13fd8c746 Update TODO.md with completed items
Mark as complete:
- Server.Run(), Shutdown(), SetupRoutes()
- Container logs viewing
- Container restart/stop/start controls
2025-12-29 15:51:54 +07:00
sneak 3f9d83c436 Initial commit with server startup infrastructure
Core infrastructure:
- Uber fx dependency injection
- Chi router with middleware stack
- SQLite database with embedded migrations
- Embedded templates and static assets
- Structured logging with slog

Features implemented:
- Authentication (login, logout, session management, argon2id hashing)
- App management (create, edit, delete, list)
- Deployment pipeline (clone, build, deploy, health check)
- Webhook processing for Gitea
- Notifications (ntfy, Slack)
- Environment variables, labels, volumes per app
- SSH key generation for deploy keys

Server startup:
- Server.Run() starts HTTP server on configured port
- Server.Shutdown() for graceful shutdown
- SetupRoutes() wires all handlers with chi router
2025-12-29 15:46:03 +07:00