Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/e2e-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ jobs:
fi
ls -la e2e/wasms/

- name: Load Stellar quickstart pin (SSOT)
run: |
set -a
. "$GITHUB_WORKSPACE/stellar-pin.env"
set +a
echo "STELLAR_QUICKSTART_IMAGE=$STELLAR_QUICKSTART_IMAGE" >> "$GITHUB_ENV"
echo "STELLAR_PROTOCOL_VERSION=$STELLAR_PROTOCOL_VERSION" >> "$GITHUB_ENV"

- name: Run E2E tests
env:
STELLAR_CLI_IMAGE: ${{ env.REGISTRY }}/${{ env.ORG }}/stellar-cli:${{ inputs.stellar_cli_version }}
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ jobs:
fi
ls -la e2e/wasms/

- name: Load Stellar quickstart pin (SSOT)
run: |
set -a
. "$GITHUB_WORKSPACE/stellar-pin.env"
set +a
echo "STELLAR_QUICKSTART_IMAGE=$STELLAR_QUICKSTART_IMAGE" >> "$GITHUB_ENV"
echo "STELLAR_PROTOCOL_VERSION=$STELLAR_PROTOCOL_VERSION" >> "$GITHUB_ENV"

- name: Run E2E tests
env:
STELLAR_CLI_IMAGE: ${{ env.REGISTRY }}/${{ env.ORG }}/stellar-cli:${{ steps.versions.outputs.stellar_cli }}
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/invite-gate-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ jobs:
mkdir -p "$GITHUB_WORKSPACE/playwright/freighter-extension"
cp -r extension/build/. "$GITHUB_WORKSPACE/playwright/freighter-extension/"

- name: Load Stellar quickstart pin (SSOT)
run: |
set -a
. "$GITHUB_WORKSPACE/stellar-pin.env"
set +a
echo "STELLAR_QUICKSTART_IMAGE=$STELLAR_QUICKSTART_IMAGE" >> "$GITHUB_ENV"
echo "STELLAR_PROTOCOL_VERSION=$STELLAR_PROTOCOL_VERSION" >> "$GITHUB_ENV"

- name: Run invite-gate tests
env:
PROVIDER_CONSOLE_PATH: ./provider-console
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/lifecycle-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ jobs:
fi
ls -la e2e/wasms/

- name: Load Stellar quickstart pin (SSOT)
run: |
set -a
. "$GITHUB_WORKSPACE/stellar-pin.env"
set +a
echo "STELLAR_QUICKSTART_IMAGE=$STELLAR_QUICKSTART_IMAGE" >> "$GITHUB_ENV"
echo "STELLAR_PROTOCOL_VERSION=$STELLAR_PROTOCOL_VERSION" >> "$GITHUB_ENV"

- name: Run Lifecycle E2E
env:
PROVIDER_IMAGE: ${{ inputs.provider_image_override != '' && inputs.provider_image_override || format('{0}/{1}/provider-platform:{2}', env.REGISTRY, env.ORG, inputs.provider_version) }}
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/multi-asset-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ jobs:
fi
ls -la e2e/wasms/

- name: Load Stellar quickstart pin (SSOT)
run: |
set -a
. "$GITHUB_WORKSPACE/stellar-pin.env"
set +a
echo "STELLAR_QUICKSTART_IMAGE=$STELLAR_QUICKSTART_IMAGE" >> "$GITHUB_ENV"
echo "STELLAR_PROTOCOL_VERSION=$STELLAR_PROTOCOL_VERSION" >> "$GITHUB_ENV"

- name: Run Multi-Asset E2E
env:
PROVIDER_IMAGE: ${{ inputs.provider_image_override != '' && inputs.provider_image_override || format('{0}/{1}/provider-platform:{2}', env.REGISTRY, env.ORG, inputs.provider_version) }}
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/quickstart-drift.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Quickstart protocol drift alarm

# Warns when Stellar testnet advances past the protocol our quickstart pin is
# frozen to (STELLAR_PROTOCOL_VERSION in stellar-pin.env). While testnet is ahead
# of the pin, this posts to Discord on EVERY scheduled run — a weekly nag, no
# stored state — until the pin is bumped.
#
# Wired to secrets.DISCORD_WEBHOOK_URL but DORMANT until that secret is set
# out-of-band: with no secret it logs the drift and posts nothing. The webhook
# URL is read ONLY from the secret — never hardcoded, never from iac.

