fix: bash 3.2 compatibility — replace mapfile, fix log stderr, harden error handling#9
Merged
Merged
Conversation
mapfile requires bash 4.0+ and fails on macOS default bash 3.2. Apply the same while-read pattern already used in mirror-github-org.sh (commit 7af0285) to provision-workshop.sh and invite-participants.sh.
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
log() now writes to stderr so info messages don't pollute stdout when functions are called inside command substitutions. This prevents jq parse errors from mixed output, especially on bash 3.2 where set -e doesn't propagate inside $(...). Also adds explicit error handling to create_org so it exits with a helpful message instead of a cryptic jq parse error when the API call fails (e.g. when the org already exists).
In bash 3.2 with set -u, expanding an empty array via "${arr[@]}"
triggers an unbound variable error. Use the ${arr[@]+"${arr[@]}"}
idiom to safely expand only when the array has elements.
When the batch enterprise invite returns a non-2xx (e.g. 422 because users already exist), fall back to looking up each email individually to resolve their user_id. This allows org assignment to proceed for users who were previously invited. Also treats org assignment failures as likely-already-assigned rather than hard failures, since re-running the script is a common workflow.
…es to verify-auth The Devin API requires enterprise_role_id when inviting members. When the config field is empty, the invite now auto-discovers the default member role via GET /v3/enterprise/roles instead of omitting the field. Also adds a 'List enterprise roles' step to verify-auth.sh so operators can see available role IDs and their names.
When no enterprise roles exist, try sending the invite without enterprise_role_id instead of dying. This handles enterprises that don't have roles configured.
The /v3/enterprise/organizations/{org_id}/members/users endpoint
requires PUT (idempotent upsert), not POST. POST returns 405.
The v3 API endpoint for org member assignment is
POST /v3/organizations/{org_id}/members/users, not
POST /v3/enterprise/organizations/{org_id}/members/users.
The extra /enterprise/ prefix caused a 405 Method Not Allowed.
The endpoint is POST /v3/enterprise/organizations/{org_id}/members/users/{user_id}
with org_role_id in the body. Previous attempts had user_id in the body
which returned 405, and removing /enterprise/ returned 404. Verified
the correct path returns 403 (auth required) instead of 405/404.
Verified against real API:
- Endpoint: POST /v3/enterprise/organizations/{org_id}/members/users/{user_id}
(user_id in URL path, not body)
- Body field is 'role_id' not 'org_role_id', defaults to 'org_member'
- Role discovery uses 'role_name' not 'name', filters to enterprise type
- verify-auth.sh uses correct field names (role_name, role_type)
Tested: invite returns 200, assign returns 200 (new) or 409 (already
assigned, treated as success).
1. Replace A && B || C with if/then/else — prevents fallback branch from running when invite succeeds but jq parsing fails. 2. Fix double-counting of failed emails — track lookup_failures separately and only add batch-level failures when lookups didn't run. 3. Failed org assignment now correctly increments failed counter instead of assigned — any failure (network, permission, etc) is counted accurately in the summary.
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.
Summary
Fixes bash 3.2 (macOS default) compatibility issues and corrects API endpoint/payload bugs in the provisioning scripts.
Bash 3.2 fixes:
mapfilecalls withwhile IFS= read -rloops (same pattern frommirror-github-org.shcommit 7af0285)${arr[@]+"${arr[@]}"}idiom forset -ucompatibilitylog()to stderr to prevent stdout pollution in$(...)command substitutions (was causing jq parse errors)create_orgsinceset -edoesn't propagate in subshells on bash 3.2API endpoint fixes (verified against real API):
POST /v3/enterprise/organizations/{org_id}/members/users/{user_id}— user_id goes in URL path, body field isrole_id(notorg_role_id), defaults toorg_memberenterprise_role_idis required — auto-discovers viaGET /v3/enterprise/roleswhen not configured (usesrole_namefield, filters torole_type == "enterprise")verify-auth.shReview & Testing Checklist for Human
./scripts/provision-workshop.sh --config configs/my-workshop.json --org-id <id> --emails-file <file>on macOS bash 3.2 — verify full invite+assign flow succeeds./scripts/verify-auth.sh— verify enterprise roles listed with correct names and types--org-idagainst an existing org name — verify clear error message suggesting--org-idNotes
account_memberby default. To override, setenterprise_role_idin config JSON.org_member. To override, setorg_role_idin config JSON../scripts/verify-auth.shorcurl -s -H "Authorization: Bearer $DEVIN_API_KEY" https://api.devin.ai/v3/enterprise/roles | jq '.items[]'Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/98665aab16bc4859a3c8b2c760fb42a2
Requested by: @DhrovS