Refactor prod-run.sh to simplify bot startup and systemd integration - #50
Conversation
Resolves all PR comments, screenshot issues, and infrastructure
gaps identified in review. Key changes:
prod-run.sh:
- git pull origin main is now the very first operation
- mkdir -p + touch for logs/, data/, data/backups/ because
.gitignore hides them and they won't exist on a fresh clone
- Project-scoped PID matcher: pgrep -f "node .*${PROJECT_DIR}/index\.js"
eliminates false matches against other Node apps on the same VPS
- systemd ExecStart now runs /usr/bin/node index.js directly instead
of prod-run.sh, removing the setup-script-on-every-restart anti-pattern
- Service user falls back to current user when 'runewager' system user
does not exist; warns clearly instead of erroring
- Logrotate create directive uses numeric UID/GID (id -u / id -g) to
fix "unknown user 'runewager'" errors
- logrotate -d validation output is captured and filtered — only actual
"error" lines are shown, suppressing the verbose dry-run spam
- Cron fallback for logrotate is idempotent (checks before inserting)
- nohup fallback when systemctl is unavailable or service install failed
- All paths are absolute; no fragile relative-path assumptions
- Structured ✔/✘ diagnostics block + last-20-log-lines display
- Final status block confirms PID, systemd state, logrotate, log paths
- Script is fully idempotent — safe to re-run at any time
runewager.service:
- ExecStart updated to /usr/bin/node index.js (not prod-run.sh)
- StandardError now appends to runewager-error.log (separate file)
- Header comment clarifies this is a repo reference template;
prod-run.sh installs the real /etc/ copy with dynamic paths
runewager.logrotate:
- Covers both runewager.log and runewager-error.log
- create directive uses numeric 0 0 (root) as safe default template
- Header comment explains prod-run.sh substitutes real uid/gid at runtime
https://claude.ai/code/session_01X3PxGFF5zzKptQwVkjYzzN
|
CodeAnt AI is reviewing your PR. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughThe PR refactors the production startup infrastructure by rewriting the production runner script into a streamlined workflow, updating the systemd service to run Node.js directly instead of through a wrapper script, and modifying logrotate configuration with explicit log file paths and numeric UID/GID placeholders. Changes
Sequence Diagram(s)sequenceDiagram
participant Script as prod-run.sh
participant Git as Git/origin
participant FS as Filesystem
participant Node as Node.js/npm
participant Systemd as systemd
participant Logrotate as logrotate
Script->>Git: Pull latest from origin main
activate Git
Git-->>Script: Code updated
deactivate Git
Script->>FS: Create runtime directories & log files
activate FS
FS-->>Script: Directories ready
deactivate FS
Script->>Node: Validate Node.js & npm availability
activate Node
Node-->>Script: Version confirmed
deactivate Node
Script->>FS: Ensure .env exists (from .env.example)
activate FS
FS-->>Script: .env ready
deactivate FS
Script->>FS: Alphabetize .env & trim lines
activate FS
FS-->>Script: .env normalized
deactivate FS
Script->>Node: Install node_modules if missing
activate Node
Node-->>Script: Dependencies ready
deactivate Node
Script->>Systemd: Create/update service with dynamic config
activate Systemd
Systemd-->>Script: Service configured
deactivate Systemd
Script->>Logrotate: Validate/create logrotate configuration
activate Logrotate
Logrotate-->>Script: Rotation configured
deactivate Logrotate
Script->>Systemd: Restart bot service
activate Systemd
Systemd->>Node: Start Node.js process
activate Node
Node-->>Systemd: Process running
deactivate Node
Systemd-->>Script: Service active
deactivate Systemd
Script->>FS: Report final status & logs
activate FS
FS-->>Script: Status displayed
deactivate FS
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
Sequence DiagramThe PR rewrites prod-run.sh to pull latest code, prepare runtime files, install deps, create systemd + logrotate configs, and start the bot by having systemd run node index.js (falling back to nohup). This diagram shows the main success path for bootstrapping and launching the bot. sequenceDiagram
participant Operator
participant prod-run.sh
participant Git
participant Filesystem
participant Systemd
participant Node
Operator->>prod-run.sh: Run production runner
prod-run.sh->>Git: git pull origin main (ensure latest code)
prod-run.sh->>Filesystem: Ensure logs/, data/, .env and node_modules (install if missing)
prod-run.sh->>Systemd: Write/enable runewager.service (ExecStart -> node index.js)
prod-run.sh->>Filesystem: Write /etc/logrotate.d/runewager (numeric uid/gid)
prod-run.sh->>Systemd: Restart/Start runewager.service (or fallback to nohup)
Systemd->>Node: Exec /usr/bin/node index.js (supervise)
Node-->>prod-run.sh: Bot running (PID) — script reports diagnostics and tail logs
Generated by CodeAnt AI |
Nitpicks 🔍
|
| systemctl daemon-reload | ||
| systemctl enable "${APP_NAME}.service" 2>/dev/null || true | ||
| say "Systemd service installed and enabled: $SERVICE_FILE" |
There was a problem hiding this comment.
Suggestion: The script unconditionally calls systemctl daemon-reload and systemctl enable in ensure_systemd_service, which will cause the script to exit with an error on hosts where systemctl is not installed (e.g., non-systemd systems), contradicting the intended graceful degradation behavior. [logic error]
Severity Level: Major ⚠️
- ❌ `npm run prod` exits early on non-systemd hosts.
- ❌ Bot is never started; nohup fallback not reached.
- ⚠️ Logrotate and diagnostics not configured or run.| systemctl daemon-reload | |
| systemctl enable "${APP_NAME}.service" 2>/dev/null || true | |
| say "Systemd service installed and enabled: $SERVICE_FILE" | |
| if command -v systemctl >/dev/null 2>&1; then | |
| systemctl daemon-reload | |
| systemctl enable "${APP_NAME}.service" 2>/dev/null || true | |
| say "Systemd service installed and enabled: $SERVICE_FILE" | |
| else | |
| warn "systemctl not found — wrote service file but did not reload/enable it" | |
| fi |
Steps of Reproduction ✅
1. On a non-systemd host (no `systemctl` binary) where `/etc/systemd/system` is writable
as root (e.g., minimal container), clone the repo into `/var/www/html/Runewager` as
described in `README.md:102-124`.
2. From the project root (`/workspace/Runewager` or `/var/www/html/Runewager`), run `npm
run prod` (entry point defined in `package.json:10-13` mapping to `./prod-run.sh`) as
root.
3. `prod-run.sh:122-181` executes `ensure_systemd_service`, which builds the unit file
and, because `/etc/systemd/system` is writable, enters the branch at
`prod-run.sh:170-177`.
4. At `prod-run.sh:172`, `systemctl daemon-reload` is invoked unconditionally; on a host
without `systemctl` this results in `bash: systemctl: command not found` (exit status
127), and due to `set -euo pipefail` at `prod-run.sh:9` the whole script exits immediately
before diagnostics, logrotate setup, or bot startup are performed.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** prod-run.sh
**Line:** 172:174
**Comment:**
*Logic Error: The script unconditionally calls `systemctl daemon-reload` and `systemctl enable` in `ensure_systemd_service`, which will cause the script to exit with an error on hosts where `systemctl` is not installed (e.g., non-systemd systems), contradicting the intended graceful degradation behavior.
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 finished reviewing your PR. |
…etection Addresses all PR #50 review comments from CodeAnt AI: 1. systemctl calls in ensure_systemd_service() now guarded with `command -v systemctl` before daemon-reload / enable — prevents set -e exit on non-systemd hosts; falls back with a clear warning. 2. logrotate binary feature-detected before validation dry-run — if logrotate is absent the script warns and returns cleanly instead of producing a noisy error or silently doing nothing. 3. crontab binary feature-detected before fallback cron job insertion — prevents unbound-variable / command-not-found errors on minimal systems that have no crontab installed. All three code paths continue to degrade gracefully with informative warn() messages and never exit the script unexpectedly. https://claude.ai/code/session_01X3PxGFF5zzKptQwVkjYzzN
User description
Summary
Completely rewrote
prod-run.shto streamline production deployment. The script now directly starts the bot via systemd instead of recursively calling itself, eliminates hundreds of lines of defensive checks, and provides clearer diagnostics.Key Changes
Simplified startup flow: Removed recursive execution pattern where systemd called
prod-run.shwhich then launched the bot. Now systemd directly runsnode index.js.Consolidated logging: Replaced multiple log files (
runewager.log,runewager-1.log,crash.log) with two clear streams:runewager.logfor standard outputrunewager-error.logfor error outputStreamlined environment setup:
Improved systemd service:
node index.jsinstead of calling the scriptrunewagersystem user doesn't existBetter diagnostics:
Updated reference templates:
runewager.service: Now a reference copy with documentation; prod-run.sh generates the authoritative versionrunewager.logrotate: Simplified with numeric UID/GID and clearer commentsImplementation Details
https://claude.ai/code/session_01X3PxGFF5zzKptQwVkjYzzN
Summary by CodeRabbit
Release Notes
CodeAnt-AI Description
Simplify production startup: install a stable systemd service, manage logs, and reliably start the bot
What Changed
Impact
✅ Fewer "unknown user" logrotate errors✅ Shorter recovery time after deploy (auto pull + auto-start)✅ Clearer startup and runtime logs (separate error log and last-20-lines diagnostics)💡 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:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
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:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
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.