Skip to content

ci(carrier): compile and test the Tauri host, which no job touched - #3541

Merged
ctwoodwa merged 3 commits into
mainfrom
fix/3533-tauri-ci
Aug 4, 2026
Merged

ci(carrier): compile and test the Tauri host, which no job touched#3541
ctwoodwa merged 3 commits into
mainfrom
fix/3533-tauri-ci

Conversation

@ctwoodwa

@ctwoodwa ctwoodwa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

ci(carrier): compile and test the Tauri host, which no job touched

Nothing in CI ran cargo for apps/carrier/src-tauri. Two consequences: the host's own protocol
contract tests never executed, and the generated-contract path dependency added by the
language-agnostic contracts work was never compiled, so a break in the Rust host's consumption of
that projection could not be caught.

The inert workflow whose path globs point at a directory that does not exist in this repository is
an intentional migration stub, and is left alone — it is documented as such rather than being
accidental coverage.

The host's cargo test now runs in the existing carrier/hull job, whose path filter already covers
the relevant trees. TAURI_CONFIG suppresses only the bundle-time external sidecar; this compiles
and tests the host without packaging or launching the desktop app.

A cargo cache is included. Without it every run recompiles the webkit bindings from scratch, and a
slow required check is how people learn to ignore CI.

The stale comment claiming CI does not test this crate is replaced with the actual coverage
boundary.

Proven by mutation: pointing the host at a generated constant that does not exist fails compilation
in the new step, so the step really does compile the host's consumption of the projection.

Honest limitation: GitHub Actions itself was not exercised. The commands were verified locally on
macOS; the Ubuntu runner path — the apt prerequisites in particular — is unverified until this runs.
Watch the first execution rather than assuming it.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Summary by CodeRabbit

  • Tests

    • Expanded automated validation to cover the Carrier desktop host and generated Rust integration.
    • Added checks that compile and test the application without packaging external platform components.
    • Improved test execution reliability with environment support and expanded coverage.
  • Chores

    • Increased CI test time limits and added retry handling for system setup.
    • Added build and dependency caching to make repeated validation runs more efficient.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ctwoodwa, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 67449f14-1bd2-4e2b-b826-93924933311c

📥 Commits

Reviewing files that changed from the base of the PR and between 6d0b7e5 and c3d5ef8.

📒 Files selected for processing (1)
  • .github/workflows/ts-suites.yml
📝 Walkthrough

Walkthrough

The TypeScript suite now tests the generated Rust projection and Carrier Tauri host. CI installs required Linux packages, caches Cargo data, and allows more execution time. Carrier documentation now reflects this test coverage.

Changes

Carrier Tauri CI coverage

Layer / File(s) Summary
Carrier host test orchestration
scripts/ts-suites.mjs, apps/carrier/src-tauri/src/lib.rs
The suite documents and runs the Carrier Tauri Rust host test. The test disables external sidecars through TAURI_CONFIG while preserving inherited environment variables.
CI environment and caching
.github/workflows/ts-suites.yml
The workflow installs Tauri Linux prerequisites with retry handling, caches Cargo data using lockfile-based keys, and increases the job timeout to 30 minutes.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change well but omits the required Summary, ICM Stage, Affected Packages, and Checklist sections. Add the template headings, select applicable ICM and package items, and mark completed checklist items or explain exceptions.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: CI now compiles and tests the Carrier Tauri host.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/3533-tauri-ci

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.

Nothing in CI ran cargo for `apps/carrier/src-tauri`. Two consequences: the host's own protocol
contract tests never executed, and the generated-contract path dependency added by the
language-agnostic contracts work was never compiled, so a break in the Rust host's consumption of
that projection could not be caught.

The inert workflow whose path globs point at a directory that does not exist in this repository is
an intentional migration stub, and is left alone — it is documented as such rather than being
accidental coverage.

The host's cargo test now runs in the existing carrier/hull job, whose path filter already covers
the relevant trees. `TAURI_CONFIG` suppresses only the bundle-time external sidecar; this compiles
and tests the host without packaging or launching the desktop app.

A cargo cache is included. Without it every run recompiles the webkit bindings from scratch, and a
slow required check is how people learn to ignore CI.

