Commit Graph
171 Commits
Author SHA1 Message Date
clawbot d661c81955 Remove unnecessary goimports install from lint stage
Check / check (pull_request) Successful in 1m27s
The lint stage only needs golangci-lint (built into base image) and
gofmt for fmt-check. Neither make fmt-check nor make lint uses the
goimports binary directly. Removing it makes the lint stage faster,
which is the whole point of the multi-stage split.

goimports is only used by 'make fmt' which is a local developer
tool, not run during Docker builds.
2026-03-01 11:30:59 -08:00
clawbot 2c4c1beaf9 split Dockerfile into lint + build stages for faster CI feedback
Check / check (pull_request) Successful in 2m26s
- Add dedicated lint stage using golangci/golangci-lint:v2.10.1 image
  (pinned by sha256 digest) for fast formatting and lint checks
- Keep build stage with golang:1.25-alpine for tests and compilation
- Remove manual golangci-lint download/install from builder stage
- Add fmt-check Makefile target for standalone format checking
- Refactor check target to use fmt-check, lint, test dependencies

The lint stage uses the official golangci-lint image which has the
linter pre-installed, eliminating the need to download it on every
build. Lint failures now surface immediately without waiting for
the download step.

closes #151
2026-03-01 10:32:31 -08:00
sneak 578c6ec842 Merge pull request 'tidy' (#148) from fix/tidy into main
Check / check (push) Successful in 2m24s
Reviewed-on: #148
1.0.0
2026-02-26 13:55:28 +01:00
sneak 1c2bf80d7d tidy
Check / check (pull_request) Successful in 2m32s
2026-02-26 19:52:09 +07:00
sneak 019ba7fe1f Merge pull request 'Fix dashboard CSRFField crash (closes #146)' (#147) from fix/dashboard-csrf-field into main
Check / check (push) Successful in 2m24s
Reviewed-on: #147
2026-02-26 12:07:42 +01:00
user c22a2877d5 fix: pass CSRFField to dashboard template (closes #146)
Check / check (pull_request) Successful in 2m30s
2026-02-26 02:56:27 -08:00
user 43cde0eefd test: add failing test for dashboard CSRFField (refs #146) 2026-02-26 02:56:00 -08:00
sneak b1c6b93d8e Merge pull request 'fix: simplify CI to docker build only (closes #130)' (#131) from fix/ci-docker-build-only into main
Check / check (push) Waiting to run
Reviewed-on: #131
2026-02-26 11:53:14 +01:00
sneak 1875792ebe Merge branch 'main' into fix/ci-docker-build-only
Check / check (pull_request) Successful in 2m47s
2026-02-26 11:53:03 +01:00
sneak 7bbaa1d08a Merge pull request 'Fix 1.0 audit bugs (closes #120, closes #121, closes #122, closes #123, closes #124, closes #125)' (#126) from fix/audit-bugs-120-125 into main
Check / check (push) Waiting to run
Reviewed-on: #126
2026-02-26 11:52:54 +01:00
user 43a0cbac70 fix: use pre-built golangci-lint binary instead of go install
Check / check (pull_request) Successful in 13m22s
go install fails in alpine Docker builder because the linker (ld) is not
available. Download the official pre-built binary with SHA256 verification
instead. Supports both amd64 and arm64 architectures.

Fixes #126
2026-02-26 02:17:54 -08:00
clawbot fb866af4e5 simplify CI to docker build only (refs #130)
Check / check (pull_request) Failing after 4s
The Dockerfile already runs make check, so the CI action only needs
to run docker build. Remove go setup, linter installation, and
direct make check invocation from the workflow.
2026-02-26 02:11:15 -08:00
user 91d6da0796 fix: move inline comments above FROM lines (fixes docker build)
Check / check (pull_request) Successful in 11m20s
Docker does not support inline comments on FROM lines. Move the
human-readable image tag comments to their own line above each FROM.

Fixes broken docker build on PR #126 and main.
2026-02-26 02:06:11 -08:00
clawbot 57e0735afa docs: expand Important note — HOST_DATA_DIR must be absolute path
Check / check (pull_request) Successful in 11m48s
Explain why relative paths break container builds and add usage example.
Addresses sneak's review feedback on PR #126.
2026-02-26 02:01:13 -08:00
clawbot 2eeead7e64 docs: clarify UPAAS_DATA_DIR default is for local dev only
The ./data default comes from Go code and works for local development.
For Docker deployments, an absolute path should be used.
Updated config table to make this distinction clear.
2026-02-26 02:01:13 -08:00
user 76fe014e9a docs: remove relative path default for HOST_DATA_DIR in docker-compose example
Users must set HOST_DATA_DIR to an explicit absolute path. Removed
the :-./data fallback from both the volume mount and environment
variable in the docker-compose example.
2026-02-26 02:01:13 -08:00
user f36732eaf5 refactor: remove internal/domain package, move types to correct packages
- ImageID + ContainerID → internal/docker/types.go
- UnparsedURL → internal/service/webhook/types.go
- Delete internal/domain/ entirely
- Update all imports throughout the codebase
2026-02-26 02:01:12 -08:00
user 3a1b1e3cd4 refactor: add String() methods to domain types, replace string() casts 2026-02-26 02:01:12 -08:00
clawbot 594537e6f5 rework: address review feedback on PR #126
Changes per sneak's review:
- Delete docker-compose.yml, add example stanza to README
- Define custom domain types: ImageID, ContainerID, UnparsedURL
- Use custom types in all function signatures throughout codebase
- Restore imageID parameter (as domain.ImageID) in deploy pipeline
- buildContainerOptions now takes ImageID directly instead of
  constructing image tag from deploymentID
- Fix pre-existing JS formatting (prettier)

make check passes with zero failures.
2026-02-26 02:01:12 -08:00
clawbot a6c76232bf fix: assign commit error to err so deferred rollback triggers (closes #125)
When Commit() failed, the error was stored in commitErr instead of err,
so the deferred rollback (which checks err) was skipped.
2026-02-26 02:00:49 -08:00
clawbot 46574f8cf1 fix: rename GetBuildDir param from appID to appName (closes #123)
The parameter is always called with app.Name, not an ID. Rename to match
actual usage and prevent confusion.
2026-02-26 02:00:49 -08:00
clawbot 074903619d fix: add 1MB size limit on deployment logs with truncation (closes #122)
Cap AppendLog at 1MB, truncating oldest lines when exceeded. Prevents
unbounded SQLite database growth from long-running builds.
2026-02-26 02:00:49 -08:00
clawbot 6cf6e89db4 fix: use renderTemplate in all error paths of HandleAppCreate/HandleAppUpdate (closes #121)
Replace direct tmpl.ExecuteTemplate calls with h.renderTemplate to ensure
buffered rendering and prevent partial HTML responses on template errors.
2026-02-26 02:00:49 -08:00
clawbot 5c20b0b23d fix: use bind mount with HOST_DATA_DIR in docker-compose.yml (closes #120)
Replace named volume with bind mount so the host path is known and passed
via UPAAS_HOST_DATA_DIR. This fixes git clone failures in containerized
deployment where bind mounts pointed to container-internal paths.
2026-02-26 02:00:49 -08:00
sneak e051245b5f Merge pull request 'Refactor: break up app.js into smaller modules' (#129) from refactor/split-app-js into main
Check / check (push) Successful in 11m41s
Reviewed-on: #129
2026-02-26 10:59:02 +01:00
user 5fe11f24d4 refactor: break up app.js into smaller modules
Check / check (pull_request) Successful in 11m29s
Split static/js/app.js (581 lines) into 5 focused modules:
- utils.js: global utilities store + legacy compat
- components.js: reusable Alpine.js components (copy, confirm, dismiss, time)
- app-detail.js: app detail page logic (status polling, logs)
- deployment.js: deployment card + deployments history page
- dashboard.js: dashboard relative time updates

Closes #128
2026-02-23 11:52:41 -08:00
sneak 28f014ce95 Merge pull request 'fix: use imageID in createAndStartContainer (closes #124)' (#127) from fix/use-image-id-in-container into main
Check / check (push) Successful in 11m32s
Reviewed-on: #127
2026-02-23 20:48:23 +01:00
sneak dc638a07f1 Merge pull request 'fix: pin all external refs to cryptographic identity (closes #118)' (#119) from fix/pin-external-refs-crypto-identity into main
Check / check (push) Has been cancelled
Reviewed-on: #119
2026-02-23 20:48:09 +01:00
user 0e8efe1043 fix: use imageID in createAndStartContainer (closes #124)
Check / check (pull_request) Successful in 11m24s
Wire the imageID parameter (returned from docker build) through
createAndStartContainer and buildContainerOptions instead of
reconstructing a mutable tag via fmt.Sprintf.

This ensures containers reference the immutable image digest,
avoiding tag-reuse races when deploys overlap.

Changes:
- Rename _ string to imageID string in createAndStartContainer
- Change buildContainerOptions to accept imageID string instead of deploymentID int64
- Use imageID directly as the Image field in container options
- Update rollback path to pass previousImageID directly
- Add test verifying imageID flows through to container options
- Add database.NewTestDatabase and logger.NewForTest test helpers
2026-02-21 02:24:51 -08:00
user 0ed2d02dfe fix: pin all external refs to cryptographic identity (closes #118)
Check / check (pull_request) Successful in 11m41s
- Pin Docker base images to sha256 digests (golang, alpine)
- Pin go install commands to commit SHAs (not version tags)
  - golangci-lint: 5d1e709b7be35cb2025444e19de266b056b7b7ee (v2.10.1)
  - goimports: 009367f5c17a8d4c45a961a3a509277190a9a6f0 (v0.42.0)
- CI workflow was already correctly pinned to commit SHAs

All references now use cryptographic identity, eliminating RCE risk
from mutable tags.
2026-02-21 00:50:44 -08:00
sneak ab526fc93d Merge pull request 'fix: disable API v1 write methods (closes #112)' (#115) from fix/disable-api-write-methods into main
Check / check (push) Successful in 11m20s
Reviewed-on: #115
2026-02-20 14:35:12 +01:00
user ab7c43b887 fix: disable API v1 write methods (closes #112)
Check / check (pull_request) Successful in 11m21s
Remove POST /apps, DELETE /apps/{id}, and POST /apps/{id}/deploy from
the API v1 route group. These endpoints used cookie-based session auth
without CSRF protection, creating a CSRF vulnerability.

Read-only endpoints (GET /apps, GET /apps/{id}, GET /apps/{id}/deployments),
login, and whoami are retained.

Removed handlers: HandleAPICreateApp, HandleAPIDeleteApp,
HandleAPITriggerDeploy, along with apiCreateRequest struct and
validateCreateRequest function.

Updated tests to use service layer directly for app creation in
remaining read-only endpoint tests.
2026-02-20 05:33:07 -08:00
sneak 4217e62f27 Merge pull request 'fix: resolve 1.0 audit bugs (closes #104, #105, #106, #107, #108)' (#109) from fix/1.0-audit-bugs into main
Check / check (push) Has been cancelled
Reviewed-on: #109
2026-02-20 13:47:12 +01:00
clawbot 327d7fb982 fix: resolve lint issues in handlers and middleware
Check / check (pull_request) Successful in 11m26s
2026-02-20 03:35:44 -08:00
clawbot 6cfd5023f9 fix: SetupRequired middleware exempts health, static, and API routes (closes #108) 2026-02-20 03:33:34 -08:00
clawbot efd3500dac fix: HandleVolumeAdd validates host and container paths (closes #107) 2026-02-20 03:33:19 -08:00
clawbot ec87915234 fix: API delete endpoint cleans up Docker container before DB deletion (closes #106) 2026-02-20 03:33:04 -08:00
clawbot cd0354e86c fix: API deploy handler uses detached context to prevent cancellation (closes #105) 2026-02-20 03:32:42 -08:00
clawbot 7d1849c8df fix: HandleEnvVarDelete uses correct varID route param (closes #104) 2026-02-20 03:32:20 -08:00
sneak 4a73a5575f Merge pull request 'ci: add Gitea Actions workflow for make check (closes #96)' (#100) from ci/check-workflow-only into main
Check / check (push) Waiting to run
Reviewed-on: #100
2026-02-20 12:19:29 +01:00
sneak a5d703a670 Merge branch 'main' into ci/check-workflow-only
Check / check (pull_request) Failing after 6m16s
2026-02-20 12:00:02 +01:00
sneak c8a8f88cd0 Merge pull request 'chore: code cleanup and best practices (closes #45)' (#95) from chore/code-cleanup into main
Reviewed-on: #95
2026-02-20 11:59:31 +01:00
sneak aab2375cfa Merge branch 'main' into chore/code-cleanup 2026-02-20 11:59:06 +01:00
sneak 2ba47d6ddd Merge pull request 'fix: validate repo URL format on app creation (closes #88)' (#91) from fix/repo-url-validation into main
Reviewed-on: #91
2026-02-20 11:58:48 +01:00
user 0bb59bf9c2 feat: sanitize container log output beyond Content-Type
Add SanitizeLogs() that strips ANSI escape sequences and non-printable
control characters (preserving newlines, carriage returns, and tabs)
from all container and deployment log output paths:

- HandleAppLogs (text/plain response)
- HandleDeploymentLogsAPI (JSON response)
- HandleContainerLogsAPI (JSON response)

Container log output is attacker-controlled data. Content-Type alone
is insufficient — the data itself must be sanitized before serving.

Includes comprehensive test coverage for the sanitization function.
2026-02-20 02:54:16 -08:00
clawbot dcff249fe5 fix: sanitize container log output and fix lint issues
- Update nolint comment on log streaming to accurately describe why
  gosec is suppressed (text/plain Content-Type, not HTML)
- Replace <script type="text/plain"> with data attribute for initial
  logs to prevent </script> breakout from attacker-controlled log data
- Move RemoveImage before unexported methods (funcorder)
- Fix file permissions in test (gosec G306)
- Rename unused parameters in export_test.go (revive)
- Add required blank line before assignment (wsl)
2026-02-20 02:54:07 -08:00
clawbot a2087f4898 fix: restrict SCP-like URLs to git user only and reject path traversal
- Changed SCP regex to only accept 'git' as the username
- Added path traversal check: reject URLs containing '..'
- Added test cases for non-git users and path traversal
2026-02-20 02:51:38 -08:00
clawbot a2fb42520d fix: validate repo URL format on app creation (closes #88) 2026-02-20 02:51:38 -08:00
clawbot 6d600010b7 ci: add Gitea Actions workflow for make check (closes #96)
Check / check (pull_request) Successful in 11m32s
All external references pinned by commit hash:
- actions/checkout@34e114876b (v4)
- actions/setup-go@40f1582b24 (v5)
- golangci-lint@5d1e709b7b (v2.10.1)
- goimports@009367f5c1 (v0.42.0)
2026-02-20 02:51:10 -08:00
sneak 8ad2c6e42c Merge pull request 'Fix all main branch lint issues (closes #101)' (#102) from fix/main-lint-issues into main
Reviewed-on: #102
2026-02-20 11:42:34 +01:00