Skip to content

t1403: fix macOS timeout compatibility and UTC timezone parsing in aidevops update#2909

Merged
marcusquinn merged 5 commits intomarcusquinn:mainfrom
johnwaldo:bugfix/fix-macos-timeout-and-timezone
Mar 5, 2026
Merged

t1403: fix macOS timeout compatibility and UTC timezone parsing in aidevops update#2909
marcusquinn merged 5 commits intomarcusquinn:mainfrom
johnwaldo:bugfix/fix-macos-timeout-and-timezone

Conversation

@johnwaldo
Copy link
Contributor

@johnwaldo johnwaldo commented Mar 5, 2026

Summary

  • macOS has no native timeout commandaidevops update calls timeout 30 npm view ... and timeout 120 bash -c "$update_cmd" which silently fail (exit 127) or hang on macOS. Added _timeout_cmd() in aidevops.sh and timeout_sec() in tool-version-check.sh using perl alarm fallback (available on all macOS).
  • Pipe to tail hangs with perl alarm — even with timeout_sec working, timeout_sec 120 bash -c "$cmd" 2>&1 | tail -2 hangs forever on macOS. The perl alarm (SIGALRM) kills the process but doesn't close the pipe's write end, so tail blocks waiting for EOF. Replaced with temp file: write output to file, then tail -2 the file.
  • UTC timezone parsing bugdate -j -f on macOS ignores the Z suffix, interpreting UTC timestamps in local time. This caused freshness checks to be off by the local UTC offset (e.g., 7 hours for MST), potentially skipping update checks. Fixed by prefixing with TZ=UTC.

Files Changed

  • aidevops.sh — Added _timeout_cmd() portable function, replaced 2 bare timeout calls
  • .agents/scripts/tool-version-check.sh — Added timeout_sec() portable function, replaced bare timeout 120 in update execution, replaced | tail -2 pipe with temp file to prevent SIGALRM hang
  • .agents/scripts/auto-update-helper.sh — Fixed 3 date -j calls to use TZ=UTC

Root Cause Analysis

Two separate bugs causing the same symptom (hang at tool update):

  1. Missing timeout command — macOS has no timeout. The shell tries to execute it, fails with exit 127, and || true swallows the error. Fixed with timeout_sec() / _timeout_cmd() using perl -e 'alarm shift; exec @ARGV'.

  2. SIGALRM + pipe deadlock — Even with the perl alarm working, piping its output to tail -2 creates a deadlock. When SIGALRM fires, perl sends the signal to the exec'd process, but the pipe's write-end file descriptor isn't closed cleanly. tail holds the read end open, waiting for EOF that never comes. Linux's timeout command avoids this by using process groups (kill -TERM -- -$pgid). Fixed by redirecting to a temp file instead of piping.

Testing

Verified on macOS (no native timeout):

  • _timeout_cmd correctly times out via perl alarm (exit 142)
  • timeout_sec correctly wraps npm/brew queries
  • UTC fix eliminates 7-hour offset in freshness calculations
  • Temp file approach correctly shows last 2 lines of output and terminates cleanly

Closes #2490

Summary by CodeRabbit

  • Bug Fixes

    • Fixed timestamp parsing on macOS so UTC-formatted timestamps (trailing Z) are handled correctly.
  • Chores

    • Standardized timeout handling across scripts with a portable wrapper to prevent hangs.
    • Capture update/version output to temporary logs and surface concise end-of-operation output (last lines) for clearer success/failure feedback.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the cross-platform compatibility and correctness of the aidevops update mechanisms, particularly for macOS users. It ensures that update operations and freshness checks function reliably by addressing OS-specific command discrepancies and timezone parsing inaccuracies, preventing silent failures or incorrect update scheduling.

Highlights

  • macOS Timeout Compatibility: Addressed the issue where macOS lacks a native timeout command, causing aidevops update to fail or hang. A portable _timeout_cmd() function was introduced in aidevops.sh using perl alarm as a fallback, and timeout_sec() is now used in tool-version-check.sh.
  • UTC Timezone Parsing Fix: Resolved a bug where date -j -f on macOS incorrectly parsed UTC timestamps by ignoring the 'Z' suffix, leading to freshness checks being off by the local UTC offset. This is fixed by explicitly setting TZ=UTC before date calls.
