Skip to content

Claude/cpu guard script dn d8u - #120

Merged
gamblecodezcom merged 4 commits into
mainfrom
claude/cpu-guard-script-DnD8u
Mar 1, 2026
Merged

Claude/cpu guard script dn d8u#120
gamblecodezcom merged 4 commits into
mainfrom
claude/cpu-guard-script-DnD8u

Conversation

@gamblecodezcom

@gamblecodezcom gamblecodezcom commented Mar 1, 2026

Copy link
Copy Markdown
Owner

User description

Summary by Sourcery

Harden Telegram alerting, CPU forensics logging, and redeploy health checks to be more robust and informative while preventing legacy service port conflicts.

New Features:

  • Add MarkdownV2-safe escaping for Telegram alert messages in rw_cpu_guard.
  • Capture full process arguments in 1-second CPU trace logs to avoid truncation.

Enhancements:

  • Switch Telegram alerts to use MarkdownV2 with proper escaping for arbitrary text.
  • Improve redeploy script to stop legacy bot service units that could conflict on the bot port.
  • Enhance health check output formatting to prefer pretty-printed JSON via python3 or jq with graceful fallback.
  • Make service status summary more reliable by distinguishing missing units from inactive ones.

CodeAnt-AI Description

Prevent bot port conflicts during redeploy and record full commands in CPU traces

What Changed

  • Redeploy now stops known legacy bot service names so they cannot restart and steal the bot port during deployment, preventing port-conflict restart loops.
  • Health check output is pretty-printed when possible (python3 → jq) and reliably falls back to raw output; short payload lines are printed without failing when formatters are absent.
  • Final status summary correctly shows "not-found" for units that systemd does not know about instead of misreporting them as inactive.
  • CPU forensic trace CSV now records a full command+arguments column (header changed from "cmd" to "args") so recorded traces include complete executable paths and all arguments.

Impact

✅ Prevent redeploy port conflicts and crash loops
✅ Clearer health check payloads during redeploy
✅ More complete CPU forensics (full command+args recorded)

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

claude added 3 commits March 1, 2026 12:40
…, jq fallback

rw_cpu_guard.sh:
- Add escape_md_v2() helper: escapes all 20 MarkdownV2 special characters
  (backslash processed first to prevent double-escaping)
- tg_alert(): escape the full composed text (prefix + caller message) via
  escape_md_v2() before sending; switch parse_mode Markdown → MarkdownV2;
  raw ${short_cmd} can no longer break message formatting or leak syntax
- CPU tracer: switch ps format 'cmd' → 'args' so the full executable path
  and every argument are captured; combined with the existing $5..$NF loop
  this gives a complete, delimiter-safe command string in every CSV row

runewager_redeploy.sh:
- _health_check pretty-print cascade: python3 -m json.tool → jq . → raw;
  diagnostics never fail when neither pretty-printer is installed

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
…t failure

rw_cpu_guard.sh:
- CSV header: cmd → args to match the ps field now being recorded

runewager_redeploy.sh:
- Extract _show_payload() helper: captures formatter output into a
  variable, then falls back to raw only when output is empty/non-zero;
  fixes the silent-failure bug where sed's exit code masked python3/jq
  failures so the || fallback never triggered
- Replace three duplicated 'echo | head -20 | sed' blocks with a single
  call to _show_payload(), keeping the python3 → jq → raw cascade

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
…d status

Two bugs exposed by the production redeploy on 2026-03-01:

1. Port-conflict crash loop:
   runewager-bot.service (previously active) has Restart=always /
   RestartSec=5.  After _kill_port freed port 3000 the legacy service
   restarted ~5 s later and reclaimed the port.  When prod-run.sh then
   started runewager.service it immediately failed with EADDRINUSE → exit 1
   crash loop.  _stop_bot_service now also stops known legacy service names
   (runewager-bot, runewager_bot) before the port-kill step so they cannot
   race back to life and steal the port.

