Skip to content

[M1962] inverts submission/validation#688

Merged
saanobhaai merged 10 commits into
devfrom
M1962
May 29, 2026
Merged

[M1962] inverts submission/validation#688
saanobhaai merged 10 commits into
devfrom
M1962

Conversation

@saanobhaai
Copy link
Copy Markdown
Member

@saanobhaai saanobhaai commented May 20, 2026

Summary by CodeRabbit

  • New Features

    • Full support for macroinvertebrate belt-transect surveys: CSV ingest, submission writer, and comprehensive validation for transects and observations.
  • Changes

    • Choice data: the prior "invertharvesttypes" choice set has been removed from choices/results.
  • Tests

    • Added unit tests covering macroinvertebrate ingest and validation flows.

Review Change Stack

@saanobhaai saanobhaai requested a review from gridcell May 20, 2026 22:26
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d8a114af-96b4-46fd-87b2-2da78208b17e

📥 Commits

Reviewing files that changed from the base of the PR and between 321a542 and 914f1d7.

📒 Files selected for processing (6)
  • src/api/submission/validations/belt_invert.py
  • src/api/submission/validations/validators/__init__.py
  • src/api/submission/validations/validators/invert_belt_transect.py
  • src/api/submission/validations/validators/invert_obs.py
  • src/api/submission/validations/validators/sample_unit_consistency.py
  • src/api/tests/test_ingest.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/api/submission/validations/validators/sample_unit_consistency.py
  • src/api/tests/test_ingest.py
  • src/api/submission/validations/validators/invert_obs.py
  • src/api/submission/validations/belt_invert.py
  • src/api/submission/validations/validators/invert_belt_transect.py

📝 Walkthrough

Walkthrough

Adds end-to-end macroinvertebrate belt-invert support: CSV ingest serializer and choices, observation/transect validators, submission writer/parsers, model migration/choice cleanup, sample-unit wiring, and tests/fixtures.

Changes

Macroinvertebrate Belt-Invert Protocol Implementation

Layer / File(s) Summary
Schema Updates & Model Changes
src/api/models/protocols/macroinvertebrate.py, src/api/migrations/0116_remove_invert_harvest_type.py, src/api/resources/choices.py
InvertHarvestType model deleted; InvertGenus.group_of_interest adds related_name="genera"; harvest-type choices removed from API choices.
CSV Ingest Serializer & Infrastructure
src/api/ingest/choices.py, src/api/ingest/macroinvertebrate_serializer.py, src/api/ingest/utils.py, src/api/ingest/__init__.py
Adds MacroInvertebrateCSVSerializer, invert-related choice helpers, and wires MACROINVERTEBRATE_PROTOCOL into ingest dispatcher and exports.
Belt-Invert Validation Ruleset
src/api/submission/validations/belt_invert.py, src/api/submission/validations/utils.py
Adds belt_invert_validations with field-, row-, and record-level checks (required transect fields, observation constraints, duplicate transect detection, cross-sample-event consistency).
Observation-Level Validators
src/api/submission/validations/validators/invert_obs.py
Adds validators for inclusion/all-excluded, count min, high-count warnings, size-bin required when sizes present, and size vs attribute max-length checks.
Transect & Sample-Event Validators
src/api/submission/validations/validators/invert_belt_transect.py, src/api/submission/validations/validators/sample_unit_consistency.py, src/api/submission/validations/validators/__init__.py
Adds UniqueInvertBeltTransectValidator to detect duplicate transects, DifferentInvertTransectWidthValidator to warn width mismatches, and re-exports validators.
Submission Writer & API Serializers
src/api/submission/writer.py, src/api/resources/sampleunitmethods/beltinvertmethod.py, src/api/submission/parser.py, src/api/submission/utils.py
Adds BeltInvertProtocolWriter, parser helpers for transect/observations, and DRF serializers for BeltInvert and ObsBeltInvert used during persistence and validation.
Supporting Utilities & Sample-Unit Fixes
src/api/utils/sample_units.py, src/api/models/core.py
Maps migrated sample-event data to beltinvert_transect and fixes CollectRecord.sample_unit to use the beltinvert_transect JSON key.
Test Fixtures & Integration Tests
src/api/tests/fixtures/collect_records.py, src/api/tests/fixtures/macroinvertebrate.py, src/api/tests/test_ingest.py, src/api/tests/test_validations.py
Adds fixtures for valid belt-invert records (species/GOI/family), a GOI fixture, macroinvertebrate CSV ingest test, and validation unit tests; updates existing ingest tests to ignore the unused second return value.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • gridcell
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[M1962] inverts submission/validation' directly summarizes the main changes: implementing macroinvertebrate submission and validation support across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch M1962

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@saanobhaai
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api/ingest/macroinvertebrate_serializer.py`:
- Around line 24-26: Annotate the mutable class attributes with typing.ClassVar
to avoid shared-state mutation: change the declarations for
additional_group_fields and composite_fields (and the other mutable class
attribute in this module) to use ClassVar with the correct types (e.g.,
ClassVar[List[str]] for additional_group_fields and ClassVar[Dict[str,
List[str]]] for composite_fields), import ClassVar from typing if needed, and
keep the existing copy() usage when deriving from
CollectRecordCSVSerializer.additional_group_fields to preserve instance-safe
mutation.

In `@src/api/resources/sampleunitmethods/beltinvertmethod.py`:
- Line 14: The Meta class uses mutable defaults causing RUF012: replace mutable
values in Meta (exclude = [] and extra_kwargs = {...}) with immutable defaults
(e.g., exclude = None or exclude = () and extra_kwargs = None or use a
frozendict/tuple) and ensure the serializer or class that consumes these values
handles None by assigning a new list/dict at runtime; update
beltinvertmethod.py's Meta (attributes exclude and extra_kwargs) to use
immutable defaults and add logic where the Meta values are read (e.g., in the
serializer/class initializer or a classmethod) to coerce None into a fresh
list/dict to preserve previous behavior.

In `@src/api/submission/validations/validators/invert_belt_transect.py`:
- Around line 40-72: The code reads self.relative_depth_path but never uses it,
so update _get_query_args to fetch relative_depth =
self.get_value(collect_record, self.relative_depth_path) or None, validate it
alongside depth (e.g., attempt float(relative_depth) inside the existing try
block and raise on failure), and include "relative_depth": relative_depth in the
returned query dict so duplicate-match queries consider relative depth;
reference symbols: _get_query_args, self.relative_depth_path, relative_depth.

In `@src/api/submission/validations/validators/invert_obs.py`:
- Around line 119-125: The try/except in the density bootstrap masks all
errors—replace the blanket except with targeted handling: catch
InvertBeltTransectWidth.DoesNotExist when the DB lookup for
InvertBeltTransectWidth (used by width_id/width_val) fails, and also catch
ValueError/TypeError for invalid numeric casts of len_surveyed/width_val; for
unexpected exceptions let them propagate (or log and raise) instead of returning
OK so real runtime/DB errors aren’t silently ignored—update the block around
transect.get("width"), float(transect.get("len_surveyed")...), and
InvertBeltTransectWidth.objects.get(...) accordingly.

In `@src/api/tests/test_ingest.py`:
- Around line 456-468: The test is unpacking two values from utils.ingest but
never uses the second (output); in src/api/tests/test_ingest.py update the call
to utils.ingest so you only capture the value you need (new_records) — either
assign new_records = utils.ingest(...)[0] or use a throwaway name (e.g.,
new_records, _ = utils.ingest(...)) and remove any reference to output; keep the
same arguments and call to utils.ingest and only change the left-hand
assignment.

In `@src/api/tests/test_validations.py`:
- Line 398: Replace the ambiguous multiplication sign characters used in the
comments (e.g., the comment showing "1m wide × 50m long = 50 m²" and the other
similar comment) with the ASCII letter "x" so Ruff RUF003 is satisfied; update
the comment text in test_validations.py (the density/area calculation comment
and the other comment around the same area) to use "1m wide x 50m long = 50 m²"
(and the equivalent replacement for the other occurrence).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7a8a2574-b6d1-4fd5-9098-88d24953d564

📥 Commits

Reviewing files that changed from the base of the PR and between c2a0520 and 03d372a.

⛔ Files ignored due to path filters (1)
  • src/api/tests/ingest_data/macroinvertebrate.csv is excluded by !**/*.csv
📒 Files selected for processing (23)
  • src/api/ingest/__init__.py
  • src/api/ingest/choices.py
  • src/api/ingest/macroinvertebrate_serializer.py
  • src/api/ingest/utils.py
  • src/api/migrations/0116_invertgroupofinterest_density_upper_bound.py
  • src/api/models/core.py
  • src/api/models/protocols/macroinvertebrate.py
  • src/api/resources/sampleunitmethods/beltinvertmethod.py
  • src/api/submission/parser.py
  • src/api/submission/utils.py
  • src/api/submission/validations/belt_invert.py
  • src/api/submission/validations/utils.py
  • src/api/submission/validations/validators/__init__.py
  • src/api/submission/validations/validators/invert_belt_transect.py
  • src/api/submission/validations/validators/invert_obs.py
  • src/api/submission/validations/validators/sample_unit_consistency.py
  • src/api/submission/writer.py
  • src/api/tests/fixtures/collect_records.py
  • src/api/tests/fixtures/macroinvertebrate.py
  • src/api/tests/test_ingest.py
  • src/api/tests/test_validations.py
  • src/api/utils/invert_goi.py
  • src/api/utils/sample_units.py

Comment thread src/api/ingest/macroinvertebrate_serializer.py
Comment thread src/api/resources/sampleunitmethods/beltinvertmethod.py
Comment thread src/api/submission/validations/validators/invert_belt_transect.py
Comment thread src/api/submission/validations/validators/invert_obs.py Outdated
Comment thread src/api/tests/test_ingest.py Outdated
Comment thread src/api/tests/test_validations.py Outdated
@saanobhaai
Copy link
Copy Markdown
Member Author

@saanobhaai
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@gridcell gridcell left a comment

Choose a reason for hiding this comment

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

AI Code Review

Assessment: The macroinvertebrate belt-transect protocol is well-implemented: all dispatch registration sites are correctly wired, validators are cleanly organised, and the batched InvertSizeValidator query avoids the N+1 anti-pattern. The most important item to address before merge is a UUID serialization bug in DifferentInvertTransectWidthValidator that will crash result persistence at runtime. The destructive migration 0116 should be verified against production row counts before applying, and test coverage for the new writer and two record-level validators is missing.

Severe Warning Question Info Praise
0 8 4 4 5

Files reviewed: 24 / 24

Cross-Cutting Concerns

  • The new BeltInvertProtocolWriter submission path has no end-to-end test (CR-005), and the new DifferentInvertTransectWidthValidator with the UUID-serialization bug (CR-001) has no test (CR-006). A submission test would have surfaced CR-001 immediately. Adding the writer test should be the highest-priority follow-up.
  • Migration 0116 and the choices endpoint removal are coupled — confirming the table is empty in production and confirming no live client reads invertharvesttypes (CR-003, CR-010) must be done together before deploy, not independently.
  • sample_unit_consistency.py and sample_units.py are shared utilities used by all protocols. The UUID-not-stringified bug (CR-001) was introduced into the shared file; reviewing similar context-dict constructions in the other (non-invert) width validators in that file is advisable to catch any inherited defects.
  • Mode B (PR URL) was used for this review — local .gitignore/.dockerignore filtering was skipped because the working tree is not the target repo. All 24 changed files were reviewed.

Findings (cross-file / praise)

CR-005 · Warning · test_gap — BeltInvertProtocolWriter.write() has no test

The new submission writer introduces four cooperating methods: get_or_create_invertbelt_transect, get_or_create_beltinvert, create_obsbeltinvert, and write(). None of these are exercised by any test in the diff. Other protocols (fish belt, benthic LIT) have end-to-end submission tests that call the writer and assert resulting DB rows. The macroinvertebrate protocol is missing a parallel test.

Suggestion: Add a submission test analogous to the existing fish belt one. Use valid_belt_invert_collect_record, call the submission endpoint or invoke BeltInvertProtocolWriter(collect_record, context).write() directly, then assert that InvertBeltTransect, BeltInvert, ObsBeltInvert, and Observer records were created with the expected field values.

Why it matters: The writer integrates four new DB models and two new parser functions. Without an integration test, regressions in any of those layers — wrong field mapping, missing transect, missing observations — will go undetected.

Applies to: src/api/submission/writer.py, src/api/tests/test_validations.py

Found by: reviewer-tests

CR-006 · Warning · test_gap — UniqueInvertBeltTransectValidator and DifferentInvertTransectWidthValidator are untested

Two new record-level validators — UniqueInvertBeltTransectValidator (detects duplicate transect submissions against existing DB records) and DifferentInvertTransectWidthValidator (warns when belt widths differ across the same sample event) — have no test coverage. These validators require pre-existing DB rows to trigger their error or warning path, which the current test suite never sets up for macroinvertebrate.

Suggestion: For UniqueInvertBeltTransectValidator: submit a valid collect record to create a BeltInvert row, then validate a second collect record with matching site/management/date/number/depth/width/observers and assert ERROR with code duplicate_invert_belt_transect. For DifferentInvertTransectWidthValidator: create an InvertBeltTransect with one width, then validate a collect record targeting the same sample event with a different width ID and assert WARN with code different_transect_width_se.

Why it matters: The duplicate-transect check is a critical data-quality guard. Leaving it untested means a regression in the observer-profile filter could allow duplicate submissions silently. Note the DifferentInvertTransectWidth path also has the UUID serialization bug (CR-001) which a test would have surfaced.

Applies to: src/api/submission/validations/validators/invert_belt_transect.py, src/api/submission/validations/validators/sample_unit_consistency.py, src/api/tests/test_validations.py

Found by: reviewer-tests

CR-010 · Question · api_contract — Was invertharvesttypes ever used by any active API client?

The choices endpoint previously exposed invertharvesttypes to API consumers. Were any mobile or third-party clients relying on that key? If genuinely unused, the cleanup is fully safe. If clients are still reading the key, they will silently receive a response missing that field after deploy. Older client versions in the wild may break without a deprecation window.

Applies to: src/api/resources/choices.py

Found by: reviewer-database

CR-011 · Question · test_gap — invert_group_of_interest_2 fixture is added but never referenced in any test

macroinvertebrate.py gains a new invert_group_of_interest_2 fixture (Crown-of-thorns starfish / COTS), but no test in the diff uses it as a parameter. Is this intended for a follow-up test that was intentionally deferred, or did the test that needs it get accidentally dropped?

Applies to: src/api/tests/fixtures/macroinvertebrate.py

Found by: reviewer-tests

CR-012 · Question · test_gap — InvertSizeValidator boundary value (exactly at 1.5x max_length) is not tested

The validator warns when size > max_length * 1.5. The existing test uses size=50, well above the threshold. There is no test for size == max_length * 1.5 (which should pass) or size == max_length * 1.5 + epsilon (which should warn). The exact boundary is a common location for off-by-one mistakes.

Applies to: src/api/tests/test_validations.py

Found by: reviewer-tests

CR-015 · Info · maintainability — Three collect record fixtures share nearly identical boilerplate

valid_belt_invert_collect_record, valid_belt_invert_collect_record_goi, and valid_belt_invert_collect_record_family are approximately 50 lines each and differ only in the invert_attribute fixture and observation list. The repeated beltinvert_transect/sample_event/observers construction could be extracted into a shared factory helper to reduce maintenance surface.

Applies to: src/api/tests/fixtures/collect_records.py

Found by: reviewer-tests

CR-016 · Info · maintainability — macroinvertebrate_file fixture defined in test module rather than conftest

All other protocol file fixtures (fishbelt_file, benthicpit_file, bleaching_file, etc.) live in a conftest.py, making them available project-wide. The new macroinvertebrate_file is defined inline in test_ingest.py and cannot be shared with any other test module that might need it in the future.

Applies to: src/api/tests/test_ingest.py

Found by: reviewer-tests

CR-017 · Praise · performance — InvertSizeValidator batches all InvertAttribute lookups into a single DB query — avoids N+1

InvertSizeValidator.__call__ collects all unique invert_attribute IDs from the observation list in a set comprehension, then issues one InvertAttribute.objects.select_related(...).filter(pk__in=...) query for all of them. The resulting max_length_lookup dict is built once and consulted in O(1) per check_invert_size call.

Applies to: src/api/submission/validations/validators/invert_obs.py

Found by: reviewer-backend-python, reviewer-database

CR-018 · Praise · maintainability — All protocol dispatch tables correctly updated — no missed registration sites

The PR correctly wires MACROINVERTEBRATE_PROTOCOL into every dispatch point that existing protocols use: ingest/utils.py (ingest()), submission/utils.py (get_writer() and _validate_collect_record()), submission/validations/utils.py (PROTOCOL_SAMPLE_UNIT_MAP and PROTOCOL_SAMPLE_EVENT_PATH), utils/sample_units.py (migrate_collect_record_sample_event()), and models/core.py (CollectRecord.sample_unit property). These registration sites are easy to miss in a protocol addition and the author has covered all of them.

Applies to: src/api/ingest/utils.py, src/api/submission/utils.py, src/api/submission/validations/utils.py, src/api/utils/sample_units.py, src/api/models/core.py

Found by: reviewer-backend-python

CR-019 · Praise · maintainability — Well-structured validation module with clear separation of concerns

The belt_invert.py validation module is comprehensively organised with clear section comments (field-level, row-level, record-level) and appropriate validator composition. The structure mirrors established patterns from other protocols and will be easy to maintain and extend.

Found by: reviewer-python-quality

CR-020 · Praise · maintainability — Robust invert_obs validators with proper null-handling and polymorphic attribute resolution

InvertSizeValidator and InvertSizeBinRequiredValidator properly handle optional/nullable size fields and apply sensible defaults. The polymorphic attribute type resolution (species → genus → family → order → class) is cleanly implemented and handles cases where an attribute might not have a max_length, preventing false-positive size warnings for GOI and family observations.

Found by: reviewer-python-quality

CR-021 · Praise · test_gap — Attribute-rank coverage for InvertSizeValidator is precisely targeted

Adding separate fixtures and tests for species-level, GOI-level, and family-level observations is a precisely targeted set of edge cases. The InvertSizeValidator iterates a fixed priority list of subattr names to find max_length — testing that GOI and family observations do not produce false-positive size warnings directly exercises the two paths where the lookup returns None and the validator must silently pass.

Applies to: src/api/tests/test_validations.py, src/api/tests/fixtures/collect_records.py

Found by: reviewer-tests

Agent Coverage

Agent Role Files Findings Blocking
reviewer-backend-python backend 21 8 0
reviewer-python-quality code_quality 21 2 0
reviewer-database database 3 7 0
reviewer-tests testing 5 9 0
reviewer-security security 24 1 0

Generated by AI Review Team

Comment thread src/api/submission/validations/validators/sample_unit_consistency.py Outdated
Comment thread src/api/ingest/choices.py
Comment thread src/api/migrations/0116_remove_invert_harvest_type.py
Comment thread src/api/submission/validations/validators/invert_belt_transect.py
Comment thread src/api/tests/test_ingest.py
Comment thread src/api/tests/test_ingest.py Outdated
Comment thread src/api/submission/validations/validators/invert_obs.py
Comment thread src/api/ingest/macroinvertebrate_serializer.py
Comment thread src/api/submission/validations/validators/invert_obs.py Outdated
@saanobhaai saanobhaai marked this pull request as ready for review May 29, 2026 19:56
@github-actions
Copy link
Copy Markdown

cdk-nag report

No unsuppressed errors.


See iac/nag_suppressions.py to add suppressions for accepted risks.

@github-actions
Copy link
Copy Markdown

cdk diff ✅ Success

Show Output
start: Building GithubAccess Template
success: Built GithubAccess Template
start: Publishing GithubAccess Template (554812291621-us-east-1-403885e2)
success: Published GithubAccess Template (554812291621-us-east-1-403885e2)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack GithubAccess
There were no differences

start: Building mermaid-api-infra-common Template
success: Built mermaid-api-infra-common Template
start: Publishing mermaid-api-infra-common Template (554812291621-us-east-1-37993ba8)
success: Published mermaid-api-infra-common Template (554812291621-us-east-1-37993ba8)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack mermaid-api-infra-common
There were no differences

start: Building dev-mermaid-static-site Template
success: Built dev-mermaid-static-site Template
start: Publishing dev-mermaid-static-site Template (554812291621-us-east-1-705b66ee)
success: Published dev-mermaid-static-site Template (554812291621-us-east-1-705b66ee)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack dev-mermaid-static-site
There were no differences

start: Building dev-mermaid-api-django Template
success: Built dev-mermaid-api-django Template
start: Publishing dev-mermaid-api-django Template (554812291621-us-east-1-b80867d7)
success: Published dev-mermaid-api-django Template (554812291621-us-east-1-b80867d7)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack dev-mermaid-api-django
Resources
[~] AWS::ECS::TaskDefinition ScheduledBackupTaskDef ScheduledBackupTaskDef48789D5A replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -147,7 +147,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:8274c8c3006067dd8787a9494ac751c481d7667719824de4575b4fe3ec13e826"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition SummaryCacheTaskDef SummaryCacheTaskDefFAAC683D replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -151,7 +151,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:8274c8c3006067dd8787a9494ac751c481d7667719824de4575b4fe3ec13e826"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition ApiTaskDefinition ApiTaskDefinition51EA709E replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -145,7 +145,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:8274c8c3006067dd8787a9494ac751c481d7667719824de4575b4fe3ec13e826"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition General/Worker/QueueProcessingTaskDef GeneralWorkerQueueProcessingTaskDef1C2A1522 replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -158,7 +158,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:8274c8c3006067dd8787a9494ac751c481d7667719824de4575b4fe3ec13e826"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition ImageProcess/Worker/QueueProcessingTaskDef ImageProcessWorkerQueueProcessingTaskDefACA5B138 replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -158,7 +158,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:8274c8c3006067dd8787a9494ac751c481d7667719824de4575b4fe3ec13e826"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",


start: Building dev-mermaid-sagemaker Template
success: Built dev-mermaid-sagemaker Template
start: Publishing dev-mermaid-sagemaker Template (554812291621-us-east-1-32848cce)
success: Published dev-mermaid-sagemaker Template (554812291621-us-east-1-32848cce)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack dev-mermaid-sagemaker
There were no differences

start: Building prod-mermaid-static-site Template
success: Built prod-mermaid-static-site Template
start: Publishing prod-mermaid-static-site Template (554812291621-us-east-1-b2d960b0)
success: Published prod-mermaid-static-site Template (554812291621-us-east-1-b2d960b0)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack prod-mermaid-static-site
There were no differences

start: Building prod-mermaid-api-django Template
success: Built prod-mermaid-api-django Template
start: Publishing prod-mermaid-api-django Template (554812291621-us-east-1-328a29b6)
success: Published prod-mermaid-api-django Template (554812291621-us-east-1-328a29b6)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)

Stack prod-mermaid-api-django
Resources
[~] AWS::ECS::TaskDefinition ScheduledBackupTaskDef ScheduledBackupTaskDef48789D5A replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -147,7 +147,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:38b11ecd7a34356ccac91b8c61f892e5a4b598bfeed13f480a5dfde2538bcce5"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition SummaryCacheTaskDef SummaryCacheTaskDefFAAC683D replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -151,7 +151,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:38b11ecd7a34356ccac91b8c61f892e5a4b598bfeed13f480a5dfde2538bcce5"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition ApiTaskDefinition ApiTaskDefinition51EA709E replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -145,7 +145,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:38b11ecd7a34356ccac91b8c61f892e5a4b598bfeed13f480a5dfde2538bcce5"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition General/Worker/QueueProcessingTaskDef GeneralWorkerQueueProcessingTaskDef1C2A1522 replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -158,7 +158,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:38b11ecd7a34356ccac91b8c61f892e5a4b598bfeed13f480a5dfde2538bcce5"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",
[~] AWS::ECS::TaskDefinition ImageProcess/Worker/QueueProcessingTaskDef ImageProcessWorkerQueueProcessingTaskDefACA5B138 replace
 └─ [~] ContainerDefinitions (requires replacement)
     └─ @@ -158,7 +158,7 @@
        [ ] ],
        [ ] "Essential": true,
        [ ] "Image": {
        [-]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:38b11ecd7a34356ccac91b8c61f892e5a4b598bfeed13f480a5dfde2538bcce5"
        [+]   "Fn::Sub": "554812291621.dkr.ecr.us-east-1.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-554812291621-us-east-1:6f7a9fd0d12f30aae7c595a1e88486fe76b4173b1e1e4bb2d521fd76c2e48b24"
        [ ] },
        [ ] "LogConfiguration": {
        [ ]   "LogDriver": "awslogs",



✨  Number of stacks with differences: 2


Workflow: pr

@saanobhaai
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@saanobhaai saanobhaai merged commit 0f1a581 into dev May 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants