Skip to content

Feat/merge (resources) STIT-361#16

Merged
mbarlow12 merged 12 commits intomainfrom
feat/merge
Mar 19, 2026
Merged

Feat/merge (resources) STIT-361#16
mbarlow12 merged 12 commits intomainfrom
feat/merge

Conversation

@AlexAxthelm
Copy link
Copy Markdown
Collaborator

@AlexAxthelm AlexAxthelm commented Feb 24, 2026

Adds a /resources/merge endpoint to API.

Note: This has not added any automated tests, and exists primarily as a springboard for adding an entity-linkage service.

Confirmed via API that:

  • merging creates new resources & repoints the merged
  • new active memberships & existing/merged set to inactive
  • coalescing looks correct (done via quick switch to return full resource instead of view, not in PR)

Testing can come in a follow up PR

@AlexAxthelm
Copy link
Copy Markdown
Collaborator Author

@mbarlow12 I'm assuming you'll want to make a bunch of changes on this. Feel free to take over the branch, but I'd prefer if we keep the signature on the new POST (i.e. takes an array of resource IDs, returns a Resource object).

@AlexAxthelm AlexAxthelm changed the title Feat/merge Feat/merge (resources) Feb 25, 2026
@AlexAxthelm AlexAxthelm marked this pull request as ready for review February 25, 2026 12:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds a new /resources/merge endpoint to the API that implements stub functionality for merging multiple resources. The endpoint accepts a list of resource IDs and repoints resources[1:] to resources[0] as the canonical target. This is explicitly noted as a springboard for future entity-linkage service development and intentionally lacks automated tests.

Changes:

  • Added POST /resources/merge endpoint with MergeRequest model for accepting resource IDs
  • Implemented merge_resources function in resource_actions that updates repointed_id field on resources
  • Added seed data (2 resources, 2 sources, 2 memberships) to support merge testing scenarios

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
deployments/api/src/stitch/api/routers/resources.py Adds merge endpoint with validation, logging, and error handling wrapper around resource_actions.merge_resources
deployments/api/src/stitch/api/db/resource_actions.py Implements merge_resources function that validates resource existence and updates repointed_id fields
deployments/api/src/stitch/api/db/init_job.py Adds test/seed data for merge scenarios: "Merge Target" and "Merge Consumed" resources with associated sources

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread deployments/api/src/stitch/api/routers/oil_gas_fields.py
Comment on lines +160 to +162
session: AsyncSession,
user: CurrentUser,
ids: Sequence[int],
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The user parameter is accepted but never used in the merge_resources function. If this is intended for future authorization checks or audit logging (e.g., updating last_updated_by_id on modified resources), consider adding a TODO comment. Otherwise, the parameter can be removed to reduce confusion.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@mbarlow12 my local IDE kept warning me about this too (User isn't consumed in the resource_actions). I'm guessing that when we start actually using permissions to filter the reesources, that's when we'll start using it?

Comment on lines +171 to +178
if not ids:
raise HTTPException(status_code=400, detail="No resource IDs provided.")
# preserve order but drop duplicates
unique_ids = list(dict.fromkeys(ids))
if len(unique_ids) < 2:
raise HTTPException(
status_code=400, detail="Provide at least 2 unique resource IDs."
)
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The validation logic in lines 171-178 duplicates the validation already performed in the router endpoint (lines 58-61 of resources.py). Since the endpoint already validates that there are at least 2 unique resource IDs before calling this function, this redundant validation can be removed. The check for empty IDs list at line 171-172 is also unnecessary since the endpoint guarantees the list is non-empty after deduplication.

Suggested change
if not ids:
raise HTTPException(status_code=400, detail="No resource IDs provided.")
# preserve order but drop duplicates
unique_ids = list(dict.fromkeys(ids))
if len(unique_ids) < 2:
raise HTTPException(
status_code=400, detail="Provide at least 2 unique resource IDs."
)
# preserve order but drop duplicates
unique_ids = list(dict.fromkeys(ids))

Copilot uses AI. Check for mistakes.
except HTTPException:
raise
except Exception as exc:
logger.exception("Error while merging resources %s: %s", unique_ids, exc)
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The logger.exception call already includes the full exception traceback and the exception message automatically. Including the exception in the log message string as well (with %s, exc) results in duplicate exception information in the logs. Consider removing exc from the message format and just using: logger.exception("Error while merging resources %s", unique_ids)

Suggested change
logger.exception("Error while merging resources %s: %s", unique_ids, exc)
logger.exception("Error while merging resources %s", unique_ids)

Copilot uses AI. Check for mistakes.

logger.info(
"Merge requested by user=%s for resource_ids=%s",
getattr(user, "sub", "<anon>"),
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The use of getattr(user, "sub", "") is unnecessary. According to the User entity definition (entities.py line 167), the 'sub' field is a required string field (not optional). The user parameter is typed as CurrentUser which is a User entity with sub always present. This can be simplified to just user.sub.

Suggested change
getattr(user, "sub", "<anon>"),
user.sub,

Copilot uses AI. Check for mistakes.
Comment thread deployments/api/src/stitch/api/db/init_job.py Outdated
Comment thread deployments/api/src/stitch/api/db/resource_actions.py Outdated
Comment thread deployments/api/src/stitch/api/routers/resources.py Outdated
Comment thread deployments/api/src/stitch/api/db/resource_actions.py Outdated
Comment thread deployments/api/src/stitch/api/routers/resources.py Outdated
@AlexAxthelm
Copy link
Copy Markdown
Collaborator Author

@mbarlow12 Copilot brought up a bunch of issues with my implementation (which all seem fair), but I'm probably not the best person to figure out what the "right" answer is. You mentioned in meeting yesterday wanting to use what's already available in stitch-core.

I'm fine if you want to either take over this PR, or close it. From a design perspective, I'd like to have a merge endpoint at /resources/merge, that takes the array payload that we have now, but everything else is totally open from my side.

@AlexAxthelm AlexAxthelm marked this pull request as draft March 2, 2026 11:55
@mbarlow12
Copy link
Copy Markdown
Contributor

@AlexAxthelm need to merge the ogsi model branch. But hopefully this'll be cleaner once that's done.

@mbarlow12 mbarlow12 marked this pull request as ready for review March 19, 2026 15:24
@mbarlow12 mbarlow12 requested review from mbarlow12 and removed request for mbarlow12 March 19, 2026 15:33
@mbarlow12
Copy link
Copy Markdown
Contributor

@AlexAxthelm had to assign you instead of requesting review since you initiated the PR. Should be good to go.

@mbarlow12 mbarlow12 changed the title Feat/merge (resources) Feat/merge (resources) STIT-361 Mar 19, 2026
@mbarlow12 mbarlow12 merged commit 44082e3 into main Mar 19, 2026
13 checks passed
@mbarlow12 mbarlow12 deleted the feat/merge branch March 19, 2026 22:37
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.

4 participants