2. Status display masked real service state as "not-found":
   systemctl is-active exits non-zero for failed/inactive/activating too,
   so the old  `state=$(…) || state="not-found"`  showed every non-active
   state as "not-found" — hiding that the service was actually in "failed".
   Now the string printed by is-active is captured directly; "not-found" is
   only set when the command produces empty output (unit truly unknown).

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
@codeant-ai

codeant-ai Bot commented Mar 1, 2026

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sourcery-ai

sourcery-ai Bot commented Mar 1, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds Telegram MarkdownV2-safe alert messaging to rw_cpu_guard, improves CPU spike forensic logging, hardens the bot redeploy script against legacy service port conflicts, makes health-check payload formatting more robust, and makes service status summarization more accurate under systemd.

Sequence diagram for Telegram MarkdownV2-safe alert messaging

sequenceDiagram
    participant rw_cpu_guard as rw_cpu_guard_script
    participant tg_alert as tg_alert_function
    participant esc as escape_md_v2
    participant tg_api as Telegram_Bot_API

    rw_cpu_guard->>tg_alert: tg_alert(msg)
    tg_alert->>tg_alert: Check TG_BOT_TOKEN and TG_ADMIN_IDS
    tg_alert->>tg_alert: Enforce alert cooldown
    tg_alert->>esc: escape_md_v2("🛡 [rw_cpu_guard] " + msg)
    esc-->>tg_alert: safe_text
    tg_alert->>tg_alert: Split TG_ADMIN_IDS into id list
    loop for each admin id
        tg_alert->>tg_api: sendMessage(chat_id=id, text=safe_text, parse_mode=MarkdownV2)
        tg_api-->>tg_alert: HTTP response (ignored)
    end
    tg_alert-->>rw_cpu_guard: return
Loading

Flow diagram for redeploy legacy service handling and health payload formatting

flowchart TD
    A[Start redeploy] --> B[Stop main bot service
BOT_SERVICE]

    B --> C{Any legacy
services active?}
    C -->|Yes| D[Loop over legacy names
runewager-bot and runewager_bot]
    D --> E{Legacy name
!= BOT_SERVICE
and active?}
    E -->|Yes| F[Log warning and
systemctl stop legacy]
    E -->|No| G[Skip legacy service]
    F --> H[Next legacy]
    G --> H
    H --> C
    C -->|No| I[Proceed to port cleanup
and start bot]

    I --> J[Begin health check loop]
    J --> K[curl HEALTH_URL
get http_code]
    K --> L{http_code == 200?}
    L -->|No| M[Sleep and retry
until timeout]
    M --> J

    L -->|Yes| N[Log bot healthy]
    N --> O[Fetch payload
curl HEALTH_URL]

    O --> P{python3 available?}
    P -->|Yes| Q[_show_payload
with python3 -m json.tool]
    P -->|No| R{jq available?}
    R -->|Yes| S[_show_payload
with jq .]
    R -->|No| T[Print raw payload
first 20 lines]

    Q --> U[Health check success]
    S --> U
    T --> U

    U --> V[Summarize services
systemctl is-active
BOT_SERVICE and rw_cpu_guard]
    V --> W[If empty output
set state to not-found]
    W --> X[End redeploy]
Loading

File-Level Changes

Change Details Files
Make Telegram alerts from rw_cpu_guard safe for MarkdownV2 and user-controlled content.
  • Introduce an escape_md_v2 shell function that backslash-escapes all Telegram MarkdownV2 special characters in arbitrary text.
  • Update tg_alert to build a single combined message string, escape it via escape_md_v2, and send it as MarkdownV2 instead of Markdown.
  • Change the curl call in tg_alert to use the escaped text parameter and parse_mode=MarkdownV2.