Changelog
  • .agents/scripts/auto-update-helper.sh
    • Modified date -j calls within check_skill_freshness, check_openclaw_freshness, and check_tool_freshness functions to prefix TZ=UTC for accurate UTC timestamp parsing on macOS.
  • .agents/scripts/tool-version-check.sh
    • Updated the update execution command to use timeout_sec instead of the bare timeout command for improved macOS compatibility.
  • aidevops.sh
    • Added a new portable function _timeout_cmd() to provide timeout functionality across different operating systems, including macOS.
    • Replaced direct calls to the timeout command with the new _timeout_cmd() for npm view and brew info operations.
Activity
  • No human activity has occurred on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 57 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.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f25ff8ec-9f55-468e-b287-e8c8c609efb6

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0b438 and 808cbe3.

📒 Files selected for processing (3)
  • .agents/scripts/auto-update-helper.sh
  • .agents/scripts/tool-version-check.sh
  • aidevops.sh

Walkthrough

This PR makes macOS date parsing UTC-aware in three freshness-check functions by prefixing TZ=UTC when running date on Darwin, and adds a portable timeout wrapper used to run version/update commands with captured output via temporary logs.

Changes

Cohort / File(s) Summary
Timestamp parsing (macOS)
.agents/scripts/auto-update-helper.sh
Three freshness-check functions (check_skill_freshness, check_openclaw_freshness, check_tool_freshness) now invoke TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%SZ" ... on Darwin to correctly parse trailing Z (UTC) timestamps; non-Darwin branches unchanged.
Timeout wrapper & output capture
.agents/scripts/tool-version-check.sh, aidevops.sh
Adds a portable _timeout_cmd wrapper in aidevops.sh; replaces direct timeout calls. tool-version-check.sh now runs version/update commands via the wrapper, captures stdout/stderr to temporary log files, extracts version from the log, prints the final two log lines, and removes temp logs after use.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • marcusquinn/aidevops#2384 — adds/adjusts portable timeout wrapper usages and timeout-related changes.
  • marcusquinn/aidevops#1591 — touches check_skill_freshness and similar timestamp-parsing logic on macOS.
  • marcusquinn/aidevops#2145 — modifies auto-update-helper.sh freshness/update flow overlapping check_tool_freshness edits.

Poem

🕒 On macOS we set UTC true,
Scripts now read the trailing Z through.
Timeouts wrapped, logs kept neat,
Temp files cleaned — output complete.
Small fixes, steady DevOps beat.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary changes: fixing macOS timeout compatibility and UTC timezone parsing issues in the aidevops update process across three modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
aidevops.sh (1)

31-44: Portable timeout implementation looks solid for cross-platform compatibility.

The fallback chain (native timeout → perl alarm → gtimeout → direct execution) correctly handles macOS environments lacking coreutils. The perl alarm approach is a well-known portable pattern.

One consideration: the final fallback (lines 42-43) runs the command without any timeout, which could still cause hangs if no timeout mechanism is available. Given the PR's goal of preventing indefinite hangs, consider logging a warning when falling back to no-timeout execution:

🛡️ Optional: Add warning for no-timeout fallback
 	else
+		# Warn: no timeout mechanism available - command may hang
+		[[ -t 2 ]] && echo -e "\033[1;33m[WARN]\033[0m No timeout command available - running without timeout" >&2
 		"$@"
 	fi

Note: Exit codes differ between mechanisms (Linux timeout: 124, perl alarm: 142). Current callers don't check for specific timeout exit codes, so this is fine.

,

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aidevops.sh` around lines 31 - 44, The final else branch of _timeout_cmd
currently executes the command with no timeout; add a warning before that
fallback so callers/ops know the command may hang. In the _timeout_cmd function,
update the last branch (the else that currently runs "$@") to first emit a
concise warning to stderr (e.g., printf or echo >&2) indicating "no timeout
available, running command without timeout" and then run the command, preserving
existing behavior and exit code propagation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@aidevops.sh`:
- Around line 31-44: The final else branch of _timeout_cmd currently executes
the command with no timeout; add a warning before that fallback so callers/ops
know the command may hang. In the _timeout_cmd function, update the last branch
(the else that currently runs "$@") to first emit a concise warning to stderr
(e.g., printf or echo >&2) indicating "no timeout available, running command
without timeout" and then run the command, preserving existing behavior and exit
code propagation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dcc41fae-2aef-45ec-ad5d-ce5e4200cf84

