Files
upaas/TODO.md
T
clawbot 978356a672
Check / check (pull_request) Skipped
Tag built images with the commit's short hash (closes #239)
Builds are tagged upaas-<app>:<short hash>, git's own short form of
the commit checked out, instead of the deployment number.

A redeploy of a commit gives the tag to the new image. The cleanup
after a deploy now also finds the app's untagged images among those
its deployments recorded, and removes them by ID once the app neither
runs them nor would roll back to them. It keeps every image any app
uses, since apps that build the same commit can share one.

The clone reads the commits from git's output after removing Docker's
log headers, which had hidden the COMMIT: line; commit_sha is now
saved on update so manual deploys keep the commit they recorded.

Model: opus-5-5
2026-09-29 11:15:22 +00:00

8.2 KiB

Workflow

  • branch (from main)
  • do the work in Next Step
  • move Next Step to the top of Completed Steps
  • move the top item of Future Steps into Next Step
  • commit (TODO.md changes in the same commit as the work)
  • merge to main if the branch is not protected, otherwise open a PR
  • push

Status

1.0+. Tagged 1.0.0 on 2026-02-26; 8 commits on main since. make check is green as of the golangci-lint v2.12.2 update.

Next Step

Confirm .gitea/workflows/check.yml gates merges on make check so main cannot regress.

Completed Steps

  • 2026-09-29: Built images are tagged upaas-<app>:<short hash>, git's short form of the commit built, instead of the deployment number. A redeploy of a commit gives its tag to the new image; the old one is kept while the app runs it or Rollback would start it, then removed by its ID, found among the images the app's deployments recorded. The removal of old images now keeps every image any app runs or would roll back to. The clone now reads the commit from git's output, which Docker's log headers had hidden, so manual deploys record their commit too (#239).

  • 2026-09-29: The app page is 50% wider on large screens (84rem instead of 56rem), its build log and container log boxes are twice as tall, the build log sits between the webhook URL and the environment variables, and the container log sits above the deploy key (#246).

  • 2026-09-29: A failed build now fails the deploy with the build's own error instead of a later "failed to inspect image", and the deployment log shows the end of the build output before that error. upaas refuses to build on a Docker Engine older than 18.09, which cannot build with BuildKit. The README's Compose section says to update with docker compose up -d --build and names the Docker Engine versions builds need (#234).

  • 2026-09-29: An image built from the Dockerfile now shows the commit it was built from (the git describe output) in the footer and /health instead of dev: .dockerignore no longer leaves out .git, nor any tracked file, which git would count as deleted and mark -dirty. upaas now also logs its version at startup; the logger's Identify() was never called (#236).

  • 2026-09-29: The app page shows the app's branch as a label in its title, next to the status badge, instead of after the repository under it (#240).

  • 2026-09-29: An app's deployments page now lists only its 10 most recent deployments, newest first, instead of 50 (#238).

  • 2026-09-29: docker-compose.yml now sets UPAAS_PORT to 8080 as well as PORT, since upaas reads UPAAS_PORT first and a UPAAS_PORT in .env made it listen away from the port mapping and healthcheck; the README's Compose section names both (#230).

  • 2026-09-29: The README Configuration table now lists every setting upaas reads, adding UPAAS_MAINTENANCE_MODE, UPAAS_SESSION_SECRET and UPAAS_CORS_ORIGINS, and gives the real default and effect of each: UPAAS_PORT wins over PORT, UPAAS_HOST_DATA_DIR falls back to UPAAS_DATA_DIR, UPAAS_DEBUG drops the session cookie's Secure flag, and UPAAS_SENTRY_DSN is not used (#229).

  • 2026-09-28: The README Configuration table now names UPAAS_DEBUG, UPAAS_SENTRY_DSN, UPAAS_METRICS_USERNAME and UPAAS_METRICS_PASSWORD, the names upaas actually reads (the unprefixed names it listed were ignored), and the UPAAS_HOST_DATA_DIR row refers to UPAAS_DATA_DIR (#224).

  • 2026-09-28: Added docker-compose.yml for deploying upaas: settings from .env, the port published on 127.0.0.1 only for a TLS proxy in front, and a healthcheck against /health; the README's plain-HTTP Compose example is replaced by a short deploy section. upaas now refuses to start when UPAAS_HOST_DATA_DIR is set to a relative path (#223).

  • 2026-09-23: Apps are now built with BuildKit, so the stages of a multi-stage build stay in Docker's size-limited build cache instead of piling up as untagged images; build progress is still written to the deployment log as plain text (#220).

  • 2026-09-23: After a successful deploy, upaas removes the app's images other than the running one and the one rollback would use, together with the untagged images they were built on (#216).

  • 2026-09-23: The git clone container is now removed together with its anonymous volume (the alpine/git image declares one at /git), so a deploy no longer leaves a Docker volume behind (#215).

  • 2026-09-23: Deployment log files are now stored under logs/<appname>/ instead of logs/<hostname>/<appname>/, so downloads keep working after the upaas container is recreated; logs written under an old hostname directory are still found (#214).

  • 2026-09-23: Fixed the flaky t.TempDir cleanup race in internal/handlers (the one fixed in internal/service/webhook by #198): TestHandleWebhookProcessesValidWebhook now waits with the webhook service's WaitForDeployments instead of sleeping (#211).

  • 2026-09-22: Vendored the canonical prettier/format toolchain from the sneak/prompts scaffold: added .prettierrc (tabWidth 4, proseWrap always), pinned package.json + yarn.lock (prettier 3.8.1), taught script/bootstrap to install a pinned node/yarn via a hash-verified nvm archive, and switched script/fmt to the pinned prettier reading .prettierrc (no inline flags) over static/js/*.js and **/*.md. Reflowed all markdown to house style; alpine.min.js stays byte-identical (#203).

  • 2026-09-22: Fixed the flaky t.TempDir cleanup race in internal/service/webhook by tracking the async deployment goroutine in a sync.WaitGroup and exposing WaitForDeployments; tests now synchronize on completion instead of sleeping (#198).

  • 2026-09-22: Linting now runs only in Docker. Added Dockerfile.lint (pinned golangci-lint v2.12.2, cache-busted via a GATE_RUN build arg so the linter always executes), reduced script/lint to building it, dropped the golangci-lint install from script/bootstrap, and switched the Dockerfile lint stage to invoke golangci-lint directly instead of make lint to avoid docker-in-docker (#188).

  • 2026-09-22: Added .prettierignore so make fmt no longer rewrites the vendored static/js/alpine.min.js bundle (#185).

  • 2026-09-22: Fixed the gosec G703 path-traversal finding in the deploy log download handler by verifying the resolved path stays within the deploy log directory before serving, returning 404 on escape (#177).

  • 2026-09-22: script/bootstrap now installs a pinned goimports (golang.org/x/tools v0.49.0) into /usr/local/bin, so make fmt succeeds on a fresh machine after make bootstrap (#184).

  • 2026-09-09: Fixed four deployability blockers found by QA: CSRF origin check over plain HTTP (UPAAS_PLAINTEXT_HTTP, #189), pulling the git image when absent (#190), the env-var editor CSRF token lookup (#191), and the port-mapping delete form's CSRF field (#192).

  • 2026-08-07: Updated golangci-lint to v2.12.2 (canonical .golangci.yml, Dockerfile lint stage pin, script/bootstrap release-archive pins) and fixed all resulting lint findings (noctx, gosec, goconst, lll, dupl, nolintlint); make check green.

  • 2026-07-07 Adopted scripts-to-rule-them-all: script/ entrypoints, Makefile shims, README Entrypoints section

  • 2026-03-11: Monolithic env var editing with bulk save (#158).

  • 2026-03-10: Webhook event history UI page (#164); added missing Makefile docker and hooks targets plus test timeout (#159); notification settings passed from create form (#160).

  • 2026-03-03: REPO_POLICIES compliance file set added (#155).

  • 2026-03-01: Module path changed to sneak.berlin/go/upaas (#143); Dockerfile split into lint and build stages with forced lint execution (#152, #154).

  • 2026-02-26: 1.0.0 tagged; dashboard CSRFField crash fixed (#146).

  • 1.0 audit bug fixes (#120-#125): deferred rollback on commit error, deployment log size cap, error path rendering, docker-compose bind mount, domain type refactor.

  • CI simplified to docker build only (#130).

  • 2025-12-29 onward: core PaaS built out: deploys with real-time build log streaming, container start/stop/restart and logs, TCP/UDP port mapping, Alpine.js UI, Slack notifications, ULID app IDs, session handling.

Future Steps

  • Resume feature work only after main is green.