Skip to content

chore(aws-tests): swap Moto for Floci as the AWS mock for integration tests#4148

Open
slang25 wants to merge 6 commits into
masterfrom
slang25/replace-moto-with-floci
Open

chore(aws-tests): swap Moto for Floci as the AWS mock for integration tests#4148
slang25 wants to merge 6 commits into
masterfrom
slang25/replace-moto-with-floci

Conversation

@slang25
Copy link
Copy Markdown
Contributor

@slang25 slang25 commented May 21, 2026

Description

Swaps motoserver/moto:5.1.22 for floci/floci:1.5.19 in docker-compose-aws.yaml and the aws-mock-ci workflow. Same port (4566), same AWS_SERVICE_URL contract, no production code touched.

Why

A few Skip.If(AWS_SERVICE_URL is set, ...) guards in the AWS tests existed because Moto either didn't implement a thing or had it gated behind a newer version than we pin. Floci handles them, so the guards come off:

  • 1× SQS tag verification (V3).
  • 4× SQS fair-queue parameterisations (V4 Standard, producer + multi-message consumer, Reactor + Proactor).
  • 4× SNS fair-queue parameterisations (V4 Standard, same shape).

Counts: V3 aws-mock-ci 136 → 137 passing, V4 aws-mock-ci 130 → 138 passing. No new skips.

Cold start is noticeably quicker too — docker run to health-endpoint-responding goes from ~2.7s on Moto to ~0.7s on Floci on my machine. Worth a few seconds per CI run.

Floci is also under active development and explicitly aims to be a drop-in LocalStack-Community replacement — Why Floci covers the project's goals.

Bonus fix exposed by stricter behaviour

When_infastructure_exists_can_verify_by_url (V3 + V4 Standard Reactor) was passing the queue name as channelName while declaring FindQueueBy.Url. Moto tolerated the mismatch; Floci (and real AWS) don't. Now uses the queue URL as the channel name, consistent with the Standard FIFO Reactor sibling.

Floci dependencies (now landed upstream)

Two issues were filed and resolved against Floci while this PR was in review; both fixes ship in the pinned 1.5.19:

  • floci-io/floci#977HEAD on {bucket}.s3.{region}.localhost:4566 returned 200 for any host. Fixed by #978. No test-side workaround required; the bucket-address template is unchanged from before this PR.
  • floci-io/floci#981 — STS GetCallerIdentity ignored the 12-digit access-key account-ID convention. Fixed by #983. Opens up a future option of per-process random account IDs for concurrent V3/V4 runs against a single Floci container; left as a follow-up.

Housekeeping

  • Xunit.SkippableFact is no longer used by either AWS test project (all Skip.If guards came out with the swap), so the PackageReference and its PackageVersion in Directory.Packages.props are removed.
  • Compose and CI healthchecks now both use just curl -sf http://localhost:4566/_localstack/health — the redundant || curl / fallback in compose is gone.

Related Issues

Upstream: floci-io/floci#977, floci-io/floci#981 — both closed.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the Contributing Guide
  • I have checked the documentation for relevant guidance
  • I have added/updated XML documentation for any public API changes
  • I have added/updated tests as appropriate
  • My changes follow the existing code style and conventions

Additional Notes

Replaces #4147 (closed; that one was branched from the fork, which meant the gated CI jobs were being skipped). Verified locally against floci/floci:1.5.19 with AWS_SERVICE_URL=http://localhost:4566: V3 137/137 and V4 138/138 passing, no skips.

Floci handles SQS tag verification and SQS/SNS fair-queue scenarios
that Moto 5.1.22 didn't, so the corresponding Skip.If guards come off
(+1 V3, +8 V4 tests now running against aws-mock-ci). Cold start is
also ~3.9x quicker (~2.7s -> ~0.7s).

Also fixes a latent test bug in the V3 + V4 Reactor ByUrl tests where
the queue name was passed as channelName while declaring FindQueueBy.Url
— Moto tolerated the mismatch, Floci (and real AWS) don't.

