Echoing hello, qDup or howdy, qDup introduces us to qDup, but now we want to use qDup to automate work. We are going to write a qDup script that builds our application and tests to make sure it is working.
This tutorial will walk through downloading and building one of the quarkus getting started applications. This introduces to:
-
how qDup handles interactive commands
-
how to observe running commands
-
how to handle common issues with re-running scripts
-
how to coordinate between scripts
qDup connects to computers through ssh. You need to have a computer that will accept ssh connections. You can setup ssh on your own computer by following the steps in the prerequisites
We are going to use the Quarkus getting started project. The best practice is to open a terminal and test each command to get familiar with the input and output. We normally run commands in terminal before adding them to a qDup script to see how the commands behave.
#> cat <<EOF > quarkus.yaml
scripts:
test-endpoint:
- wait-for: ready
then:
- sh: curl localhost:8080/hello
- signal: done #tells qDup that the "testing" is done
ensure-quarkus-cli:
- sh: quarkus version #to see if the command exists
then:
- regex: "command not found"
then: #install quarkus by following: https://quarkus.io/get-started/
- sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/"
- sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio"
- sh: "source ~/.bashrc" # jbang change your environment if you don't have jbang in the PATH
getting-started:
- sh: cd /tmp/
- sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" # prevent cloning again
- sh: cd quarkus-quickstarts
- sh: cd getting-started
- script: ensure-quarkus-cli
- sh:
command: quarkus dev
prompt:
"Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r"
timer:
2m: #a short timeout
- abort: quarkus dev did not exit before the timer expired
watch:
- regex: "Tests completed"
then:
- signal: ready
on-signal:
done:
- ctrlC #exits the process
hosts:
test: $USER@localhost
roles:
setup-env:
hosts:
- test
run-scripts:
- getting-started
- test-endpoint
EOFRun with java -jar qDup-0.8.5-uber.jar -i ~/.ssh/qdup quarkus.yaml -ix. It will take some time and in the end you will see:
All 2 tests are passing (0 skipped), 2 tests were run in 4289ms. Tests completed at 13:34:11.
Press [e] to edit command line args (currently ''), [r] to re-run, [o] Toggle test output, [:] for the terminal, [h] for more options>
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.915 s
[INFO] Finished at: 2025-01-09T13:34:12-03:00
[INFO] ------------------------------------------------------------------------
Finished in 31.238 at /tmp/20250109_133335It means that the qDup script worked fine and finished in 31 seconds.
Change directory to /tmp and clone the repository if quarkus-quickstarts doesn’t exist. Change directory to quarkus-quickstarts and then to getting-started
- sh: cd /tmp/
- sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git"
- sh: cd quarkus-quickstarts
- sh: cd getting-startedCall the qDup ensure-quarkus-cli script.
- script: ensure-quarkus-cliCall quarkus version command and if the command has an output that matches command not found, then install quarkus using jbang
ensure-quarkus-cli:
- sh: quarkus version
then:
- regex: "command not found"
then:
- sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/"
- sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio"
- sh: "source ~/.bashrc"quarkus dev is interactive and expects user input. When the output matches Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options> we simulate pressing the letter r. This will run the test but quarkus dev does not exit, and we want to test the endpoints while the process is running. When the output has Tests completed, send the signal ready.
- sh:
command: quarkus dev
prompt:
"Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r"
watch:
- regex: "Tests completed"
then:
- signal: readyWhen the qDup script test-endpoint receives the ready signal, call the endpoint and send the signal done
The curl output will show the output in the qDup console but qDup will not exit because the quarkus dev is still running.
test-endpoint:
- wait-for: ready
then:
- sh: curl localhost:8080/hello
- signal: doneWhen the qDup script receives the done signal, send the SIGINT POSIX signal. This will stop the quarkus dev command and exit the qDup script.
on-signal:
done:
- ctrlCIf you rerun the script, it will fail because you have quarkus-quickstarts folder. In order to workaround that, we add the command [[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts. The command will have the exit code 0 if the folder doesn’t exist. If the folder exists, the command will exit with code 1. The -ix flag is added to the command line above to ignore individual status code checks for simplicity. However, in a production environment, your bash scripts should be designed to return an exit code of 0.
Some of you may find the qDup process is still stuck and you are not seeing curl in the logs. This usually happens when quarkus dev does not log Tests paused because it had an issue starting. qDup has an internal web server that exposes diagnostics data. We can get the active commands with:
curl localhost:31337/activeIf you see quarkus dev as an active command then check the output for an error message. Most of the time we get errors due to port conflicts (something else is using port 8080).
We don’t want our qDup scripts getting stuck in our automated environment. We add a timer to any sh commands that do not automatically exit. This forces a limit on execution time and alerts us to errors.
timer:
2m:
- abort: quarkus dev did not exit before the timer expiredAt this point you know how to write a script and how to work with sh commands that prompt and do not automatically exit. Next we will explore using setup-scripts and cleaup-scripts and how to work with commands that package their own cli by using hyperfoil to load test the getting-started application