Branch and pull request association

Updated Jul 14, 2026

Once a task has been created from an issue, a branch reference can be associated with it. Multiple tasks may share the same branch. Each individual task has at most one active branch and at most one open pull request.

Associating a pull request with a task automatically transitions the task state to in_review.

use std::sync::Arc;

use corbusier::context::{CorrelationId, RequestContext, SessionId, UserId};
use corbusier::tenant::TenantId;
use corbusier::task::{
    adapters::memory::InMemoryTaskRepository,
    domain::{BranchRef, PullRequestRef, TaskState},
    services::{
        AssociateBranchRequest, AssociatePullRequestRequest, CreateTaskFromIssueRequest,
        TaskLifecycleService,
    },
};
use mockable::DefaultClock;

async fn associate_branch_and_pr() -> Result<(), Box<dyn std::error::Error>> {
    let service = TaskLifecycleService::new(
        Arc::new(InMemoryTaskRepository::new()),
        Arc::new(DefaultClock),
    );
    let ctx = RequestContext::new(
        TenantId::new(),
        CorrelationId::new(),
        UserId::new(),
        SessionId::new(),
    );

    // Create a task from an issue.
    let task = service
        .create_from_issue(&ctx, CreateTaskFromIssueRequest::new(
            "github",
            "corbusier/core",
            200,
            "Implement branch tracking",
        ))
        .await?;

    // Associate a branch with the task.
    let updated = service
        .associate_branch(&ctx, AssociateBranchRequest::new(
            task.id(),
            "github",
            "corbusier/core",
            "feature/branch-tracking",
        ))
        .await?;
    assert!(updated.branch_ref().is_some());

    // Retrieve the task by branch reference.
    let branch_ref = BranchRef::from_parts("github", "corbusier/core", "feature/branch-tracking")?;
    let found = service.find_by_branch_ref(&ctx, &branch_ref).await?;
    assert_eq!(found.len(), 1);

    // Associate a pull request — this transitions the task to in_review.
    let reviewed = service
        .associate_pull_request(&ctx, AssociatePullRequestRequest::new(
            task.id(),
            "github",
            "corbusier/core",
            42,
        ))
        .await?;
    assert_eq!(reviewed.state(), TaskState::InReview);

    // Retrieve the task by pull request reference.
    let pr_ref = PullRequestRef::from_parts("github", "corbusier/core", 42)?;
    let found = service.find_by_pull_request_ref(&ctx, &pr_ref).await?;
    assert_eq!(found.len(), 1);

    Ok(())
}