Skip to content

feat(motd): add uwelcome + update umotd - #815

Open
theMimolet wants to merge 25 commits into
projectbluefin:mainfrom
theMimolet:feature/update-motd
Open

feat(motd): add uwelcome + update umotd#815
theMimolet wants to merge 25 commits into
projectbluefin:mainfrom
theMimolet:feature/update-motd

Conversation

@theMimolet

@theMimolet theMimolet commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Good day 👋

PR pipeline

opened ──▶ review ──▶ approved ──▶ merged
                    [lgtm]      auto-merge
                                when CI green

Add do-not-merge at any time to block automation.
/approve or lgtm from a maintainer triggers merge queue.

What does this change?

It replaces the old unified umotd config file by the two new ones for umotd and uwelcome.

Why?

To update them and make them work together.
(also so you can use umotd in other programs as it only prints translated messages)

Checklist

  • just check passes
  • pre-commit run --all-files passes
  • PR title follows Conventional Commits (fix:, feat:, chore:, etc.)

Summary by CodeRabbit

  • New Features
    • Added support for additional desktop/profile tags, including Bluefin and GNOME.
    • Updated the welcome/MOTD experience to use uwelcome toggle, including updated greeting structure and MOTD command grouping.
  • Bug Fixes
    • Refreshed welcome and MOTD behavior to improve consistency of the displayed greeting/prompt.
  • Chores / Security
    • Updated the container build to compile and ship uwelcome alongside umotd, and refreshed bundled udev asset verification.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds system tags, updates uwelcome configuration, builds uwelcome alongside umotd, and switches profile and task integration to uwelcome.

Changes

System Welcome Integration

Layer / File(s) Summary
Update welcome configuration
system_files/shared/etc/ublue-os/tags.json, system_files/shared/etc/uwelcome/config.json
Adds bluefin and gnome tags, changes the toggle command to uwelcome toggle, relocates the greeting prefix, and replaces prior MOTD settings with motd.commands: ["umotd"].
Build and install welcome utilities
Containerfile
Updates pinned umotd build inputs, adds a pinned uwelcome build stage, preserves image setup and udev verification, and copies both binaries into the output.
Update welcome entry points
system_files/shared/etc/profile.d/uwelcome.sh, system_files/shared/usr/share/ublue-os/just/default.just
Switches the profile script to invoke uwelcome and removes the obsolete toggle-user-motd task.

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

Suggested reviewers: ahmedadan, inffy, ledif, renner0e, castrojo

Poem

A rabbit hops through tags of blue,
And welcomes fresh commands anew,
Two tools now build and land just right,
The MOTD starts its morning light. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, conventional, and accurately summarizes the main change.
Description check ✅ Passed The description follows the template structure and clearly explains what changed and why.
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

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.

theMimolet and others added 2 commits July 15, 2026 18:19
…pace

Assisted-by: Claude Sonnet 4.6 via GitHub Copilot
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@castrojo
castrojo added this pull request to the merge queue Jul 19, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 19, 2026
castrojo added a commit that referenced this pull request Jul 19, 2026
## Root cause

