Skip to content

test: BATS coverage for etc/profile.d/uwelcome.sh — tests/test_uwelcome_profile.bats - #1118

Merged
castrojo merged 3 commits into
mainfrom
quality/test-uwelcome-profile
Sep 23, 2026
Merged

castrojo merged 3 commits into
mainfrom
quality/test-uwelcome-profile

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Test Improvement

Adds BATS coverage for system_files/shared/etc/profile.d/uwelcome.sh, which previously had none.

Closes #1117

Files claimed by this PR:

  • tests/test_uwelcome_profile.bats (new file, 9 tests)
  • Justfile — one added line, bats tests/test_uwelcome_profile.bats, inserted directly after the existing bats tests/test_profile_d.bats line (not at the end of the recipe, to stay clear of common#1064, which appends its test_apps_just.bats line there)

Cluster: login-shell etc/profile.d coverage.

Why

tests/test_profile_d.bats is named generically but covers only caffeinate.sh — its header says so and it defines a single CAFFEINATE_SCRIPT path. Nothing in tests/ referenced uwelcome.sh, even though it is sourced by every login shell on every image built from common.

What is covered

Behaviour in uwelcome.sh Tests
Legacy ~/.config/no-show-user-motd to ~/.config/uwelcome/disabled migration marker present, marker absent (no stray dir created), pre-existing uwelcome/ dir preserved, migration still runs for root
Root skip guard [ "$(id -u)" != "0" ] — exists because the portal lookup can stall the prompt greeting runs as uid 1000, skipped as uid 0
UWELCOME_SHOWN double-greeting guard skipped when already set, runs when empty, and the export is proven by a chained bash -c '. profile; bash profile' asserting exactly one invocation

id and uwelcome are stubbed on PATH in a mktemp -d workdir, matching the mock style already used in tests/test_profile_d.bats and tests/test_bonedigger_report.bats. No network, no root, no systemd.

Verification

  • bats tests/test_uwelcome_profile.bats gives 9/9 pass (bats 1.14.0)
  • Mutation check: deleting the [ "$(id -u)" != "0" ] && guard from uwelcome.sh turns tests 5 and 8 red, confirming the suite actually asserts behaviour rather than passing vacuously.

Explicitly not claimed here

The unit-tests.yml / Justfile test-catalog drift (12 suites in the Justfile that CI never runs, plus fully orphaned tests/test_image_repo.bats) is already tracked by #968 and #1105 and owned by common#1106 — this PR does not touch .github/workflows/unit-tests.yml, tests/test_ujust.bats, tests/test_shared_just.bats, or tests/test_apps_just.bats.


Filed by quality agent (hold-gated mode). Human review required.

— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.78

system_files/shared/etc/profile.d/uwelcome.sh runs in every login shell on
every image but had zero test coverage: tests/test_profile_d.bats covers only
caffeinate.sh, and no other suite references the file.

Adds tests/test_uwelcome_profile.bats (9 tests) covering the three behaviours
the script actually implements:

- legacy ~/.config/no-show-user-motd marker migration to
  ~/.config/uwelcome/disabled, including the no-marker and pre-existing-
  directory cases
- the root skip guard (id -u = 0), which exists so root shells never stall on
  the portal lookup
- the UWELCOME_SHOWN double-greeting guard, including the export that stops a
  chained shell (bash login shell starting fish) from greeting twice

Wired into the Justfile test recipe next to the existing test_profile_d.bats
line. Verified with bats 1.14.0: 9/9 pass, and removing the root guard from
uwelcome.sh turns two of them red.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sec-check[bot] <sec-check[bot]@users.noreply.github.com>
@hivecommons-hive hivecommons-hive Bot added hold Work is intentionally paused. quality Code quality or test-coverage work. testing Test authoring or test infrastructure. agent/quality Filed or owned by the quality agent. hive/hosted-projectbluefin-knuckle-gjvq Routed by the hosted Project Bluefin Hive deployment. labels Sep 13, 2026
@hanthor

hanthor commented Sep 14, 2026

Copy link
Copy Markdown
Member

The tests are sound — I mutation-tested all four behaviours in uwelcome.sh and each is caught by the right test:

drop the root guard                -> not ok 5, 8
drop the UWELCOME_SHOWN guard      -> not ok 6, 7
drop `export UWELCOME_SHOWN`       -> not ok 7
drop `mkdir -p ~/.config/uwelcome` -> not ok 1, 8

Stubbing id is a genuine improvement: all 9 pass as root and as non-root, which the existing file can't claim.

The question is whether this should be a new file. tests/test_motd_integration.bats on main already tests this exact script — it declares the same UWELCOME_PROFILE path and has a "profile.d/uwelcome.sh" section of 8 tests:

1 uwelcome.sh: invokes uwelcome
2 uwelcome.sh: migrates legacy opt-out and still runs uwelcome
3 uwelcome.sh: migration creates uwelcome config dir when absent
4 uwelcome.sh: is a no-op migration when no legacy marker exists
5 uwelcome.sh: migration is idempotent across repeated logins
6 uwelcome.sh: does not gate the uwelcome call on the legacy marker
7 uwelcome.sh: does not call legacy ublue-motd
8 uwelcome.sh: skips invocation if UWELCOME_SHOWN is set

Against that, roughly four of the nine here are restatements: "legacy marker migrates" ≈ 2/3, "no config dir when marker absent" ≈ 4, "runs for a non-root user" ≈ 1, "skipped when UWELCOME_SHOWN is set" ≈ 8.

The genuinely new coverage is the root guard (5), the export/chained-shell case (7), root-still-migrates (8), the empty-string case (9), and preserving an existing uwelcome dir (3). Those are worth having — because the existing file predates the root guard, and its comment is now stale:

# uwelcome is invoked unconditionally; it owns the opt-out decision

That's no longer true for root.

I'd rather see the five new cases folded into test_motd_integration.bats, the stub_id helper adopted there, and that stale comment corrected — one file that tells the whole truth about uwelcome.sh, rather than two that each tell part of it and disagree about whether the invocation is conditional. As filed, this leaves the next reader to work out which file to extend.

Verified: base fbbb193 test_motd_integration.bats 21/21 as non-root (1, 2 and 4 fail as root — pre-existing, because that file doesn't stub id). This branch's new file: 9/9 as both root and non-root. Justfile wiring is correct.


Generated by Claude Code

@hivecommons-hive hivecommons-hive Bot changed the title [quality] test: BATS coverage for etc/profile.d/uwelcome.sh — tests/test_uwelcome_profile.bats test: BATS coverage for etc/profile.d/uwelcome.sh — tests/test_uwelcome_profile.bats Sep 17, 2026
@hivecommons-hive hivecommons-hive Bot added the agent/scanner Filed or owned by the scanner agent. label Sep 17, 2026

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

Ran bats tests/test_uwelcome_profile.bats at head: 9/9 pass. Executes etc/profile.d/uwelcome.sh under a sandboxed HOME with uwelcome stubbed, and covers the legacy-marker migration, the root skip, and the UWELCOME_SHOWN double-greeting guard. Closes the #1117 gap.

Same caveat as #1106/#1138: registered in the Justfile only; unit-tests.yml needs the line added by a human (#1105).

@Danathar Danathar removed the hold Work is intentionally paused. label Sep 21, 2026
@Danathar

Copy link
Copy Markdown
Contributor

Hold removed: this was the Hive's ACMM level gate, which I operate, and the PR has a human approval with CI green. Ready for a maintainer to merge.

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

correctness

  • Tests 5 and 8 can pass vacuously on a real Bluefin host. setup() (tests/test_uwelcome_profile.bats:9-23) never unsets UWELCOME_SHOWN, and the tests "uwelcome is skipped for root" (line 86) and "root still gets the legacy marker migrated" (line 116) don't either. If the bats process inherits UWELCOME_SHOWN=1 from a login shell that already sourced uwelcome.sh — exactly the machines this repo builds — the greeting is skipped by the [ -z "${UWELCOME_SHOWN-}" ] guard, not the root guard, so the PR's mutation claim (deleting the root guard turns 5/8 red) only holds in a clean environment. Fix: unset UWELCOME_SHOWN in setup().

intent-alignment

  • The new suite is only wired into the Justfile (Justfile:26); .github/workflows/unit-tests.yml runs each bats suite as an explicit step and gains no step for test_uwelcome_profile.bats, so CI never executes these tests. The PR body scopes this out deliberately (tracked by #968/#1105/#1106), but until that lands the coverage #1117 asked for is local-only.

style

  • ! called (lines 92, 102, 124) only asserts because it happens to be the last command in each test — bash's errexit ignores !-inverted failures elsewhere. [ ! -f "${WORKDIR}/calls" ] would be robust to future edits.

No findings from: security, docs-currency.

— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.78

unset UWELCOME_SHOWN in setup() so root-guard tests exercise the root
branch instead of passing vacuously when the bats process inherits
UWELCOME_SHOWN=1 from a Bluefin login shell.

Replace '! called' with a not_called helper: errexit ignores failures of
!-inverted commands, so the assertion only held as the final command.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

intent-alignment

  • (low) The new suite is wired into Justfile:26 but not .github/workflows/unit-tests.yml, which enumerates bats suites step-by-step (e.g. lines 72–121) and runs tests/test_profile_d.bats at line 112 without the new file. Until #1106 lands, CI never executes this coverage — it only runs via local just test. The PR body discloses this, but a maintainer merging for "coverage" should know the gate is local-only; adding one workflow step here would close it without touching the drift cleanup.

style

  • (low) stub_id (tests/test_uwelcome_profile.bats:33–39) relies on the unquoted << MOCK heredoc expanding "$1" at generation time, baking the uid literal into the stub. It works, but unlike the uwelcome mock above it (line 13 comment), nothing flags the intentional unquoted delimiter — a future editor quoting 'MOCK' for consistency with tests/test_profile_d.bats:14 would silently break every id-dependent test.

Verified at d2ab58c: suite passes 9/9 locally, and the PR body's mutation claim reproduces (removing the root guard from uwelcome.sh:13 fails exactly tests 5 and 8). Justfile insertion point matches the stated conflict-avoidance placement.

No findings from: correctness, security, docs-currency.

— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.78

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

Re-approved at d2ab58c after the push dismissed my approval of b90f1a8. The one new commit hardens the suite: it unsets UWELCOME_SHOWN inherited from a Bluefin login shell, which would have made both root-guard tests pass vacuously, and replaces ! called with a not_called helper because errexit ignores a failed !-inverted command that is not the last line. Both are correct bats practice. Nine tests, CI green.

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

LGTM. Thorough BATS suite for uwelcome.sh profile behavior and migration.

@castrojo
castrojo added this pull request to the merge queue Sep 23, 2026
Merged via the queue into main with commit ecfad79 Sep 23, 2026
10 checks passed
@castrojo
castrojo deleted the quality/test-uwelcome-profile branch September 23, 2026 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent/quality Filed or owned by the quality agent. agent/scanner Filed or owned by the scanner agent. hive/hosted-projectbluefin-knuckle-gjvq Routed by the hosted Project Bluefin Hive deployment. quality Code quality or test-coverage work. testing Test authoring or test infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[quality] etc/profile.d/uwelcome.sh has zero test coverage — login-shell guard logic untested

4 participants