Skip to content

Conversation

@yagoveloso
Copy link

Adds an interactive bash script to automate worker group creation and configuration for self-hosted Trigger.dev supervisor instances.
✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing
Successfully tested all features:

  1. Help flag: Verified --help displays complete usage information
  2. List projects: Tested --list-projects against live API, correctly displays both external refs and internal IDs
  3. Dry-run mode: Confirmed --dry-run shows expected actions without executing
  4. Error handling: Tested invalid PAT format, verified proper error messages and guidance
  5. Worker creation: Successfully created test worker and received valid token
  6. Project resolution: Verified automatic conversion from external ref (proj_...) to internal ID
  7. Configuration methods: Tested CLI arguments, environment variables, and interactive prompts
  8. Self-hosted instance: Tested against real self-hosted deployment
    All tests passed successfully.

Changelog
Added

  • Interactive setup script (apps/supervisor/scripts/setup-worker.sh):
    • Automates worker group creation via Admin API
    • Supports three configuration methods: CLI args, environment variables, and interactive prompts
    • Auto-resolves project external refs to internal IDs
    • Includes --list-projects command to discover project identifiers
    • Includes --dry-run mode for testing without execution
    • Color-coded output for better UX
    • Input validation (PAT format, API URL, connectivity)
    • Clear error messages with solutions
  • Documentation updates (apps/supervisor/README.md):
    • New "Quick Setup (Recommended)" section with examples
    • Self-hosted usage examples
    • Instructions for finding PAT on all platforms (macOS, Linux, Windows)
    • Appendix explaining project ID types (external ref vs internal ID)
    • Updated existing dev setup section to reference new script
      Benefits
  • Simplifies self-hosted supervisor setup (previously required manual curl commands)
  • Reduces setup errors through validation and clear error messages
  • Improves developer experience with interactive mode
  • Documents previously undocumented PAT locations

Screenshots
Screenshot 2026-01-17 at 14 42 36

- Add interactive bash script to automate worker group creation
- Support CLI arguments, environment variables, and .env files
- Auto-resolve project external refs to internal IDs
- Include dry-run mode for testing
- Add --list-projects command to discover project IDs
- Add comprehensive documentation in README with Quick Setup section
- Include finding PAT instructions for all platforms
- Add appendix explaining project ID types
@changeset-bot
Copy link

changeset-bot bot commented Jan 17, 2026

⚠️ No Changeset found

Latest commit: 1473654

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

Walkthrough

This pull request adds comprehensive documentation and a new automation script to the supervisor application. The README.md is expanded with setup instructions, prerequisites, usage examples, script options, and guidance on finding credentials and managing worker groups. A new setup-worker.sh Bash script is introduced that automates the creation and configuration of Trigger.dev worker groups for self-hosted instances, including features for dependency checking, environment loading, argument parsing, interactive prompting, API validation, project listing, and worker creation with dry-run support.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.76% 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
Title check ✅ Passed The title directly and clearly describes the main change: adding an automated worker setup script for the supervisor application.
Description check ✅ Passed The description follows the template structure with completed checklist, comprehensive testing details, detailed changelog, and screenshots demonstrating the feature.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

@vibe-kanban-cloud
Copy link

Review Complete

Your review story is ready!

View Story

Comment !reviewfast on this PR to re-generate the story.

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: 8

🤖 Fix all issues with AI agents
In `@apps/supervisor/README.md`:
- Around line 68-72: The PAT placeholder in the options table for `--pat`
currently uses `tr*pat*...` which renders with emphasis; replace that
placeholder with escaped underscores so it reads `tr\_pat\_...` (matching the
existing `proj\_...` pattern used for `--project-ref`) to prevent markdown
formatting and display the literal underscores.
- Around line 98-102: Replace the Windows PowerShell snippet that uses CMD-style
%APPDATA% and the alias type with PowerShell-native equivalents: use
$env:APPDATA instead of %APPDATA% and use Get-Content in place of type, then
pipe to jq as before (locate the README snippet containing "%APPDATA%" and "type
%APPDATA%\trigger\config.json | jq -r \".profiles.default.accessToken\"").