The stale comment claiming CI does not test this crate is replaced with the actual coverage
boundary.

Proven by mutation: pointing the host at a generated constant that does not exist fails compilation
in the new step, so the step really does compile the host's consumption of the projection.

Honest limitation: GitHub Actions itself was not exercised. The commands were verified locally on
macOS; the Ubuntu runner path — the apt prerequisites in particular — is unverified until this runs.
Watch the first execution rather than assuming it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ctwoodwa
ctwoodwa force-pushed the fix/3533-tauri-ci branch from 5fec358 to d875c35 Compare August 2, 2026 14:39
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

thought (non-blocking):

Accessibility audit (advisory)

The sharded axe audit is report-only while the baseline and runtime budget mature.
Unknown moderate-or-higher findings must be resolved or added to the reviewed
accessibility baseline.

Shard Result Findings
1/4 pass 0 axe finding(s), 1 coverage warning(s)
2/4 pass 0 axe finding(s), 1 coverage warning(s)
3/4 pass 0 axe finding(s), 1 coverage warning(s)
4/4 pass No moderate-or-higher findings
Shard 1 report
[shipyard-syncstate-indicator] skipping directionalIcons enforcement: component has not opted in via [data-shipyard-direction="<state>"] sentinel.
Shard 2 report
[shipyard-button] skipping keyboardMap enforcement: component has not opted in via data-shipyard-keyboard-map="enabled".
Shard 3 report
[shipyard-dialog] skipping keyboardMap enforcement: component has not opted in via data-shipyard-keyboard-map="enabled".

…uild

Two one-liners from the review, both protecting a required check.

The 15-minute ceiling was sized for a Node-only job. A cold Rust build of the Tauri host measured
3m33s wall and about 935 CPU-seconds on a 16-core Mac, and the Linux runner additionally compiles
the webkit and gtk binding crates on fewer, slower cores. That build now shares the budget with apt,
pnpm install, two dist builds, four lints, four vitest suites, the Rust projection test and the
renderer production build.

The compounding part is why this is not a nit: a timeout CANCELS the job, and a cancelled job skips
the cache save, so the next run is cold again. An undersized ceiling on a required check is
self-perpetuating.

The apt step is the only one in any workflow here and had no retry, so a single transient mirror
failure would block merge on a PR that merely touched the contracts package. Three attempts with a
short backoff.

The review refuted my own worry about the cargo cache masking a compile break, with evidence: both
break-mutations went red against a warm target holding 319 cached dependency archives, because cargo
recompiled only the changed crate. Restored caches carry archived mtimes older than the sources
checkout writes, so the failure direction is over-rebuild, never under-rebuild.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

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

🤖 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/ts-suites.yml:
- Around line 91-94: Update the apt-get retry loop in the workflow so exhausting
all three attempts exits non-zero instead of succeeding because sleep is the
final command. Preserve the five-second delay between attempts, but explicitly
fail after the final unsuccessful apt-get update before continuing to package
installation.
- Around line 94-99: Update the prerequisite installation command in the
workflow step to include apt-get’s non-interactive option while preserving the
existing package list and no-recommends behavior, so the Tauri dependencies
install without prompting before pnpm ts-suites runs.

In `@scripts/ts-suites.mjs`:
- Around line 141-146: Update the `run` invocation for `test Carrier Tauri Rust
host` to include Cargo’s `--locked` flag alongside the existing test arguments,
ensuring the command uses the committed `apps/carrier/src-tauri/Cargo.lock`
dependency graph.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ae70e5-c76e-4e9c-ad1e-227299e832f3

📥 Commits

Reviewing files that changed from the base of the PR and between ed9c43b and 6d0b7e5.

📒 Files selected for processing (3)
  • .github/workflows/ts-suites.yml
  • apps/carrier/src-tauri/src/lib.rs
  • scripts/ts-suites.mjs

Comment on lines +91 to +94
# Retry: this is the only apt-get in any workflow here, and a single transient mirror
# failure would block merge on a PR that merely touched packages/contracts/**.
for i in 1 2 3; do sudo apt-get update && break || sleep 5; done
sudo apt-get install --no-install-recommends \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- workflow snippet ---\n'
if [ -f .github/workflows/ts-suites.yml ]; then
  nl -ba .github/workflows/ts-suites.yml | sed -n '1,140p'