scripts/rw_cpu_guard.sh
Improve CPU forensics tracing to capture full command lines and label them accurately.
  • Rename the CSV header column from cmd to args in the 1-second CPU tracer output.
  • Switch ps from the cmd column to args so the full command path and all arguments are captured.
  • Use awk to join fields 5..NF into a single command string while preserving spaces and replacing commas with semicolons for CSV safety.
scripts/rw_cpu_guard.sh
Ensure redeploy script stops legacy bot services to avoid port conflicts during redeploy.
  • Extend _stop_bot_service to iterate over known legacy service names runewager-bot and runewager_bot.
  • For each legacy service that is active and differs from BOT_SERVICE, emit a warning and attempt to stop it, treating failures as non-fatal.
scripts/runewager_redeploy.sh
Make health-check payload pretty-printing more robust with graceful fallback across multiple formatters.
  • Introduce a local helper function _show_payload inside _health_check to pipe text through a formatter and fall back to raw output if formatting fails or is empty.
  • Use _show_payload with python3 -m json.tool when python3 is available, falling back to jq . if python3 is absent, and finally to raw payload when neither is present.
  • Limit pretty-printed or raw payload output to the first 20 lines and indent for readability, matching prior behavior where relevant.
scripts/runewager_redeploy.sh
Improve service status summary handling under systemd.
  • Change _summary to capture the printed output of systemctl is-active instead of relying on its exit status for rw_cpu_guard and the bot service.
  • Only default the service state to not-found when systemctl is-active produces no output at all, distinguishing truly unknown units from failed or inactive ones.
scripts/runewager_redeploy.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Mar 1, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between eedb1c3 and c8790ad.

📒 Files selected for processing (2)
  • scripts/runewager_redeploy.sh
  • scripts/rw_cpu_guard.sh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/cpu-guard-script-DnD8u

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.

@gamblecodezcom
gamblecodezcom merged commit a3b317f into main Mar 1, 2026
4 checks passed
@gamblecodezcom
gamblecodezcom deleted the claude/cpu-guard-script-DnD8u branch March 1, 2026 12:58
@codeant-ai codeant-ai Bot added the size:S This PR changes 10-29 lines, ignoring generated files label Mar 1, 2026

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

Hey - I've left some high level feedback:

  • The _show_payload helper is defined inside the _health_check loop and redefined on every iteration; consider hoisting it to a top-level helper to avoid repeated function definition and make it easier to reuse elsewhere.
  • In _show_payload, formatted=$(printf '%s' "$text" | $formatter 2>/dev/null) relies on word-splitting for the formatter command; using an array or bash -c to invoke the formatter would avoid subtle bugs if you later pass a formatter with spaces or special characters in its arguments.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `_show_payload` helper is defined inside the `_health_check` loop and redefined on every iteration; consider hoisting it to a top-level helper to avoid repeated function definition and make it easier to reuse elsewhere.
- In `_show_payload`, `formatted=$(printf '%s' "$text" | $formatter 2>/dev/null)` relies on word-splitting for the formatter command; using an array or `bash -c` to invoke the formatter would avoid subtle bugs if you later pass a formatter with spaces or special characters in its arguments.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codeant-ai

codeant-ai Bot commented Mar 1, 2026

Copy link
Copy Markdown

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Legacy services
    The redeploy now attempts to stop legacy service names to avoid port conflicts. This check only stops services reported as "active" and does not handle socket-activated units, enabled-but-inactive units, or masked units that might still cause conflicts. Consider whether you should stop or mask units unconditionally, also check for corresponding ".socket" units, and ensure you don't accidentally stop an unrelated service with a matching name.

  • Trace CSV robustness
    The forensic tracer writes a CSV header and then logs args into a comma-separated file. Although commas are replaced with semicolons, command arguments can still contain newlines or other characters that break CSV parsing. Consider using a safer delimiter (tab or NUL), proper quoting/escaping, or encoding (base64) for the args field to ensure robust parsing later.

  • Health payload printing
    The health-check fallback now prints raw payload with printf. Extremely large or binary payloads could flood logs or produce unexpected output. Consider bounding or sanitizing the payload size before printing and ensure the fallback behaves consistently across shells.

