cli/builbo: portable POSIX getopts + fix default action#26
Merged
Conversation
Copilot
AI
changed the title
[WIP] Fix default action behavior in cli/builbo
cli/builbo: portable POSIX getopts + fix default action
Mar 19, 2026
ACTION was set to ${DEFAULT_ACTION} ("help"), then
immediately overwritten with ACTION="" two lines later, causing
the script to have no action when the user provides no action flag.
Remove the overwrite so that ACTION retains its default value of
"help", consistent with DEFAULT_ACTION. This means running builbo
with no action flag now correctly displays the usage/help text.
9bbc372 to
0f65a4b
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates cli/builbo to work on stock macOS by removing reliance on GNU getopt long-option parsing, and fixes a bug where invoking builbo without an explicit action did nothing instead of defaulting to help.
Changes:
- Replace GNU
getopt -llong-option parsing with a long→short rewrite pass plus POSIXgetopts. - Add parsing support for
--shell/-i(previously documented but not actually parsed). - Fix the default-action initialization so no-action invocation defaults to
help.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ACTION="${DEFAULT_ACTION}" | ||
| # action that was explicitly set from the command line: | ||
| SELECTED_ACTION="" | ||
| ACTION="${DEFAULT_ACTION}" |
| --os) | ||
| if [ $# -lt 2 ] || [[ "$2" == -* ]]; then | ||
| echo "error: option '$1' requires a value." >&2 | ||
| usage |
Comment on lines
114
to
128
| --lang) | ||
| if [ $# -lt 2 ] || [[ "$2" == -* ]]; then | ||
| echo "error: option '$1' requires a value." >&2 | ||
| usage | ||
| exit 1 | ||
| fi | ||
| rewrite_args+=("-l" "$2"); shift 2 ;; | ||
| --lang=*) rewrite_args+=("-l" "${1#*=}"); shift ;; | ||
| --registry) | ||
| if [ $# -lt 2 ] || [[ "$2" == -* ]]; then | ||
| echo "error: option '$1' requires a value." >&2 | ||
| usage | ||
| exit 1 | ||
| fi | ||
| rewrite_args+=("-r" "$2"); shift 2 ;; |
| rewrite_args+=("-i" "$2"); shift 2 ;; | ||
| --shell=*) rewrite_args+=("-i" "${1#*=}"); shift ;; | ||
| --help) rewrite_args+=("-h"); shift ;; | ||
| --test) rewrite_args+=("-t"); shift ;; |
Copilot stopped work on behalf of
obnoxxx due to an error
March 19, 2026 15:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
cli/builbousedgetopt -l(GNU extension) for long-option parsing, which breaks on stock macOS where/usr/bin/getoptis BSD. Two separate commits address this and a pre-existing default-action bug.Commit 1 — Replace GNU
getoptwith portable POSIXgetopts--long-opt value/--long-opt=valueinto short-option equivalents via awhile/caseloop into a bash array, then feeds the result into POSIXgetopts.eval set --.--shell/-i, which appeared inusagetext but was absent from the oldoptstring_longand never actually parsed.--*options now emit a clearerror: unknown option '...'instead of falling through silently.Commit 2 — Fix default action
DEFAULT_ACTION="help"was set, thenACTION="${DEFAULT_ACTION}"assigned — then immediately clobbered byACTION=""two lines later. Runningbuilbowith no action flag produced no action. Changed the overwrite toACTION="${DEFAULT_ACTION}"so no-arg invocation defaults to showing help.Original prompt
Update the in-progress PR for
TheBuildBox/buildbox(basemain) that portscli/builboaway from GNUgetoptto also fix the default action behavior.ACTION issue:
DEFAULT_ACTION="help"and thenACTION="${DEFAULT_ACTION}", but later overwrites withACTION="", which prevents the default action from beinghelpwhen no action is specified.help(consistent withDEFAULT_ACTION).Commit requirement:
File:
cli/builboAlso ensure:
set_actionremains intact.The following is the prior conversation context from the user's chat exploration (may be truncated):
User: Whil everything is fine in the CI, locally, on one of my mac machines the command line processing does not work. It word fine on fedora linux machines and another mac. What could be the cause?
Assistant: The most likely cause is a
getoptmismatch on that one Mac.In
cli/builboline ~110 you do:parsed_args=$(getopt -n "builbo" -o "$optstring" -l "$optstring_long" -- "$@")That relies on GNU
getoptbehavior (supports-llong options and returns a normalized argument list that works witheval set -- ...).Why it works in CI + Fedora + “another Mac”, but not on one Mac
getoptis GNUutil-linux→ supports-land your parsing pattern./usr/bin/getoptis typically BSDgetopt, which does not support-l(and has different semantics). On a Mac with only the systemgetopt, this script’s parsing will fail or behave strangely.getoptinstalled (often via Homebrewgnu-getopt) and it’s earlier inPATH, sogetoptbehaves like Linux.Quick confirmation on the failing Mac
Run:
getopt --versionerrors or doesn’t mention GNU/util-linux, you’re on BSDgetopt./opt/homebrew/opt/gnu-getopt/bin/getopt/usr/local/opt/gnu-getopt/bin/getoptFix options (pick one)
getoptentirely and usegetopts(short options only) or a small bash argument parser.getoptif present.--lang, etc.) and stick to short options so you can use POSIXgetopts.One more mac-specific gotcha (secondary)
Make sure the script is executed with bash, not
sh/dash. Your shebang is#!/usr/bin/env bash, so it should be fine, but if someone runssh cli/builbo ...then${DEPS//,/ }and other bashisms can break.If you paste the exact command you ran and the output from the failing Mac (especially the “error:invalid args.” part, plus
which getopt/getopt --version), I can tell you which fix is the cleanest and what minimal patch to apply.User: rightm the working mac has gnu-getopt installed from hombrew, the other is on stock (BSD) getopt.
Assistant: Yep—that explains it. Your script uses GNU
getoptlong-option parsing (getopt ... -l "$optstring_long"), and macOS’s BSD/usr/bin/getoptdoesn’t support that interface, so argument parsing breaks on the stock Mac.What to do (practical options)
Option A (recommended): Detect GNU
getoptand fail with a clear messageAdd a check before line 110 that verifies GNU getopt is available, and on macOS suggests installing
gnu-getopt.Example snippet (bash):
Then use
"${GETOPT_BIN}"instead ofgetoptin yourparsed_args=$(...)call.Why: fastest/safest change, and it makes the failure mode obvious.
Option B: Prefer Homebrew GNU
getoptautomatically (if present)On macOS, try to use
$(brew --prefix gnu-getopt)/bin/getoptif it exists; otherwise error.This makes it “just work” on Macs where it’s installed, without requiring users to edit PATH.
Option C: Remove dependency on GNU
getoptIf you want this to work on “stock macOS” with no extra packages, you’ll need to:
getopts(short flags only), or...This pull request was created from Copilot chat.
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.