JasperFx.Aspire: startup gates (A2)#404
Merged
Merged
Conversation
…rvice starts (A2)
Extends JasperFx.Aspire (same package as A1) with run-to-completion startup gates.
One line runs a JasperFx provisioning verb to completion BEFORE the owning service
starts, wired via Aspire's WaitForCompletion:
builder.AddProject<Projects.Api>("api")
.WithReference(db).WaitFor(db)
.WithJasperFxStartup("resources", "setup");
Unlike A1's on-demand buttons, a gate is a first-class Aspire resource pointing at
the SAME project with the verb as args — so Aspire injects connection strings/env
natively (no callback-spawn or env-resolution trick; A2 sidesteps A1's main risk).
- WithJasperFxStartup (single-verb + fluent forms) + JasperFxStartupGate
(ResourceName/Parallel/BlockOnFailure/RunWhen/ConfigureGate) + JasperFxStartupBuilder
(Run/Check). Parent constraint is IResourceWithEnvironment + IResourceWithWaitSupport.
- Gate factory: AddProject(name, sameProjectPath) + WithArgs(verb, arg); clones the
parent's reference/env annotations (EnvironmentCallbackAnnotation/WaitAnnotation/
ResourceRelationshipAnnotation) onto the gate, snapshotting them BEFORE wiring so
WaitForCompletion annotations don't leak onto later gates.
- Sequential WaitForCompletion chaining in declaration order; Parallel opt-out;
check-env opt-in blocking; RunWhen environment gating; fail-fast on non-zero exit.
Defaults: resources -> setup, codegen -> write (distinct from A1's codegen -> preview).
20 new tests (pure helpers + app-model assertions over AddProject/WaitForCompletion/
clone wiring via DistributedApplication.CreateBuilder, no Docker). Sample AppHost gains
a resources-setup + blocking check-env gate. Docs: new "Startup gates" section on the
Aspire dashboard integration page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced May 31, 2026
Closed
Closed
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.
Implements A2 from the design doc (
.claude/docs/jasperfx-aspire-startup-gates-design.md), the orchestration-time complement to A1 (merged in #402). Ships in the sameJasperFx.Aspirepackage.Run a JasperFx provisioning verb as a run-to-completion resource that finishes before the service starts, wired via Aspire's
WaitForCompletion:Why this is low-risk vs A1
A1's hard problem was resolving a resource's environment inside a callback and spawning a child by hand. A2 has no such problem — each gate is a first-class Aspire resource pointing at the same project with the verb as args, so Aspire injects connection strings/env natively. The gate inherits the parent's references (declared before
WithJasperFxStartup).What's here
WithJasperFxStartup(single-verb + fluent forms) +JasperFxStartupGate(ResourceName/Parallel/BlockOnFailure/RunWhen/ConfigureGate) +JasperFxStartupBuilder(Run/Check). Parent constraint isIResourceWithEnvironment, IResourceWithWaitSupport.AddProject(name, sameProjectPath)+WithArgs(verb, arg); clones the parent's reference/env annotations (EnvironmentCallbackAnnotation/WaitAnnotation/ResourceRelationshipAnnotation) onto the gate. Annotations are snapshotted before any wiring so theWaitForCompletionannotations added to the parent don't leak onto later gates.WaitForCompletionchaining in declaration order;Parallelopt-out.check-envis an opt-in blocking gate (Check()/WithJasperFxStartup("check-env"));RunWhenmakes a gate environment-conditional; non-zero exit fails fast.resources→setup,codegen→write(distinct from A1'scodegen→preview).Verification
dotnet build jasperfx.slnx -c Releaseclean; VitePress docs build clean.AddProject/WaitForCompletion/ annotation-clone wiring viaDistributedApplication.CreateBuilder— no Docker.resources setup+ blockingcheck-envgate and compiles.dotnet run --project src/AspireSample/AspireSample.AppHost) — confirm the gates show Finished andapistarts only after them. The app-model tests cover the wiring; a live run can't be automated headlessly.Spike findings (design step 0)
Validated against real Aspire 13.3.1: run-to-completion modeling of a project-with-verb-args,
WaitForCompletiongating, and annotation cloning. Two corrections vs the draft API: the parent needs theIResourceWithWaitSupportconstraint (not justIResourceWithEnvironment), and the wait annotation type isWaitAnnotation.Docs
New "Startup gates" section on the Aspire dashboard integration page (
/cli/aspire).Downstream docs
Tracking issues for Marten / Wolverine / Polecat filed separately (design §9).
🤖 Generated with Claude Code