In this post, I’ll implement a post deployment check that waits until the application is running with the expected version. The first step is to make the application aware of its version. The easiest way to do that in our setup is with an environment variable. We’ll modify the deployment template of the Helm chart:

  - name: APP_VERSION
    value: {{ .Values.image.tag }}

The .Values.image.tag is already set to the correct version during deployment, so we get this for free.

The second step is to expose this version information from the application. We’ll create a new endpoint, /version, which will simply print this version information:

app.get('/version', (req, res) => res.send(process.env.APP_VERSION));

At this point, our application is able to print its version. We’ll use this endpoint in a script. The script,, will poll this endpoint until it prints the expected version:

# Wait until the version endpoint reports the expected version.
# Usage: version-url expected-version
# Example: 1.3.0
set -e

if [ -z "$VERSION_URL" ]; then
    >&2 echo "ERROR: first parameter should be version URL."
    exit 1

if [ -z "$EXPECTED_VERSION" ]; then
    >&2 echo "ERROR: second parameter should be the expected version."
    exit 1

# how many times to retry

# how many seconds to wait between retries

until [ $n -ge $RETRY_COUNT ]
    echo "Waiting for url $VERSION_URL to be at version $EXPECTED_VERSION, attempt $n..."
    if [ "$EXPECTED_VERSION" = "$ACTUAL_VERSION" ]; then
        echo "Version is correct!"
        exit 0

    echo "Version was $ACTUAL_VERSION"
    sleep $SLEEP_TIME

>&2 echo "ERROR: expected version did not appear in time."
exit 1

To use this script, we’ll add a new step in the deploy template which uses it. First, we’ll setup a few parameters in the template:

  • the host name e.g. for the test environment.
  • app.baseurl: the base URL e.g.
  • app.version.url: the URL the script should use to get the application's version, e.g.

Note that the only parameter we need to specify in the deployment build configurations is the; the others can be calculated based on that:

The build step is simply running the wait-for-version script, with parameters %app.version.url% and %build.number%:

Here’s an example of the output log:

[09:55:39][Step 2/2] Waiting for url to be at version 1.7.1, attempt 0...
[09:55:39][Step 2/2] Version was 1.7.0
[09:55:44][Step 2/2] Waiting for url to be at version 1.7.1, attempt 1...
[09:55:44][Step 2/2] Version was <html>
[09:55:44][Step 2/2] <head><title>503 Service Temporarily Unavailable</title></head>
[09:55:44][Step 2/2] <body bgcolor="white">
[09:55:44][Step 2/2] <center><h1>503 Service Temporarily Unavailable</h1></center>
[09:55:44][Step 2/2] <hr><center>nginx/1.13.6</center>
[09:55:44][Step 2/2] </body>
[09:55:44][Step 2/2] </html>
[09:55:49][Step 2/2] Waiting for url to be at version 1.7.1, attempt 2...
[09:55:49][Step 2/2] Version is correct!

As you can see, initially the version was old (1.7.0 instead of the expected 1.7.1). Then, the app returned 503 as it was being deployed. Finally, the correct version was activated, so the script succeeded.