Test helper uses the short-vhost bucket-address template when
AWS_SERVICE_URL is set, to work around floci-io/floci#977 (200 OK on
HEAD against the region-qualified vhost form regardless of bucket
existence). Real-AWS runs still use the default full vhost template.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions github-actions Bot added the Maintenance Build, CI, refactoring, testing infrastructure, and other chores label May 21, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Review by Claude (Opus 4.7) - solid, well-scoped chore PR. Net effect: more tests running in CI, faster cold start, and one production-relevant bug surfaced. Full review follows in subsequent comments due to length constraints.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

What is good: 8 previously-skipped V4 fair-queue parameterisations + 1 V3 SQS tag test now run in aws-mock-ci. Skip.If/SkippableTheory fully removed from both AWS test projects. Genuine bug fix in When_infrastructure_exists_can_verify_by_url.cs (Standard Reactor, V3+V4): was declaring findQueueBy QueueFindBy.Url but passing the queue name as channelName. The Standard FIFO Reactor variant already passed the URL (Fifo/Reactor/When_infastructure_exists_can_verify_by_url.cs line 69), so this brings Standard Reactor in line. Floci vhost workaround in CredentialsChain.cs is properly documented with a link to floci-io/floci#977. Cold-start improvement (~2s) is cumulative across CI runs.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Nit on the PR description: it claims the Reactor fix just makes things consistent with the Async sibling, but the Standard async sibling (Standard/Proactor/When_infrastructure_exists_can_verify_by_url_async.cs lines 58-65) does NOT set findQueueBy QueueFindBy.Url on its validation subscription at all (only on the producer). So they are still not symmetric after this PR. Not a blocker, just noting the PR text overstates the consistency angle - the real motivation is that real AWS, like Floci, rejects a name where a URL is expected.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Concern 1 (biggest): floci/floci:latest is unpinned in both docker-compose-aws.yaml (line 3) and .github/workflows/ci.yml (line 454). The image being replaced was pinned to motoserver/moto:5.1.22, which is the right pattern. Floci is explicitly described as 'under active development', which makes :latest extra risky - a future Floci push could break CI on master without any code change in this repo. Recommend pinning to a specific semver tag (or, even better, an image digest) and bumping deliberately via Dependabot or a manual PR. The same hazard that motivated the original 5.1.22 Moto pin now applies in reverse.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Concern 2: Health-check drift between docker-compose-aws.yaml and the CI workflow. The compose file uses CMD-SHELL with a fallback (try /_localstack/health, otherwise /), while ci.yml uses only /_localstack/health. Pick one. If the fallback is genuinely needed for local docker compose (e.g., older Floci builds people might pull), then CI is silently relying on the new endpoint always existing - which combined with :latest is two coupled hazards. If the fallback is not needed, drop it from compose so they match. Either way, having them diverge invites the local-passes-CI-fails or vice-versa class of bug.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Concern 3: Orphan dependency. Xunit.SkippableFact is still referenced in tests/Paramore.Brighter.AWS.Tests/Paramore.Brighter.AWS.Tests.csproj (line 21) and tests/Paramore.Brighter.AWS.V4.Tests/Paramore.Brighter.AWS.V4.Tests.csproj (line 20), but there are zero remaining Skippable or Skip.If usages in either project after this PR. Either remove the PackageReference (and the Directory.Packages.props line 156 PackageVersion if nothing else needs it) in this PR, or open a follow-up. Worth doing here so the dead reference does not linger.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Concern 4 (minor): The Floci workaround in CredentialsChain.GetBucketAddressTemplate() unconditionally switches to short-vhost form whenever AWS_SERVICE_URL is set. The comment correctly links to floci-io/floci#977, but if a future emulator (or a Moto comeback) requires the full region-qualified form, this override quietly becomes wrong. Consider either gating the override behind an explicit env signal (something like USE_SHORT_VHOST=1) or adding a clear TODO with revert instructions tied to the upstream issue. Easy to forget once #977 is resolved.

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Non-issues / scope notes: No src/ changes - confirmed test-only, no production code touched. No security or regression surface. Whitespace-only edit in When_creating_luggagestore_missing_ACL (V3 + V4) is a harmless drive-by. When_posting_a_message_resources_are_tagged_async going from SkippableFact to Fact is correct now that Floci handles SQS tag verification, but only exists for the V3 Proactor - matches the PR's stated counts (V3 +1, V4 +8) but worth a quick check that V4 does not have a similar un-skip opportunity hiding elsewhere. Test coverage: counts in the PR description (V3 136 to 137, V4 130 to 138) align with the diff (9 newly-running parameterisations total).

