Skip to content

fix(ci): run macdeployqt to bundle QML module plugins on macOS - #292

Merged
fernandotonon merged 3 commits into
masterfrom
fix/macos-bundle-qml
Apr 17, 2026
Merged

fix(ci): run macdeployqt to bundle QML module plugins on macOS#292
fernandotonon merged 3 commits into
masterfrom
fix/macos-bundle-qml

Conversation

@fernandotonon

@fernandotonon fernandotonon commented Apr 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Run macdeployqt on the macOS app bundle after the manual framework/QML module copy step so Qt can discover QML imports and bundle the missing module plugins (Controls, Layouts, Dialogs, Effects, Templates, NativeStyle, ...)
  • Fixes: installed Homebrew bundles from 2.x releases had a blank Inspector panel and the Material editor list failed to open. Source builds were unaffected because the developer's Qt installation resolved the plugins directly.

Root cause

Our manual cp -R .../qml/QtQml .../PlugIns/qml/ only copies the top-level QtQml and QtQuick trees. QQuickWidget loads QtQuick.Controls, QtQuick.Layouts, QtQuick.Dialogs, QtQuick.Effects, QtQuick.Templates, QtQuick.NativeStyle, etc. at runtime — those module plugins and their backing QtQuickControls2*.framework dylibs were missing from installed bundles.

macdeployqt -qmldir=<workspace>/qml scans our QML source for imports and pulls in every missing module plugin plus its framework, and also fixes up rpaths/install_names.

Test plan

  • Reproduced the missing-plugin state locally by running the manual CI copy commands against a clean QtMeshEditor.app — only QtQml and QtQuick appeared under Contents/PlugIns/qml/
  • Ran the new macdeployqt invocation against the same bundle — Contents/PlugIns/qml/ now includes QtQuick/{Controls,Dialogs,Effects,Layouts,Templates,NativeStyle,Window,Shapes,...} and Contents/Frameworks/ includes the matching QtQuickControls2*.framework dylibs
  • Watch CI: macOS build job completes successfully
  • Post-merge: cut a patch release and verify the Homebrew-installed bundle renders the Inspector panel and opens the Material editor list

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Enhanced macOS application packaging in the build workflow to ensure all required QML modules are properly bundled with the application during deployment.

The macOS CI previously did manual framework and QML module copying, but
missed the module plugins QQuickWidget needs at runtime (Controls,
Layouts, Dialogs, Effects, Templates, NativeStyle). Installed bundles
rendered the inspector panel blank and the material editor list would
not open.

macdeployqt scans the qml/ source tree for imports and pulls in the
missing module plugins plus their backing frameworks.

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

coderabbitai Bot commented Apr 17, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@fernandotonon has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 37 minutes and 56 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 37 minutes and 56 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 626e98ef-ade2-462b-b5f1-bc8c68cef8ce

📥 Commits

Reviewing files that changed from the base of the PR and between 07b2c0b and 37f6748.

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

Walkthrough

A macOS packaging step was added to the deploy workflow that conditionally runs macdeployqt to bundle Qt QML modules into the built application. The step references the Qt installation path and QML directory, with output capture and graceful error handling.

Changes

Cohort / File(s) Summary
macOS QML Bundling
.github/workflows/deploy.yml
Added conditional macdeployqt step to bundle missing Qt QML module plugins for macOS app deployment with verbose output and continued workflow on warnings or tool unavailability.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A hop, skip, and Qt away,
macdeployqt saves the day!
QML bundled tight in the app so bright,
Mac releases now take flight.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: running macdeployqt to bundle QML module plugins on macOS, which directly addresses the root cause of the missing plugins issue.
Description check ✅ Passed The pull request description is well-structured with Summary, Root cause analysis, and Test plan sections that align with the template's intent, providing detailed technical context and verification steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/macos-bundle-qml

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 and usage tips.

@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

🧹 Nitpick comments (1)
.github/workflows/deploy.yml (1)

1519-1519: Optional: extract the macdeployqt invocation into its own step.

The new block is appended inside the Copy Qt libs to app folder step, which makes the step name a little misleading (it now also bundles QML modules and adjusts rpaths via macdeployqt). A dedicated step (e.g., Run macdeployqt to bundle QML modules) would read better in the Actions UI and make failures easier to localize — no functional change needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy.yml at line 1519, The step currently named "Copy Qt
libs to app folder" also runs macdeployqt and adjusts rpaths; split the
macdeployqt invocation into a separate GitHub Actions step (e.g., "Run
macdeployqt to bundle QML modules") so the original step only copies Qt libs and
the new step runs macdeployqt and any rpath/QML bundling commands; update the
workflow to move the macdeployqt commands out of the "Copy Qt libs to app
folder" step and place them in the new step while keeping the same commands and
dependencies, referencing the existing macdeployqt invocation and the "Copy Qt
libs to app folder" step to preserve ordering.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy.yml:
- Around line 1575-1588: The macdeployqt step can place QML imports under
Contents/Resources/qml (mismatching the later qt.conf Qml2Imports = PlugIns/qml)
and its exit status is masked by the pipe to tail; update the job to (1) inspect
the created bundle after running MACDEPLOYQT (referencing MACDEPLOYQT and the
app path used) to list Contents/PlugIns/qml vs Contents/Resources/qml so you can
confirm where newly-added modules landed, (2) fix runtime lookup by either
setting Qml2Imports = Resources/qml in the qt.conf writer or adding
Resources/qml alongside PlugIns/qml or moving/symlinking the modules from
Resources/qml into PlugIns/qml after macdeployqt, and (3) preserve macdeployqt's
exit code by enabling pipefail or capturing $PIPESTATUS (i.e., record
macdeployqt's exit status before piping to tail) so failures are not swallowed.

---

Nitpick comments:
In @.github/workflows/deploy.yml:
- Line 1519: The step currently named "Copy Qt libs to app folder" also runs
macdeployqt and adjusts rpaths; split the macdeployqt invocation into a separate
GitHub Actions step (e.g., "Run macdeployqt to bundle QML modules") so the
original step only copies Qt libs and the new step runs macdeployqt and any
rpath/QML bundling commands; update the workflow to move the macdeployqt
commands out of the "Copy Qt libs to app folder" step and place them in the new
step while keeping the same commands and dependencies, referencing the existing
macdeployqt invocation and the "Copy Qt libs to app folder" step to preserve
ordering.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 452ab132-b2c9-4ce7-ade2-606cc7f6c55f

📥 Commits

Reviewing files that changed from the base of the PR and between 3d629f4 and 07b2c0b.

📒 Files selected for processing (1)
  • .github/workflows/deploy.yml

Comment thread .github/workflows/deploy.yml

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07b2c0b2b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/deploy.yml Outdated
sudo "$MACDEPLOYQT" "${{github.workspace}}/bin/QtMeshEditor.app" \
-qmldir="${{github.workspace}}/qml" \
-verbose=2 \
-no-strip 2>&1 | tail -60 || echo "macdeployqt reported warnings, continuing..."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Do not mask macdeployqt deployment failures

In the macOS Copy Qt libs to app folder step, the macdeployqt command is wrapped with || echo "...continuing", which converts any non-zero exit into a successful step. When macdeployqt fails (for example due to unresolved QML imports or plugin copy/link errors), CI will still publish a bundle, and the app can ship with missing Qt modules despite this fix. This should fail the job (or only ignore explicitly-known benign conditions) so broken bundles are caught during CI.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Addressed in 56326ba — the step now captures macdeployqt's exit code into $rc, prints the tail of the log, and exit $rc on non-zero. A missing macdeployqt binary is also now a hard error.

fernandotonon and others added 2 commits April 17, 2026 11:48
Previously the macdeployqt exit code was masked by the `| tail -60` pipe
and a trailing `|| echo`. A hard failure would still succeed the step
and ship a broken bundle. Capture the exit code explicitly, print the
tail, and exit non-zero on failure.

Also treat a missing macdeployqt binary as a hard error instead of a
warning, since we now depend on it for QML module discovery.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
macdeployqt already adds @executable_path/../Frameworks to the main
binary, so our subsequent install_name_tool -add_rpath fails with
"would duplicate path" and aborts the step (shell runs with -e).

Silence the duplicate errors so the step remains idempotent whether
or not macdeployqt touched the binary first. The dylib loop below
already uses the same pattern.
@sonarqubecloud

Copy link
Copy Markdown

@fernandotonon
fernandotonon merged commit d8d447e into master Apr 17, 2026
19 checks passed
@fernandotonon
fernandotonon deleted the fix/macos-bundle-qml branch April 17, 2026 16:29
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