on:
schedule:
- cron: "0 9 * * 1" # Mondays 09:00 UTC
workflow_dispatch:

permissions:
contents: read

jobs:
drift-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Compare testnet protocol to our pin
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run: |
set -euo pipefail

# Our pinned protocol — single source of truth.
set -a
. ./stellar-pin.env
set +a
ours="$STELLAR_PROTOCOL_VERSION"

# Testnet's live protocol: Horizon primary, Soroban RPC fallback.
testnet="$(curl -sf https://horizon-testnet.stellar.org/ \
| jq -r '.current_protocol_version // empty' || true)"
if [ -z "$testnet" ]; then
testnet="$(curl -sf https://soroban-testnet.stellar.org \
-X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getNetwork"}' \
| jq -r '.result.protocolVersion // empty' || true)"
fi

case "$testnet" in
''|*[!0-9]*) echo "Could not read a numeric testnet protocol (got '$testnet'); skipping."; exit 0;;
esac
echo "Testnet protocol: $testnet | our pin: $ours"

if [ "$testnet" -le "$ours" ]; then
echo "Pin is current (testnet $testnet <= pin $ours). No drift."
exit 0
fi
echo "DRIFT: testnet ($testnet) is ahead of our pin ($ours)."

if [ -z "${DISCORD_WEBHOOK_URL:-}" ]; then
echo "DISCORD_WEBHOOK_URL not set — alarm is dormant, not posting."
exit 0
fi

printf -v msg '%s\n%s\n%s' \
":warning: **Stellar quickstart pin is behind testnet**" \
"Testnet is on protocol **$testnet**; local-dev is pinned to protocol **$ours**." \
"Bump the pin in \`local-dev/stellar-pin.env\` (STELLAR_QUICKSTART_IMAGE + STELLAR_PROTOCOL_VERSION). It feeds the docker-compose.*.yml files, e2e/lifecycle/multi-asset compose, test.sh, infra-up.sh, down.sh and lifecycle/provider.ts."

jq -n --arg content "$msg" '{content: $content}' \
| curl -sf -X POST -H 'Content-Type: application/json' -d @- "$DISCORD_WEBHOOK_URL" \
&& echo "Posted drift alert to Discord."
7 changes: 5 additions & 2 deletions docker-compose.e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.governance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.invite-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.lifecycle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.multi-asset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.otel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.pos-instant.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
healthcheck:
test: >
curl -sf http://localhost:8000/soroban/rpc -X POST
Expand Down
8 changes: 8 additions & 0 deletions down.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BASE_DIR="${BASE_DIR:-$(dirname "$SCRIPT_DIR")}"

# Stellar quickstart pin (single source of truth) — exported so the lifecycle
# `docker compose down` below can interpolate the pinned image without warnings.
set -a
# shellcheck source=stellar-pin.env
. "$SCRIPT_DIR/stellar-pin.env"
set +a

PROVIDER_PLATFORM_PATH="${PROVIDER_PLATFORM_PATH:-$BASE_DIR/provider-platform}"
COUNCIL_PLATFORM_PATH="${COUNCIL_PLATFORM_PATH:-$BASE_DIR/council-platform}"
NETWORK_DASHBOARD_PLATFORM_PATH="${NETWORK_DASHBOARD_PLATFORM_PATH:-$BASE_DIR/network-dashboard-platform}"
Expand Down
7 changes: 5 additions & 2 deletions e2e/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ services:
retries: 15

stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
ports:
- "8000:8000"
healthcheck:
Expand Down
24 changes: 17 additions & 7 deletions infra-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BASE_DIR="${BASE_DIR:-$(dirname "$SCRIPT_DIR")}"

# Stellar quickstart pin (image tag + local-network protocol) — single source of
# truth, shared with the compose files, test.sh, provider.ts and the drift alarm.
set -a
# shellcheck source=stellar-pin.env
. "$SCRIPT_DIR/stellar-pin.env"
set +a