📥 Commits

Reviewing files that changed from the base of the PR and between c928aaa and 3e8ab0c.

📒 Files selected for processing (3)
  • .agents/scripts/auto-update-helper.sh
  • .agents/scripts/tool-version-check.sh
  • aidevops.sh

@marcusquinn
Copy link
Owner

This PR is from an external contributor (@johnwaldo). Auto-merge is disabled for external PRs — a maintainer must review and merge manually.

@marcusquinn marcusquinn added the external-contributor PR from external contributor, requires maintainer review label Mar 5, 2026
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces important compatibility fixes for macOS by adding a portable timeout implementation and correcting a UTC date parsing issue. The changes are logical and well-targeted. I've suggested a small improvement to the timeout function to prefer gtimeout over the perl fallback for better robustness. Additionally, I've pointed out a few places where error output is being suppressed with 2>/dev/null, which goes against the repository's conventions for error handling and debugging. Removing these suppressions will make the script more transparent when issues occur.

aidevops.sh Outdated
Comment on lines +37 to +40
elif command -v perl &>/dev/null; then
perl -e 'alarm shift; exec @ARGV' "$secs" "$@"
elif command -v gtimeout &>/dev/null; then
gtimeout "$secs" "$@"

Choose a reason for hiding this comment

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

medium

The gtimeout command (from GNU coreutils, often installed on macOS via Homebrew) is a more robust implementation of timeout than the perl one-liner, as it properly handles exit codes. It's better to prefer gtimeout if it's available. I suggest checking for gtimeout before falling back to perl.

Suggested change
elif command -v perl &>/dev/null; then
perl -e 'alarm shift; exec @ARGV' "$secs" "$@"
elif command -v gtimeout &>/dev/null; then
gtimeout "$secs" "$@"
elif command -v gtimeout &>/dev/null; then
gtimeout "$secs" "$@"
elif command -v perl &>/dev/null; then
perl -e 'alarm shift; exec @ARGV' "$secs" "$@"

aidevops.sh Outdated
if [[ "$pkg_ref" == brew:* ]]; then
local brew_pkg="${pkg_ref#brew:}"
latest=$(timeout 30 brew info --json=v2 "$brew_pkg" 2>/dev/null | jq -r '.formulae[0].versions.stable // empty' 2>/dev/null || true)
latest=$(_timeout_cmd 30 brew info --json=v2 "$brew_pkg" 2>/dev/null | jq -r '.formulae[0].versions.stable // empty' 2>/dev/null || true)

Choose a reason for hiding this comment

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

medium

This line suppresses stderr from both brew info and jq using 2>/dev/null. This goes against the project's general rules, which advise against blanket error suppression to ensure that issues like authentication failures, syntax errors, or system problems remain visible for debugging. Please remove the 2>/dev/null redirections to improve error visibility. The || true at the end is sufficient to prevent the script from exiting on failure.

Suggested change
latest=$(_timeout_cmd 30 brew info --json=v2 "$brew_pkg" 2>/dev/null | jq -r '.formulae[0].versions.stable // empty' 2>/dev/null || true)
latest=$(_timeout_cmd 30 brew info --json=v2 "$brew_pkg" | jq -r '.formulae[0].versions.stable // empty' || true)
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.
  2. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

aidevops.sh Outdated
latest=$(_timeout_cmd 30 brew info --json=v2 "$brew_pkg" 2>/dev/null | jq -r '.formulae[0].versions.stable // empty' 2>/dev/null || true)
else
latest=$(timeout 30 npm view "$pkg_ref" version 2>/dev/null || true)
latest=$(_timeout_cmd 30 npm view "$pkg_ref" version 2>/dev/null || true)

Choose a reason for hiding this comment

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

medium

This line suppresses stderr from npm view using 2>/dev/null. This can hide important error messages related to network issues or non-existent packages. According to the project's general rules, it's better to avoid blanket error suppression. Please remove 2>/dev/null to make debugging easier. The || true will still prevent the script from exiting on failure.

