Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/build-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,7 @@ jobs:

# Move the built binary to the expected location
mkdir -p target/x86_64-pc-windows-gnu/release
chmod -R ug+rwX target/x86_64-pc-windows-gnu/release
cp -f temporal-service/temporal-service.exe target/x86_64-pc-windows-gnu/release/temporal-service.exe
mv temporal-service/temporal-service.exe target/x86_64-pc-windows-gnu/release/temporal-service.exe
echo "temporal-service.exe built successfully for Windows"

- name: Download temporal CLI (Linux/macOS)
Expand Down Expand Up @@ -401,4 +400,4 @@ jobs:
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # pin@v4
with:
name: goose-${{ matrix.architecture }}-${{ matrix.target-suffix }}
path: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT }}
87 changes: 26 additions & 61 deletions temporal-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"time"

Expand Down Expand Up @@ -177,79 +176,45 @@ func findTemporalCLI() (string, error) {

// If not found in PATH, try different possible locations for the temporal CLI
log.Println("Checking bundled/local locations for temporal CLI...")
currentPaths := []string{
"./temporal",
"./temporal.exe",
}
if path, err := getExistingTemporalCLIFrom(currentPaths); err == nil {
return path, nil
} else {
log.Printf("Attempt to find in local directory failed: %s.", err)
possiblePaths := []string{
"./temporal", // Current directory
}

// Also try relative to the current executable (most important for bundled apps)
exePath, err := os.Executable()
if err != nil {
if exePath, err := os.Executable(); err == nil {
exeDir := filepath.Dir(exePath)
log.Printf("Executable directory: %s", exeDir)
additionalPaths := []string{
filepath.Join(exeDir, "temporal"),
filepath.Join(exeDir, "temporal.exe"), // Windows
// Also try one level up (for development)
filepath.Join(exeDir, "..", "temporal"),
filepath.Join(exeDir, "..", "temporal.exe"),
}
possiblePaths = append(possiblePaths, additionalPaths...)
log.Printf("Will check these additional paths: %v", additionalPaths)
} else {
log.Printf("Failed to get executable path: %v", err)
}
exeDir := filepath.Dir(exePath)
log.Printf("Executable directory: %s", exeDir)
additionalPaths := []string{
filepath.Join(exeDir, "temporal"),
filepath.Join(exeDir, "temporal.exe"), // Windows
// Also try one level up (for development)
filepath.Join(exeDir, "..", "temporal"),
filepath.Join(exeDir, "..", "temporal.exe"),
}
log.Printf("Will check these additional paths: %v", additionalPaths)
return getExistingTemporalCLIFrom(additionalPaths)
}

// getExistingTemporalCLIFrom gets a list of paths and returns one of those that is an existing and working Temporal CLI binary
func getExistingTemporalCLIFrom(possiblePaths []string) (string, error) {
log.Printf("Checking %d possible paths for temporal CLI", len(possiblePaths))

// Check all possible paths in parallel, pick the first one that works.
pathFound := make(chan string)
var wg sync.WaitGroup
// This allows us to cancel whatever remaining work is done when we find a valid path.
psCtx, psCancel := context.WithCancel(context.Background())
// Test each possible path
for i, path := range possiblePaths {
wg.Add(1)
go func() {
defer wg.Done()
log.Printf("Checking path %d/%d: %s", i+1, len(possiblePaths), path)
if _, err := os.Stat(path); err != nil {
log.Printf("File does not exist at %s: %v", path, err)
return
}
log.Printf("Checking path %d/%d: %s", i+1, len(possiblePaths), path)
if _, err := os.Stat(path); err == nil {
log.Printf("File exists at: %s", path)
// File exists, test if it's executable and the right binary
cmd := exec.CommandContext(psCtx, path, "--version")
if err := cmd.Run(); err != nil {
log.Printf("Failed to verify temporal CLI at %s: %v", path, err)
return
}
select {
case pathFound <- path:
cmd := exec.Command(path, "--version")
if err := cmd.Run(); err == nil {
log.Printf("Successfully verified temporal CLI at: %s", path)
case <-psCtx.Done():
// No need to report the path not chosen.
return path, nil
} else {
log.Printf("Failed to verify temporal CLI at %s: %v", path, err)
}
}()
}
// We transform the workgroup wait into a channel so we can wait for either this or pathFound
pathNotFound := make(chan bool)
go func() {
wg.Wait()
pathNotFound <- true
}()
select {
case path := <-pathFound:
psCancel() // Cancel the remaining search functions otherwise they'll just exist eternally.
return path, nil
case <-pathNotFound:
// No need to do anything, this just says that none of the functions were able to do it and there's nothing left to cleanup
} else {
log.Printf("File does not exist at %s: %v", path, err)
}
}

return "", fmt.Errorf("temporal CLI not found in PATH or any of the expected locations: %v", possiblePaths)
Expand Down
Binary file modified temporal-service/temporal-service
Binary file not shown.
Loading