In `@apps/supervisor/scripts/setup-worker.sh`:
- Around line 186-195: The interactive prompt in function prompt_interactive
currently reads the PAT with read -r which echoes the token; change the read
invocation for PAT to use a silent read (add the -s flag) so input is not shown,
and after the silent read emit a newline (e.g., an extra echo) so the terminal
prompt formatting stays correct; update the read that assigns to the PAT
variable and ensure subsequent logic that uses PAT remains unchanged.
- Around line 227-235: In validate_pat(), avoid printing the full secret;
instead build a masked version of the PAT that shows only the first 7 and last 4
characters and replace the middle with asterisks (e.g., "${PAT:0:7}***${PAT:
-4}"), then use that masked value in the echo that currently prints "Got:     
$PAT" so logs show the masked token while preserving the existing error messages
and behavior.
- Around line 336-352: In create_worker, the jq payload currently uses
($projectId // null) which returns an empty string instead of null when
PROJECT_ID is empty; update the jq expression in the json_payload construction
so it explicitly converts an empty projectId to null (e.g., by testing length or
equality and returning null for empty strings) while still passing PROJECT_ID
via --arg, so projectId becomes null when no project is selected.
- Around line 255-274: In test_api_connection(), curl can fail and abort the
script under set -euo pipefail; modify the curl invocation to capture its exit
code (e.g., initialize curl_exit=0, run response=$(curl -sS -w "\n%{http_code}"
-H "Authorization: Bearer $PAT" "$API_URL/api/v1/projects" 2>&1) ||
curl_exit=$?), then check curl_exit first and on non-zero emit a clear error via
error "Curl failed (exit $curl_exit)" plus the captured response/body and exit
1; otherwise parse http_code/body as before and keep the existing HTTP status
check.
- Around line 488-499: The CLI allows the --default flag without a project,
causing an invalid payload; add a validation that if the default flag is set
(e.g., DEFAULT or MAKE_DEFAULT variable) then either PROJECT_REF or PROJECT_ID
must be present (or resolve_project_id must succeed) and otherwise print an
error and exit; implement this check after resolve_project_id is run (use
resolve_project_id, PROJECT_REF, PROJECT_ID and the default flag variable names
from the script) so the CLI path mirrors the interactive prompt enforcement.
- Around line 138-183: In parse_arguments, validate the presence and content of
the value for options that consume $2 (e.g., --name -> WORKER_NAME, --pat ->
PAT, --api-url -> API_URL, --project-ref -> PROJECT_REF, --project-id ->
PROJECT_ID) before shifting; specifically check that a non-empty argument exists
(guarding against set -u unbound errors) and that the next token is not another
flag (starts with '-') and emit a clear error and exit if validation fails, then
only assign and shift 2 when the check passes.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72594a4 and 1473654.

📒 Files selected for processing (2)
  • apps/supervisor/README.md
  • apps/supervisor/scripts/setup-worker.sh
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/supervisor/README.md
🧠 Learnings (6)
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Run `npx trigger.devlatest init` to initialize a Trigger.dev project

Applied to files:

  • apps/supervisor/README.md
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Use `trigger.dev/redis-worker` for background job and worker system needs in the webapp and run engine

Applied to files:

  • apps/supervisor/README.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Run `npx trigger.devlatest dev` to start the Trigger.dev development server

Applied to files:

  • apps/supervisor/README.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure Trigger.dev project in `trigger.config.ts` using `defineConfig()` with project ref and task directories

Applied to files:

  • apps/supervisor/README.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • apps/supervisor/README.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/supervisor/README.md

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +68 to +72
| Option | Description |
| --------------------- | ----------------------------------------- |
| `--name <name>` | Worker group name (required) |
| `--pat <token>` | Personal Access Token (tr*pat*...) |
| `--api-url <url>` | Trigger.dev API URL |
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

head -n 75 apps/supervisor/README.md | tail -n 15

Repository: triggerdotdev/trigger.dev

Length of output: 717


Use escaped underscores for the PAT format placeholder, matching the project-ref pattern.

In the options table, tr*pat*... will render with asterisks creating emphasis. However, the suggested fix using tr_pat_... doesn't solve this since underscores also trigger markdown formatting. Use escaped underscores instead: tr\_pat\_... to match the proj\_... pattern already used in the same table for the --project-ref option.

✅ Suggested fix
-| `--pat <token>`       | Personal Access Token (tr*pat*...)        |
+| `--pat <token>`       | Personal Access Token (tr\_pat\_...)       |
🤖 Prompt for AI Agents
In `@apps/supervisor/README.md` around lines 68 - 72, The PAT placeholder in the
options table for `--pat` currently uses `tr*pat*...` which renders with
emphasis; replace that placeholder with escaped underscores so it reads
`tr\_pat\_...` (matching the existing `proj\_...` pattern used for
`--project-ref`) to prevent markdown formatting and display the literal
underscores.

Comment on lines +98 to +102
**Windows:**

```powershell
type %APPDATA%\trigger\config.json | jq -r ".profiles.default.accessToken"
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

git ls-files "apps/supervisor/README.md"

Repository: triggerdotdev/trigger.dev

Length of output: 194


🏁 Script executed:

cat -n apps/supervisor/README.md | sed -n '95,105p'

Repository: triggerdotdev/trigger.dev

Length of output: 339


🌐 Web query:

PowerShell %APPDATA% variable expansion vs $env:APPDATA

💡 Result:

Short answer

  • %APPDATA% is the CMD/Windows “%VAR%” expansion syntax; PowerShell does not expand it. Use $env:APPDATA (or .NET APIs) in PowerShell. [1][2][3]

Details + examples

  • PowerShell exposes environment variables through the Env: drive and $env:Name shorthand; $env:APPDATA returns the AppData path. Use that inside strings: "$env:APPDATA\MyApp". [3][4]
  • %APPDATA% will only be expanded if you run it inside cmd.exe (e.g. & cmd /c "echo %APPDATA%") or explicitly call an API that expands %VAR% (e.g. [Environment]::ExpandEnvironmentVariables). PowerShell itself treats "%APPDATA%" as a literal string. [2][5]
  • Alternatives:
    • $env:APPDATA — recommended for scripts.
    • [Environment]::GetEnvironmentVariable("APPDATA") — explicit .NET call.
    • [Environment]::ExpandEnvironmentVariables("%APPDATA%\x") — expands percent notation if you must use it. [5]

Example

  • Correct PowerShell:
    • $p = "$env:APPDATA\MyApp"
  • If you have a literal "%APPDATA%\X" and want it expanded:
    • $p = [Environment]::ExpandEnvironmentVariables("%APPDATA%\MyApp") . [5]

References

  1. StackOverflow: % is for cmd.exe; use $env:... in PowerShell. [1].
  2. Microsoft Q&A / PowerShell guidance recommending $env:USERNAME. [2].
  3. SS64 / PowerShell Env: drive documentation. [4].
  4. Opensource.com article on environment variables in PowerShell. [3].
  5. .NET Environment methods (ExpandEnvironmentVariables / GetEnvironmentVariable) referenced in SS64 and docs. [4][5].

PowerShell syntax: %APPDATA% is CMD-style and will not expand in PowerShell.

Use $env:APPDATA instead. Additionally, use Get-Content (the native PowerShell command) rather than type.

✅ Suggested fix
-type %APPDATA%\trigger\config.json | jq -r ".profiles.default.accessToken"
+Get-Content "$env:APPDATA\trigger\config.json" | jq -r ".profiles.default.accessToken"
🤖 Prompt for AI Agents
In `@apps/supervisor/README.md` around lines 98 - 102, Replace the Windows
PowerShell snippet that uses CMD-style %APPDATA% and the alias type with
PowerShell-native equivalents: use $env:APPDATA instead of %APPDATA% and use
Get-Content in place of type, then pipe to jq as before (locate the README
snippet containing "%APPDATA%" and "type %APPDATA%\trigger\config.json | jq -r
\".profiles.default.accessToken\"").

Comment on lines +138 to +183
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
--name)
WORKER_NAME="$2"
shift 2
;;
--pat)
PAT="$2"
shift 2
;;
--api-url)
API_URL="$2"
shift 2
;;
--project-ref)
PROJECT_REF="$2"
shift 2
;;
--project-id)
PROJECT_ID="$2"
shift 2
;;
--default)
MAKE_DEFAULT=1
shift
;;
--list-projects)
LIST_PROJECTS=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--help|-h)
show_help
exit 0
;;
*)
error "Unknown option: $1"
echo "Run with --help for usage information"
exit 1
;;
esac
done
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/supervisor/scripts/setup-worker.sh | head -200

Repository: triggerdotdev/trigger.dev

Length of output: 6127


🏁 Script executed:

sed -n '200,350p' apps/supervisor/scripts/setup-worker.sh | cat -n

Repository: triggerdotdev/trigger.dev

Length of output: 5153


🏁 Script executed:

sed -n '350,450p' apps/supervisor/scripts/setup-worker.sh | cat -n

Repository: triggerdotdev/trigger.dev

Length of output: 3378


🏁 Script executed:

sed -n '400,500p' apps/supervisor/scripts/setup-worker.sh | cat -n

Repository: triggerdotdev/trigger.dev

Length of output: 3115


🏁 Script executed:

# Test the actual behavior of parse_arguments with missing argument value
cat > /tmp/test_parse.sh << 'EOF'
#!/bin/bash
set -euo pipefail

ERROR_TRIGGERED=0
trap 'ERROR_TRIGGERED=1' ERR

# Simulate parse_arguments
parse_arguments() {
  while [[ $# -gt 0 ]]; do
    case $1 in
      --name)
        WORKER_NAME="$2"
        shift 2
        ;;
      *)
        echo "Unknown: $1"
        exit 1
        ;;
    esac
  done
}

# Test 1: Missing argument value
echo "Test 1: --name without value"
if ! parse_arguments --name 2>&1; then
  echo "ERROR: Script failed as expected"
fi

echo ""
echo "Test 2: --name with value"
parse_arguments --name "my-worker"
echo "SUCCESS: Script completed normally"
EOF
chmod +x /tmp/test_parse.sh
bash /tmp/test_parse.sh 2>&1 || true

Repository: triggerdotdev/trigger.dev

Length of output: 147


🏁 Script executed:

# Test more edge cases to understand the behavior fully
cat > /tmp/test_parse2.sh << 'EOF'
#!/bin/bash
set -euo pipefail

WORKER_NAME=""
PAT=""

parse_arguments() {
  while [[ $# -gt 0 ]]; do
    case $1 in
      --name)
        WORKER_NAME="$2"
        shift 2
        ;;
      --pat)
        PAT="$2"
        shift 2
        ;;
      *)
        echo "Unknown: $1"
        exit 1
        ;;
    esac
  done
}

# Test 1: --name followed by another flag
echo "Test 1: --name followed by --pat"
if parse_arguments --name --pat 2>&1; then
  echo "RESULT: parse_arguments completed"
  echo "WORKER_NAME='$WORKER_NAME'"
  echo "PAT='$PAT'"
else
  echo "FAILED"
fi
EOF
chmod +x /tmp/test_parse2.sh
bash /tmp/test_parse2.sh 2>&1 || true

Repository: triggerdotdev/trigger.dev

Length of output: 162


🏁 Script executed:

# Test the projectId handling and PAT echo issue
cat > /tmp/test_json.sh << 'EOF'
#!/bin/bash

# Test 1: Empty PROJECT_ID
echo "Test 1: Empty PROJECT_ID"
PROJECT_ID=""
WORKER_NAME="test"
MAKE_DEFAULT="false"

json_payload=$(jq -n \
  --arg name "$WORKER_NAME" \
  --arg projectId "$PROJECT_ID" \
  --argjson makeDefault "$MAKE_DEFAULT" \
  '{name: $name, projectId: ($projectId // null), makeDefaultForProject: $makeDefault}')
echo "Result: $json_payload"

echo ""
echo "Test 2: Non-empty PROJECT_ID"
PROJECT_ID="cmk_123"
json_payload=$(jq -n \
  --arg name "$WORKER_NAME" \
  --arg projectId "$PROJECT_ID" \
  --argjson makeDefault "$MAKE_DEFAULT" \
  '{name: $name, projectId: ($projectId // null), makeDefaultForProject: $makeDefault}')
echo "Result: $json_payload"
EOF
bash /tmp/test_json.sh

Repository: triggerdotdev/trigger.dev

Length of output: 294


🏁 Script executed:

# Verify the PAT echo issue
grep -n "Got:" apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 98


🏁 Script executed:

# Verify curl error handling with set -euo pipefail
cat > /tmp/test_curl.sh << 'EOF'
#!/bin/bash
set -euo pipefail

# Simulate curl failure
test_curl_error() {
  local response
  response=$(curl -sS "http://invalid.example.com/api" 2>&1 || echo "CURL_FAILED")
  echo "Response: $response"
}

echo "Testing curl error with set -euo pipefail:"
test_curl_error 2>&1 || echo "Function failed"
EOF
bash /tmp/test_curl.sh

Repository: triggerdotdev/trigger.dev

Length of output: 187


Validate option values before consuming $2.

With set -u, a missing argument value causes an unbound variable error that exits the script abruptly. Additionally, if an option is followed by another flag instead of a value (e.g., --name --pat), the next flag gets consumed as the value, misaligning subsequent argument parsing. Add explicit guards for options requiring values.

✅ Suggested fix
 parse_arguments() {
+  require_value() {
+    local opt="$1"
+    local val="${2-}"
+    if [[ -z "$val" || "$val" == --* ]]; then
+      error "Option $opt requires a value"
+      exit 1
+    fi
+  }
   while [[ $# -gt 0 ]]; do
     case $1 in
       --name)
+        require_value --name "$2"
         WORKER_NAME="$2"
         shift 2
         ;;
       --pat)
+        require_value --pat "$2"
         PAT="$2"
         shift 2
         ;;
       --api-url)
+        require_value --api-url "$2"
         API_URL="$2"
         shift 2
         ;;
       --project-ref)
+        require_value --project-ref "$2"
         PROJECT_REF="$2"
         shift 2
         ;;
       --project-id)
+        require_value --project-id "$2"
         PROJECT_ID="$2"
         shift 2
         ;;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
--name)
WORKER_NAME="$2"
shift 2
;;
--pat)
PAT="$2"
shift 2
;;
--api-url)
API_URL="$2"
shift 2
;;
--project-ref)
PROJECT_REF="$2"
shift 2
;;
--project-id)
PROJECT_ID="$2"
shift 2
;;
--default)
MAKE_DEFAULT=1
shift
;;
--list-projects)
LIST_PROJECTS=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--help|-h)
show_help
exit 0
;;
*)
error "Unknown option: $1"
echo "Run with --help for usage information"
exit 1
;;
esac
done
parse_arguments() {
require_value() {
local opt="$1"
local val="${2-}"
if [[ -z "$val" || "$val" == --* ]]; then
error "Option $opt requires a value"
exit 1
fi
}
while [[ $# -gt 0 ]]; do
case $1 in
--name)
require_value --name "$2"
WORKER_NAME="$2"
shift 2
;;
--pat)
require_value --pat "$2"
PAT="$2"
shift 2
;;
--api-url)
require_value --api-url "$2"
API_URL="$2"
shift 2
;;
--project-ref)
require_value --project-ref "$2"
PROJECT_REF="$2"
shift 2
;;
--project-id)
require_value --project-id "$2"
PROJECT_ID="$2"
shift 2
;;
--default)
MAKE_DEFAULT=1
shift
;;
--list-projects)
LIST_PROJECTS=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--help|-h)
show_help
exit 0
;;
*)
error "Unknown option: $1"
echo "Run with --help for usage information"
exit 1
;;
esac
done
}
🤖 Prompt for AI Agents
In `@apps/supervisor/scripts/setup-worker.sh` around lines 138 - 183, In
parse_arguments, validate the presence and content of the value for options that
consume $2 (e.g., --name -> WORKER_NAME, --pat -> PAT, --api-url -> API_URL,
--project-ref -> PROJECT_REF, --project-id -> PROJECT_ID) before shifting;
specifically check that a non-empty argument exists (guarding against set -u
unbound errors) and that the next token is not another flag (starts with '-')
and emit a clear error and exit if validation fails, then only assign and shift
2 when the check passes.

Comment on lines +186 to +195
prompt_interactive() {
# Prompt for PAT if missing
if [[ -z "$PAT" ]]; then
warning "PAT not found in environment or .env"
echo ""
echo "Please enter your Personal Access Token (PAT):"
echo " Format: tr_pat_..."
echo " Location: ~/.config/trigger/config.json or ~/Library/Preferences/trigger/config.json"
read -r -p "PAT: " PAT
echo ""
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check if file exists and view the content at specified lines
head -200 apps/supervisor/scripts/setup-worker.sh | tail -20

Repository: triggerdotdev/trigger.dev

Length of output: 610


🏁 Script executed:

# Also verify the exact lines 186-195 with line numbers
sed -n '186,195p' apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 438


🏁 Script executed:

# Check for other instances of read commands in this file
rg "read\s+" apps/supervisor/scripts/setup-worker.sh -n

Repository: triggerdotdev/trigger.dev

Length of output: 429


Mask PAT input during interactive prompt to prevent accidental credential exposure.

The current read -r command echoes input characters to the terminal. Add the -s flag to suppress echo of the token:

Suggested fix
-    read -r -p "PAT: " PAT
+    read -rs -p "PAT: " PAT
     echo ""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
prompt_interactive() {
# Prompt for PAT if missing
if [[ -z "$PAT" ]]; then
warning "PAT not found in environment or .env"
echo ""
echo "Please enter your Personal Access Token (PAT):"
echo " Format: tr_pat_..."
echo " Location: ~/.config/trigger/config.json or ~/Library/Preferences/trigger/config.json"
read -r -p "PAT: " PAT
echo ""
prompt_interactive() {
# Prompt for PAT if missing
if [[ -z "$PAT" ]]; then
warning "PAT not found in environment or .env"
echo ""
echo "Please enter your Personal Access Token (PAT):"
echo " Format: tr_pat_..."
echo " Location: ~/.config/trigger/config.json or ~/Library/Preferences/trigger/config.json"
read -rs -p "PAT: " PAT
echo ""
🤖 Prompt for AI Agents
In `@apps/supervisor/scripts/setup-worker.sh` around lines 186 - 195, The
interactive prompt in function prompt_interactive currently reads the PAT with
read -r which echoes the token; change the read invocation for PAT to use a
silent read (add the -s flag) so input is not shown, and after the silent read
emit a newline (e.g., an extra echo) so the terminal prompt formatting stays
correct; update the read that assigns to the PAT variable and ensure subsequent
logic that uses PAT remains unchanged.

Comment on lines +227 to +235
validate_pat() {
if [[ ! "$PAT" =~ ^tr_pat_ ]]; then
error "Invalid Personal Access Token format"
echo ""
echo "Expected: tr_pat_... (40 characters)"
echo "Got: $PAT"
echo ""
echo "PAT starts with 'tr_pat_', not 'tr_prod_' or 'tr_dev_'"
echo ""
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "setup-worker.sh" -type f

Repository: triggerdotdev/trigger.dev

Length of output: 110


🏁 Script executed:

# Once we find the file, let's read lines 227-235
sed -n '220,240p' apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 670


Mask the PAT before displaying in error output.

The code echoes the full PAT to stdout/stderr, which leaks the secret credential into logs and terminal history. Use the suggested masking approach to display only the first 7 and last 4 characters:

Suggested fix
-    echo "Got:      $PAT"
+    local pat_redacted="$PAT"
+    if [[ ${`#PAT`} -gt 10 ]]; then
+      pat_redacted="${PAT:0:7}***${PAT: -4}"
+    fi
+    echo "Got:      $pat_redacted"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validate_pat() {
if [[ ! "$PAT" =~ ^tr_pat_ ]]; then
error "Invalid Personal Access Token format"
echo ""
echo "Expected: tr_pat_... (40 characters)"
echo "Got: $PAT"
echo ""
echo "PAT starts with 'tr_pat_', not 'tr_prod_' or 'tr_dev_'"
echo ""
validate_pat() {
if [[ ! "$PAT" =~ ^tr_pat_ ]]; then
error "Invalid Personal Access Token format"
echo ""
echo "Expected: tr_pat_... (40 characters)"
local pat_redacted="$PAT"
if [[ ${`#PAT`} -gt 10 ]]; then
pat_redacted="${PAT:0:7}***${PAT: -4}"
fi
echo "Got: $pat_redacted"
echo ""
echo "PAT starts with 'tr_pat_', not 'tr_prod_' or 'tr_dev_'"
echo ""
🤖 Prompt for AI Agents
In `@apps/supervisor/scripts/setup-worker.sh` around lines 227 - 235, In
validate_pat(), avoid printing the full secret; instead build a masked version
of the PAT that shows only the first 7 and last 4 characters and replace the
middle with asterisks (e.g., "${PAT:0:7}***${PAT: -4}"), then use that masked
value in the echo that currently prints "Got:      $PAT" so logs show the masked
token while preserving the existing error messages and behavior.

Comment on lines +255 to +274
test_api_connection() {
info "Testing API connection..."

local response
local http_code
local body

response=$(curl -sS -w "\n%{http_code}" \
-H "Authorization: Bearer $PAT" \
"$API_URL/api/v1/projects" 2>&1)

http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')

if [[ "$http_code" != "200" ]]; then
error "Failed to connect to API (HTTP $http_code)"
echo ""
echo "Response: $body"
exit 1
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/supervisor/scripts/setup-worker.sh | head -50

Repository: triggerdotdev/trigger.dev

Length of output: 1513


🏁 Script executed:

sed -n '255,274p' apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 536


Handle curl failures explicitly to avoid set -e aborts.

The script has set -euo pipefail enabled (line 11). When curl encounters a network error (connection refused, timeout, etc.), it exits with a non-zero code, causing the script to abort immediately before the HTTP code check runs. Capture curl's exit status with the || curl_exit=$? pattern so you can emit a clear error message.

✅ Suggested fix
-  response=$(curl -sS -w "\n%{http_code}" \
-    -H "Authorization: Bearer $PAT" \
-    "$API_URL/api/v1/projects" 2>&1)
+  local curl_exit=0
+  response=$(curl -sS -w "\n%{http_code}" \
+    -H "Authorization: Bearer $PAT" \
+    "$API_URL/api/v1/projects" 2>&1) || curl_exit=$?
+
+  if [[ $curl_exit -ne 0 ]]; then
+    error "Failed to connect to API (curl exit $curl_exit)"
+    echo ""
+    echo "Response: $response"
+    exit 1
+  fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test_api_connection() {
info "Testing API connection..."
local response
local http_code
local body
response=$(curl -sS -w "\n%{http_code}" \
-H "Authorization: Bearer $PAT" \
"$API_URL/api/v1/projects" 2>&1)
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [[ "$http_code" != "200" ]]; then
error "Failed to connect to API (HTTP $http_code)"
echo ""
echo "Response: $body"
exit 1
fi
test_api_connection() {
info "Testing API connection..."
local response
local http_code
local body
local curl_exit=0
response=$(curl -sS -w "\n%{http_code}" \
-H "Authorization: Bearer $PAT" \
"$API_URL/api/v1/projects" 2>&1) || curl_exit=$?
if [[ $curl_exit -ne 0 ]]; then
error "Failed to connect to API (curl exit $curl_exit)"
echo ""
echo "Response: $response"
exit 1
fi
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [[ "$http_code" != "200" ]]; then
error "Failed to connect to API (HTTP $http_code)"
echo ""
echo "Response: $body"
exit 1
fi
🤖 Prompt for AI Agents
In `@apps/supervisor/scripts/setup-worker.sh` around lines 255 - 274, In
test_api_connection(), curl can fail and abort the script under set -euo
pipefail; modify the curl invocation to capture its exit code (e.g., initialize
curl_exit=0, run response=$(curl -sS -w "\n%{http_code}" -H "Authorization:
Bearer $PAT" "$API_URL/api/v1/projects" 2>&1) || curl_exit=$?), then check
curl_exit first and on non-zero emit a clear error via error "Curl failed (exit
$curl_exit)" plus the captured response/body and exit 1; otherwise parse
http_code/body as before and keep the existing HTTP status check.

Comment on lines +336 to +352
create_worker() {
local json_payload
local make_default_bool

# Convert 0/1 to false/true for JSON boolean
if [[ $MAKE_DEFAULT -eq 1 ]]; then
make_default_bool="true"
else
make_default_bool="false"
fi

json_payload=$(jq -n \
--arg name "$WORKER_NAME" \
--arg projectId "$PROJECT_ID" \
--argjson makeDefault "$make_default_bool" \
'{name: $name, projectId: ($projectId // null), makeDefaultForProject: $makeDefault}')

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the file
find . -name "setup-worker.sh" -type f

Repository: triggerdotdev/trigger.dev

Length of output: 110


🏁 Script executed:

# Test jq behavior with the alternative operator and empty strings
# Create a test to see if // operator treats empty strings as falsy

cat << 'EOF' | jq '.projectId = (if $projectId == "" then null else $projectId end)' --arg projectId ""
{"projectId": ""}
EOF

echo "---"

cat << 'EOF' | jq '.projectId = ($projectId // null)' --arg projectId ""
{"projectId": ""}
EOF

echo "---"

# Test with a non-empty projectId
cat << 'EOF' | jq '.projectId = ($projectId // null)' --arg projectId "my-project"
{"projectId": ""}
EOF
EOF

Repository: triggerdotdev/trigger.dev

Length of output: 216


🏁 Script executed:

# Examine the actual file to confirm the code matches the review comment
sed -n '336,352p' ./apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 530


Fix empty projectId conversion in JSON payload.

jq's alternative operator // only treats null and false as falsy; empty strings are truthy. The current code ($projectId // null) produces "projectId": "" when no project is chosen, but it should be null.

Fix
-    '{name: $name, projectId: ($projectId // null), makeDefaultForProject: $makeDefault}')
+    '{
+      name: $name,
+      projectId: (if $projectId == "" then null else $projectId end),
+      makeDefaultForProject: $makeDefault
+    }')
🤖 Prompt for AI Agents
In `@apps/supervisor/scripts/setup-worker.sh` around lines 336 - 352, In
create_worker, the jq payload currently uses ($projectId // null) which returns
an empty string instead of null when PROJECT_ID is empty; update the jq
expression in the json_payload construction so it explicitly converts an empty
projectId to null (e.g., by testing length or equality and returning null for
empty strings) while still passing PROJECT_ID via --arg, so projectId becomes
null when no project is selected.

Comment on lines +488 to +499
# 9. Validate worker name
if [[ -z "$WORKER_NAME" ]]; then
error "Worker name is required"
echo "Run with --help for usage information"
exit 1
fi

# 10. Resolve project ID
if [[ -n "$PROJECT_REF" ]]; then
resolve_project_id
fi

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 108


🏁 Script executed:

wc -l apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 112


🏁 Script executed:

cat -n apps/supervisor/scripts/setup-worker.sh

Repository: triggerdotdev/trigger.dev

Length of output: 16241


Validate that --default requires a project reference.

Currently, the --default flag can be set via CLI without requiring --project-ref or --project-id. This would result in sending makeDefaultForProject: true with projectId: null to the API, which is invalid since a worker cannot be made default for an unspecified project. The interactive prompt correctly enforces this requirement (lines 211–224), but the CLI path does not.

Suggested fix
   # 9. Validate worker name
   if [[ -z "$WORKER_NAME" ]]; then
     error "Worker name is required"
     echo "Run with --help for usage information"
     exit 1
   fi
+
+  if [[ $MAKE_DEFAULT -eq 1 && -z "$PROJECT_REF" && -z "$PROJECT_ID" ]]; then
+    error "--default requires --project-ref or --project-id"
+    exit 1
+  fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# 9. Validate worker name
if [[ -z "$WORKER_NAME" ]]; then
error "Worker name is required"
echo "Run with --help for usage information"
exit 1
fi
# 10. Resolve project ID
if [[ -n "$PROJECT_REF" ]]; then
resolve_project_id
fi
# 9. Validate worker name
if [[ -z "$WORKER_NAME" ]]; then
error "Worker name is required"
echo "Run with --help for usage information"
exit 1
fi
if [[ $MAKE_DEFAULT -eq 1 && -z "$PROJECT_REF" && -z "$PROJECT_ID" ]]; then
error "--default requires --project-ref or --project-id"
exit 1
fi
# 10. Resolve project ID
if [[ -n "$PROJECT_REF" ]]; then
resolve_project_id
fi
🤖 Prompt for AI Agents
In `@apps/supervisor/scripts/setup-worker.sh` around lines 488 - 499, The CLI
allows the --default flag without a project, causing an invalid payload; add a
validation that if the default flag is set (e.g., DEFAULT or MAKE_DEFAULT
variable) then either PROJECT_REF or PROJECT_ID must be present (or
resolve_project_id must succeed) and otherwise print an error and exit;
implement this check after resolve_project_id is run (use resolve_project_id,
PROJECT_REF, PROJECT_ID and the default flag variable names from the script) so
the CLI path mirrors the interactive prompt enforcement.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant