Skip to content

Conversation

Mic92
Copy link
Member

@Mic92 Mic92 commented Sep 30, 2025

Summary by CodeRabbit

  • New Features

    • Alias-aware scheduling: detects jobs that are aliases of previously scheduled jobs and logs a clear "alias" skip message.
  • Bug Fixes

    • Prevents re-scheduling duplicate jobs, reducing redundant work and improving reliability.
    • Improved cancellation handling: cancelled builds are detected, logged as "Build was cancelled," and reported as cancelled.
  • Chores

    • Tracks seen jobs during a run so unique jobs proceed unchanged while aliases are consistently skipped and counted.

Copy link

coderabbitai bot commented Sep 30, 2025

Walkthrough

Adds alias detection to scheduling by tracking seen derivation paths in SchedulingContext (new public field seen_drvs). During _schedule_ready_jobs, jobs with already-seen drvPath are skipped with an alias log and counted; first-seen drvPath records its attr. SchedulingContext is initialized with an empty seen_drvs. Also improves error handling: wait_for_finish_deferred catches FirstError to detect cancellation, logs "Build was cancelled" and returns CANCELLED; other errors are re-raised.

Changes

Cohort / File(s) Change Summary
Scheduling alias detection & context
buildbot_nix/buildbot_nix/build_trigger.py
- Add public field SchedulingContext.seen_drvs: dict[str, str] and pass an empty mapping when creating the context
- In _schedule_ready_jobs, iterate jobs by attr order and skip jobs whose drvPath already exists in seen_drvs (log alias relationship and increment skipped count)
- On first encounter of a drvPath, record seen_drvs[drvPath] = attr and proceed with existing scheduling logic
Cancel handling in wait-for-finish
buildbot_nix/buildbot_nix/build_trigger.py
- wait_for_finish_deferred now catches FirstError to detect CancelledError, logs “Build was cancelled” and returns CANCELLED; other exceptions are re-raised

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant Scheduler as _schedule_ready_jobs
  participant Ctx as SchedulingContext\n(seen_drvs)
  participant Logger

  Caller->>Scheduler: invoke scheduling
  loop each ready job (ordered by attr)
    Scheduler->>Ctx: is drvPath in seen_drvs?
    alt drvPath seen (alias)
      Scheduler->>Logger: log "alias: <attr> -> <first_attr>"
      Scheduler->>Ctx: increment skipped count
      note right of Scheduler: job skipped (no schedule)
    else drvPath not seen
      Scheduler->>Ctx: seen_drvs[drvPath] = attr
      Scheduler->>Scheduler: proceed with existing scheduling checks
      alt schedulable
        Scheduler->>Logger: log scheduled
      else not schedulable
        Scheduler->>Logger: log skipped_out_path (existing behavior)
      end
    end
  end
Loading
sequenceDiagram
  autonumber
  participant Caller
  participant Waiter as wait_for_finish_deferred
  participant Logger

  Caller->>Waiter: await build completion
  alt build cancelled (FirstError->CancelledError)
    Waiter->>Logger: log "Build was cancelled"
    Waiter-->>Caller: return CANCELLED
  else other error
    Waiter-->>Caller: re-raise error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “build-trigger: skip aliased derivations” concisely and accurately summarizes the primary change by indicating that the build-trigger component now skips derivations that are aliases, which directly reflects the core enhancement described in the pull request.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch failed-statuses

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f54d0b4 and 65ca5a1.

📒 Files selected for processing (1)
  • buildbot_nix/buildbot_nix/build_trigger.py (5 hunks)
🔇 Additional comments (4)
buildbot_nix/buildbot_nix/build_trigger.py (4)

11-17: LGTM!

The additional imports (CANCELLED and proper exception handling) align with the improved error handling in wait_for_finish_deferred.


104-104: LGTM!

The new field is well-documented and properly typed for tracking derivation aliases.


594-602: LGTM!

The error handling correctly detects cancellation by unwrapping FirstError to check for CancelledError, logs appropriately, and returns CANCELLED status. Re-raising other errors preserves existing error handling.


744-744: LGTM!

The initialization of seen_drvs as an empty dict is correct and matches the field's type annotation.


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
🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

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

Copy link

@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: 1

🧹 Nitpick comments (1)
buildbot_nix/buildbot_nix/build_trigger.py (1)

534-534: Verify that sorting by attr is intentional for deterministic alias selection.

The sort order determines which attribute becomes the "original" and which becomes the "alias." For example, if a-foo and z-bar point to the same derivation, a-foo will be built and z-bar will be skipped as an alias. While this ensures deterministic behavior, it may not match user expectations in all cases.

Consider documenting this behavior in the code comment or function docstring to clarify the selection criteria.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3d8469 and f54d0b4.

📒 Files selected for processing (1)
  • buildbot_nix/buildbot_nix/build_trigger.py (3 hunks)
🔇 Additional comments (2)
buildbot_nix/buildbot_nix/build_trigger.py (2)

98-98: LGTM! Clear field addition with helpful comment.

The new seen_drvs field is well-typed and documented, making the alias detection mechanism transparent.


730-730: LGTM! Proper initialization.

The seen_drvs dictionary is correctly initialized as empty at the start of the scheduling context.

Comment on lines +536 to +544
if job.drvPath in ctx.seen_drvs:
original_attr = ctx.seen_drvs[job.drvPath]
ctx.scheduler_log.addStdout(
f"\t- {job.attr} (skipped, alias of {original_attr})\n"
)
skipped_jobs.append(job)
self._skipped_count += 1
continue
ctx.seen_drvs[job.drvPath] = job.attr
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential issue: Aliased jobs don't set required output path properties.

When a job is skipped as an alias, schedule_success is never called (due to continue at line 543), so the properties normally set at lines 216-217 ({attr}-out_path, {attr}-drv_path) are never stored in build_props. This differs from the "already built" skip case (lines 560-565), where schedule_success is called first and sets these properties.

If downstream processes (e.g., gcroot registration) expect these properties for all jobs, this could cause issues.

Consider calling schedule_success for aliased jobs or manually setting the required properties before skipping:

         for job in sorted(ctx.schedule_now, key=lambda j: j.attr):
             # Check if we've already scheduled a build for this derivation (alias detection)
             if job.drvPath in ctx.seen_drvs:
                 original_attr = ctx.seen_drvs[job.drvPath]
+                # Still need to set output path properties for downstream processes
+                source = "nix-eval-nix"
+                out_path = job.outputs["out"] or None
+                build_props.setProperty(f"{job.attr}-out_path", out_path, source)
+                build_props.setProperty(f"{job.attr}-drv_path", job.drvPath, source)
+                if out_path and job.cacheStatus == CacheStatus.local:
+                    build_props.setProperty(f"{job.attr}-skipped_out_path", out_path, source)
                 ctx.scheduler_log.addStdout(
                     f"\t- {job.attr} (skipped, alias of {original_attr})\n"
                 )
                 skipped_jobs.append(job)
                 self._skipped_count += 1
                 continue
             ctx.seen_drvs[job.drvPath] = job.attr
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if job.drvPath in ctx.seen_drvs:
original_attr = ctx.seen_drvs[job.drvPath]
ctx.scheduler_log.addStdout(
f"\t- {job.attr} (skipped, alias of {original_attr})\n"
)
skipped_jobs.append(job)
self._skipped_count += 1
continue
ctx.seen_drvs[job.drvPath] = job.attr
if job.drvPath in ctx.seen_drvs:
original_attr = ctx.seen_drvs[job.drvPath]
# Still need to set output path properties for downstream processes
source = "nix-eval-nix"
out_path = job.outputs["out"] or None
build_props.setProperty(f"{job.attr}-out_path", out_path, source)
build_props.setProperty(f"{job.attr}-drv_path", job.drvPath, source)
if out_path and job.cacheStatus == CacheStatus.local:
build_props.setProperty(f"{job.attr}-skipped_out_path", out_path, source)
ctx.scheduler_log.addStdout(
f"\t- {job.attr} (skipped, alias of {original_attr})\n"
)
skipped_jobs.append(job)
self._skipped_count += 1
continue
ctx.seen_drvs[job.drvPath] = job.attr

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.

1 participant