@elench/testkit 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -30
- package/lib/cli.mjs +55 -3
- package/lib/config.mjs +295 -176
- package/lib/runner.mjs +874 -362
- package/package.json +4 -3
- package/infra/fly-app-ensure.sh +0 -23
- package/infra/fly-build.sh +0 -55
- package/infra/fly-destroy.sh +0 -21
- package/infra/fly-down.sh +0 -19
- package/infra/fly-up.sh +0 -142
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elench/testkit",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "CLI for running
|
|
3
|
+
"version": "0.1.12",
|
|
4
|
+
"description": "CLI for running manifest-defined local test suites across k6 and Playwright",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"testkit": "bin/testkit.mjs"
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
11
|
"lib/",
|
|
12
|
-
"infra/",
|
|
12
|
+
"infra/neon-up.sh",
|
|
13
|
+
"infra/neon-down.sh",
|
|
13
14
|
"vendor/"
|
|
14
15
|
],
|
|
15
16
|
"dependencies": {
|
package/infra/fly-app-ensure.sh
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Ensures the Fly app exists, creating it if necessary.
|
|
3
|
-
# Idempotent — safe to call on every run.
|
|
4
|
-
# Requires: FLY_APP, FLY_ORG
|
|
5
|
-
set -eo pipefail
|
|
6
|
-
|
|
7
|
-
export PATH="$PATH:/snap/bin:$HOME/.fly/bin"
|
|
8
|
-
|
|
9
|
-
FLY_APP="${FLY_APP:?FLY_APP required}"
|
|
10
|
-
FLY_ORG="${FLY_ORG:?FLY_ORG required}"
|
|
11
|
-
|
|
12
|
-
if fly status --app "$FLY_APP" >/dev/null 2>&1; then
|
|
13
|
-
echo "Fly app '$FLY_APP' already exists"
|
|
14
|
-
else
|
|
15
|
-
echo "Creating Fly app '$FLY_APP' in org '$FLY_ORG'..."
|
|
16
|
-
fly apps create "$FLY_APP" --org "$FLY_ORG"
|
|
17
|
-
|
|
18
|
-
# Allocate IPs so *.fly.dev DNS resolves
|
|
19
|
-
fly ips allocate-v4 --shared --app "$FLY_APP"
|
|
20
|
-
fly ips allocate-v6 --app "$FLY_APP"
|
|
21
|
-
|
|
22
|
-
echo "Fly app '$FLY_APP' created"
|
|
23
|
-
fi
|
package/infra/fly-build.sh
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Builds Docker image from current source and pushes to Fly registry.
|
|
3
|
-
# Requires: FLY_APP, FLY_ORG, Docker, fly CLI
|
|
4
|
-
set -eo pipefail
|
|
5
|
-
|
|
6
|
-
export PATH="$PATH:/snap/bin:$HOME/.fly/bin"
|
|
7
|
-
|
|
8
|
-
STATE_DIR="${STATE_DIR:-.state}"
|
|
9
|
-
API_DIR="$(cd "${API_DIR:?API_DIR required — set to the product directory}" && pwd)"
|
|
10
|
-
DOCKERFILE_DIR="$(cd "${DOCKERFILE_DIR:-$API_DIR}" && pwd)"
|
|
11
|
-
FLY_APP="${FLY_APP:?FLY_APP required}"
|
|
12
|
-
|
|
13
|
-
SHORT_SHA=$(git -C "$API_DIR" rev-parse --short HEAD)
|
|
14
|
-
IMAGE="registry.fly.io/$FLY_APP:testkit-$SHORT_SHA"
|
|
15
|
-
|
|
16
|
-
# Warn if working tree is dirty (image will include uncommitted changes
|
|
17
|
-
# but tag references HEAD)
|
|
18
|
-
if ! git -C "$API_DIR" diff --quiet 2>/dev/null; then
|
|
19
|
-
echo "WARNING: uncommitted changes will be included in the build"
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
mkdir -p "$STATE_DIR"
|
|
23
|
-
|
|
24
|
-
# Skip if image tag unchanged (same commit, clean tree)
|
|
25
|
-
if [ -f "$STATE_DIR/fly_image" ]; then
|
|
26
|
-
STORED_IMAGE=$(cat "$STATE_DIR/fly_image")
|
|
27
|
-
if [ "$STORED_IMAGE" = "$IMAGE" ] && git -C "$API_DIR" diff --quiet 2>/dev/null; then
|
|
28
|
-
echo "Image $IMAGE unchanged — skipping build"
|
|
29
|
-
exit 0
|
|
30
|
-
fi
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
# Skip if image already exists in registry (e.g. built by a previous run without state)
|
|
34
|
-
if git -C "$API_DIR" diff --quiet 2>/dev/null; then
|
|
35
|
-
fly auth docker 2>/dev/null
|
|
36
|
-
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
|
|
37
|
-
echo "Image $IMAGE already in registry — skipping build"
|
|
38
|
-
echo "$IMAGE" > "$STATE_DIR/fly_image"
|
|
39
|
-
exit 0
|
|
40
|
-
fi
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
# Ensure the Fly app exists (registry requires it)
|
|
44
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
45
|
-
bash "$SCRIPT_DIR/fly-app-ensure.sh"
|
|
46
|
-
|
|
47
|
-
echo "Building image: $IMAGE"
|
|
48
|
-
docker build -t "$IMAGE" -f "$DOCKERFILE_DIR/Dockerfile" "$API_DIR"
|
|
49
|
-
|
|
50
|
-
echo "Pushing to Fly registry..."
|
|
51
|
-
fly auth docker
|
|
52
|
-
docker push "$IMAGE"
|
|
53
|
-
|
|
54
|
-
echo "$IMAGE" > "$STATE_DIR/fly_image"
|
|
55
|
-
echo "Image ready: $IMAGE"
|
package/infra/fly-destroy.sh
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Destroys the Fly machine permanently (use fly-down.sh for stop/reuse)
|
|
3
|
-
# Requires: FLY_APP
|
|
4
|
-
set -eo pipefail
|
|
5
|
-
|
|
6
|
-
export PATH="$PATH:/snap/bin:$HOME/.fly/bin"
|
|
7
|
-
|
|
8
|
-
STATE_DIR="${STATE_DIR:-.state}"
|
|
9
|
-
FLY_APP="${FLY_APP:?FLY_APP required}"
|
|
10
|
-
|
|
11
|
-
if [ ! -f "$STATE_DIR/fly_machine_id" ]; then
|
|
12
|
-
echo "No Fly machine to destroy"
|
|
13
|
-
exit 0
|
|
14
|
-
fi
|
|
15
|
-
|
|
16
|
-
MACHINE_ID=$(cat "$STATE_DIR/fly_machine_id")
|
|
17
|
-
echo "Destroying Fly machine: $MACHINE_ID"
|
|
18
|
-
fly machines stop "$MACHINE_ID" --app "$FLY_APP" 2>/dev/null || true
|
|
19
|
-
fly machines destroy "$MACHINE_ID" --app "$FLY_APP" --force 2>/dev/null || true
|
|
20
|
-
rm -f "$STATE_DIR/fly_machine_id"
|
|
21
|
-
echo "Fly machine destroyed"
|
package/infra/fly-down.sh
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Stops the Fly machine (preserves it for reuse on next run)
|
|
3
|
-
# Requires: FLY_APP
|
|
4
|
-
set -eo pipefail
|
|
5
|
-
|
|
6
|
-
export PATH="$PATH:/snap/bin:$HOME/.fly/bin"
|
|
7
|
-
|
|
8
|
-
STATE_DIR="${STATE_DIR:-.state}"
|
|
9
|
-
FLY_APP="${FLY_APP:?FLY_APP required}"
|
|
10
|
-
|
|
11
|
-
if [ ! -f "$STATE_DIR/fly_machine_id" ]; then
|
|
12
|
-
echo "No Fly machine to stop"
|
|
13
|
-
exit 0
|
|
14
|
-
fi
|
|
15
|
-
|
|
16
|
-
MACHINE_ID=$(cat "$STATE_DIR/fly_machine_id")
|
|
17
|
-
echo "Stopping Fly machine: $MACHINE_ID"
|
|
18
|
-
fly machines stop "$MACHINE_ID" --app "$FLY_APP" 2>/dev/null || true
|
|
19
|
-
echo "Fly machine stopped (preserved for next run)"
|
package/infra/fly-up.sh
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Ensures a Fly machine is running with the correct env vars and image.
|
|
3
|
-
# Reuses an existing stopped machine if available; creates a new one if not.
|
|
4
|
-
# Requires: FLY_APP, FLY_REGION
|
|
5
|
-
# Image required only for --build or new machines (FLY_IMAGE / FLY_IMAGE_DEFAULT / .state/fly_image)
|
|
6
|
-
# Optional: DB_URL_ENV_NAME (default: DATABASE_URL), FLY_PORT, FLY_ENV_FILE
|
|
7
|
-
set -eo pipefail
|
|
8
|
-
|
|
9
|
-
export PATH="$PATH:/snap/bin:$HOME/.fly/bin"
|
|
10
|
-
|
|
11
|
-
STATE_DIR="${STATE_DIR:-.state}"
|
|
12
|
-
FLY_APP="${FLY_APP:?FLY_APP required}"
|
|
13
|
-
FLY_REGION="${FLY_REGION:-lhr}"
|
|
14
|
-
|
|
15
|
-
# Ensure the Fly app exists (idempotent — creates on first run)
|
|
16
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
|
-
bash "$SCRIPT_DIR/fly-app-ensure.sh"
|
|
18
|
-
|
|
19
|
-
# Resolve image if available (not required yet — may not be needed for reuse)
|
|
20
|
-
if [ -z "$FLY_IMAGE" ] && [ -f "$STATE_DIR/fly_image" ]; then
|
|
21
|
-
FLY_IMAGE="$(cat "$STATE_DIR/fly_image")"
|
|
22
|
-
fi
|
|
23
|
-
FLY_IMAGE="${FLY_IMAGE:-$FLY_IMAGE_DEFAULT}"
|
|
24
|
-
|
|
25
|
-
if [ ! -f "$STATE_DIR/database_url" ]; then
|
|
26
|
-
echo "ERROR: No database_url — run neon-up.sh first"
|
|
27
|
-
exit 1
|
|
28
|
-
fi
|
|
29
|
-
DATABASE_URL=$(cat "$STATE_DIR/database_url")
|
|
30
|
-
|
|
31
|
-
DB_URL_ENV_NAME="${DB_URL_ENV_NAME:-DATABASE_URL}"
|
|
32
|
-
FLY_PORT="${FLY_PORT:-443:3000/tcp:tls:http}"
|
|
33
|
-
|
|
34
|
-
# Load target-specific env args (sets FLY_ENV_ARGS array)
|
|
35
|
-
FLY_ENV_ARGS=()
|
|
36
|
-
if [ -n "$FLY_ENV_FILE" ] && [ -f "$FLY_ENV_FILE" ]; then
|
|
37
|
-
# shellcheck disable=SC1090
|
|
38
|
-
source "$FLY_ENV_FILE"
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
MACHINE_ID=""
|
|
42
|
-
|
|
43
|
-
# ── 1. Try state file ────────────────────────────────────────────────────
|
|
44
|
-
if [ -f "$STATE_DIR/fly_machine_id" ]; then
|
|
45
|
-
EXISTING_ID=$(cat "$STATE_DIR/fly_machine_id")
|
|
46
|
-
if fly machines status "$EXISTING_ID" --app "$FLY_APP" >/dev/null 2>&1; then
|
|
47
|
-
MACHINE_ID="$EXISTING_ID"
|
|
48
|
-
else
|
|
49
|
-
echo "Stored machine $EXISTING_ID gone — will discover or create"
|
|
50
|
-
rm -f "$STATE_DIR/fly_machine_id"
|
|
51
|
-
fi
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
# ── 2. Discover existing machine on the app ──────────────────────────────
|
|
55
|
-
if [ -z "$MACHINE_ID" ]; then
|
|
56
|
-
DISCOVERED_ID=$(fly machines list --app "$FLY_APP" --json 2>/dev/null \
|
|
57
|
-
| jq -r '.[0].id // empty')
|
|
58
|
-
if [ -n "$DISCOVERED_ID" ]; then
|
|
59
|
-
MACHINE_ID="$DISCOVERED_ID"
|
|
60
|
-
echo "Discovered existing machine: $MACHINE_ID"
|
|
61
|
-
fi
|
|
62
|
-
fi
|
|
63
|
-
|
|
64
|
-
# ── 3. Update and start existing machine ─────────────────────────────────
|
|
65
|
-
if [ -n "$MACHINE_ID" ]; then
|
|
66
|
-
echo "Reusing machine $MACHINE_ID — updating config"
|
|
67
|
-
|
|
68
|
-
# Build update args array: always update DATABASE_URL + target env
|
|
69
|
-
UPDATE_ARGS=(--env "$DB_URL_ENV_NAME=$DATABASE_URL" "${FLY_ENV_ARGS[@]}")
|
|
70
|
-
|
|
71
|
-
# Only update image if one was provided (--build was used)
|
|
72
|
-
if [ -n "$FLY_IMAGE" ]; then
|
|
73
|
-
UPDATE_ARGS+=(--image "$FLY_IMAGE")
|
|
74
|
-
fi
|
|
75
|
-
|
|
76
|
-
fly machines update "$MACHINE_ID" --app "$FLY_APP" \
|
|
77
|
-
"${UPDATE_ARGS[@]}" \
|
|
78
|
-
--yes 2>&1
|
|
79
|
-
|
|
80
|
-
# Start if not already running (update may auto-restart)
|
|
81
|
-
fly machines start "$MACHINE_ID" --app "$FLY_APP" 2>/dev/null || true
|
|
82
|
-
fly machines wait "$MACHINE_ID" --app "$FLY_APP" --state started --wait-timeout 60s
|
|
83
|
-
|
|
84
|
-
echo "$MACHINE_ID" > "$STATE_DIR/fly_machine_id"
|
|
85
|
-
fi
|
|
86
|
-
|
|
87
|
-
# ── 4. Create new machine if needed ──────────────────────────────────────
|
|
88
|
-
if [ -z "$MACHINE_ID" ]; then
|
|
89
|
-
# Image is required for new machines
|
|
90
|
-
FLY_IMAGE="${FLY_IMAGE:?FLY_IMAGE required — run with --build or set FLY_IMAGE}"
|
|
91
|
-
|
|
92
|
-
echo "Creating Fly machine (app: $FLY_APP, region: $FLY_REGION)"
|
|
93
|
-
|
|
94
|
-
if ! RESULT=$(fly machines run "$FLY_IMAGE" \
|
|
95
|
-
--app "$FLY_APP" \
|
|
96
|
-
--region "$FLY_REGION" \
|
|
97
|
-
--vm-memory 512 \
|
|
98
|
-
--autostop=stop \
|
|
99
|
-
--env "$DB_URL_ENV_NAME=$DATABASE_URL" \
|
|
100
|
-
"${FLY_ENV_ARGS[@]}" \
|
|
101
|
-
--port "$FLY_PORT" \
|
|
102
|
-
2>&1); then
|
|
103
|
-
echo "ERROR: fly machines run failed:"
|
|
104
|
-
echo "$RESULT"
|
|
105
|
-
exit 1
|
|
106
|
-
fi
|
|
107
|
-
|
|
108
|
-
echo "$RESULT"
|
|
109
|
-
|
|
110
|
-
MACHINE_ID=$(echo "$RESULT" | grep 'Machine ID:' | awk '{print $3}')
|
|
111
|
-
if [ -z "$MACHINE_ID" ]; then
|
|
112
|
-
echo "ERROR: Could not extract machine ID from output"
|
|
113
|
-
exit 1
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
echo "Waiting for machine $MACHINE_ID to start..."
|
|
117
|
-
fly machines wait "$MACHINE_ID" --app "$FLY_APP" --state started --wait-timeout 60s
|
|
118
|
-
fi
|
|
119
|
-
|
|
120
|
-
echo "$MACHINE_ID" > "$STATE_DIR/fly_machine_id"
|
|
121
|
-
|
|
122
|
-
# Ephemeral machines aren't publicly DNS-routable by ID.
|
|
123
|
-
# Route via the app hostname with fly-force-instance-id header.
|
|
124
|
-
HOSTNAME="https://$FLY_APP.fly.dev"
|
|
125
|
-
echo "$HOSTNAME" > "$STATE_DIR/fly_hostname"
|
|
126
|
-
|
|
127
|
-
# Wait for app to become reachable (new apps need DNS propagation)
|
|
128
|
-
echo "Waiting for $HOSTNAME to become reachable..."
|
|
129
|
-
for i in $(seq 1 30); do
|
|
130
|
-
if curl -sf --max-time 5 -o /dev/null "$HOSTNAME/health" \
|
|
131
|
-
-H "fly-force-instance-id: $MACHINE_ID" 2>/dev/null; then
|
|
132
|
-
echo "App reachable after ${i}s"
|
|
133
|
-
break
|
|
134
|
-
fi
|
|
135
|
-
if [ "$i" -eq 30 ]; then
|
|
136
|
-
echo "WARNING: App not reachable after 30s — DNS may still be propagating"
|
|
137
|
-
fi
|
|
138
|
-
sleep 1
|
|
139
|
-
done
|
|
140
|
-
|
|
141
|
-
echo "Fly machine ready: $MACHINE_ID"
|
|
142
|
-
echo "Hostname: $HOSTNAME (routed via fly-force-instance-id header)"
|