else
  echo 'missing .github/workflows/ts-suites.yml'
fi

printf '\n--- bash behavior probe for retry pattern ---\n'
bash -c '
set -e
for i in 1 2 3; do
  test "$i" != 3 || (echo "i=$i"; exit 77)
  false && break || sleep 0
  echo "loop_iteration_ended_i=$i"
done
echo "after_loop_status=$?"
' || echo "script_exited_status=$?"

Repository: Harborline-Software/shipyard

Length of output: 257


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workflow snippet ---'
if [ -f .github/workflows/ts-suites.yml ]; then
  nl -ba .github/workflows/ts-suites.yml | sed -n '1,160p'
else
  echo 'missing .github/workflows/ts-suites.yml'
fi

printf '%s\n' ''
printf '%s\n' '--- bash behavior probe for retry pattern ---'
bash -c '
set -e
for i in 1 2 3; do
  test "$i" != 3 || (echo "i=$i"; exit 77)
  false && break || sleep 0
  echo "loop_iteration_ended_i=$i"
done
echo "after_loop_status=$?"
' || echo "script_exited_status=$?"

printf '%s\n' ''
printf '%s\n' '--- behavioral pattern probe: failed apt with exit 65 ---'
tmp="$(mktemp)"
cat > "$tmp" <<'BASH'
set -u
failed=0
for i in 1 2 3; do
  failed=$((failed + 1))
  if false; then
    break
  fi
  if [ "$i" -eq 3 ]; then
    echo "apt-get update failed after 3 attempts" >&2
    exit 65
  fi
  sleep 0
done
echo "completed_with_failed_attempts=$failed"
BASH
set -euo pipefail
bash "$tmp" || echo "script_exited_status=$?"
rm -f "$tmp"

Repository: Harborline-Software/shipyard

Length of output: 231


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workflow snippet ---'
if [ -f .github/workflows/ts-suites.yml ]; then
  awk '{printf "%6d  %s\n", NR, $0}' .github/workflows/ts-suites.yml | sed -n '1,180p'
else
  echo 'missing .github/workflows/ts-suites.yml'
fi

printf '%s\n' ''
printf '%s\n' '--- behavioral pattern probe: failed apt with exit 65 ---'
tmp="$(mktemp)"
cat > "$tmp" <<'BASH'
set -u
failed=0
for i in 1 2 3; do
  failed=$((failed + 1))
  if false; then
    break
  fi
  if [ "$i" -eq 3 ]; then
    echo "apt-get update failed after 3 attempts" >&2
    exit 65
  fi
  sleep 0
done
echo "completed_with_failed_attempts=$failed"
BASH
set -euo pipefail
bash "$tmp" || echo "script_exited_status=$?"
rm -f "$tmp"

printf '%s\n' ''
printf '%s\n' '--- installed commands list ---'
for cmd in awk sed cat bash diff echo; do
  command -v "$cmd" || echo "$cmd not found"
done

Repository: Harborline-Software/shipyard

Length of output: 8869


issue [blocking]: Fail closed when apt retries run out.

apt-get update && break || sleep 5 returns success after the third failed update because sleep is the final command. The workflow then continues with failed package indexes. Make the third failure exit non-zero.

Proposed retry fix
-          for i in 1 2 3; do sudo apt-get update && break || sleep 5; done
+          for i in 1 2 3; do
+            if sudo apt-get update; then
+              break
+            fi
+            if [ "$i" -eq 3 ]; then
+              echo "apt-get update failed after 3 attempts" >&2
+              exit 1
+            fi
+            sleep 5
+          done
📝 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
# Retry: this is the only apt-get in any workflow here, and a single transient mirror
# failure would block merge on a PR that merely touched packages/contracts/**.
for i in 1 2 3; do sudo apt-get update && break || sleep 5; done
sudo apt-get install --no-install-recommends \
# Retry: this is the only apt-get in any workflow here, and a single transient mirror
# failure would block merge on a PR that merely touched packages/contracts/**.
for i in 1 2 3; do
if sudo apt-get update; then
break
fi
if [ "$i" -eq 3 ]; then
echo "apt-get update failed after 3 attempts" >&2
exit 1
fi
sleep 5
done
sudo apt-get install --no-install-recommends \
🤖 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/ts-suites.yml around lines 91 - 94, Update the apt-get
retry loop in the workflow so exhausting all three attempts exits non-zero
instead of succeeding because sleep is the final command. Preserve the
five-second delay between attempts, but explicitly fail after the final
unsuccessful apt-get update before continuing to package installation.

Source: Path instructions

Comment on lines +94 to +99
sudo apt-get install --no-install-recommends \
libwebkit2gtk-4.1-dev \
libxdo-dev \
libssl-dev \
libayatana-appindicator3-dev \
librsvg2-dev

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Workflow context:"
if [ -f .github/workflows/ts-suites.yml ]; then
  nl -ba .github/workflows/ts-suites.yml | sed -n '1,180p'
else
  echo ".github/workflows/ts-suites.yml not found"
fi

echo
echo "Search for apt-get install in workflows:"
rg -n "apt-get install|apt install|pnpm ts-suites|paths-filter" .github/workflows -S || true

echo
echo "Check whether sudo pip install has a non-interactive flag nearby (for related install context):"
rg -n "sudo apt-get install --no-install-recommends|sudo pip install|DEBIAN_FRONTEND|wget -nv --no-check-certificate" .github/workflows/ts-suites.yml -S || true

Repository: Harborline-Software/shipyard

Length of output: 224


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find workflow file:"
find .github/workflows -maxdepth 1 -name 'ts-suites.yml' -print 2>/dev/null || true

echo
echo "Workflow context using sed:"
if [ -f .github/workflows/ts-suites.yml ]; then
  sed -n '1,180p' .github/workflows/ts-suites.yml
else
  echo ".github/workflows/ts-suites.yml not found"
fi

echo
echo "Search for apt-get install in workflows:"
grep -RInE "apt-get install|apt install|pnpm ts-suites|paths-filter" .github/workflows || true

echo
echo "Check non-interactive flags nearby:"
grep -RInE "DEBIAN_FRONTEND|wget -nv --no-check-certificate|sudo apt-get install --no-install-recommends|sudo pip install" .github/workflows/ts-suites.yml .github/workflows 2>/dev/null || true

Repository: Harborline-Software/shipyard

Length of output: 9455


🌐 Web query:

Tauri v2 CI prerequisites debian ubuntu apt-get install -y libwebkit2gtk-4.1-dev libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev

💡 Result:

To set up a development environment for Tauri v2 on Debian or Ubuntu, you must install the required system dependencies [1]. The official documentation recommends the following command [1]: sudo apt update sudo apt install libwebkit2gtk-4.1-dev \ build-essential \ curl \ wget \ file \ libxdo-dev \ libssl-dev \ libayatana-appindicator3-dev \ librsvg2-dev Key points regarding these prerequisites: 1. WebKitGTK 4.1: Tauri v2 requires libwebkit2gtk-4.1-dev [1][2]. This dependency is available in modern distributions such as Debian Bookworm (12+) and Ubuntu 22.04+ [3][4]. Attempting to build on older distributions that do not provide this package will result in build failures [5]. 2. libxdo-dev: This library is necessary for enabling features like Cut, Copy, Paste, and Select All in menus [6][7]. While older versions of documentation may have omitted it, it is currently included in the official prerequisite list [1][6]. 3. Build Environment: Because system library versions (specifically glibc) can impact compatibility, it is recommended to build your application on a distribution version that matches your target, or to use Docker/GitHub Actions to maintain a consistent environment [3][8]. Always ensure your system package information is updated via sudo apt update before attempting to install these packages [1][4].

Citations:


🌐 Web query:

Tauri v2 tests webdriver CI apt-get install -y libwebkit2gtk-4.1-dev libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev ubuntu-22.04

💡 Result:

For Tauri v2 WebDriver testing in a Linux CI environment (specifically Ubuntu 22.04), you must install specific system dependencies to support the Tauri application's runtime and the tauri-driver tool [1][2]. To set up your CI environment, use the following apt-get installation command [1]: sudo apt-get update && sudo apt-get install -y \ libwebkit2gtk-4.1-dev \ libayatana-appindicator3-dev \ webkit2gtk-driver \ xvfb Explanation of the key components: - libwebkit2gtk-4.1-dev: Required as the underlying WebView engine for Tauri v2 [3][4][5]. - libayatana-appindicator3-dev: Often necessary for system tray and notification support in Tauri apps [6][3]. - webkit2gtk-driver: The native WebDriver server for Linux (WebKitGTK) that tauri-driver uses to interact with your application [1][2][7]. - xvfb: A virtual framebuffer X server commonly required in CI environments to run GUI applications (or WebViews) in "headless" mode without a physical display [1]. While your query mentioned libxdo-dev, libssl-dev, and librsvg2-dev (which are standard build-time dependencies for Tauri applications [6]), they are not explicitly listed in the minimal CI pipeline for WebDriver testing provided by official Tauri v2 documentation [1]. However, if your application requires these for building, you may include them in your installation step [6]. Ensure that the tauri-driver binary is installed in your CI environment as well, typically via cargo install tauri-driver --locked [2][7].

Citations:


🌐 Web query:

apt-get install without -y will prompt confirmation prompt

💡 Result:

To run apt-get install or other commands without being stopped by confirmation prompts, you can use the following methods depending on the type of prompt you are encountering. Basic Confirmation Prompts For the standard "Do you want to continue [Y/n]?" prompt, use the --yes (or -y) flag [1][2]: sudo apt-get install -y <package_name> Handling Configuration and Interactive Prompts Some packages require additional input during installation (e.g., configuring services). To automate these and force the system to use default answers, set the DEBIAN_FRONTEND environment variable to noninteractive [3][4]: sudo DEBIAN_FRONTEND=noninteractive apt-get install -y <package_name> Advanced Configuration Management If an installation stops due to configuration file conflicts, you can instruct the underlying dpkg utility to keep existing files or use default options using the --option (or -o) flag [4][5]: sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' <package_name> Additional Automation Techniques - Pre-seeding: For more complex packages that require specific answers, you can use debconf-set-selections to pre-seed the desired responses into the debconf database before running the installation [6]. - Ensure apt-utils is installed: If non-interactive mode is still prompting, ensure the apt-utils package is installed on the system, as it is often required for proper non-interactive operation [7]. Top results: [3][1][7][4][6][5]

Citations:


issue [blocking]: Make the Tauri prerequisite installation non-interactive.

apt-get install can prompt for sudo apt-get install --no-install-recommends, which stops the required CI check before pnpm ts-suites runs. Add the non-interactive flag to the install command.

Proposed install change
-          sudo apt-get install --no-install-recommends \
+          sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
📝 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
sudo apt-get install --no-install-recommends \
libwebkit2gtk-4.1-dev \
libxdo-dev \
libssl-dev \
libayatana-appindicator3-dev \
librsvg2-dev
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
libwebkit2gtk-4.1-dev \
libxdo-dev \
libssl-dev \
libayatana-appindicator3-dev \
librsvg2-dev
🤖 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/ts-suites.yml around lines 94 - 99, Update the
prerequisite installation command in the workflow step to include apt-get’s
non-interactive option while preserving the existing package list and
no-recommends behavior, so the Tauri dependencies install without prompting
before pnpm ts-suites runs.

