powershellmockingazure-pipelines-tasks

How to start server in azure pipelines (Linux agent)?


My problem is specifically that I cannot reliably start a mock server in a step and keep it alive for the following steps. Either the server shuts down or the step never completes.

Context: for a couple of days I have been struggling with running a mock server on Azure pipelines. In this case I am using prism mock server, but the same issue applies to any other mock server (e.g. mockoon) I have developed a simple powershell script which reads contents of CSV file, which contains Port and Path columns. Then I create a number of prism mock servers for later use. Here's the key part of the script


foreach($pathAndPortPair in $pathsPortsDictionary.GetEnumerator()) {

  $key = $pathAndPortPair.Name
  $value = $pathAndPortPair.Value
  if (-Not $value.Contains($rootFolder)) {
    $value = Join-Path $rootFolder $value
  }

  if($IsWindows) {
    start-process pwsh.exe -ArgumentList "-noexit -command prism mock -d -p $key $value"
  }
  
  if($IsLinux) {
    ...
  }
}

where $key is port and $value is path to api spec. It all works peachy on my Windows machine. But when I try to run the script on Azure pipeline I encounter a number of issues. Specifically, as I wrote above, I cannot reliably start the server and keep it alive for the following steps.

I tried the following commands to start the server:

  1. Start-Process -FilePath "npx" -ArgumentList "prism mock -d -p $key $value - doesn't work, npm error is displayed.

  2. Invoke-Expression "/bin/bash prism mock -d -p $key $value - doesn't work, bash scripting error: /usr/local/bin/npx: npx: line 3: syntax error near unexpected token (' /usr/local/bin/npx: npx: line 3: const cli = require('../lib/cli.js')

  3. Start-Job -ScriptBlock { prism mock -d -p $key $value } - the Jobs start... but then shut down, presumable just after the server starts. When I run Get-Job command, the Job status is marked as Complete, and no further operations on that server yield and desired results.

  4. Start-Process -FilePath "prism" -ArgumentList "mock -d -p $key $value - this actually starts servers, but because the process runs in foreground, the step never ends in azure pipeline. I also get an error message: "The STDIO streams did not close within 10 seconds of the exit event from process '/usr/bin/pwsh'. This may indicate a child process inherited the STDIO streams and has not yet exited."

  5. start-process pwsh.exe -ArgumentList "-noexit -command prism mock -d -p $key $value" - message is displayed: An error occurred trying to start process 'pwsh.exe' with working | directory '/home/vsts/work/1/s'. No such file or directory

Does anyone have any other ideas? I am completely at a loss. How to run those servers in the background so that the pipeline steps ends, and a new step starts, but the servers are not terminated?


Solution

  • I must admit I gave up on powershell and created a simple bash script that does the job. The key thing was using nohup prefix to prevent the process from being terminated once the step on Azure pipeline was complete. I also redirected outputs into null and set the process into background.

    If there is a similar way to do this in powershell, I have no idea how to do it.

    Anyway, I will share it here so that other people may benefit:

    #!/bin/bash
    # Get root folder of git repo
    rootFolder=$(git rev-parse --show-toplevel)
    
    # Set path to csv file and read it
    echo "Top-level directory: $rootFolder"
    fullPath="$rootFolder/testFiles/csvs/test_csv.csv"
    csv_file=$(cat $fullPath)
    
    # Initialize an empty associative array (dictionary)
    declare -A port_path_dict
    
    # Split the CSV file into lines
    lines=($csv_file)
    
    # Skip the header line
    for ((i=1; i<${#lines[@]}; i++)); do
        # Split each line into port and path
        line="${lines[$i]}"
        IFS=',' read -r port path <<< "$line"
        # Remove quotes from port and path
        port="${port//\"}"
        path="${path//\"}"
        # Add to the dictionary
        port_path_dict["$port"]="$path"
    done
    
    # Iterate over values in the dictionary and start servers
    for port in "${!port_path_dict[@]}"; do
        path=${port_path_dict[$port]}
        # Run mock server but disable terminating it after terminal is closed
        nohup $(npx prism mock -d -p $port ${port_path_dict[$port]}) >/dev/null 2>&1 &
    done