Skip to content

feat(LAB-4291): add copy_workflow_from_project SDK method#2033

Merged
florianlega merged 7 commits intomainfrom
feature/lab-4291-aau-from-the-sdk-i-copy-the-workflow-from-one-project-to
Mar 30, 2026
Merged

feat(LAB-4291): add copy_workflow_from_project SDK method#2033
florianlega merged 7 commits intomainfrom
feature/lab-4291-aau-from-the-sdk-i-copy-the-workflow-from-one-project-to

Conversation

@RuellePaul
Copy link
Copy Markdown
Contributor

Add a high-level method to copy a workflow from one project to another, including step configurations (consensus, coverage, sendBackStepId).

  • Add copy_workflow_from_project to presentation client and use cases
  • Add send_back_step_id field to WorkflowStepCreate and WorkflowStepUpdate
  • Add sendBackStepId mapping in the GraphQL step mapper
  • Validate destination project has no labels before copying
  • Remap sendBackStepId references to new step IDs after creation
  • Don't copy assignees per specification
  • Add unit tests for all scenarios

paulruelle and others added 4 commits March 19, 2026 17:58
Add a high-level method to copy a workflow from one project to another,
including step configurations (consensus, coverage, sendBackStepId).

- Add `copy_workflow_from_project` to presentation client and use cases
- Add `send_back_step_id` field to WorkflowStepCreate and WorkflowStepUpdate
- Add `sendBackStepId` mapping in the GraphQL step mapper
- Validate destination project has no labels before copying
- Remap sendBackStepId references to new step IDs after creation
- Don't copy assignees per specification
- Add unit tests for all scenarios

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Guard against self-copy (source == destination project ID)
- Validate source step names are unique before name-based remapping
- Log warning when fetching destination steps fails instead of silent swallow
- Preserve original result when sendBackStepId remap produces no updates
- Add tests for self-copy and duplicate step name edge cases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@florianlega florianlega self-assigned this Mar 26, 2026
@florianlega florianlega force-pushed the feature/lab-4291-aau-from-the-sdk-i-copy-the-workflow-from-one-project-to branch from 86b8e63 to f83a12a Compare March 26, 2026 14:20
Copy link
Copy Markdown
Collaborator

@baptiste-olivier baptiste-olivier left a comment

Choose a reason for hiding this comment

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

Can you add a notebook, and add it to our e2e stack ? 🙏

@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@florianlega florianlega force-pushed the feature/lab-4291-aau-from-the-sdk-i-copy-the-workflow-from-one-project-to branch from 0ab4fce to 2e62b1f Compare March 27, 2026 15:19
@florianlega florianlega requested a review from FannyGaudin March 30, 2026 12:13
@florianlega florianlega merged commit cb2d249 into main Mar 30, 2026
15 checks passed
@florianlega florianlega deleted the feature/lab-4291-aau-from-the-sdk-i-copy-the-workflow-from-one-project-to branch March 30, 2026 13:52
Copy link
Copy Markdown
Collaborator

@baptiste-olivier baptiste-olivier left a comment

Choose a reason for hiding this comment

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

Auto Review Summary

Verdict: Needs discussion (already merged)

Severity Count
Blocker 0
Required 1
Suggestion 3
Question 2
Praise 2

Well-structured feature with good validations and test coverage, but one potential bug in the first-step update and some architectural concerns.


[PRAISE] Comprehensive validations

Good defensive checks: same project ID guard, destination has no labels, duplicate step names detection, and labeler count for consensus. These prevent confusing runtime errors.

[PRAISE] Thorough test coverage

11 test cases covering happy path, error conditions, sendBackStepId remapping, assignee routing, and edge cases (no existing workflow, extra dest steps). Well-structured test helpers (_make_source_steps, _setup_happy_path).

)

delete_steps = [str(step["id"]) for step in dest_steps[1:]] or None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[REQUIRED] _build_step_update doesn't copy stepCoverage or type for the first step

When updating the first destination step to match the first source step, only name, consensusCoverage, and numberOfExpectedLabelsForConsensus are set. The stepCoverage and type fields from the source step are not copied. If the first source step has a stepCoverage value, or a different type than the existing destination step, those properties will be silently lost.

# Current - missing stepCoverage and type
def _build_step_update(dest_step_id, source_step):
    update = {"id": dest_step_id, "name": ...}
    # only sets consensusCoverage, numberOfExpectedLabelsForConsensus
    # Missing: stepCoverage, type
    return update

create_steps: Optional[list[WorkflowStepCreate]]
update_steps: Optional[list[WorkflowStepUpdate]]
delete_steps: Optional[list[str]]
for_copy: bool = False
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SUGGESTION] for_copy flag leaks through the architecture

This flag is threaded from the use case through ProjectWorkflowDataKiliAPIGatewayInput into the mapper, just to change serialization behavior (keeping None for consensus fields). The adapter layer shouldn't know about "copy" semantics. A cleaner approach would be to explicitly set consensusCoverage=0 or have the use case pass a sentinel to signal "include this field even if None", keeping the mapper stateless.



def update_step_mapper(data: Union[WorkflowStepCreate, WorkflowStepUpdate]) -> dict:
def update_step_mapper(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SUGGESTION] Typo: "worklow" → "workflow". Also ## is unusual for a Python comment — typically single #.

]
}
],
"source": [
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SUGGESTION] Notebook outputs contain real-looking test environment emails (test+edouard@kili-technology.com, test+max@kili-technology.com) and internal IDs. Consider clearing outputs or using placeholder data to avoid leaking internal information.

# 1. Fetch source workflow steps and settings
logger.info("Fetching workflow steps from source project %s", source_project_id)
source_steps = self._kili_api_gateway.get_steps(source_project_id, _SOURCE_STEP_FIELDS)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[QUESTION] Consensus validation only checks the first step

_validate_consensus_labelers is only called for source_steps[0]. Is it guaranteed that only the first step can have consensus settings? If a later step could also have numberOfExpectedLabelsForConsensus, the copy would succeed but the destination workflow might be misconfigured.

"""
if source_project_id == destination_project_id:
raise ValueError(
"Source and destination project IDs must be different."
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[QUESTION] No source project workflow V2 validation

The code validates the destination project is V2 but does not check the source project. If the source uses V1, get_steps might return unexpected data. Is this intentional because V1 projects can't have multi-step workflows anyway?

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.

6 participants