|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# Spin up a local Conductor OSS stack and run the SDK integration suite against |
| 4 | +# it, mirroring the `integration-tests-oss` job in |
| 5 | +# .github/workflows/pull_request.yml. Orkes-only tests are gated out via |
| 6 | +# CONDUCTOR_SERVER_TYPE=oss (see the test:integration:oss npm script). |
| 7 | +# |
| 8 | +# The stack (Conductor OSS + Postgres + httpbin) is defined in |
| 9 | +# scripts/docker-compose-oss.yaml and is torn down automatically on exit. |
| 10 | +# |
| 11 | +# Test output is written to both stdout and a log file (default: |
| 12 | +# scripts/oss-test-run.log, override with -l|--log) so it can be shared later. |
| 13 | +# |
| 14 | +# Usage: |
| 15 | +# scripts/run-integration-oss.sh [-t|--test <path|pattern>] [-l|--log <file>] [--keep-up] [-- jest args] |
| 16 | +# Examples: |
| 17 | +# scripts/run-integration-oss.sh # full OSS-gated suite |
| 18 | +# scripts/run-integration-oss.sh --test WorkflowExecutor |
| 19 | +# scripts/run-integration-oss.sh --log /tmp/oss.log # custom log path |
| 20 | +# scripts/run-integration-oss.sh --keep-up # leave the stack running afterwards |
| 21 | +# scripts/run-integration-oss.sh -- --testPathPatterns="EventClient" |
| 22 | +set -euo pipefail |
| 23 | + |
| 24 | +TEST_PATTERN="" |
| 25 | +KEEP_UP=0 |
| 26 | +LOG_FILE="" |
| 27 | + |
| 28 | +# Print the leading comment block (everything after the shebang up to the first |
| 29 | +# non-comment line) as help text, so it stays in sync with the header above. |
| 30 | +usage() { awk 'NR>1 && /^#/ {sub(/^# ?/, ""); print; next} NR>1 {exit}' "$0"; } |
| 31 | + |
| 32 | +extra=() |
| 33 | +while [[ $# -gt 0 ]]; do |
| 34 | + case "$1" in |
| 35 | + -t|--test) TEST_PATTERN="${2:?--test needs a path or pattern}"; shift 2 ;; |
| 36 | + -l|--log) LOG_FILE="${2:?--log needs a file path}"; shift 2 ;; |
| 37 | + --keep-up) KEEP_UP=1; shift ;; |
| 38 | + -h|--help) usage; exit 0 ;; |
| 39 | + --) shift; extra=("$@"); break ;; |
| 40 | + *) echo "Unknown argument: $1" >&2; usage; exit 1 ;; |
| 41 | + esac |
| 42 | +done |
| 43 | + |
| 44 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 45 | +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" |
| 46 | +COMPOSE_FILE="${SCRIPT_DIR}/docker-compose-oss.yaml" |
| 47 | +LOG_FILE="${LOG_FILE:-${SCRIPT_DIR}/oss-test-run.log}" |
| 48 | +cd "${REPO_ROOT}" |
| 49 | + |
| 50 | +# Guard: this script spins up and tests against a *local* OSS stack. If enterprise |
| 51 | +# / remote server vars are already in the environment they would silently redirect |
| 52 | +# the suite at a deployed server (e.g. sdkdev) and make Orkes-only tests pass, |
| 53 | +# defeating the purpose of the OSS run. Refuse to run unless explicitly overridden. |
| 54 | +if [[ "${ALLOW_REMOTE_SERVER:-0}" != "1" ]]; then |
| 55 | + offending=() |
| 56 | + [[ -n "${CONDUCTOR_AUTH_KEY:-}" ]] && offending+=("CONDUCTOR_AUTH_KEY") |
| 57 | + [[ -n "${CONDUCTOR_AUTH_SECRET:-}" ]] && offending+=("CONDUCTOR_AUTH_SECRET") |
| 58 | + if [[ -n "${CONDUCTOR_SERVER_URL:-}" \ |
| 59 | + && ! "${CONDUCTOR_SERVER_URL}" =~ ^https?://(localhost|127\.0\.0\.1)(:|/|$) ]]; then |
| 60 | + offending+=("CONDUCTOR_SERVER_URL=${CONDUCTOR_SERVER_URL}") |
| 61 | + fi |
| 62 | + if (( ${#offending[@]} > 0 )); then |
| 63 | + echo "Error: refusing to run the OSS suite — remote/enterprise server vars are set:" >&2 |
| 64 | + printf ' - %s\n' "${offending[@]}" >&2 |
| 65 | + echo >&2 |
| 66 | + echo "This script runs against a LOCAL OSS stack. Unset these first:" >&2 |
| 67 | + echo " unset CONDUCTOR_SERVER_URL CONDUCTOR_AUTH_KEY CONDUCTOR_AUTH_SECRET" >&2 |
| 68 | + echo "Or set ALLOW_REMOTE_SERVER=1 to bypass this check intentionally." >&2 |
| 69 | + exit 1 |
| 70 | + fi |
| 71 | +fi |
| 72 | + |
| 73 | +CONDUCTOR_SERVER_URL="${CONDUCTOR_SERVER_URL:-http://localhost:8080/api}" |
| 74 | +HEALTH_URL="${CONDUCTOR_SERVER_URL%/api}/health" |
| 75 | + |
| 76 | +compose() { docker compose -f "${COMPOSE_FILE}" "$@"; } |
| 77 | + |
| 78 | +cleanup() { |
| 79 | + if [[ "${KEEP_UP}" == "1" ]]; then |
| 80 | + echo "--keep-up set: leaving the OSS stack running. Tear down with:" |
| 81 | + echo " docker compose -f ${COMPOSE_FILE} down -v" |
| 82 | + return |
| 83 | + fi |
| 84 | + echo "Tearing down Conductor OSS stack..." |
| 85 | + compose down -v || true |
| 86 | +} |
| 87 | +trap cleanup EXIT |
| 88 | + |
| 89 | +echo "Starting Conductor OSS stack (${COMPOSE_FILE})..." |
| 90 | +compose up -d |
| 91 | + |
| 92 | +echo "Waiting for Conductor to be healthy at ${HEALTH_URL} ..." |
| 93 | +# Portable wait loop using bash's built-in SECONDS (macOS has no `timeout`). |
| 94 | +HEALTH_TIMEOUT="${HEALTH_TIMEOUT:-180}" |
| 95 | +deadline=$(( SECONDS + HEALTH_TIMEOUT )) |
| 96 | +until curl -sf "${HEALTH_URL}" >/dev/null 2>&1; do |
| 97 | + if (( SECONDS >= deadline )); then |
| 98 | + echo "Error: Conductor did not become healthy within ${HEALTH_TIMEOUT}s." >&2 |
| 99 | + compose logs conductor-server || true |
| 100 | + exit 1 |
| 101 | + fi |
| 102 | + sleep 5 |
| 103 | +done |
| 104 | +echo "Conductor is up." |
| 105 | + |
| 106 | +export CONDUCTOR_SERVER_URL |
| 107 | +export CONDUCTOR_SERVER_TYPE=oss |
| 108 | +export HTTPBIN_SERVICE_HOSTNAME="${HTTPBIN_SERVICE_HOSTNAME:-httpbin}" |
| 109 | +export CONDUCTOR_REQUEST_TIMEOUT_MS="${CONDUCTOR_REQUEST_TIMEOUT_MS:-120000}" |
| 110 | +export CONDUCTOR_RETRY_SERVER_ERRORS="${CONDUCTOR_RETRY_SERVER_ERRORS:-true}" |
| 111 | + |
| 112 | +test_cmd=(npm run test:integration:oss -- --ci --runInBand --testTimeout=120000) |
| 113 | +if [[ -n "${TEST_PATTERN}" ]]; then |
| 114 | + # Targeting a specific test: pass it straight through as a path pattern. |
| 115 | + test_cmd+=("--testPathPatterns=${TEST_PATTERN}") |
| 116 | +fi |
| 117 | +if (( ${#extra[@]} > 0 )); then |
| 118 | + test_cmd+=("${extra[@]}") |
| 119 | +fi |
| 120 | + |
| 121 | +if [[ -n "${TEST_PATTERN}" ]]; then |
| 122 | + echo "Running OSS integration tests | test '${TEST_PATTERN}' | server ${CONDUCTOR_SERVER_URL}" |
| 123 | +else |
| 124 | + echo "Running OSS integration tests | full OSS-gated suite | server ${CONDUCTOR_SERVER_URL}" |
| 125 | +fi |
| 126 | +echo "Writing output to ${LOG_FILE}" |
| 127 | + |
| 128 | +# Tee to a log file for later sharing. pipefail ensures the test command's exit |
| 129 | +# status (not tee's) is what propagates. |
| 130 | +"${test_cmd[@]}" 2>&1 | tee "${LOG_FILE}" |
0 commit comments