@claude
Copy link
Copy Markdown

claude Bot commented May 21, 2026

Summary: LGTM in intent and almost all the mechanics. The single must-do before this lands is pinning the Floci image - :latest on a 'under active development' upstream is the same hazard that motivated the original Moto pin. Ideally also drop the now-unused Xunit.SkippableFact reference in the same PR (or as an immediate follow-up). Reconcile the docker-compose vs CI health-check definitions while you are at it. The CredentialsChain workaround is fine to merge as-is given the linked upstream issue, but worth a TODO to make the revert obvious later. Nice cleanup of the test-skip backlog.

…ound

- Pin floci/floci to 1.5.19 in docker-compose-aws.yaml and ci.yml
  rather than tracking :latest (Floci is under active development).
- Drop the short-vhost bucket-address template workaround: 1.5.19
  ships floci-io/floci#978 which fixes the region-qualified vhost
  HEAD bug (floci-io/floci#977), so the helper can return the
  default {bucket}.s3.{region}.{host} form again.
- Drop the now-redundant /_localstack/health || / fallback from the
  compose healthcheck so it matches the CI workflow.
- Remove the orphan Xunit.SkippableFact PackageReference from both
  AWS test projects and from Directory.Packages.props — the last
  SkippableFact/Skip.If usages came out with this PR's first commit.

Verified locally against 1.5.19: V3 137/137 and V4 138/138 passing,
no skips.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude
Copy link
Copy Markdown

claude Bot commented May 26, 2026

Review

Nice, focused PR — test-infra only, scoped tightly, version pinned, no production code touched. I verified the cleanup is complete (no SkippableFact/Skip.If references remain anywhere) and the latent ByUrl bug fix is consistent with the FIFO and Async siblings, which already pass new ChannelName(queueUrl) when declaring QueueFindBy.Url. Coverage goes up by 9 previously-skipped tests with no new skips.

A couple of things worth addressing

1. Documentation still mentions Moto (likely out of scope, but easy follow-ups):

  • CONTRIBUTING.md:421 — table row still labels docker-compose-aws.yaml as ""Moto (AWS)""
  • samples/Scheduler/QuartzTaskQueue/README.md — lines 10, 39, 41, 47, 51, 70 walk users through ""Moto"" setup
  • samples/Scheduler/AwsTaskQueue/GreetingsPumper/Program.cs:35-36 and GreetingsReceiverConsole/Program.cs:94-95 — comments say ""EventBridge Scheduler is not implemented by Moto, so this sample always targets real AWS"". The premise may or may not still hold for Floci; either rewording to ""by the local AWS mock"" or verifying Floci's coverage would tidy this up.

Not blocking, but the CONTRIBUTING.md row is the one most likely to confuse new contributors who clone the repo and grep for ""Moto"".

2. Healthcheck form changed in docker-compose-aws.yaml — went from exec form [""CMD"", ""curl"", ""-sf"", ...] to shell form [""CMD-SHELL"", ""curl -sf ...""]. Both work; the shell form requires /bin/sh to be available in the container, which it is for Floci. Functionally equivalent here, just calling it out so the diff isn't misread as needing shell features (it doesn't — curl -sf is a single command). Could be left as-is or kept aligned with the original exec form; up to you.

3. Minor / nit: Both When_creating_luggagestore_missing_parameters.cs files have a trailing-whitespace-only change unrelated to the PR's theme. CLAUDE.md asks to keep changes scoped to what was requested; these are presumably leftovers from the now-reverted vhost workaround. Fine to leave, just noting.