Suggested change
latest=$(_timeout_cmd 30 npm view "$pkg_ref" version 2>/dev/null || true)
latest=$(_timeout_cmd 30 npm view "$pkg_ref" version || true)
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
.agents/scripts/tool-version-check.sh (1)

374-387: Excellent fix for the macOS SIGALRM pipe deadlock.

The temp file approach is the right solution here. The comments clearly explain the root cause (perl alarm doesn't close the pipe's write end), and the implementation is clean:

  • Proper mktemp usage with TMPDIR fallback
  • Output captured to temp file, then displayed via tail -2
  • Cleanup via rm -f ensures removal in both success and failure paths

For extra robustness against script interruption (Ctrl+C between mktemp and rm), you could add trap-based cleanup. This is optional since orphaned temp files in /tmp are low-risk:

🛡️ Optional: trap-based cleanup for interrupt resilience
 			# causing tail to block forever. Use a temp file instead.
 			local _update_log
 			_update_log=$(mktemp "${TMPDIR:-/tmp}/tool-update.XXXXXX")
+			trap 'rm -f "$_update_log"' EXIT
 			if timeout_sec 120 bash -c "$update_cmd" >"$_update_log" 2>&1; then
 				tail -2 "$_update_log"
 				echo -e "  ${GREEN}✓ Updated${NC}"
 			else
 				tail -2 "$_update_log"
 				echo -e "  ${RED}✗ Failed${NC}"
 			fi
 			rm -f "$_update_log"
+			trap - EXIT
 			echo ""
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/tool-version-check.sh around lines 374 - 387, Add a trap to
ensure the temporary file created by mktemp (stored in _update_log) is removed
on script exit or interruption: after creating _update_log, register a trap for
EXIT/INT/TERM that runs the same cleanup as rm -f "$_update_log" (and clear the
trap after cleanup if needed). Ensure the trap is set before calling timeout_sec
and that rm -f "$_update_log" remains in the success/failure branches so normal
completion still works; reference the local _update_log variable, mktemp usage,
timeout_sec invocation, and existing rm -f call when adding the trap.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.agents/scripts/tool-version-check.sh:
- Around line 374-387: Add a trap to ensure the temporary file created by mktemp
(stored in _update_log) is removed on script exit or interruption: after
creating _update_log, register a trap for EXIT/INT/TERM that runs the same
cleanup as rm -f "$_update_log" (and clear the trap after cleanup if needed).
Ensure the trap is set before calling timeout_sec and that rm -f "$_update_log"
remains in the success/failure branches so normal completion still works;
reference the local _update_log variable, mktemp usage, timeout_sec invocation,
and existing rm -f call when adding the trap.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3cc14b29-64d1-4bb1-b92a-2f0b778fd376

📥 Commits

Reviewing files that changed from the base of the PR and between 3e8ab0c and 7611bb4.

📒 Files selected for processing (1)
  • .agents/scripts/tool-version-check.sh

@robstiles
Copy link

Permission check failed for this PR (HTTP 403 from collaborator permission API). Unable to determine if @johnwaldo is a maintainer or external contributor. A maintainer must review and merge this PR manually. This is a fail-closed safety measure — the pulse will not auto-merge until the permission API succeeds.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.agents/scripts/tool-version-check.sh (1)

121-130: Guard mktemp failures to keep update checks resilient under set -e.

Both temp-log paths assume mktemp always succeeds. If it fails, redirection/tail paths become brittle and can abort the run without a clear recovery path.

♻️ Suggested hardening patch
-		local _ver_log
-		_ver_log=$(mktemp "${TMPDIR:-/tmp}/tool-ver.XXXXXX")
+		local _ver_log
+		if ! _ver_log=$(mktemp "${TMPDIR:-/tmp}/tool-ver.XXXXXX"); then
+			echo "unknown"
+			return 0
+		fi
@@
-				local _update_log
-				_update_log=$(mktemp "${TMPDIR:-/tmp}/tool-update.XXXXXX")
+				local _update_log
+				if ! _update_log=$(mktemp "${TMPDIR:-/tmp}/tool-update.XXXXXX"); then
+					echo -e "  ${RED}✗ Failed to create temp log${NC}"
+					continue
+				fi

As per coding guidelines ".agents/scripts/*.sh: Automation scripts - focus on: Reliability and robustness ... Error recovery mechanisms."

