Skip to content

fix(watchdog): stop the script dying silently under bash -e - #2544

Merged
Hugo0 merged 1 commit into
mainfrom
fix/watchdog-bash-e
Jul 28, 2026
Merged

fix(watchdog): stop the script dying silently under bash -e#2544
Hugo0 merged 1 commit into
mainfrom
fix/watchdog-bash-e

Conversation

@Hugo0

@Hugo0 Hugo0 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Third fix for this watchdog, and the root cause was the same all three times: I verified in an environment that wasn't the one it runs in.

The bug

The last run produced no output at all — nothing between the env block and exit 1:

  RUN_URL: https://github.com/.../actions/runs/30352752517
  ##[endgroup]
  ##[error]Process completed with exit code 1.

GitHub runs the step as bash -e {0}. With set -o pipefail, any non-zero anywhere kills the script at that line with no message. It died on the first loop iteration: grep returns 1 when a commit touched no mirrored paths — a normal answer, not an error — and d9a33de is exactly that case.

Reproduced in isolation:

$ bash -e repro.sh
exit=1          # and the line after never runs

The fix

set +e, explicitly and with the reasoning in a comment. Every branch in this script already decides for itself and reports why; -e contributes nothing except the ability to die mid-check without saying so.

Also filter LIVE/TIP/EXPECTED through a 40-hex check — on failure gh prints its error body to stdout, which was landing in those vars and being compared as though it were a sha (tip={ "m). Now a broken call resolves to empty and trips the labelled DEGRADED branch.

Verification — the check I should have run from the start

Extracted the step from the YAML and executed it under bash -e against the real APIs, both paths:

healthy:       expected mono@0b0740a | mirrored @0b0740a | peanut-content c268e5d | live c268e5d
               production content is current.                        EXIT=0  (silent)

broken token:  ::error::WATCHDOG DEGRADED — could not evaluate the pipeline
               (expected=0b0740a mirrored=none live=c268e5d tip=)     EXIT=1

bash -n and dry-running the logic in my own shell both passed every time and caught none of this, because neither has -e set.

Summary by CodeRabbit

  • Bug Fixes
    • Improved content pipeline monitoring reliability when checking commit synchronization.
    • Prevented API errors or malformed commit values from triggering incorrect “stuck” alerts.
    • Ensured watchdog checks continue handling failures visibly instead of terminating unexpectedly.

Third fix, same root cause each time: I verified in an environment that was not
the one it runs in.

GitHub runs the step as `bash -e {0}`. Combined with `set -o pipefail` that
means any non-zero anywhere kills the script at that line with NO output — a red
run and an empty log, which is the least debuggable possible failure. It hit
twice: the Actions-API 403, then `grep` returning 1 because a commit touched no
mirrored paths. grep exiting 1 on no-match is a normal answer, not an error, and
it was the very first loop iteration — so the last run produced literally
nothing between the env block and `exit 1`.

`set +e` explicitly. Every branch here decides for itself and reports why; `-e`
adds nothing but the ability to die mid-check without saying so.

Also filter LIVE/TIP/EXPECTED through a 40-hex check. On failure `gh` prints its
error body to stdout, which was landing in those vars and being compared as if
it were a sha; now a broken call resolves to empty and trips the labelled
DEGRADED branch instead.

Verified by extracting the step and running it under `bash -e` against the real
APIs, both paths: healthy -> "production content is current", exit 0, silent;
broken token -> one WATCHDOG DEGRADED line, exit 1. That is the check I should
have been running from the first commit.
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Jul 28, 2026 11:05am

Request Review

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The watchdog now continues through expected command failures and validates API-derived commit SHAs before deciding whether content is stuck or degraded.

Changes

Watchdog fault tolerance

Layer / File(s) Summary
Shell and SHA validation
.github/workflows/content-pipeline-watchdog.yml
The watchdog explicitly disables set -e for non-critical checks and filters LIVE, TIP, and EXPECTED to valid 40-hex commit SHAs before comparison.

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

Possibly related PRs

🚥 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 matches the main change: making the watchdog script survive bash -e instead of exiting silently.
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/watchdog-bash-e

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 6309.47 → 6309.47 (0)
Findings: 0 net (+0 new, -0 resolved)

@github-actions

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2234 ran, 0 failed, 0 skipped, 38.2s

📊 Coverage (unit)

metric %
statements 61.7%
branches 45.1%
functions 51.0%
lines 62.1%
⏱ 10 slowest test cases
time test
3.7s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.3s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.4s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in validateInviteCode body
0.4s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.2s src/utils/__tests__/url.utils.test.ts › uses the public BASE_URL in Capacitor, not the localhost WebView origin
0.2s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › keeps stickers off the username pill (final pass respects the keep-out)
0.2s src/utils/__tests__/demo-balance.test.ts › keeps a spent-down balance across a cold start within the TTL
0.2s src/utils/__tests__/demo-balance.test.ts › auto-refills a wallet older than the TTL on cold start
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

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

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/content-pipeline-watchdog.yml:
- Around line 52-60: Update the watchdog script’s `gh` result handling so every
call validates its exit status before downstream use, including `TIP_AT`, `NUM`,
`PR_SHA`, and `CI`; clear invalid outputs rather than treating error text as
data. Validate the timestamp before computing `AGE`, ensure invalid or unset
values cannot trigger `set -u`, and route all such failures to the existing
`WATCHDOG DEGRADED` outcome.
🪄 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

Run ID: 0d3898dc-25d9-403a-995a-b97536b76aee

📥 Commits

Reviewing files that changed from the base of the PR and between d439dd4 and dad34d2.

📒 Files selected for processing (1)
  • .github/workflows/content-pipeline-watchdog.yml

Comment on lines +52 to +60
# `set +e` is deliberate, and `-e` here is actively harmful.
# GitHub runs this step as `bash -e {0}`, which combined with
# pipefail means ANY non-zero anywhere kills the script at that
# line with no output at all — a red run and an empty log. It bit
# twice: a 403 from the Actions API, then a `grep` with no match
# inside the mirrored-paths filter (grep exits 1 on no-match, which
# is a normal answer, not an error). This script decides everything
# explicitly below; it must never die silently mid-check.
set +e

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Handle every failed gh result before downstream use.

set +e allows the script to continue, but only LIVE, TIP, and EXPECTED are sanitized. A failed gh call can still place error text in TIP_AT; line 135 then passes it to date, potentially leaving AGE invalid or unset, and the later $AGE expansion can abort under set -u before WATCHDOG DEGRADED is reported. Preserve each command’s exit status and clear or validate outputs such as TIP_AT, NUM, PR_SHA, and CI; invalid timestamps should also mark the watchdog degraded.

Also applies to: 94-102

🤖 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/content-pipeline-watchdog.yml around lines 52 - 60, Update
the watchdog script’s `gh` result handling so every call validates its exit
status before downstream use, including `TIP_AT`, `NUM`, `PR_SHA`, and `CI`;
clear invalid outputs rather than treating error text as data. Validate the
timestamp before computing `AGE`, ensure invalid or unset values cannot trigger
`set -u`, and route all such failures to the existing `WATCHDOG DEGRADED`
outcome.

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