A build whose output ends in Docker's error line now fails with that error, instead of going on to inspect a tag that was never created. The build output is written to the deployment log before the failure is recorded, so the log ends in order. Before building, upaas compares the daemon's API version with 1.39 (Docker Engine 18.09), the first that builds with BuildKit without experimental mode, and fails the deploy on an older daemon instead of letting it use the legacy builder. The README's Compose section gives the update command and the Docker Engine versions builds need. Disclosure: merged after a rebase that changed only TODO.md; the review gated this tree on the current next. Model: opus-5-5 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
7.4 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.mdchanges in the same commit as the work) - merge to
mainif 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: 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 --buildand names the Docker Engine versions builds need (#234). -
2026-09-29: An image built from the
Dockerfilenow shows the commit it was built from (thegit describeoutput) in the footer and/healthinstead ofdev:.dockerignoreno 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'sIdentify()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.ymlnow setsUPAAS_PORTto 8080 as well asPORT, since upaas readsUPAAS_PORTfirst and aUPAAS_PORTin.envmade 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_SECRETandUPAAS_CORS_ORIGINS, and gives the real default and effect of each:UPAAS_PORTwins overPORT,UPAAS_HOST_DATA_DIRfalls back toUPAAS_DATA_DIR,UPAAS_DEBUGdrops the session cookie'sSecureflag, andUPAAS_SENTRY_DSNis not used (#229). -
2026-09-28: The README Configuration table now names
UPAAS_DEBUG,UPAAS_SENTRY_DSN,UPAAS_METRICS_USERNAMEandUPAAS_METRICS_PASSWORD, the names upaas actually reads (the unprefixed names it listed were ignored), and theUPAAS_HOST_DATA_DIRrow refers toUPAAS_DATA_DIR(#224). -
2026-09-28: Added
docker-compose.ymlfor deploying upaas: settings from.env, the port published on127.0.0.1only 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 whenUPAAS_HOST_DATA_DIRis 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/gitimage 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 oflogs/<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.TempDircleanup race ininternal/handlers(the one fixed ininternal/service/webhookby #198):TestHandleWebhookProcessesValidWebhooknow waits with the webhook service'sWaitForDeploymentsinstead of sleeping (#211). -
2026-09-22: Vendored the canonical prettier/format toolchain from the
sneak/promptsscaffold: added.prettierrc(tabWidth 4, proseWrap always), pinnedpackage.json+yarn.lock(prettier 3.8.1), taughtscript/bootstrapto install a pinned node/yarn via a hash-verified nvm archive, and switchedscript/fmtto the pinned prettier reading.prettierrc(no inline flags) overstatic/js/*.jsand**/*.md. Reflowed all markdown to house style;alpine.min.jsstays byte-identical (#203). -
2026-09-22: Fixed the flaky
t.TempDircleanup race ininternal/service/webhookby tracking the async deployment goroutine in async.WaitGroupand exposingWaitForDeployments; 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 aGATE_RUNbuild arg so the linter always executes), reducedscript/lintto building it, dropped the golangci-lint install fromscript/bootstrap, and switched theDockerfilelint stage to invokegolangci-lintdirectly instead ofmake lintto avoid docker-in-docker (#188). -
2026-09-22: Added
.prettierignoresomake fmtno longer rewrites the vendoredstatic/js/alpine.min.jsbundle (#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/bootstrapnow installs a pinnedgoimports(golang.org/x/toolsv0.49.0) into/usr/local/bin, somake fmtsucceeds on a fresh machine aftermake 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,Dockerfilelint stage pin,script/bootstraprelease-archive pins) and fixed all resulting lint findings (noctx, gosec, goconst, lll, dupl, nolintlint);make checkgreen. -
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.