The merge queue has silently ejected every entry since 2026-07-06 (PRs
#802, #815, #817, #824, #825 — nothing has merged in two weeks).
common#660 added `if: github.event_name != 'merge_group'` to the
**Export image for scanning** and **Scan image for CVEs** steps, but
left these on `!= 'pull_request'` (which matches merge_group):

- **Promote image to root storage** — reads `/tmp/scan-image.tar`, which
the skipped export never produced: `open /tmp/scan-image.tar: no such
file or directory` ([failing merge-group
run](https://github.com/projectbluefin/common/actions/runs/29701193456))
- **Push image / Write digest / Upload digest / manifest job** — these
would push per-arch tags and re-sign `:latest` from a throwaway queue
ref if the promote step hadn't failed first

## Fix

Merge queue lane is now build-only: every push-lane step carries
`github.event_name != 'pull_request' && github.event_name !=
'merge_group'`. The queue verifies the combined commit builds; pushing,
digests, manifests, and signing stay exclusive to the push/dispatch
lanes.

Self-healing: merge_group runs execute the workflow from the merged ref,
so this PR's own queue run uses the fixed YAML.

## Skill update (same PR)

`docs/skills/ci-tooling.md` merge_group section extended with the
build-only rule and the artifact-lane tracing checklist.

## Validation

- actionlint + full pre-commit: pass
- `just check`: pass

Unblocks #824 (MIME defaults) and #825 (game-devices-udev checksum),
plus the stalled Renovate queue.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Prevented merge queue builds from attempting image promotion,
publishing, manifest creation, or digest uploads when required artifacts
are unavailable.

* **Documentation**
* Added guidance for correctly gating merge queue workflow steps and
tracing artifact availability across build lanes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Jorge Castro <jorge@projectbluefin.io>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@castrojo castrojo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don’t see a ship/install path for uwelcome in this repo. The new config switches the command to , but the image only appears to install/ship
�[38;5;104;1m󱍢 Welcome to�[m�[38;5;104;1m Bluefin�[m

[Ci] �[38;5;104;1m ghcr.io/projectbluefin/dakota:latest �[m

_ Command │ Description
──────────────────────────────────────┼─────────────────────────────────────
�[38;5;104;1m ujust --choose �[m │ List all available commands
�[38;5;104;1m umotd toggle �[m │ Toggle this banner on/off
�[38;5;104;1m ujust bluefin-cli �[m │ Enable terminal bling
�[38;5;104;1m brew help �[m │ Manage command line packages

�[38;5;104;1mSupport indie game preservation and OSS developers!�[m — �]8;id=1207160287;https://patreon.com/hitsave��[1mJoin Hit Save!'s�[m�]8;;�
�]8;id=1207160287;https://patreon.com/hitsave��[1mPatreon�[m�]8;;� �[38;5;104;4m�]8;id=1207160287;https://patreon.com/hitsave�https://patreon.com/hitsave�]8;;��[m

• �]8;id=3541281617;https://issues.projectbluefin.io/��[1mReport an issue�[m�]8;;� �[38;5;104;4m�]8;id=3541281617;https://issues.projectbluefin.io/�https://issues.projectbluefin.io/�]8;;��[m
• �]8;id=3766875054;https://ask.projectbluefin.io/��[1mAsk Bluefin�[m�]8;;� �[38;5;104;4m�]8;id=3766875054;https://ask.projectbluefin.io/�https://ask.projectbluefin.io/�]8;;��[m
• �]8;id=772340340;https://docs.projectbluefin.io/��[1mDocumentation�[m�]8;;� �[38;5;104;4m�]8;id=772340340;https://docs.projectbluefin.io/�https://docs.projectbluefin.io/�]8;;��[m today. Please either wire up uwelcome in the image or keep the config aligned with the actually shipped binary so the new path is functional.

@castrojo castrojo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don’t see a ship/install path for uwelcome in this repo. The new config switches the command to uwelcome toggle, but the image only appears to install/ship umotd today. Please either wire up uwelcome in the image or keep the config aligned with the actually shipped binary so the new path is functional.

@theMimolet

Copy link
Copy Markdown
Contributor Author

tbf I was expecting you to do your magic
but I can try something out

@castrojo

Copy link
Copy Markdown
Contributor

Vanguard Lab Strike Report

Field Value
Workflow common-815-feat-motd-add-uwelcome-update-l7vdh (link: http://192.168.1.102:32746/workflows/argo/common-815-feat-motd-add-uwelcome-update-l7vdh)
Phase Failed
Duration 32m31s
Variants tested bluefin:testing
Suites run smoke

Results

Workflow phase: Failed
Failed nodes: 6 / 15 total (3 succeeded, 6 skipped)

assert-cd node:
  phase: Failed
  message: main: Error (exit code 1)

Relevant log/script excerpt:
  TAG="{{inputs.parameters.containerdisk-tag}}"
  CD_IMAGE="192.168.1.102:30500/bluefin-containerdisk:${TAG}"
  DIGEST=$(skopeo inspect --tls-verify=false --format '{{.Digest}}' \
    "docker://${CD_IMAGE}" 2>/dev/null || echo "")
  if [[ -n "${DIGEST}" ]]; then
    echo "containerdisk ${CD_IMAGE} ready: ${DIGEST}"
  else
    echo "ERROR: containerdisk ${CD_IMAGE} not found in Zot" >&2
    echo "The digest-watch CronWorkflow builds it when GHCR changes." >&2
    echo "Check: argo list -n argo --field-selector metadata.name=~build-cd-sync" >&2
    exit 1
  fi

Outcome:
  - The smoke test lane failed before provisioning a VM.
  - The common suite was skipped because the submitted workflow was configured with suites=smoke only.
  - No motd/uwelcome behavior was exercised.

Evidence collected via

  • argo_get_workflow — workflow phase and node summary
  • argo_logs_workflow — cleanup-orphan-vms log (test pod logs already recycled)
  • kubernetes-mcp-resources_list — VMI state confirmed Ready (n/a: container-only pipeline)
  • VM/orphan check — zero orphaned VMs after teardown

Merge-queue eligibility

  • Argo workflow success: no
  • No regressions vs base image: no / not determined
  • PR mergeable (no conflicts, approvals present): no

Blockers / issues filed

  • The existing Argo run for SHA 18ef56fc3d94 failed at the assert-cd step because bluefin-containerdisk:testing was not present in the cluster-local Zot registry.
  • Only the smoke suite was submitted; the requested common suite was not run.
  • PR has no human approvals (reviewDecision empty, label pr/needs-review) and mergeStateStatus is UNKNOWN.

@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.

🧹 Nitpick comments (1)
Containerfile (1)

35-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use an absolute path for consistency.

The destination path out/shared/... is relative. While this works because the default working directory is /, it is inconsistent with other absolute paths used in this file (e.g., /out/shared/... in line 37). Consider adding a leading slash to ensure correctness if the working directory ever changes.

💡 Proposed refactor
-    install -Dpm0644 "$f" "out/shared/usr/lib/udev/rules.d/71-${f##*/}"; \
+    install -Dpm0644 "$f" "/out/shared/usr/lib/udev/rules.d/71-${f##*/}"; \
🤖 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 `@Containerfile` at line 35, Update the install destination in the
Containerfile command to use the absolute /out/shared/usr/lib/udev/rules.d path,
matching the other absolute output paths while leaving the source handling
unchanged.
🤖 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.

Nitpick comments:
In `@Containerfile`:
- Line 35: Update the install destination in the Containerfile command to use
the absolute /out/shared/usr/lib/udev/rules.d path, matching the other absolute
output paths while leaving the source handling unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ad85393f-41c1-4596-b6f2-40603bf70edf

📥 Commits

Reviewing files that changed from the base of the PR and between 18ef56f and 3ea6b0a.

📒 Files selected for processing (1)
  • Containerfile

@theMimolet

Copy link
Copy Markdown
Contributor Author

It should be good now 👍

@theMimolet
theMimolet requested a review from castrojo July 20, 2026 14:18

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Holding a neutral review — the build wiring looks coherent but I can't confirm the greeting path end-to-end from the diff alone, and there are a couple of concrete gaps worth resolving first:

  1. uwelcome is installed but nothing in the image invokes it. The config moves from etc/umotd/config.json to etc/uwelcome/config.json and the new binary lands at /usr/bin/uwelcome, but on this branch both greeting entrypoints — fish_greeting.fish (function fish_greeting; umotd; end) and profile.d/umotd.sh — still call umotd, not uwelcome. If the new umotd is now "only prints translated messages" (per the PR description) and uwelcome is the front-end that reads etc/uwelcome/config.json, then the greeting needs to switch to uwelcome; otherwise the interactive welcome (commands/links) silently regresses. If instead umotd still delegates internally, please confirm it reads the new etc/uwelcome/ path.

  2. default.just toggle mismatch. umotd toggle in default.just is unchanged, but the new config's toggle command is uwelcome toggle. These should agree.

  3. Supply chain: uwelcome is cloned from the personal github.com/themimolet/uwelcome rather than an org-owned repo (unlike umotd from projectbluefin/motd). Intentional, or should it be migrated under the org before it ships in the image?

Minor: the Containerfile carries a lot of unrelated 2→4-space reindentation churn (the gdu checksum block, etc.). The values are unchanged — CodeRabbit's "refreshed SHA-256" note is a misread of the whitespace — but the noise makes the diff harder to audit; consider splitting it out. CI is green. Happy to approve once the greeting wiring (item 1) is confirmed.

@theMimolet

Copy link
Copy Markdown
Contributor Author

For No. 1 I completely forgot.
For No. 2 I thought it was already the case.
For No. 3 I don't have permission to create repos, so I'm doing what I can 🥲

@theMimolet

Copy link
Copy Markdown
Contributor Author

yeah my bad, i don't know why I didn't think about it
all good now 👍

@theMimolet
theMimolet requested a review from hanthor July 26, 2026 10:27
@castrojo castrojo added 4-review A pull request is awaiting review. and removed area/bling labels Jul 28, 2026

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The uwelcome migration is a good direction, but there are two things to fix before this ships.

1. The fish migration will error on every shell start

system_files/shared/usr/share/fish/vendor_conf.d/fish_greeting.fish:

if test -e ~/.config/no-show-user-motd
    mv ~/.config/no-show-user-motd ~/.config/uwelcome/disabled
end

Two problems, and they compound:

  • There's no 2>/dev/null here, unlike the profile.d version.
  • ~/.config/uwelcome/ is not created anywhere in this PR. If it doesn't exist, mv fails.

So for any user who had opted out via no-show-user-motd, the mv fails, fish prints an mv error, and — because the source file is never removed — it fails again on every new fish shell, forever. The profile.d path has the same missing-directory bug; it just hides the error instead of showing it, which means the opt-out silently never migrates.

Both paths need the directory created first, e.g.:

if test -e ~/.config/no-show-user-motd
    mkdir -p ~/.config/uwelcome
    mv ~/.config/no-show-user-motd ~/.config/uwelcome/disabled 2>/dev/null
end

and the equivalent in uwelcome.sh. Worth confirming against uwelcome upstream that ~/.config/uwelcome/disabled is actually the path it checks, since the whole migration hinges on it.

2. Two tests were commented out rather than fixed

In tests/test_motd_integration.bats:

# @test "uwelcome.sh: does not contain no-show-user-motd check" {
# @test "fish_greeting: does not check no-show-user-motd (opt-out delegated to uwelcome)" {

These were live assertions in test_umotd_integration.bats and are now dead. I understand why — the migration shim does reference no-show-user-motd, so they'd fail as written. But leaving them commented out means the file's own header comment ("Neither profile.d nor fish_greeting should check for that file or gate the uwelcome invocation") no longer describes the code, and nothing enforces the shim's shape.

Please either delete them and update the header comment to describe the migration as it actually is, or rewrite them to assert what you now want — e.g. that the reference appears only inside the migration block and that uwelcome is invoked unconditionally afterward. A commented-out test is the one outcome that leaves no record of which it was.

Minor

  • tests/test_umotd_integration.bats also dropped the three toggle-user-motd recipe tests along with the recipe itself. That's consistent (the recipe moved to uwelcome toggle in the config JSON), but users with muscle memory for ujust toggle-user-motd now get "recipe not found" with no pointer. Consider keeping a stub recipe that execs uwelcome toggle.
  • The Containerfile reindentation is a large share of the diff and makes the substantive uwelcome-build-stage addition harder to spot. Not worth re-rolling for, just noting for next time.

Generated by Claude Code

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Following up my earlier review with actual patches — the two mkdir -p suggestions are click-to-apply, and the third replaces one of the commented-out tests with one that pins the bug.

I verified the failure against the branch rather than reading it off the diff: ~/.config/uwelcome/ is not created by anything in this PR, so on a machine where uwelcome has never written its config dir, the mv fails in both shells. The fish path shows the error every shell start; the bash path swallows it and silently leaves the user opted in despite their earlier opt-out.


Generated by Claude Code

Comment thread system_files/shared/usr/share/fish/vendor_conf.d/fish_greeting.fish
Comment thread system_files/shared/etc/profile.d/uwelcome.sh
Comment thread tests/test_motd_integration.bats Outdated
@theMimolet

Copy link
Copy Markdown
Contributor Author

Thanks for the fixes and tests, I didn't think about that
I restored the spaces by hand (i'm rather curious on which formatter you use)

As for the supply chain issue you mentioned a while back now, I've invited Ahmed and Jorge on the repos and so they'll be able to transfer them whenever.

@ahmedadan

Copy link
Copy Markdown
Contributor

Thanks for the fixes and tests, I didn't think about that I restored the spaces by hand (i'm rather curious on which formatter you use)

As for the supply chain issue you mentioned a while back now, I've invited Ahmed and Jorge on the repos and so they'll be able to transfer them whenever.

I can help, can you go to settings and in the danger zone tell me if you can transfer ownership to the org? I don't have repository permissions to allow me to move them via GitHub.

@theMimolet

Copy link
Copy Markdown
Contributor Author

I can't transfer them either, I don't have any permissions in projectbluefin
image

@ahmedadan

Copy link
Copy Markdown
Contributor

I can't transfer them either, I don't have any permissions in projectbluefin

You'll need to give me more broad repository access then? I don't see the danger zone at all.

@theMimolet

Copy link
Copy Markdown
Contributor Author

I am probably missing something but I don't see how I could (?)
Otherwise I might need to transfer the repos to you first
image

@ahmedadan

Copy link
Copy Markdown
Contributor

Can you try inviting me as an admin?

@ahmedadan

Copy link
Copy Markdown
Contributor

I moved them both, thanks again for all the work here @theMimolet

@theMimolet

Copy link
Copy Markdown
Contributor Author

Thanks a lot !
I observed there's no role management for personal repos, so this was the best solution

@theMimolet
theMimolet requested a review from hanthor July 31, 2026 19:20
@theMimolet
theMimolet requested review from a team and repires as code owners July 31, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4-review A pull request is awaiting review. blocked Work is blocked on human input or an external dependency.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants