v0.0.1-alpha.28
Pre-releaseOvercast v0.0.1-alpha.28
Docker Images
Full image with the web management console:
- Pull:
ghcr.io/neaox/overcast:0.0.1-alpha.28 - Channel tag:
ghcr.io/neaox/overcast:alpha - Registry: overcast package
Headless slim image for CI pipelines:
- Pull:
ghcr.io/neaox/overcast-slim:0.0.1-alpha.28 - Channel tag:
ghcr.io/neaox/overcast-slim:alpha - Registry: overcast-slim package
docker run --rm -p 4566:4566 -p 4567:4567 ghcr.io/neaox/overcast:0.0.1-alpha.28
docker run --rm -p 4566:4566 ghcr.io/neaox/overcast-slim:0.0.1-alpha.28Native Binaries
Download a binary for your platform from the assets below and verify it with SHA256SUMS.
| Asset | SHA256 |
|---|---|
overcast-darwin-amd64 |
d8925bba8eafb54ecffd4fa8466cf5066e38e99728386996fe91b024ed26f5fd |
overcast-darwin-arm64 |
2bc691314e779c7a0c58b1bfd8980a172dbfb45dd48cd3773bbe81354ffaa761 |
overcast-linux-amd64 |
d97aed759b89fdcf3c2d1ee3439c324e1c6cab738bd5b9af69be66eb9d9be1c9 |
overcast-linux-arm64 |
6aa30a5abda0be9908871517f6be26c30c72a5ac04545f19f429cf6a94cdddc7 |
overcast-windows-amd64.exe |
17ffc17b7c910a5a2ce851881fae57c4b5fd16fa508afd81c10b6e8e4118ebb4 |
overcastd-darwin-amd64 |
a08780aee173ee4c327e86f768115c661f86ffab09104521d237bb4f57018658 |
overcastd-darwin-arm64 |
ad1174ba17a6a35e89c2238b07c0f20f661b5a45da4528dce904ec0430320e76 |
overcastd-linux-amd64 |
ea535937329ff166bb1cc5fe39829ac6186000b049d509cc004045d0d853ddb9 |
overcastd-linux-arm64 |
e7c22fac2bff97ba89648cedc7d79fa9da1b33a9460411ff94a37eb6bcc36c3f |
overcastd-windows-amd64.exe |
38a8285550d6ca6377687d5afb26b645d25057781c5aec37b42ceeb1752c54c5 |
Release Notes
Added
-
[cloudformation]
AWS::EFS::FileSystem,AWS::EFS::MountTarget, andAWS::EFS::AccessPointprovision end-to-end, includingFileSystemPolicy,LifecyclePolicies,BackupPolicy,FileSystemProtection, tag sync on update, and AWS-matching replacement semantics -
[docker] the internal Docker client gained volume operations (
CreateVolume,RemoveVolume,ListVolumes) with the standard managed labels -
[ecs] task definitions now model
volumes(includingefsVolumeConfiguration) and containermountPoints, with AWS's undefined-volume validation; when EFS live mode is active, task containers mount the file system's backing Docker volume at each mount point (honoringreadOnly), sharing real file data with Lambda functions that mount the same file system -
[ecs]
RegisterTaskDefinitionnow rejectsefsVolumeConfigurationcombining anaccessPointIdwith arootDirectoryother than/, matching AWS -
[efs] opt-in live mode (
OVERCAST_EFS_MODE=live): each file system is backed by a named Docker volume (overcast-efs-<FileSystemId>), created onCreateFileSystem, removed onDeleteFileSystem, and reconciled on startup (missing volumes recreated, orphans removed); the control plane degrades gracefully when Docker is unavailable -
[efs] live-mode mounts now honor root directories: Lambda
FileSystemConfigsmounts are scoped to the access point'sRootDirectory, and ECSefsVolumeConfigurationmounts to the access point's root or the declaredrootDirectory, via Docker volume subpath mounts (Docker Engine 26+). Access points withCreationInfohave the directory created in the volume with the declared ownership and permissions before the first mount; withoutCreationInfoa missing directory fails the mount, matching AWS -
[efs] new service: EFS control-plane emulation under the real
/2015-02-01/REST-JSON API — file systems (create/describe/update/delete, protection), mount targets (incl. security groups), access points, file-system policies, lifecycle configuration, backup policy, tagging (current + legacy APIs), and account preferences, withcreating→available→deletinglifecycle states -
[lambda]
FileSystemConfigsis now modeled on CreateFunction, UpdateFunctionConfiguration, and GetFunctionConfiguration (one config max, EFS access-point ARN,/mnt/<name>mount path — matching AWS validation); when EFS live mode is active, the function's containers mount the backing Docker volume atLocalMountPath, so invocations share real file data with each other and with other services mounting the same file system -
[lambda] REPORT log lines now carry
Init Durationon the cold-start invocation of on-demand execution environments (measured from container start to the runtime's firstGET /next), in AWS's field order and format; warm invokes and provisioned-concurrency environments omit it, as on AWS -
[lambda] opt-in proactive initialization (
LAMBDA_PROACTIVE_INIT): once a function's configuration settles after a deploy, one execution environment is pre-created in the background so the next request lands warm — mirroring AWS's documented proactive initialization, includingAWS_LAMBDA_INITIALIZATION_TYPE=on-demandand noInit Durationon the first REPORT line -
[release] changelog entries carry a compatibility marker, so a release bump can be derived rather than chosen.
-Removed defaults to breaking and everything else to compatible, prose naming an input or output contract ("now requires", "now rejects") forces an explicit answer either way, and a breaking entry must carry amigration:note. Calibrated against the entries in flight: 2 of 32 are asked -
[release] a
Release Prepworkflow (workflow_dispatch) prepares a release end to end: derives the version, assembles and inserts the changelog section, repoints both compare links, writesVERSION, deletes the consumed fragments, opens the PR, and comments a summary listing breaking changes with their migration notes. It never merges —VERSIONis CODEOWNER-owned and publishing still waits on thereleaseenvironment. Re-running against an open release PR reports the fragments that have landed since rather than rewriting the section, so curation is never discarded -
[release]
changelog.py releaseapplies the mechanical release-prep edit andchangelog.py next-versionderives the next version. While in alpha that is the prerelease counter incrementing; deriving a stable bump from the entries stays unimplemented until 1.0 rather than guessing the policy -
[route53] Route 53 is now emulated at inert level (25 operations, up from 10). New:
ListHostedZonesByName,GetHostedZoneCount,UpdateHostedZoneComment, tags (ChangeTagsForResource,ListTagsForResource,ListTagsForResources), and health check CRUD (CreateHealthCheck,GetHealthCheck,ListHealthChecks,GetHealthCheckCount,UpdateHealthCheck,DeleteHealthCheck). Hosted zones now get default apex NS/SOA records and a delegation set,CreateHostedZoneenforces caller-reference uniqueness (HostedZoneAlreadyExists) and returns theLocationheader,DeleteHostedZoneenforcesHostedZoneNotEmpty,ChangeResourceRecordSetsvalidates batches atomically with AWS error codes (InvalidChangeBatchfor duplicate creates, missing/mismatched deletes, out-of-zone names, apex CNAMEs) and stores routing metadata (SetIdentifier,Weight,Region,Failover,GeoLocation,MultiValueAnswer), list operations paginate in DNS order, names are canonicalised to lowercase, and errors use Route 53'sErrorResponseenvelope. CloudFormation gainsAWS::Route53::HealthCheckplus hosted-zone tag/VPC pass-through and comment-only in-place updates. -
[release] a release PR now keeps itself mergeable: every push to
mainmerges into the release branch and appends any new changelog entries to the version section already there, deleting their fragment files, so the changelog gate goes green without anyone editing anything. Folding is additive — no bullet already in the section is read, reordered or rewritten — so curation done by hand survives, and rewording the appended bullets is optional polish rather than a chore every merge forces -
[release] the release-prep workflow now runs on every push to
main: when a release PR is open it mergesmaininto the release branch, pushes, and comments with the entries still to curate. Refreshing the branch is what re-runs the PR checks, so a release PR can no longer sit green while going stale
Changed
-
[apigateway] proxied requests no longer re-scan and re-decode the API's entire resource/route set on every request — routing state is cached per API and invalidated on any resource or route write
-
[lambda] the invoke path no longer SHA-256s the whole deployment package on every invocation (and every configuration read) — the hash is computed once when code is written and stored on the function record, cutting per-invoke CPU for large packages
-
[lambda] deployment packages are stored separately from function records, so invoke-path reads no longer base64-decode the whole zip on every invocation (and S3 code-sync events no longer decode every function's package); existing records migrate automatically on their next write
-
[lambda] cold starts reuse cached artifacts instead of rebuilding them every time: code and layer tars are kept in a byte-bounded in-memory cache (
LAMBDA_TAR_CACHE_MB, default 256, 0 disables), the bootstrap and TLS trust-root tars are built once, and the per-acquire image-presence check is skipped once an image is verified -
[lambda] removing a runtime image mid-session (
docker rmi) no longer breaks that runtime until restart — a container create that finds the image missing re-pulls it and retries -
[lambda] cold-start artifacts (code and layer tars) are pre-built in the background once a deploy settles, so even the first cold start of a new code version skips the package fetch and conversion; the artifact cache is reported on the
/_lambda/instancesdebug endpoint -
[lambda] proactive initialization now counts API Gateway integrations and AppSync Lambda data sources as trigger evidence, so wired functions get a warm environment after a deploy even in a fresh process
-
[lambda] REPORT lines'
Max Memory Usednow reports the execution environment's running peak across warm invocations — matching AWS — and is sampled concurrently with handler execution, so writing the REPORT line no longer holds up the invoke response waiting on Docker stats -
[lambda] cold starts provision the container filesystem with a single archive (code, layers, TLS trust root, bootstrap) instead of up to four sequential Docker copy round trips — measured cold-start p50 ~355 ms → ~300 ms for cached-image hello-world functions
-
[release] changelog fragments are now entry lines rather than frontmatter documents: one file per PR, and each line carries its own category, scope and compatibility marker (
<+|-|~|*|section>[!|.] [area] prose).scripts/changelog.py newwrites them, appending to the branch's file so later commits land alongside earlier entries;assemblegroups at entry rather than file granularity, so entries about one service sort together even from different PRs -
[ci] the VERSION guard accepts the release App as well as the repository owner, so a generated release PR can bump
VERSION. Dispatching the workflow already needs write access, so the set of people who can produce aVERSIONchange is unchanged -
[lambda] the tail wait is now paid only by invokes that asked for a log tail (
X-Amz-Log-Type: Tail, and the console's test tab). Asynchronous invokes, event-source mappings, function URLs and service-to-service calls discardLogResultand no longer wait on log delivery to produce it -
[release] the release summary comment lists the entries as they will read in the changelog rather than only counting them, with breaking changes and their migration notes first
-
[ci] the release-candidate comment is reposted on each build instead of edited in place, so its own timestamp shows when it last changed — GitHub anchors an edited comment at its original position and hides the update behind an "edited" marker, which made a refreshed RC invisible. The new comment is posted before the old one is removed, so a release PR is never left without a candidate to test, and the header now names the head commit it was built for
Fixed
-
[ci] compat baseline auto-promotion works again as a PR-based flow: the old direct push to
mainhad been rejected by branch protection on every run since required-check enforcement (#393), silently stranding improvements (#440). The workflow now force-pushes a coalescingautomation/baseline-promotionbranch and auto-merges it through the normal required checks, using GitHub App credentials; until the App secrets are configured it emits an accurate warning instead of the old false "will retry" message -
[compat] the last quarantined flake, cdk
VerifyTopicSubscription(#435), was a suite-side consumer race: the SNS topic fed the same queue the stack's Lambda event source mapping polls, so the ESM intermittently consumed the published message before the test's ReceiveMessage saw it (it would flake identically on real AWS). The topic now feeds a dedicated queue with no competing consumer, and the delivery wait budget rose from 2.5s to 10s;compat/flaky.jsonis empty for the first time -
[compat] the compose path can now run the cdk suite: the CDK asset publisher addresses the bootstrap bucket virtual-hosted (
{bucket}.overcast), which needed a wildcard-free/etc/hostsentry in the runner services plusOVERCAST_HOSTNAME=overcaston the emulator so host classification recognises the compose hostname as a virtual-host base -
[compat] the stable
cli/lambda-invoke/InvokeDryRunCI failure (plan item R7) is fixed: it was the only invoke test that didn't wait for the function to leavePending, and CI never pre-pulled the python runtime image its function uses, so the cold pull outlasted the invoke on every run. The test now waits like its siblings, CI pre-pullspublic.ecr.aws/lambda/python:3.12, and the Active waiter survives a cold pull and fails fast with theStateReasonwhen a function entersFailed -
[compat] the #388 "created-then-not-found" flake family was three suite-side group-isolation bugs, not an emulator race: dotnet's
sns-topicsteardown swept sibling groups' live topics via an over-broad name prefix, and the cli SES and EventBridge groups each shared one identity/bus that sibling groups' teardowns deleted mid-run (suite groups run in 8 parallel slots). Each group now owns its resources; ninecompat/flaky.jsonentries deleted, and the remaining cdk entry moved to its own issue (#435) -
[ecs/rds] removing a task or database image mid-session (
docker rmi) no longer breaks launches until restart: a failed pull is retried on the next launch attempt instead of being cached forever, and a container create that finds its image missing re-pulls and retries once — the same resilience Lambda gained earlier -
[efs]
DescribeFileSystemsnow rejects requests carrying bothFileSystemIdandCreationTokenwithBadRequest, matching AWS -
[efs]
DescribeFileSystemsamortizes one mount-target scan across the whole page instead of scanning per file system -
[efs] deleting a file system whose volume is still held by a running container now retries the volume removal (3 attempts, 30 s apart) before deferring to startup reconciliation
-
[lambda] invoking a function still in
Pendingstate now returns AWS's 409ResourceConflictException("The operation cannot be performed at this time…") instead of a 400InvalidParameterValueException, matching real Lambda's state-conflict semantics -
[lambda]
CodeSha256in function and version responses is now the base64-encoded SHA-256 AWS returns, not hex — tooling that compares its locally computed hash (CDK change detection among them) no longer sees permanent code drift -
[lambda] layer version responses now populate
Content.CodeSha256(base64, as on AWS); layers published before this release omit it -
[lambda] layer archives are stored separately from layer records, so listing layers no longer base64-decodes every layer's full zip per call
-
[lambda] a function deleted while its background image pull was still running could be resurrected as "Active": the pull-completion callback, the startup Pending-reconciler, and the S3 code-sync watcher all wrote back records snapshotted before their slow operation started. All three now merge into a fresh read and skip a function that was deleted (or transitioned) meanwhile — this was the intermittent compat
lambda-crud/DeleteFunction"function still exists" failure (#414), and the same stale write could silently clobber anUpdateFunction*revision landing mid-pull -
[lambda] instance memory/CPU in the instances panel are now sampled from Docker instead of always reading 0, and the REPORT line's
Max Memory Usedno longer reads 0 on slow (Docker-in-Docker) hosts — container stats are fetched withone-shot=true, which also removes the daemon's ~1–2 s two-cycle stats wait from every invocation's response path -
[lambda/ecs] the TLS trust-root archive is built once per process instead of per container launch
-
[release] the release-prep workflow authenticates with the App client ID;
app-idis deprecated fromcreate-github-app-tokenv3 and warned on every run -
[routing] host classification no longer allocates intermittently on host-routed requests: the region-shape check used a package
regexp, whose pooled matcher state is only amortized allocation-free (and is deliberately dropped at random under the race detector, which madeTestHostClassifier_lowercaseHostStaysAllocationFreeflake in CI); it is now a hand-rolled matcher pinned to the old regexp by an oracle test -
[lambda]
X-Amz-Log-Resultcould come back without the handler's own output — just theSTART/END/REPORTlines the emulator writes itself. The wait that lets Docker's log stream catch up keyed off a container-lifetime watermark, so it could not tell "nothing read yet" from "nothing to read", and returned early on cold containers and warm reuse alike -
[ci] a release-candidate build is skipped when the build context is unchanged: the image is content-addressed by a hash of the paths
.dockerignoreallowlists plus the build args, carried as a second tag, so an unchanged context is retagged registry-side in seconds instead of rebuilt. Safe because.dockerignoreignores everything and then allowlists — anything Docker can see is in the hash, and anything it cannot see cannot affect the image. The candidate comment states which happened -
[ci] release-candidate images are stamped with the release version; they were built without the
VERSIONbuild arg and so reporteddev -
[ci] the release-candidate content hash covers only what can actually reach the image — the compiled
cmd/overcast, the files the runtime stage copies, and whatembed.goembeds — so a candidate is not rebuilt for a change that cannot alter it. Go test files andtestdata/are dropped because the toolchain excludes them fromgo build; othercmd/*trees because apackage maincannot be imported; anddocs/plans,docs/devanddocs/generatedbecauseembed.godeliberately does not embed them and the runtime stages copy in nothing but the binary. Measured over 40 commits, half no longer trigger a rebuild -
[ci] release-candidate images are now built for linux/amd64 and linux/arm64, the same platforms a release publishes. They were built only for the CI runner, so pulling one on an arm64 host ran emulated amd64 bits — for an emulator that itself launches containers that is a different environment rather than merely a slower one, and it made a platform problem indistinguishable from a regression
Release: https://github.com/Neaox/overcast/releases/tag/v0.0.1-alpha.28