Skip to content

feat(drop): deploy uploaded source archives - #549

Merged
dviejokfs merged 8 commits into
mainfrom
feat/vercel-zero-config-compat
Aug 4, 2026
Merged

feat(drop): deploy uploaded source archives#549
dviejokfs merged 8 commits into
mainfrom
feat/vercel-zero-config-compat

Conversation

@dviejokfs

Copy link
Copy Markdown
Contributor

Summary

  • add /drop project inspection and uploaded-source deployment APIs
  • detect framework/runtime presets from uploaded ZIP manifests
  • persist source bundles and execute them through the deployment workflow without Git
  • add browser and CLI Drop flows with project creation, deployment-detail redirect, rollback, and cleanup
  • remove project-owned Docker containers and stored bundles when a project is deleted
  • add a transient zero-config compatibility harness

Paired fixture PR: gotempsh/temps-examples#13

Status

Draft — security review is currently REQUEST_CHANGES. Do not merge yet.

Known blocking work:

  • extraction cleanup records the parent directory and leaks uploaded-source-* trees
  • project.directory needs strict relative-path validation and canonical containment before becoming a Docker build context
  • uploaded Docker Compose candidates bypass source extraction
  • PR evidence is still missing migration down/up proof, corrected UI capture, and a real CLI invocation

Additional follow-up findings include streaming large multipart uploads rather than buffering 500 MB, enforcing extraction quotas from actual bytes written, regenerating SDK operations for both endpoints, restricting advertised archives to implemented formats, and adding .NET manifest detection.

Evidence

Rust

cargo check --lib
cargo clippy --lib -- -D warnings

Result: both completed successfully. Cargo check built 540 crates with zero errors; clippy completed with zero errors.

Web

cd web
bunx tsc --noEmit
bun test src/lib/drop-archive.test.ts src/lib/drop-project-name.test.ts

Result: TypeScript passed; 11 tests passed, 0 failed.

Compatibility harness

bash scripts/test-zero-config-compat.sh
bash -n scripts/zero-config-compat.sh

Result: zero-config compatibility harness test passed.

Uploaded-source runtime matrix

The paired temps-examples runner packaged each source directory, called /api/drop/inspect, created an uploaded-source project, deployed it, verified / and /health, deleted the project, and checked Docker cleanup.

Runtime Result
Java 17 passed
Python passed
Rust passed
Go passed
.NET 8 inspection failed because .csproj detection is not implemented

Project rows, stored fixture archives, and labeled Docker containers were removed. The run reproduced the extraction-directory leak; the seven test directories were then removed manually.

Known baseline check failure

apps/temps-cli/bun run typecheck reports existing errors in openapi-ts.config.ts, env-sync, environments, notifications, and providers. It reported no error in the new Drop command. This draft does not claim the repository-wide CLI type-check is green.

Review findings to resolve

  • move uploaded-source orchestration from the handler into a typed service and make durable writes atomic
  • validate archive/build paths at every boundary
  • make extraction cleanup reliable on success, failure, and cancellation
  • stream uploads and account for actual extracted bytes
  • add handler/service/planner/job tests, including Compose and wrapped static ZIPs
  • regenerate web and CLI SDK clients and replace raw endpoint fetches
  • add .tempsignore/.gitignore packaging behavior to avoid uploading secrets and build directories

Add browser and CLI Drop flows, preset inspection, persisted source bundles, uploaded-source workflow planning, and project container cleanup.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

📓 Changelog preview

This is what your commits will add to the generated CHANGELOG.md at release time (via git-cliff). Do not edit CHANGELOG.md by hand — it is generated from your Conventional Commit messages.

## [Unreleased]

### Added

- **drop:** Deploy uploaded source archives
- **drop:** Add header entry point and a project-scoped drop page

### Fixed

- **drop:** Harden uploaded deployments and cleanup
- **drop:** Bound archive inspection memory and CPU

### Testing

- **deployments:** Stub container-ownership lookup in cleanup tests

Resolve conflicts:
- crates/temps-presets/src/mod.rs: keep the branch's deduplicated import
  block and fold in main's autopack_preset re-export.
- Generated SDKs (apps/temps-cli + web/src/api/client): regenerated from a
  three-way merged openapi.json instead of hand-merging, so both clients now
  match a fresh codegen and pick up the react-query hooks for the Drop
  endpoints.
Both the security audit and the standards review flagged /api/drop/inspect
as an unbounded-allocation vector.

- inspect_zip_manifests capped count and per-entry size but not the
  aggregate. MAX_FILES x MAX_MANIFEST_BYTES is 20 GiB, and manifests
  compress ~1000:1, so a ~5 MB upload could pin gigabytes of String per
  request and OOM the whole binary on the 4 GB reference box. Add an
  aggregate manifest budget (16 MiB, counted against bytes actually read,
  not the declared header size), a manifest count cap, and a budget on the
  retained entry paths.
- detect_project_candidates ran after the spawn_blocking closure, so the
  concurrency permit no longer covered it and the work landed on an async
  runtime thread. Its has_extension closure also rescanned every key per
  root, making it O(roots x files). Index paths by directory once, run
  detection inside the same spawn_blocking, skip dependency/build-output
  directories, bound root depth, and cap the candidate list.
- archive_security: replace the two .expect() calls with typed errors.

Verified against a 5.2 MB archive of 4000 x 1 MiB manifests: 413 in 36 ms
with server RSS flat at 301 MB.
Picks up teams/project-scoped RBAC (#486) and AI-proposed metric alert
rules (#521).

Resolve conflicts:
- migration/mod.rs: both sides add a migration; keep both in date order
  (m20260730 teams RBAC before m20260731 source bundles).
- Generated SDKs: regenerated from a three-way merged openapi.json rather
  than hand-merged, so both clients match a fresh codegen.
Drop was only reachable from the project-creation flow, and re-uploading
source into an existing project used a bare `<input type="file">` dialog
that accepted a ZIP only — no drag-and-drop, no folder support, no preset
detection. That was a worse experience than the front door for the users
most likely to repeat the action.

- Add a global header button (UploadCloud, matching every other Drop
  surface) so Drop follows you across the console instead of living only
  under Projects.
- Extract the drag-and-drop surface into `components/drop/DropZone` and the
  browser file-reading helpers into `lib/drop-files`, so `/drop` and the new
  page cannot drift apart.
- Add `/projects/:slug/drop`, replacing the modal. Accepts a folder, a
  single HTML file, or a ZIP; runs the same detect-then-deploy flow.
  It may change the build directory and preset only — ports, resources and
  environment variables are deliberately left alone.
This branch added a runtime ownership check to
`cleanup_project_containers` — it calls `get_container_info` and refuses
to remove a container whose `sh.temps.*` labels do not match the project
and environment being deleted. Three pre-existing cleanup tests were not
updated, so they panicked on
`MockContainerDeployer::get_container_info(...): No matching expectation
found` rather than exercising the behaviour they assert.

Add a shared `expect_owned_container_info` helper and wire it into all
three, plus a test for the guard itself: a container whose labels claim a
different project must fail closed, must never reach `remove_container`,
and must not be marked deleted.
@dviejokfs
dviejokfs marked this pull request as ready for review August 4, 2026 14:03
@dviejokfs
dviejokfs merged commit c6bd08d into main Aug 4, 2026
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant