Skip to content

fix(release): pre-build UI bundles of path-dependency crates - #747

Merged
ytallo merged 1 commit into
mainfrom
fix/prebuild-dependency-ui-bundles
Aug 7, 2026
Merged

fix(release): pre-build UI bundles of path-dependency crates#747
ytallo merged 1 commit into
mainfrom
fix/prebuild-dependency-ui-bundles

Conversation

@ytallo

@ytallo ytallo commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Failure

eval/v0.2.0-experimental died in every binary shard:

panicked at harness/build.rs:50:
SKIP_UI_BUILD set but harness/ui/dist/page.js is missing

Cause

The Pre-build SPA bundle job builds only the released worker's frontend, but SKIP_UI_BUILD applies to the entire cargo build. Since MOT-4096, eval has a path dependency on the harness crate — whose build.rs runs the same contract (dist must pre-exist under SKIP_UI_BUILD) and found nothing.

Fix

  • The dirs step scans the released worker's Cargo.toml for direct path = "../…" dependencies and adds each one's ui/ (when it has a package.json) to the bundle list.
  • Bundles are now repo-relative end to end: staged under .release-frontend-bundle/<crate>/ui/dist, artifact uploaded repo-rooted, restored at ./ — every dist/ lands exactly where its crate's build.rs expects.

Verified locally: for eval, the scan yields harness/ui ✓; for workers without UI deps the list is unchanged.

Note

release.yml runs from the tag's ref, so the in-flight eval/v0.2.0-experimental cannot be fixed by re-run — after merge, cut the next version (0.2.1-experimental) through Release Control.

Summary by CodeRabbit

  • Bug Fixes
    • Improved frontend build workflows to correctly discover and build bundles from direct path dependencies.
    • Preserved repository-relative bundle locations in build artifacts.
    • Ensured build shards restore dependency bundles where required for successful compilation.

eval/v0.2.0-experimental died in every binary shard:

  panicked at harness/build.rs:50:
  SKIP_UI_BUILD set but harness/ui/dist/page.js is missing

The SPA pre-build job only built the released worker's own frontend,
but SKIP_UI_BUILD applies to the whole cargo build — any path-dependency
crate with an injected console UI (eval → harness since MOT-4096) runs
the same build.rs contract and finds no dist.

The pre-build now scans the released worker's Cargo.toml for direct
path dependencies and builds their ui/ bundles too. The artifact
switches from worker-rooted to repo-rooted paths so each dist/ restores
exactly where its crate's build.rs expects it.
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview Aug 7, 2026 4:40pm
workers-tech-spec Ready Ready Preview Aug 7, 2026 4:40pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Rust binary workflow now discovers frontend bundles across the repository and direct path dependencies. It stages bundles with repository-relative paths and restores the artifact at the repository root for build shards.

Changes

Frontend bundle artifact flow

Layer / File(s) Summary
Frontend bundle discovery
.github/workflows/_rust-binary.yml
The workflow records repository-relative web and ui bundle paths, including ui/package.json files in direct path dependencies.
Repository-relative bundle staging
.github/workflows/_rust-binary.yml
The workflow builds and stages each bundle under its full repository-relative path.
Build-shard artifact restoration
.github/workflows/_rust-binary.yml
Build shards download the frontend artifact into the repository root so worker and dependency bundles are available during Rust builds.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • iii-hq/workers#591: Both changes update frontend bundle discovery, packaging, and restoration in the Rust binary workflow.
  • iii-hq/workers#601: Both changes package and restore multiple frontend bundles for Rust build shards.

Suggested labels: no-ticket

Suggested reviewers: guibeira, sergiofilhowz

Poem

I hop through paths, both near and far,
And pack each bundle like a star.
At root I leave the goods in place,
So every build can find its trace.
Squeak-squeak, the workflow runs! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the release fix for pre-building UI bundles in path-dependent crates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/prebuild-dependency-ui-bundles

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.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 56 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@ytallo
ytallo merged commit be50099 into main Aug 7, 2026
17 of 18 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 @.github/workflows/_rust-binary.yml:
- Around line 166-170: Replace the regex-based Cargo.toml path extraction in the
dependency bundle loop with TOML parsing of the worker manifest’s
[dependencies.*].path entries. Resolve each parsed path relative to the worker
manifest, include only paths that remain within the repository, and preserve
adding directories containing ui/package.json to bundles so ui/dist builds are
not skipped.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a620a89d-ba95-4786-bbb7-3bec01386886

📥 Commits

Reviewing files that changed from the base of the PR and between eba6782 and 47bb766.

📒 Files selected for processing (1)
  • .github/workflows/_rust-binary.yml

Comment on lines +166 to +170
while IFS= read -r dep; do
if [[ -f "$dep/ui/package.json" ]]; then
bundles+=("$dep/ui")
fi
done < <(grep -oE 'path *= *"\.\./[A-Za-z0-9_-]+"' "$worker/Cargo.toml" | sed 's|.*"\.\./||; s|"||' | sort -u)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show release workflow callers and their manifest paths.
rg -n -C4 --glob '*.yml' --glob '*.yaml' \
  '_rust-binary\.yml|manifest_path:' .github/workflows

# Show every Cargo path value and the directory it resolves to.
python3 - <<'PY'
from pathlib import Path
import re

root = Path.cwd().resolve()
pattern = re.compile(r'path\s*=\s*"([^"]+)"')

for manifest in sorted(root.rglob("Cargo.toml")):
    for raw_path in pattern.findall(manifest.read_text()):
        resolved = (manifest.parent / raw_path).resolve()
        try:
            relative = resolved.relative_to(root)
        except ValueError:
            relative = f"OUTSIDE_REPOSITORY: {resolved}"
        print(f"{manifest.relative_to(root)}: {raw_path} -> {relative}")
PY

Repository: iii-hq/workers

Length of output: 11087


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- workflow relevant section ---\n'
sed -n '110,210p' .github/workflows/_rust-binary.yml | cat -n

printf '\n--- manifest paths from workflow setup ---\n'
sed -n '1,120p' .github/workflows/release.yml | cat -n

printf '\n--- manifest path examples ---\n'
python3 - <<'PY'
from pathlib import Path
import re

root = Path.cwd().resolve()
pattern = re.compile(r'path\s*=\s*"([^"]+)"')
worker_manifests = Path.cwd() / ".github" / "setup.manifest-path"
if worker_manifests.exists():
    print(worker_manifests.read_text())
for manifest in sorted(root.rglob("Cargo.toml")):
    text = manifest.read_text()
    found = re.findall(r'path\s*=\s*"([^"]+)"', text)
    if found:
        print(f"\n{manifest.relative_to(root)}")
        for raw in found:
            resolved = (manifest.parent / raw).resolve()
            try:
                relative = resolved.relative_to(root)
            except ValueError:
                relative = f"OUTSIDE_REPOSITORY: {resolved}"
            print(f"  {raw!r} -> {relative}")
PY

Repository: iii-hq/workers

Length of output: 243


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workflow setup variables ---'
rg -n -C3 'manifest|worker|SKIP_UI_BUILD|bundle|packages_to_cache|ui/package|restores-artifacts|bundles|dep_path' .github/workflows/_rust-binary.yml

printf '%s\n' '--- worker selection files ---'
sed -n '1,220p' .github/workflows/release.yml | cat -n

Repository: iii-hq/workers

Length of output: 20226


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from collections import defaultdict
from pathlib import Path
import re

root = Path.cwd().resolve()
pattern = re.compile(r'path\s*=\s*"([^"]+)"')
by_level = defaultdict(list)

for manifest in sorted(root.rglob("Cargo.toml")):
    text = manifest.read_text()
    found = re.findall(r'path\s*=\s*"([^"]+)"', text)
    if not found:
        continue
    for raw in found:
        resolved = (manifest.parent / raw).resolve()
        depth = len(Path(raw).parts)
        by_level[depth].append(f"{manifest.relative_to(root)}: {raw!r} -> {resolved.relative_to(root)!r}")

print("Cargo path dependency levels and resolved paths:")
for depth, items in sorted(by_level.items()):
    print(f"\ndepth={depth}:")
    for item in sorted(set(items)):
        print(f"  {item}")
PY

Repository: iii-hq/workers

Length of output: 10322


Resolve Cargo paths through TOML parsing before extending to the root.

Currently, crates/console-ui passes the root-level regex because it appears as ../crates/console-ui, but the parsing is still TOML-unsafe. If a dependency uses spaces, quoted keys, or inline [dependencies], this can treat invalid TOML as a package directory and skip the ui/dist build.

Use a TOML parser for the [dependencies.*].path entries, resolve each value against the worker manifest, and convert only repository-relative paths to bundles.

🤖 Prompt for 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.

In @.github/workflows/_rust-binary.yml around lines 166 - 170, Replace the
regex-based Cargo.toml path extraction in the dependency bundle loop with TOML
parsing of the worker manifest’s [dependencies.*].path entries. Resolve each
parsed path relative to the worker manifest, include only paths that remain
within the repository, and preserve adding directories containing
ui/package.json to bundles so ui/dist builds are not skipped.

ytallo added a commit that referenced this pull request Aug 7, 2026
The repo-rooted upload from #747 pointed upload-artifact at
.release-frontend-bundle/ itself — and with the action's default
include-hidden-files: false, a dot-directory as the glob root excludes
everything: 'No files were found'. The previous layout only worked by
accident because its search root was a child of the dot-directory.

eval/v0.2.1-experimental built every bundle correctly (the dists are in
the job log) and still shipped an empty artifact. Drop the dot: hidden
semantics have no business in a CI staging path.
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