Add Vercel deployment integration#1447
Draft
davidfowl wants to merge 33 commits into
Draft
Conversation
Adds a preview Vercel hosting integration for Dockerfile-based deployments, including publish/deploy/destroy pipeline steps, execution configuration processing, TypeScript AppHost exports, docs, examples, and tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1447Or
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1447" |
Adds focused unit coverage for Vercel pipeline step registration, deploy and destroy flows, CLI prerequisite handling, deployment state fallback, and API overloads. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Refactor Vercel deployments to consume Aspire Dockerfile build annotations instead of Vercel-specific source root and Dockerfile settings. Stage generated or non-default Dockerfiles as Dockerfile before invoking the Vercel CLI, and update tests/docs/examples for the new model. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Update the Vercel example and docs to use Aspire language workload integrations instead of requiring app-authored Dockerfiles. Make PublishAsVercel work for executable-derived language resources that already registered generated Dockerfile metadata. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove the Vercel-specific PublishAsVercel marker API and discover Dockerfile-backed compute resources through Aspire's compute environment targeting model. Vercel now uses the single compute environment default and WithComputeEnvironment for ambiguous AppHosts while continuing to consume existing Dockerfile publish metadata from language and project integrations. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use the standard vercel executable from PATH for deploy and destroy instead of modeling CLI path configuration in the AppHost API. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add state-safe deploy/destroy behavior, Vercel inspect verification, staging safeguards, explicit unsupported-feature validation, TypeScript publish coverage, and CI matrix compatibility for the Vercel deployment target. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Make destroy state-first, persist Vercel deployment state incrementally, validate managed project-name uniqueness, and require explicit verified deployment outputs before saving state. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Break the Vercel deployment implementation into focused partial files for orchestration, plan generation, CLI handling, state, Build Output/VCR setup, environment mapping, model validation, and shared types. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move Vercel CLI arguments, output parsing, Docker digest parsing, project naming, Build Output generation, environment mapping, deployment model validation, plan writing, and state handling into focused internal components while keeping the deployment step as the Aspire pipeline coordinator. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove the compatibility helper facade so tests exercise the extracted components directly. Centralize shared Vercel protocol constants, remove trivial wrappers, and keep state serialization in the state store. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the loose VercelJson helper with typed DTOs for Vercel CLI, project settings, OIDC token, and Docker manifest JSON shapes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add focused comments and Vercel documentation links for CLI JSON shapes, Build Output API deployment, project linking, generated URLs, VCR auth, and secret environment handling. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add class-level purpose comments across the Vercel deployment components so future maintainers can quickly see each unit's responsibility and why it exists. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Stop rejecting Aspire wait relationships for Vercel deployments and cover the behavior with a deployment-plan regression test. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Stop rejecting Aspire replica annotations for Vercel deployments and cover the behavior with a deployment-plan regression test. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Stop rejecting Aspire health check annotations for Vercel deployments while continuing to reject container and endpoint probes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the standalone Vercel CLI argument bag helper with typed Vercel and Docker runner operations, keeping raw process execution private to the concrete runner and updating tests to exercise the typed seam. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
|
Map public Aspire workloads to Vercel projects and referenced private workloads to Vercel services. Generate service-aware Build Output API artifacts, push service-scoped VCR images, and validate unsupported grouping shapes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes N/A
Adds a preview
CommunityToolkit.Aspire.Hosting.Verceldeployment integration for Vercel Dockerfile/container-image hosting. The integration models Vercel as an Aspire compute environment: one Aspire Vercel environment maps to one Vercel project, and every image-build resource assigned to that environment becomes a Vercel Service in that project.Vercel docs that enable this integration
vercel deploy --prebuilt.--prebuilt,--prod, and deployment flow.Cardinality model
VercelEnvironmentResourcemaps to one Vercel project.vcr.vercel.com/<owner>/<project>/<service>:<tag>.Code sample and Vercel deployment mapping
This sample deploys one public frontend plus one private backend into a single Vercel project.
C#:
TypeScript:
AddVercelEnvironment("vercel").WithVercelProjectName("my-frontend")my-frontend; production URL ishttps://my-frontend.vercel.app..WithVercelProductionDeployments()vercel deploy --prodand enables deterministic cross-environment production URLs.backendwithisExternal: falsebackend; pushes image tovcr.vercel.com/<owner>/my-frontend/backend:<tag>.frontendwithisExternal: truefrontend; pushes image tovcr.vercel.com/<owner>/my-frontend/frontend:<tag>and routes public traffic to it.WithEnvironment("BACKEND_URL", backend.GetEndpoint("http"))BACKEND_URL, givingfrontenda private URL forbackend.aspire deployvercel deploy --prebuilt, verifies withvercel inspect, and saves project state for destroy.Mapping diagram
graph TD AppHost["Aspire AppHost sample"] --> Env["Vercel environment: vercel"] Env --> Project["Vercel project: my-frontend"] Project --> Frontend["Service: frontend<br/>public root<br/>external HTTP endpoint"] Project --> Backend["Service: backend<br/>private/internal HTTP endpoint"] Frontend -- "BACKEND_URL service binding" --> Backend Project --> Route["Build Output route<br/>/* -> frontend"] Project --> VCR["VCR project repository<br/>vcr.vercel.com/<owner>/my-frontend"] VCR --> FrontendImage["/frontend:<tag><br/>linux/amd64 digest pinned"] VCR --> BackendImage["/backend:<tag><br/>linux/amd64 digest pinned"] Project --> Deploy["vercel deploy --prebuilt --prod"] Deploy --> Url["https://my-frontend.vercel.app"]Additional usage samples
Deploy a .NET project with
AddProjectC#:
TypeScript:
Deploy a Node.js app with
AddNodeAppC#:
TypeScript:
Deploy a Next.js app with
AddNextJsAppC#:
TypeScript:
Customize the Vercel project name
C#:
TypeScript:
Linked projects with
.vercel/project.jsonkeep their existing Vercel identity. If multiple targeted source roots are linked, they must all resolve to the same Vercel project because the environment maps to one project.Implementation notes
VercelEnvironmentResourceowns the Vercel project name/link. Environment-levelWithVercelProjectNameis the supported API; the old resource-level C# method is retained as a non-exported compatibility method and deployment validation tells users to move the setting to the environment.VercelDeploymentProjectGrouperbuilds one deployment group per Vercel environment. Single-resource deployments remain compatible. Multi-resource deployments require exactly one public root service; the rest become private services in the same project.aspire publishwrites a deterministicvercel-deployments.jsonplan with command shape and environment variable names.aspire deployresolves values, mutates Vercel, pushes images, writes Build Output API files, deploys prebuilt output, and saves state.aspire deploy --list-stepsshowsvercel-prepare-project-*, Aspirebuild-*/push-*,vercel-generate-plan-*, andvercel-deploy-prebuilt-*. The Vercel prepare step runs before Aspire push validation so VCR registry annotations are available to built-in image push steps..vercel/outputtree for the environment project with root routes,experimentalServicesV2, service manifests, service bindings, and per-service container function configs under.vercel/output/services/<service>/functions/index.func/.vc-config.json.handler, because Vercel Container Images rejected OCI index digests in live validation.vercel env add --sensitiveover stdin.Expected failure modes
These failures are validated during
aspire publish/deploy preflight before provider mutation so users and agents get a concrete AppHost fix. Deploy preflight validates every Vercel environment in the AppHost before any one environment creates or links a provider project.AddVercelEnvironment(...)resources withWithComputeEnvironment(...).WithEndpoint(..., isExternal: true)orWithExternalHttpEndpoints(), or deploy only one resource.WithVercelProjectNamebuilder.AddVercelEnvironment("vercel").WithVercelProjectName("my-project")..vercel/project.jsonproject IDs in one environmentHost/Portinstead of a URLWithEnvironment("BACKEND_URL", backend.GetEndpoint("http")), or split environments if host/port properties are required.WithVercelProductionDeployments()on the referenced Vercel environment, or keep services in the same environment and use service bindings.Included
CommunityToolkit.Aspire.Hosting.Vercelpackage with Vercel environment APIs, environment-project naming, Vercel CLI execution, VCR setup, Build Output API generation, deploy, and destroy support.experimentalServicesV2, service manifests, container function configs, non-secret env vars, and service bindings.Validation
dotnet build src/CommunityToolkit.Aspire.Hosting.Vercel/CommunityToolkit.Aspire.Hosting.Vercel.csproj --nologodotnet test tests/CommunityToolkit.Aspire.Hosting.Vercel.Tests/CommunityToolkit.Aspire.Hosting.Vercel.Tests.csproj --no-restorepwshunavailable for the TypeScript AppHost start smoke)git diff --check/Users/davidfowler/.copilot/session-state/28b8f56e-6de0-47f7-a45d-1fda1ba0f978/files/vercel-cardinality-e2e-20260703202823.aspire deploy --list-steps --non-interactiveshowed onevercel-prepare-project-vercel, two build/push paths, and onevercel-deploy-prebuilt-vercel.aspire deploy --non-interactivedeployed one environment project:ct-vercel-card-e2e-20260703202823./backend:<tag>and/frontend:<tag>.vercel inspect --format=jsonreturnedREADY.BACKEND_URLVercel service binding.aspire publish --non-interactive -o publish-env-project-rerunoutput and verified both service entries use the same<vercel-project>placeholder.aspire destroy --non-interactive --yesand verified Vercel no longer listed the project./Users/davidfowler/.copilot/session-state/28b8f56e-6de0-47f7-a45d-1fda1ba0f978/files/vercel-multi-service-e2e-202607032213.aspire deploy --list-steps --non-interactiveshowed one project prepare step, three parallel build/push paths, and one prebuilt deploy.aspire deploy --non-interactivedeployed one project:ct-vercel-multi-e2e-202607032213./backend:<tag>,/frontend:<tag>, and/worker:<tag>.BACKEND_URLandWORKER_URLVercel service-binding URLs.vercel inspect --format=jsonreturnedREADYand three container service outputs:services/backend/index,services/frontend/index, andservices/worker/index.aspire destroy --non-interactive --yesand verifiedvercel project inspectreported no project forct-vercel-multi-e2e-202607032213./Users/davidfowler/.copilot/session-state/28b8f56e-6de0-47f7-a45d-1fda1ba0f978/files/vercel-e2e-error-matrix./Users/davidfowler/.copilot/session-state/28b8f56e-6de0-47f7-a45d-1fda1ba0f978/files/vercel-deploy-error-matrix-202607032224.aspire deploy --non-interactive: multiple public roots, no public root, resource-level project naming, same-project host-property references, cross-environment preview references, and multiple linked projects.PR Checklist