feat(aws/ec2): KeyPair resource + hosted Instance HTTP serving - #714
Merged
Conversation
`AWS.ECS.Task` (and `AWS.EC2.Instance`) programs that yield `ServerHost` failed during plan/deploy with `Service not found: Alchemy::ServerHost`. The service was declared and consumed but never provided, and the ECS Task runtime context was an incomplete stub missing `exports` and `serve`. - Platform provides `ServerHost` whenever the runtime context carries `run` - Share one host runtime context (run + serve + exports.program) between EC2 Instance and ECS Task via `createHostRuntimeContext` - Fix the generated container/instance entry to resolve the `exports` Effect before reading `.program` (was reading `.program` off an Effect) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Complete the ECS Task container runtime so a long-running `{ fetch }` /
`ServerHost.run` program actually runs on Fargate:
- bundle the entry with a Bun HTTP server (`BunServices` + `BunHttpServer`)
and ship every rolldown chunk into the image (was: first chunk only, so
dynamic imports crashed the container)
- build the image for the architecture `runtimePlatform` declares (default
linux/amd64) — an image built on an ARM64 host was rejected by Fargate
- guard the role-deletion `list*` calls against NoSuchEntityException so
delete is idempotent
Mirror the same Bun HTTP server + multi-chunk bundling into the shared EC2
hosted runtime (`AWS.EC2.Instance`).
Add a real end-to-end smoke test: builds + pushes the image, runs the task
on Fargate behind a managed ALB, and asserts over HTTP that `{ fetch }` is
served (`/health`) and the `ServerHost.run` background loop is executing in
the container (`/ticks` climbs). Skipped under FAST=1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep only the shared host-context refactor + `exports → program` resolution
fix for `AWS.EC2.Instance` here. The Bun HTTP server + multi-chunk bundling
(so a hosted Instance actually serves `{ fetch }`) and its end-to-end test
land in a separate PR.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…urce - HostProps extends PlatformProps so the test Platform resource satisfies the ResourceLike constraint - drop the now-unused @ts-expect-error on the makePlan return expression Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror the ECS Task container runtime onto AWS.EC2.Instance: bundle the hosted entry with a Bun HTTP server (BunServices + BunHttpServer) and zip every rolldown chunk (not just the entry) so dynamic imports resolve on the instance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Launch a real EC2 instance running a bundled long-running program, and
assert over HTTP (against the instance public IP) that the { fetch } handler
is served and the ServerHost.run background loop runs on the instance
(/ticks climbs). Skipped under FAST=1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nd (#706) Add `AWS.EC2.KeyPair` (generate or import; private key captured as a secret) and use it from the hosted-Instance e2e fixture. Make the e2e green: - hosted user-data is now reboot-safe: it only writes the systemd unit + setup script and enables the service. The service (Restart=always) installs bun (with retries), syncs the bundle from S3, and runs the program on every start — so a flaky `bun.sh` install or cloud-init's once-per-instance user-data skip self-heals (previously a transient failure left nothing serving). - `amazonLinux2023()` now selects the standard AMI (`al2023-ami-2023.*`); the broader glob matched `al2023-ami-minimal-*`, which ships no SSM agent and a stripped toolset. - extend the instance terminate-wait (was ~64s, timed out intermittently). Test: real instance launched into a public subnet, served over HTTP (`/health` + `/ticks` proves the ServerHost.run loop runs in-instance), with the KeyPair's private key returned from the stack and printed. Skipped under FAST=1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
Install the packages built from this commit: alchemy bun add alchemy@https://pkg.ing/alchemy/a24c74a@alchemy.run/better-auth bun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/a24c74a@alchemy.run/pr-package bun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/a24c74a |
- KeyPair.read: pass a Record to `hasTags` (ec2 `Tag[]` has optional Key/Value, not assignable to `Tags`) - KeyPair.delete: drop the `InvalidKeyPair.NotFound` catch — `deleteKeyPair` is idempotent and does not have that tag in its typed error union - Instance/hosted `keyName` accepts `Input<string>` so it can take a reference like `AWS.EC2.KeyPair(...).keyName` in the Effect-props form - Instance fixture: runtime stub omits infra-derived props (were ill-typed `""`) and asserts the resolved AMI id is defined Verified with `bun tsc -b` (0 errors). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…osted-e2e # Conflicts: # distilled # packages/alchemy/src/AWS/EC2/hosted.ts
DavidJFelix
pushed a commit
to DavidJFelix/alchemy-effect
that referenced
this pull request
Aug 7, 2026
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.
Stacked on #713. Adds
AWS.EC2.KeyPairand makes the hostedAWS.EC2.Instance(theServerHost+host.run+{ fetch }pattern from #706) work end to end on a real instance.AWS.EC2.KeyPairGenerate (or import) an EC2 key pair; the generated private key is captured as a
Redactedsecret (AWS returns it only once, at create).Making the hosted Instance serve
Restart=always) installs bun (with retries), syncs the bundle from S3, and runs the program on every start — so a transientbun.shinstall or cloud-init's once-per-instance user-data skip self-heals (previously a single failure left nothing serving).amazonLinux2023()selectedal2023-ami-minimal-*(no SSM agent, stripped tools) because the global2023-ami-*matched it. Narrowed toal2023-ami-2023.*.amazonLinux2023(),Network(...)) fail withService not found: AWS::Environment. The fixture guards them behind__ALCHEMY_RUNTIME__(folded totruein the bundle, DCE-ing the AWS SDK out).Test
test/AWS/EC2/Instance.smoke.test.tslaunches a real instance into a public subnet and asserts over HTTP (against the public IP) that/healthis served and/ticksproves theServerHost.runloop runs in-instance; theKeyPairprivate key is returned from the stack and printed. PlusKeyPair.test.ts(create/capture/list/delete). Skipped underFAST=1.