PROVIDER_PLATFORM_PATH="${PROVIDER_PLATFORM_PATH:-$BASE_DIR/provider-platform}"
PROVIDER_CONSOLE_PATH="${PROVIDER_CONSOLE_PATH:-$BASE_DIR/provider-console}"
COUNCIL_CONSOLE_PATH="${COUNCIL_CONSOLE_PATH:-$BASE_DIR/council-console}"
Expand Down Expand Up @@ -146,13 +154,15 @@ if curl -sf "http://localhost:${STELLAR_RPC_PORT}/soroban/rpc" -X POST \
info "Stellar RPC on port $STELLAR_RPC_PORT is healthy (shared)."
else
info "Stellar RPC not running, starting local network..."
# Pin to v639-b1103.1-latest — see local-dev PR #120: the rolling
# stellar/quickstart:testing tag (default for `stellar container start`)
# silently rejects all WASM uploads with HostError(Context,
# InternalError) since 2026-06-15. PR #120 pinned the docker-compose
# paths; this pins the CLI path used by up.sh.
stellar container start local --image-tag-override v639-b1103.1-latest 2>/dev/null \
|| stellar container start local 2>/dev/null \
# Image tag + protocol come from stellar-pin.env (SSOT). --protocol-version is
# a WORKAROUND for the quickstart image's broken default (it selects protocol
# 25 on an image whose stellar-core is v27, which fails every WASM upload with
# HostError(Context, InternalError)); remove it when a fixed image ships.
stellar_tag="${STELLAR_QUICKSTART_IMAGE#stellar/quickstart:}"
stellar container start local \
--image-tag-override "$stellar_tag" \
--protocol-version "$STELLAR_PROTOCOL_VERSION" 2>/dev/null \
|| stellar container start local --image-tag-override "$stellar_tag" 2>/dev/null \
|| true

info "Waiting for Stellar RPC to be ready..."
Expand Down
7 changes: 5 additions & 2 deletions lifecycle/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
services:
stellar:
image: stellar/quickstart:v639-b1103.1-latest
command: --local --limits unlimited
# Pinned build + protocol come from stellar-pin.env (SSOT). --protocol-version is a
# WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27 image),
# which fails contract upload; remove it when a fixed image ships. See stellar-pin.env.
image: ${STELLAR_QUICKSTART_IMAGE}
command: --local --limits unlimited --protocol-version ${STELLAR_PROTOCOL_VERSION}
ports:
- "8000:8000"
healthcheck:
Expand Down
33 changes: 32 additions & 1 deletion lifecycle/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,35 @@ const PROVIDER_PORT = 3030;

const NETWORK_PASSPHRASE = "Standalone Network ; February 2017";

// Stellar quickstart pin (image tag + local-network protocol) — read from the
// single source of truth (stellar-pin.env at the repo root) so this local-runner
// path can't drift from the compose files / infra-up.sh. --protocol-version is a
// WORKAROUND for the image's broken default (protocol 25 on a stellar-core v27
// image, which fails WASM upload); remove it when a fixed image ships.
function loadStellarPin(): { image: string; protocolVersion: string } {
const env = Deno.readTextFileSync(
new URL("../stellar-pin.env", import.meta.url),
);
const vars: Record<string, string> = {};
for (const line of env.split("\n")) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const eq = trimmed.indexOf("=");
if (eq === -1) continue;
vars[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim();
}
const image = vars["STELLAR_QUICKSTART_IMAGE"];
const protocolVersion = vars["STELLAR_PROTOCOL_VERSION"];
if (!image || !protocolVersion) {
throw new Error(
"stellar-pin.env missing STELLAR_QUICKSTART_IMAGE / STELLAR_PROTOCOL_VERSION",
);
}
return { image, protocolVersion };
}

const STELLAR_PIN = loadStellarPin();

export interface Infrastructure {
rpcUrl: string;
friendbotUrl: string;
Expand Down Expand Up @@ -58,10 +87,12 @@ export async function startStellar(): Promise<{
STELLAR_CONTAINER,
"-p",
`${STELLAR_PORT}:8000`,
"stellar/quickstart:latest",
STELLAR_PIN.image,
"--local",
"--limits",
"unlimited",
"--protocol-version",
STELLAR_PIN.protocolVersion,
]);

// Wait for RPC health
Expand Down
Loading
Loading