Comment thread scripts/ts-suites.mjs
Comment on lines +141 to +146
run(
'test Carrier Tauri Rust host',
'cargo',
['test', '--manifest-path', 'apps/carrier/src-tauri/Cargo.toml'],
'.',
{ TAURI_CONFIG: '{"bundle":{"externalBin":[]}}' },

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '^scripts/ts-suites\.mjs$|^apps/carrier/src-tauri/(Cargo\.toml|Cargo\.lock)$|^_shared/engineering/code-review-policy\.yaml$|\.github/workflows|package\.json|pnpm-lock' || true

echo
echo "== ts-suites around command =="
if [ -f scripts/ts-suites.mjs ]; then
  nl -ba scripts/ts-suites.mjs | sed -n '110,175p'
fi

echo
echo "== references to test Carrier / Cargo.lock =="
rg -n "test Carrier|Cargo.lock|cargo test|cargo update|src-tauri/Cargo.toml|cargo --locked|--locked" .github scripts apps/carrier/src-tauri -S || true

echo
echo "== Cargo manifest deps =="
if [ -f apps/carrier/src-tauri/Cargo.toml ]; then
  nl -ba apps/carrier/src-tauri/Cargo.toml | sed -n '1,140p'
fi

echo
echo "== Cache/dependency cache references =="
rg -n "cache.*Cargo|cargo-cache|target/.cargo|Cargo.lock|actions/cache" .github scripts -S || true

echo
echo "== package scripts =="
for f in package.json pnpm-workspace.yaml; do
  [ -f "$f" ] && nl -ba "$f" | sed -n '1,160p'
done

Repository: Harborline-Software/shipyard

Length of output: 2383


🌐 Web query:

Cargo test --locked documentation missing Cargo.lock will fail exit code

💡 Result:

For most Cargo commands that utilize the --locked flag—including cargo test—the presence of a Cargo.lock file is strictly required [1][2][3]. If the lock file is missing, Cargo will exit with an error [1][2]. The official Cargo documentation explicitly states that when --locked is used, Cargo asserts that the exact same dependencies and versions are used as when the existing Cargo.lock file was originally generated [1][4]. Consequently, Cargo will exit with an error if the lock file is missing or if the current dependency resolution requires updating the lock file [1][2][4]. While this behavior is consistent across most commands (such as cargo test, cargo build, and cargo update), there have been historical discrepancies and discussions regarding specific edge cases, particularly with cargo install, where behaviors or documentation may occasionally appear inconsistent [5][6]. However, for standard project operations like cargo test, the requirement is definitive: a missing Cargo.lock file results in a failure [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ts-suites.mjs size and command section =="
wc -l scripts/ts-suites.mjs
sed -n '120,155p' scripts/ts-suites.mjs

echo
echo "== Cargo files existing/tracked =="
for f in scripts/ts-suites.mjs apps/carrier/src-tauri/Cargo.lock apps/carrier/src-tauri/Cargo.toml; do
  if [ -f "$f" ]; then
    echo "-- $f --"
    sed -n '1,180p' "$f"
  else
    echo "-- missing: $f --"
  fi
done

echo
echo "== cargo test references =="
rg -n "cargo test|Cargo.lock|--locked|src-tauri/Cargo.toml|cache.*Cargo|actions/cache" \
  .github/workflows scripts apps/carrier . \
  -g '!**/pnpm-lock.yaml' -g '!**/Cargo.lock' || true

echo
echo "== workflow names referencing ts suites or carrier cargo =="
rg -n "ts-suites|test Carrier|Carrier Tauri|cargo" .github/workflows scripts/ts-suites.mjs -S || true

Repository: Harborline-Software/shipyard

Length of output: 50384


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ts-suites workflow relevant action setup =="
sed -n '1,145p' .github/workflows/ts-suites.yml

echo
echo "== read-only Cargo lockfile/hashfiles facts =="
python3 - <<'PY'
from pathlib import Path
import re, hashlib, subprocess

root = Path('.')
for path in ["scripts/ts-suites.mjs", ".github/workflows/ts-suites.yml", "apps/carrier/src-tauri/Cargo.toml", "apps/carrier/src-tauri/Cargo.lock", "packages/contracts/rust/Cargo.lock"]:
    p = root / path
    print(f"{p}: exists={p.exists()}")

mjs = root / "scripts/ts-suites.mjs"
print("cargo args in scripts/ts-suites.mjs:")
payload = mjs.read_text()
for line in payload.splitlines():
    if "apps/carrier/src-tauri/Cargo.toml" in line:
        print("  ", line.strip())

yml = (root / ".github/workflows/ts-suites.yml").read_text()
action = yml.split("runTsSuites:")[-1].split("  ts-suite")[0]
print("ts-suites action key/hashfiles:")
for line in action.splitlines()[40:100]:
    if "hashFiles" in line or "restore-keys" in line or "cargo" in line:
        print(line)

cargo = (root / "apps/carrier/src-tauri/Cargo.toml").read_text()
direct_names = set()
for m in re.finditer(r'^([a-z0-9_-]+)\s*=\s*\{', cargo, re.M):
    direct_names.add(m.group(1))
lock = (root / "apps/carrier/src-tauri/Cargo.lock").read_text()
for entry in re.finditer(r'\[\[package]]\n', lock):
    start = entry.start()
    block = lock[start:lock.find("\n[[package]]", start + 1) or len(lock)]
    name = re.search(r'^name\s*=\s*"([^"]+)"', block, re.M)
    if name:
        version = re.search(r'^[ ]*version\s*=\s*"([^"]+)"', block, re.M)
        direct = name.group(1) in direct_names
        if version and direct and name.group(1) in ("tauri", "tauri-build", "tauri-plugin-shell", "tauri-plugin-http", "serde_json", "reqwest", "keyring"):
            print("direct workspace dependency:", name.group(1), "version", version.group(1), "direct", direct)
PY

Repository: Harborline-Software/shipyard

Length of output: 7896


issue [blocking]: Pin the Carrier Tauri Cargo test to the committed lockfile.

This required Rust test omits --locked, so Cargo can regenerate dependency selections while apps/carrier/src-tauri/Cargo.lock exists. Add --locked so CI must use the committed dependency graph rather than an updated one.

Proposed command change
-  ['test', '--manifest-path', 'apps/carrier/src-tauri/Cargo.toml'],
+  ['test', '--locked', '--manifest-path', 'apps/carrier/src-tauri/Cargo.toml'],
📝 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
run(
'test Carrier Tauri Rust host',
'cargo',
['test', '--manifest-path', 'apps/carrier/src-tauri/Cargo.toml'],
'.',
{ TAURI_CONFIG: '{"bundle":{"externalBin":[]}}' },
run(
'test Carrier Tauri Rust host',
'cargo',
['test', '--locked', '--manifest-path', 'apps/carrier/src-tauri/Cargo.toml'],
'.',
{ TAURI_CONFIG: '{"bundle":{"externalBin":[]}}' },
🤖 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 `@scripts/ts-suites.mjs` around lines 141 - 146, Update the `run` invocation
for `test Carrier Tauri Rust host` to include Cargo’s `--locked` flag alongside
the existing test arguments, ensuring the command uses the committed
`apps/carrier/src-tauri/Cargo.lock` dependency graph.

Source: Path instructions

Kept HEAD's new step-5 addition (compile + cargo test the Carrier Tauri
Rust host, with TAURI_CONFIG externalBin suppressed so the run does not
need the platform sidecar) plus its explanatory comment, positioned
right after the contracts Rust projection test as authored. Took
origin/main's package rename of the four test() labels and filter
targets from shipyard/* to harborline-software/* (an unrelated rename
that landed on main after this branch forked). The workflow file
(.github/workflows/ts-suites.yml) auto-merged cleanly: HEAD's raised
timeout, apt-get prerequisites and cargo cache steps combined with
origin/main's added ui-react/ui-adapters-react path-filter entries.

For verification, a fresh pnpm install --frozen-lockfile showed no
lockfile drift, node --check on the merged script found no syntax
error, and a label-by-label diff confirmed every run() step present on
origin/main is still present post-merge with exactly one addition. The
new step's own command was then run directly — cargo test
--manifest-path apps/carrier/src-tauri/Cargo.toml with TAURI_CONFIG
set to disable externalBin — which compiles the full Tauri host and
passes 45 of 47 tests (2 intentionally ignored, desktop-only),
including the protocol contract test that consumes the complete
generated command inventory. The unaffected contracts Rust projection
suite also still passes (2/2), as a sanity check on the earlier step.

Refs: shipyard#3541
@ctwoodwa
ctwoodwa merged commit 34af21d into main Aug 4, 2026
49 checks passed
@ctwoodwa
ctwoodwa deleted the fix/3533-tauri-ci branch August 4, 2026 10:11
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