Also applies to: 386-395

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/tool-version-check.sh around lines 121 - 130, The mktemp
call that sets local _ver_log may fail and leave _ver_log unset, causing
subsequent redirections and head/grep to error under set -e; fix by checking the
mktemp return and providing a safe fallback file (e.g.,
_ver_log="${TMPDIR:-/tmp}/tool-ver.$$") when mktemp fails, ensure _ver_log is
non-empty before using it with timeout_sec "$cmd" $ver_flag and head/grep, and
only rm -f "$_ver_log" if the variable is set and the file exists; reference the
local variable _ver_log and the usage sites of timeout_sec, "$cmd", and
$ver_flag to locate where to add the guard and fallback logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/tool-version-check.sh:
- Around line 382-388: The timeout_sec function currently prefers perl over
gtimeout; change its precedence to prefer gtimeout when available by checking
for gtimeout first and only falling back to perl if gtimeout is absent — update
the logic in the timeout_sec function to test for the gtimeout command before
testing for perl (refer to the timeout_sec function and the gtimeout and perl
checks) so the gtimeout implementation is used whenever present for more
reliable timeout and pipe handling.

---

Nitpick comments:
In @.agents/scripts/tool-version-check.sh:
- Around line 121-130: The mktemp call that sets local _ver_log may fail and
leave _ver_log unset, causing subsequent redirections and head/grep to error
under set -e; fix by checking the mktemp return and providing a safe fallback
file (e.g., _ver_log="${TMPDIR:-/tmp}/tool-ver.$$") when mktemp fails, ensure
_ver_log is non-empty before using it with timeout_sec "$cmd" $ver_flag and
head/grep, and only rm -f "$_ver_log" if the variable is set and the file
exists; reference the local variable _ver_log and the usage sites of
timeout_sec, "$cmd", and $ver_flag to locate where to add the guard and fallback
logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 838533dc-967f-41ab-938e-50904de79aa5

📥 Commits

Reviewing files that changed from the base of the PR and between 7611bb4 and 4a0b438.

📒 Files selected for processing (2)
  • .agents/scripts/tool-version-check.sh
  • aidevops.sh

AI DevOps and others added 5 commits March 5, 2026 15:17
…g in auto-update

The original timeout fix (PR marcusquinn#2384) patched version check functions but
missed two locations that still use bare `timeout` (unavailable on macOS):

1. tool-version-check.sh:374 — update execution path. When a user answers
   'y' to 'Run full tool update?', the update commands run without any
   timeout on macOS, causing indefinite hangs on slow npm installs.

2. aidevops.sh:852-854 — quick key-tool staleness check in `aidevops status`.
   Uses bare `timeout 30` which silently fails on macOS (exit 127), making
   the staleness check always report 'up to date'.

Additionally, auto-update-helper.sh has a timezone bug that prevents tool,
skill, and OpenClaw freshness checks from ever triggering on macOS:

- State file stores timestamps in UTC (e.g., 2026-03-05T08:35:51Z)
- macOS `date -j -f` ignores the Z suffix and interprets as local time
- This produces negative elapsed times, so the time gate always skips
- Fix: prefix with TZ=UTC to force correct interpretation

Note: ~20 other scripts in the repo have the same date -j -f pattern
(model-registry-helper, pulse, dispatch, etc.). Those are lower-risk
(archived or less frequently hit) and should be fixed in a follow-up.
…acOS

The perl alarm fallback (used on macOS which lacks timeout) doesn't close
the pipe's write end on SIGALRM. When timeout_sec output is piped to
tail -2, tail blocks forever waiting for EOF. Use a temp file instead.
…timeout warning

- Swap gtimeout before perl in timeout_sec() for more robust timeout handling
- Guard mktemp failures in get_installed_version() and update loop
- Add stderr warning when no timeout mechanism is available
- Addresses CodeRabbit CHANGES_REQUESTED and Gemini review comments
@marcusquinn marcusquinn force-pushed the bugfix/fix-macos-timeout-and-timezone branch from fc66c31 to 808cbe3 Compare March 5, 2026 15:18
@marcusquinn marcusquinn merged commit 8f8d51f into marcusquinn:main Mar 5, 2026
8 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor PR from external contributor, requires maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

t1356: perf: fix aidevops update exceeding 120s timeout

3 participants