Comment on lines +125 to +134
# Stop legacy service names so they can't restart and steal port ${BOT_PORT}
# while this redeploy is in progress. Failures are non-fatal.
local _legacy
for _legacy in "runewager-bot" "runewager_bot"; do
if [[ "$_legacy" != "$BOT_SERVICE" ]] \
&& systemctl is-active --quiet "$_legacy" 2>/dev/null; then
warn "Legacy service '${_legacy}' is running — stopping to prevent port conflict"
systemctl stop "$_legacy" 2>/dev/null || true
fi
done

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The legacy service stopping block ignores the dry-run flag and calls systemctl stop directly, so running the script with --dry-run will still stop any legacy systemd units, violating the documented "no action" contract for dry runs and potentially causing unexpected service interruption. [logic error]

Severity Level: Major ⚠️
- ⚠️ Dry-run redeploy unexpectedly stops legacy bot services.
- ⚠️ Violates documented "print steps, no action" contract.
- ⚠️ Operators may cause downtime while testing changes.
Suggested change
# Stop legacy service names so they can't restart and steal port ${BOT_PORT}
# while this redeploy is in progress. Failures are non-fatal.
local _legacy
for _legacy in "runewager-bot" "runewager_bot"; do
if [[ "$_legacy" != "$BOT_SERVICE" ]] \
&& systemctl is-active --quiet "$_legacy" 2>/dev/null; then
warn "Legacy service '${_legacy}' is running — stopping to prevent port conflict"
systemctl stop "$_legacy" 2>/dev/null || true
fi
done
# Stop legacy service names so they can't restart and steal port ${BOT_PORT}
# while this redeploy is in progress. Failures are non-fatal.
local _legacy
for _legacy in "runewager-bot" "runewager_bot"; do
if [[ "$_legacy" != "$BOT_SERVICE" ]] \
&& systemctl is-active --quiet "$_legacy" 2>/dev/null; then
warn "Legacy service '${_legacy}' is running — stopping to prevent port conflict"
if (( DRY_RUN )); then
warn "[DRY-RUN] would stop legacy service '${_legacy}'"
else
systemctl stop "$_legacy" 2>/dev/null || true
fi
fi
done
Steps of Reproduction ✅
1. On a host where this repo is deployed, ensure a legacy systemd unit is present and
active, e.g. run `systemctl start runewager-bot` so that `systemctl is-active
runewager-bot` returns "active".

2. Execute the redeploy script in dry-run mode: `sudo ./scripts/runewager_redeploy.sh
--dry-run` (entrypoint `main()` in `scripts/runewager_redeploy.sh` near the end of the
file parses `--dry-run` and sets `DRY_RUN=1` before calling `_stop_bot_service`).

3. During STEP 1, function `_stop_bot_service()` at
`scripts/runewager_redeploy.sh:117-135` runs; after handling `$BOT_SERVICE`, it enters the
legacy loop at lines 125-134, where it checks `systemctl is-active --quiet "$_legacy"`
and, if active, prints the warning and executes `systemctl stop "$_legacy" 2>/dev/null ||
true` without consulting `DRY_RUN`.

4. After the script finishes, verify that the legacy service has been stopped by running
`systemctl is-active runewager-bot` and observing it is no longer "active", despite the
script being invoked with `--dry-run` and the header comment advertising `--dry-run #
print steps, no action`.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** scripts/runewager_redeploy.sh
**Line:** 125:134
**Comment:**
	*Logic Error: The legacy service stopping block ignores the dry-run flag and calls `systemctl stop` directly, so running the script with `--dry-run` will still stop any legacy systemd units, violating the documented "no action" contract for dry runs and potentially causing unexpected service interruption.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

@codeant-ai

codeant-ai Bot commented Mar 1, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants