beta
Documentation

Capture After a Deploy

The most common use of the API: once a new version is live on an environment, capture it, compare it, and read the verdict — from a deploy script, a pipeline step, or any tool that can make an HTTP call.

Before you start

The steps

  1. Start a capture batch on the environment: POST …/environments/{environment_id}/capture-batches. Keep the id it answers.
  2. Wait for it to end and its diffs to be started. Read the batch every few seconds until its status is DONE, WARN or ERROR and its auto_diffs is no longer null. Both: the diffs are started just after the capture ends.
  3. Wait for each diff. For each of auto_diffs.self and auto_diffs.reference whose status is launched, read the diff batch named by diff_batch_id until its status is DONE, CANCELLED or ERROR.
  4. Read the verdict of each diff: PASS, WARN, FAIL or SKIPPED — or no verdict, when the diff batch ended in ERROR: its error says why, as when the reference environment has no capture yet. What it means for your release is yours to decide — stop on FAIL, report a WARN, or only link to the diff in the dashboard.

Give the whole a time limit: a capture takes from seconds to a few minutes, depending on the number of pages and how fast they load.

An example in shell

With curl and jq:

shell
#!/usr/bin/env bash
set -euo pipefail

API="https://deploydiff.com/api/v1/projects/$DEPLOYDIFF_PROJECT_ID"
AUTH="Authorization: Bearer $DEPLOYDIFF_API_KEY"
ENVIRONMENT="$DEPLOYDIFF_ENVIRONMENT_ID"
deadline=$((SECONDS + 900)) # 15 minutes for the whole

# Read an address. Stop on an error the API answers — a revoked key, an id
# not found — and show it: an error answer is `{"error": …}`, never an
# object, which has an `object` field (and may have an `error` of its own).
# An answer that is not JSON, such as the firewall's 429, is left to the
# loop, which reads again.
read_api() {
  local body
  body=$(curl -sS -H "$AUTH" "$1")
  if jq -e '.object == null and .error != null' <<<"$body" >/dev/null 2>&1; then
    echo "$body" >&2
    exit 1
  fi
  printf '%s' "$body"
}

wait_or_give_up() {
  [ "$SECONDS" -lt "$deadline" ] || { echo "Timed out" >&2; exit 1; }
  sleep 10
}

start_capture() {
  curl -sS -X POST -H "$AUTH" "$API/environments/$ENVIRONMENT/capture-batches"
}

# 1. Start the capture. A capture on demand too soon after the last one is
#    refused with the seconds to wait: wait them once, and try again.
batch=$(start_capture)
if [ "$(jq -r '.error.code // empty' <<<"$batch" 2>/dev/null)" = "capture_interval" ]; then
  sleep "$(jq -r '.error.retry_after' <<<"$batch")"
  batch=$(start_capture)
fi
id=$(jq -r '.id // empty' <<<"$batch" 2>/dev/null || true)
[ -n "$id" ] || { echo "$batch" >&2; exit 1; }

# 2. Wait until it has ended and its automatic diffs are settled.
until jq -e '(.status | IN("DONE", "WARN", "ERROR")) and .auto_diffs != null' <<<"$batch" >/dev/null 2>&1; do
  wait_or_give_up
  batch=$(read_api "$API/capture-batches/$id")
done

# 3 and 4. Wait for each diff it started, and print its verdict — or, for a
#    diff that ended in Error, its error code.
for diff_id in $(jq -r '.auto_diffs | (.self, .reference) | select(.status == "launched") | .diff_batch_id' <<<"$batch"); do
  diff=$(read_api "$API/diff-batches/$diff_id")
  until jq -e '.status | IN("DONE", "CANCELLED", "ERROR")' <<<"$diff" >/dev/null 2>&1; do
    wait_or_give_up
    diff=$(read_api "$API/diff-batches/$diff_id")
  done
  echo "$diff_id: $(jq -r '.verdict // .error.code' <<<"$diff")"
done

Each read is a billed call: reading every 10 seconds, a capture of a few minutes and its diffs take a few dozen calls. See the rate on the pricing page.

Without automated diffing

To compare with something of your choosing instead, start the diff yourself once the capture is DONE or WARN: POST …/diff-batches with your capture batch as the candidate and, as the reference, any finished capture batch of the project — for the environment's previous capture, the latest batch before yours in its list that is DONE or WARN.

When something goes wrong

See errors for every answer the API can give.