Things I checked and am happy with

  • Version pin: floci/floci:1.5.19 (not :latest) — good, especially given the upstream is under active development and the PR description notes the second commit existed specifically because 1.5.19 picks up the fix(s3): accept region-qualified virtual-host form bucket.s3.<region>.<host> floci-io/floci#978 vhost fix. The pin makes that traceable.
  • Healthcheck endpoint: /_localstack/health confirms Floci's LocalStack-compatible API surface; matches what the AWS_SERVICE_URL plumbing in GatewayFactory/CredentialsChain already expects.
  • Bug fix correctness: The Standard Reactor ByUrl tests (V3 and V4) now match every other QueueFindBy.Url test in the suite. Moto tolerating the mismatch was the bug, not the fix.
  • Package removal: Xunit.SkippableFact is fully gone — grepped both Skip.If and SkippableFact/SkippableTheory across the whole repo, no orphans.
  • Test count delta: +1 V3, +8 V4 actually executing, with the rationale spelled out in the PR body (SQS tagging + 4× SQS fair-queue + 4× SNS fair-queue parameterisations).

Security / supply chain

Floci is a smaller, newer project than Moto, so the pin matters more. The PR is doing the right thing by pinning explicitly rather than chasing :latest. Worth a periodic bump cadence in mind, but no immediate concern. No credentials or secrets in the diff.

Performance

The ~2.7s → ~0.7s cold-start improvement is a real CI win across the AWS jobs. Not a primary motivation but a nice bonus.


Approve from my side once the CONTRIBUTING.md row is at least updated; the sample READMEs and EventBridge comments can be a separate follow-up.

🤖 Generated with Claude Code

…mments

Addresses follow-up review notes on the Floci swap:

- CONTRIBUTING.md compose-file table row: "Moto (AWS)" -> "Floci (AWS)".
- samples/Scheduler/QuartzTaskQueue/README.md: walk-through and resource
  link now point at Floci instead of Moto.
- samples/Scheduler/AwsTaskQueue/{GreetingsPumper,GreetingsReceiverConsole}/Program.cs:
  remove the stale "EventBridge Scheduler is not implemented by Moto"
  comment and have the samples honour AWS_SERVICE_URL when set. Verified
  against floci/floci:1.5.19 that scheduler.CreateSchedule actually fires
  and delivers to an SQS target on time, so the samples can now be run
  end-to-end against the local emulator.
- Revert an unintentional trailing-whitespace edit in
  When_creating_luggagestore_missing_ACL (V3 + V4) that snuck in via an
  earlier reverted change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude
Copy link
Copy Markdown

claude Bot commented May 26, 2026

Code Review

Focused, low-risk swap — read through the full diff and spot-checked the sibling tests around the bonus fix. Looks good to merge. A few observations below; none are blockers.

What works well

  • Scope discipline. Image swap + the guards it unblocks + a single related test bug + the now-unused Xunit.SkippableFact cleanup. No drive-by edits, no defaults touched. Matches CLAUDE.md's change-scope guidance.
  • Bonus fix is correct. When_infastructure_exists_can_verify_by_url.cs (V3 + V4) was self-inconsistent: the producer below the validate-subscription block was already constructed with new ChannelName(queueUrl) + FindQueueBy = QueueFindBy.Url (V3 line 70, V4 line 70), while the subscription used channel.Name with the same QueueFindBy.Url enum. Moto tolerated the mismatch; Floci surfaces it. The fix aligns the subscription with the producer — that's the right direction.
  • Compose/CI parity. Both healthchecks now hit /_localstack/health, and docker-compose-aws.yaml drops the redundant || curl / fallback. Good consistency.
  • No leftovers. Verified: zero SkippableFact / SkippableTheory / Skip.If / Xunit.SkippableFact references remain in the codebase; the only surviving Moto mention is the historical comment in docker-compose-aws.yaml:5 explaining why port 4566 is still used (kept on purpose, makes sense).
  • Net +9 enabled tests, zero new skips. Matches the PR description's counts and the intent of the swap.

Observations / follow-up candidates (non-blocking)

  1. Async siblings of the bonus-fixed test have a related-but-different smell. tests/Paramore.Brighter.AWS.{V4.,}Tests/MessagingGateway/Sqs/Standard/Proactor/When_infrastructure_exists_can_verify_by_url_async.cs builds the validate SqsSubscription<MyCommand> without findQueueBy: QueueFindBy.Url (V4 lines 58-65, V3 lines 58-65) — only the producer below uses FindQueueBy.Url. So the test name claims "verify by url" but only the producer side actually does. It's not broken (the consumer falls back to lookup-by-name, which works), so it's outside this PR's scope — flagging only as a follow-up: either rename the test or wire the subscription through QueueFindBy.Url consistently with the now-fixed Reactor sibling.

  2. Scheduler samples now honour AWS_SERVICE_URL — verify Floci covers EventBridge Scheduler. The deleted comment in samples/Scheduler/AwsTaskQueue/{GreetingsPumper,GreetingsReceiverConsole}/Program.cs was specifically about EventBridge Scheduler not being in Moto. The PR description's verification block covers the AWS test projects (V3 137/137, V4 138/138), but doesn't mention running these scheduler samples against Floci. If AWS_SERVICE_URL is unset the behaviour is identical to before, so the regression risk is zero — but if Floci doesn't implement EventBridge Scheduler today, someone setting AWS_SERVICE_URL=http://localhost:4566 and following the README will hit a confusing error. Worth either (a) a quick smoke-test of AwsSchedulerFactory against Floci, or (b) a one-line note in the sample README clarifying which scheduler ops are supported by the local mock.

  3. Upstream Floci dependency note worth keeping visible. Two of the three Floci fixes (floci#977, floci#981) landed only days before this PR, both shipping in the pinned 1.5.19. That's fine for now, but if Floci ever yanks/replaces that tag the AWS CI job will silently break in a non-obvious way. Pinning by digest (floci/floci@sha256:…) instead of by tag would future-proof both the compose file and the CI service. Optional and definitely follow-up material.

Tests

  • Test coverage stays the same or grows. No assertions were weakened to make Floci pass — only Skip.If guards (which were defensive workarounds) were lifted.
  • TDD/scope guidance from CLAUDE.md is respected: no speculative changes, only what was needed to keep behaviour green under the new mock.

Security / performance

  • Nothing security-relevant. Local-only emulator on the same loopback port; no secrets touched.
  • ~2s faster cold start per CI run × ≥2 jobs is a free win.

Summary

LGTM. The bonus fix is the most consequential code change and it's both correct and minimal. The two scheduler-sample lines and one async-sibling-test concern are worth a quick triage but neither belongs in this PR.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude
Copy link
Copy Markdown

claude Bot commented May 26, 2026

Code Review

Reviewed the swap from motoserver/moto:5.1.22 to floci/floci:1.5.19. Overall: a clean, well-scoped infrastructure change with a real bug fix surfaced as a bonus. Description does a good job of accounting for what's actually being unblocked and why.

What's working well

  • Scope discipline. No production code touched. Port (4566) and AWS_SERVICE_URL contract preserved, so downstream tests/samples don't have to know which emulator is behind it.
  • Skip-guard cleanup is honest. All nine Skip.If guards removed correspond to capabilities Floci genuinely handles (SQS tags, SQS/SNS fair queues). No silent test loss — counts go 136→137 (V3) and 130→138 (V4). The follow-on Xunit.SkippableFact removal from both .csproj files and Directory.Packages.props is the right way to keep things tidy.
  • Real bug fix. When_infrastructure_exists_can_verify_by_url.cs (V3 + V4) was passing the queue name to channelName while declaring findQueueBy: QueueFindBy.Url. Moto was lenient; Floci/real AWS are not. The fix (channelName: new ChannelName(queueUrl)) is consistent with the FIFO Reactor sibling at tests/Paramore.Brighter.AWS.Tests/MessagingGateway/Sqs/Fifo/Reactor/When_infastructure_exists_can_verify_by_url.cs:69. Good catch.
  • Supply-chain hygiene. Pinned to 1.5.19, with upstream issues (floci#977, floci#981) filed and resolved before merge. Engaging the upstream rather than patching around it is the right move.

Concerns

1. (Medium) Sample programs may break against AWS_SERVICE_URL if Floci doesn't implement EventBridge Scheduler.

samples/Scheduler/AwsTaskQueue/GreetingsPumper/Program.cs:35 and samples/Scheduler/AwsTaskQueue/GreetingsReceiverConsole/Program.cs:93 now read AWS_SERVICE_URL instead of forcing string.Empty. The removed comment was explicit:

EventBridge Scheduler is not implemented by Moto, so this sample always targets real AWS and ignores AWS_SERVICE_URL.

But these samples use AwsSchedulerFactory from Paramore.Brighter.MessageScheduler.AWS.V4 (see GreetingsPumper/Program.cs:75), which is the EventBridge Scheduler API surface. The PR description enumerates SQS tags + SQS/SNS fair queues as the things Floci unblocks — EventBridge Scheduler isn't in that list, and Floci's stated goal is parity with LocalStack-Community (which does not implement EventBridge Scheduler).

Either:

  • Confirm Floci 1.5.19 implements EventBridge Scheduler well enough for this sample (and ideally add a note in the sample README), or
  • Revert these two sample files to keep forcing real AWS until verified.

As-is, a user with AWS_SERVICE_URL set will run the sample and silently get a failure or no-op against Floci that previously worked against real AWS.

2. (Low) Healthcheck shell-form vs exec-form change.

docker-compose-aws.yaml switched from [\"CMD\", \"curl\", ...] to [\"CMD-SHELL\", \"curl -sf ...\"]. Both work, but CMD (exec form) was cleaner and didn't depend on sh being in the image. Not blocking — but worth keeping in CMD form unless there's a reason for the shell, since you're not using any shell features.

3. (Low / pre-existing, not introduced here) The async sibling at When_infrastructure_exists_can_verify_by_url_async.cs (V3 and V4) sets findTopicBy: TopicFindBy.Arn on the validate-subscription but not findQueueBy: QueueFindBy.Url — so it validates the queue by convention/name despite the file name suggesting URL-based verification. Not in scope for this PR, but the same bug-class lives there waiting to bite next time Floci tightens. Worth a follow-up.

Tests

Net +9 active tests (no losses, no new skips). The bug fix is exercised by the previously-passing-but-incorrectly-configured When_infrastructure_exists_can_verify_by_url test, so coverage is fine.

Security / performance

  • Performance: stated ~2.7s → ~0.7s cold start is a nice CI win.
  • Security: this is a CI/dev-only image swap, container is pinned, image source is documented. No exposure surface change.

Summary

Approve once point 1 (sample behavior change) is either substantiated or reverted. Points 2 and 3 are nits/follow-ups.

Floci treats a 12-digit AWS_ACCESS_KEY_ID as the account ID for
per-account resource isolation. Pinned Floci 1.5.19 (via earlier
commit in this PR) also includes floci-io/floci#983 which makes STS
GetCallerIdentity honour the same convention, so ARN construction
via the convention validator now matches the SNS/SQS namespace.

CredentialsChain in both AWS test projects now hands out a random
12-digit access key per test-runner process (cached in a static
field). This means V3 and V4 can share a single Floci container
without name collisions, and we can later run them as parallel
`dotnet test` invocations in aws-mock-ci.

Verified locally against floci/floci:1.5.19 with V3 and V4 running
concurrently as separate dotnet test processes:
- V3 137/137 passed
- V4 138/138 passed
- Wall clock 43s vs. ~67s sequential

Note: parallel `dotnet test` invocations on the same solution will
race on shared project output (e.g. Paramore.Brighter.deps.json),
so a future CI parallelisation will need to pre-build the test
projects and then run with --no-build --no-restore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude
Copy link
Copy Markdown

claude Bot commented May 26, 2026

Code Review

Overall this is a clean, well-scoped infrastructure swap. The PR description does an excellent job documenting the rationale, the bonus fix, and the upstream Floci issues. Production code is untouched, test coverage strictly improves (8 fewer skips on V4, 1 fewer on V3), and the dependency surface shrinks (Xunit.SkippableFact removed). Nice work.

A few observations:

Potential concern: Scheduler samples will likely break under AWS_SERVICE_URL

samples/Scheduler/AwsTaskQueue/GreetingsPumper/Program.cs previously hard-forced serviceURL = string.Empty; with a comment explaining why: EventBridge Scheduler wasn't implemented by Moto. After this change the sample honors AWS_SERVICE_URL, which means a developer running docker-compose -f docker-compose-aws.yaml up and then running the Pumper sample will now point Brighter's AwsSchedulerFactory (line 75) at Floci.

The signal that this may not work: tests/Paramore.Brighter.AWSScheduler.Tests/Helpers/GatewayFactory.cs and tests/Paramore.Brighter.AWSScheduler.V4.Tests/Helpers/GatewayFactory.cs still have the cfg.ServiceURL = serviceURL block commented out (lines 31-35 in both). If Floci supported EventBridge Scheduler, you would presumably have un-commented that block and dropped at least some of those tests' AWS-only guarding alongside this PR.

If Floci doesn't yet implement EventBridge Scheduler, please either:

  • Leave the sample's serviceURL = string.Empty; override (with an updated comment naming Floci instead of Moto), or
  • Document explicitly in the sample README/comment that the Pumper requires real AWS even when Floci is up.

The GreetingsReceiverConsole change is fine — it only consumes SQS/SNS, not Scheduler.

Minor: healthcheck format change

docker-compose-aws.yaml changed from ["CMD", "curl", ...] to ["CMD-SHELL", "curl ..."]. The new command has no shell-specific syntax (no pipes, no || fallback now that the redundant fallback was removed), so CMD would still work and avoids spawning /bin/sh. Not a real issue, just inconsistent with the CI workflow which uses the exec-style --health-cmd form. Feel free to ignore.

Nice touches

  • The per-process random 12-digit account ID in CredentialsChain.cs is clever and the explanatory comment is exactly the right length — it tells the reader why the random number exists (per-account namespace isolation in Floci so V3/V4 runners can share a container) without re-stating what the code does. The 100B–999B range correctly covers all 12-digit values and uses thread-safe Random.Shared.
  • The channelName: new ChannelName(queueUrl) fix in When_infrastructure_exists_can_verify_by_url.cs (both V3 and V4) is a legitimate correctness fix that was masked by Moto's leniency — exactly the kind of bug Floci's stricter behaviour is supposed to surface. Matches the pattern used by the FIFO Reactor sibling.
  • Removing the // TODO: remove once Moto pin in #4096 is bumped to 5.1.23+ comments instead of carrying them forward is the right call.
  • Documentation updates in CONTRIBUTING.md and samples/Scheduler/QuartzTaskQueue/README.md are thorough.

Security / Performance

Nothing of concern. The BasicAWSCredentials(s_localAccountId, "test") only takes effect when AWS_SERVICE_URL is set (i.e. test/local context), so no risk of these placeholder credentials being used against real AWS. The ~2s cold-start improvement is a nice bonus.

Test coverage

Strictly improves. 9 parameterisations that were skipping against Moto now execute against Floci, and no new skips were introduced. The bug fix on verify_by_url is also now exercised against the mock rather than only against real AWS.


TL;DR: ship it, but please confirm the Scheduler sample behaviour against Floci before merging — that's the only thing that gave me pause.

Follow-up to the Floci swap. The two Scheduler/AwsTaskQueue samples
honored AWS_SERVICE_URL after the earlier commit but still wouldn't
start against Floci end-to-end because:

1. Both samples gated all service registration on
   CredentialProfileStoreChain.TryGetAWSCredentials("default"), so a
   developer with no AWS profile (which is most people running against
   a local emulator) silently got no services at all. Now: when
   AWS_SERVICE_URL is set, hand out a random 12-digit BasicAWSCredentials
   (Floci uses 12 digits as the account ID for per-account namespace
   isolation); otherwise fall back to the default profile as before.

2. AwsSchedulerFactory in the Pumper assumed the IAM role
   "brighter-scheduler" already existed. The AWSScheduler test fixtures
   already set MakeRole = OnMissingRole.Create for the same reason;
   the sample should too, otherwise the first run anywhere (including
   real AWS in a fresh account) blows up before scheduling anything.

Verified locally against floci/floci:1.5.19 with
AWS_SERVICE_URL=http://localhost:4566:
- Pumper schedules 200 messages over 2 minutes without errors.
- Floci logs confirm CreateRole, CreateScheduleAsync, and SNS topic
  setup all succeeded.
- (Receiver has a pre-existing FIFO topic/queue Type mismatch — out
  of scope for this PR.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@slang25 slang25 closed this May 26, 2026
@slang25 slang25 reopened this May 26, 2026
Copy link
Copy Markdown

@codescene-delta-analysis codescene-delta-analysis Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No application code in the PR — skipped Code Health checks.

See analysis details in CodeScene

Quality Gate Profile: Clean Code Collective
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Maintenance Build, CI, refactoring, testing infrastructure, and other chores

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant