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
66 changes: 66 additions & 0 deletions .github/docker-compose/laravel-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: manticore-streams-laravel-tests

services:
mysql:
image: mysql:5.7.22@sha256:aaba540cdd9313645d892f4f20573e8b42b30e5be71c054b7befed2f7da5f85b
platform: linux/amd64
environment:
MYSQL_DATABASE: mysql
MYSQL_ROOT_PASSWORD: mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -pmysql --silent"]
interval: 5s
timeout: 3s
retries: 60

manticore:
image: streams/manticore:ci
platform: linux/amd64
environment:
MANTICORE_RULES: json=json|url=url|text=source|text=text|text=title|text=statustext|url=merged|url=merged2
MANTICORE_PORT: "9306"
PIPELINE: m
INSTANCE_LABEL: laravel-tests
STAGE: dev
BLACKLIST_MODE: "1"
healthcheck:
test: ["CMD-SHELL", "mysql -h 127.0.0.1 -P 9306 -e 'SELECT * FROM m_cluster:pq LIMIT 0'"]
interval: 5s
timeout: 3s
retries: 60

columnar:
image: manticoresearch/manticore:25.0.0@sha256:4b1595624dbe4a9f917c34e65a06455793fecee15d3b74c4f03c0eb28de7e1c1
platform: linux/amd64
environment:
EXTRA: "1"
searchd_mysql_version_string: "5.5.21"
searchd_max_packet_size: "128M"
searchd_pid_file: /tmp/searchd.pid
healthcheck:
test: ["CMD-SHELL", "mysql -h 127.0.0.1 -P 9306 -e 'SELECT 1'"]
interval: 5s
timeout: 3s
retries: 60

ui:
image: streams/ui:ci
platform: linux/amd64
environment:
DB_HOST: mysql
DB_DATABASE: mysql
DB_USERNAME: root
DB_PASSWORD: mysql
MANTICORE_HOST: manticore
MANTICORE_PORT: "9306"
COLUMNAR_HOST: columnar
COLUMNAR_PORT: "9306"
extra_hosts:
- "dev.manticoresearch.com=127.0.0.1"
depends_on:
mysql:
condition: service_healthy
manticore:
condition: service_healthy
columnar:
condition: service_healthy
8 changes: 8 additions & 0 deletions .github/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CI scripts

This directory contains helpers owned by GitHub Actions workflows.

- `k8s/` contains K3s E2E orchestration and diagnostics invoked by `.github/workflows/ci.yml`.
- `materialize-chart-version.sh` materializes the source-archive chart version for CI packaging and releases.

The developer-run local K3d/K3s harness may reuse these CI helpers; its entry points remain in `dev-environment/`.
7 changes: 7 additions & 0 deletions .github/scripts/k8s/capture-kafka-start-offsets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euxo pipefail

input_start_offset=$(kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-get-offsets.sh --bootstrap-server localhost:9092 --topic my-docs | awk -F: 'END { print $3 }')
start_offset=$(kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-get-offsets.sh --bootstrap-server localhost:9092 --topic my-results | awk -F: 'END { print $3 }')
echo "INPUT_START_OFFSET=${input_start_offset:-0}" >> "$GITHUB_ENV"
echo "START_OFFSET=${start_offset:-0}" >> "$GITHUB_ENV"
23 changes: 23 additions & 0 deletions .github/scripts/k8s/collect-diagnostics.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env sh
set -u

ARTIFACT_DIR=${1:-artifacts/k8s}
APP_NAMESPACE=${APP_NAMESPACE:-manticore-streams}
KAFKA_NAMESPACE=${KAFKA_NAMESPACE:-kafka}
RELEASE_NAME=${RELEASE_NAME:-manticore-streams}
KUBECTL_TIMEOUT=${KUBECTL_TIMEOUT:-30s}
mkdir -p "$ARTIFACT_DIR"

for namespace in "$APP_NAMESPACE" "$KAFKA_NAMESPACE"; do
kubectl --request-timeout="$KUBECTL_TIMEOUT" get all,cm,pvc -n "$namespace" -o wide >"$ARTIFACT_DIR/${namespace}-resources.txt" 2>&1 || true
kubectl --request-timeout="$KUBECTL_TIMEOUT" get events -n "$namespace" --sort-by=.lastTimestamp >"$ARTIFACT_DIR/${namespace}-events.txt" 2>&1 || true
for pod in $(kubectl --request-timeout="$KUBECTL_TIMEOUT" get pods -n "$namespace" -o name 2>/dev/null || true); do
safe_name=$(printf '%s' "$pod" | tr '/' '_')
(
kubectl --request-timeout="$KUBECTL_TIMEOUT" describe -n "$namespace" "$pod" >"$ARTIFACT_DIR/${namespace}-${safe_name}-describe.txt" 2>&1 || true
) &
done
wait
done
timeout 45s helm status "$RELEASE_NAME" -n "$APP_NAMESPACE" >"$ARTIFACT_DIR/helm-status.txt" 2>&1 || true
kubectl --request-timeout="$KUBECTL_TIMEOUT" get nodes -o wide >"$ARTIFACT_DIR/nodes.txt" 2>&1 || true
5 changes: 5 additions & 0 deletions .github/scripts/k8s/create-kafka-test-topics.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euxo pipefail

kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --if-not-exists --topic my-docs --partitions=1 --replication-factor=1
kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --if-not-exists --topic my-results --partitions=1 --replication-factor=1
17 changes: 17 additions & 0 deletions .github/scripts/k8s/import-ci-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euxo pipefail

tag=$(awk '/^appVersion:/ { print $2; exit }' helm-chart/Chart.yaml)
for image_archive in ci-images/*.tar.gz; do
gzip -dc "$image_archive" | docker load
done
components=(manticore scaler rules_checker worker ui ui-nginx)
for component in "${components[@]}"; do
docker image inspect "streams/${component}:ci" >/dev/null
docker tag "streams/${component}:ci" "ghcr.io/manticoresoftware/streams/${component}:${tag}"
done
for component in "${components[@]}"; do
image="ghcr.io/manticoresoftware/streams/${component}:${tag}"
docker image save "$image" | sudo k3s ctr -n k8s.io images import -
sudo k3s ctr -n k8s.io images list -q | grep -Fx "$image"
done
49 changes: 49 additions & 0 deletions .github/scripts/k8s/install-k3s.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
set -euo pipefail

: "${K3S_VERSION:?K3S_VERSION must be set}"
: "${K3S_BINARY_SHA256:?K3S_BINARY_SHA256 must be set}"

workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
k3s_binary="$workdir/k3s"
curl --fail --location --proto '=https' --tlsv1.2 --retry 3 \
--output "$k3s_binary" \
"https://github.com/k3s-io/k3s/releases/download/${K3S_VERSION}/k3s"
printf '%s %s\n' "$K3S_BINARY_SHA256" "$k3s_binary" | sha256sum --check --status

sudo install -m 0755 "$k3s_binary" /usr/local/bin/k3s
sudo tee /etc/systemd/system/k3s.service >/dev/null <<'EOF'
[Unit]
Description=Lightweight Kubernetes
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
KillMode=process
Delegate=yes
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStart=/usr/local/bin/k3s server --disable=traefik --disable=servicelb

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now k3s

kubeconfig="${RUNNER_TEMP:-/tmp}/k3s.yaml"
sudo install -m 0600 -o "$(id -u)" -g "$(id -g)" /etc/rancher/k3s/k3s.yaml "$kubeconfig"
echo "KUBECONFIG=$kubeconfig" >> "$GITHUB_ENV"
end=$(( $(date +%s) + TIMEOUT_SECONDS ))
until sudo k3s kubectl get nodes --no-headers 2>/dev/null | grep -q .; do
[ "$(date +%s)" -lt "$end" ] || { echo 'K3s did not register a node in time' >&2; sudo journalctl -u k3s --no-pager; exit 1; }
sleep 2
done
sudo k3s kubectl wait --for=condition=Ready node --all --timeout="${TIMEOUT_SECONDS}s"
60 changes: 60 additions & 0 deletions .github/scripts/k8s/install-kafka.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env sh
set -eu

KAFKA_NAMESPACE=${KAFKA_NAMESPACE:-kafka}
KAFKA_RELEASE_NAME=${KAFKA_RELEASE_NAME:-my-kafka}
KAFKA_CHART_VERSION=${KAFKA_CHART_VERSION:-32.4.3}
KAFKA_CHART_SHA256=${KAFKA_CHART_SHA256:-235ae1c09c837fbb1e670ddb83c816352ee91c05a5336e31bbd51f243a7a3687}
TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-600}

collect_diagnostics() {
status=$?
[ "$status" -eq 0 ] && return

set +e
echo "Kafka installation failed; collecting diagnostics" >&2
kubectl -n "$KAFKA_NAMESPACE" get all,cm,pvc -o wide >&2
kubectl -n "$KAFKA_NAMESPACE" get events --sort-by=.lastTimestamp >&2
helm status "$KAFKA_RELEASE_NAME" -n "$KAFKA_NAMESPACE" >&2
for pod in $(kubectl -n "$KAFKA_NAMESPACE" get pods -o name 2>/dev/null); do
kubectl -n "$KAFKA_NAMESPACE" describe "$pod" >&2
kubectl -n "$KAFKA_NAMESPACE" logs "$pod" --all-containers --prefix >&2
kubectl -n "$KAFKA_NAMESPACE" logs "$pod" --all-containers --prefix --previous >&2
done
exit "$status"
}

trap collect_diagnostics EXIT

chart_archive=$(mktemp)
curl --fail --location --proto '=https' --tlsv1.2 --retry 3 \
--output "$chart_archive" \
"https://charts.bitnami.com/bitnami/kafka-${KAFKA_CHART_VERSION}.tgz"
printf '%s %s\n' "$KAFKA_CHART_SHA256" "$chart_archive" | sha256sum --check --status
helm upgrade --install "$KAFKA_RELEASE_NAME" "$chart_archive" \
--namespace "$KAFKA_NAMESPACE" --create-namespace \
--version "$KAFKA_CHART_VERSION" \
--set image.repository=bitnamilegacy/kafka \
--set image.tag=4.0.0-debian-12-r10 \
--set image.digest=sha256:aa0b2aee8c5610dd1d18d48b4f1df0dbe3267b5d4c338d36c9af9cbf0529c0b0 \
--set controller.replicaCount=1 \
--set broker.replicaCount=0 \
--set listeners.client.protocol=PLAINTEXT \
--set listeners.controller.protocol=PLAINTEXT \
--set listeners.interbroker.protocol=PLAINTEXT \
--set overrideConfiguration.offsets\\.topic\\.replication\\.factor=1 \
--set overrideConfiguration.transaction\\.state\\.log\\.replication\\.factor=1 \
--set overrideConfiguration.transaction\\.state\\.log\\.min\\.isr=1 \
--set provisioning.enabled=false \
--wait --timeout "${TIMEOUT_SECONDS}s"

kubectl -n "$KAFKA_NAMESPACE" rollout status statefulset/"${KAFKA_RELEASE_NAME}"-controller --timeout="${TIMEOUT_SECONDS}s"
kubectl -n "$KAFKA_NAMESPACE" exec "${KAFKA_RELEASE_NAME}"-controller-0 -c kafka -- \
/opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --if-not-exists \
--topic ci-kafka-coordinator-readiness --partitions=1 --replication-factor=1
kubectl -n "$KAFKA_NAMESPACE" exec "${KAFKA_RELEASE_NAME}"-controller-0 -c kafka -- sh -c \
"printf 'ready\\n' | /opt/bitnami/kafka/bin/kafka-console-producer.sh --bootstrap-server localhost:9092 --topic ci-kafka-coordinator-readiness"
timeout 60s kubectl -n "$KAFKA_NAMESPACE" exec "${KAFKA_RELEASE_NAME}"-controller-0 -c kafka -- \
/opt/bitnami/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 \
--topic ci-kafka-coordinator-readiness --group ci-kafka-coordinator-readiness --from-beginning \
--max-messages 1 --timeout-ms 30000 >/dev/null
24 changes: 24 additions & 0 deletions .github/scripts/k8s/install-streams-chart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail

export TIMEOUT_SECONDS=600
bash .github/scripts/k8s/install-kafka.sh
tag=$(awk '/^appVersion:/ { print $2; exit }' helm-chart/Chart.yaml)
ci_overrides=(
--set ingress.enabled=false
--set podSecurityPolicy.enabled=false
--set-json 'imagePullSecrets=[]'
--set 'worker.resources.requests.cpu=250m'
--set 'worker.resources.requests.memory=512Mi'
--set 'worker.resources.limits.cpu=1'
--set 'worker.resources.limits.memory=1Gi'
--set-string "ui.image.tag=${tag}"
--set-string "ui.nginx.image.tag=${tag}"
--set-string "scaler.php.image.tag=${tag}"
--set-string "worker.image.tag=${tag}"
--set-string "manticore.image.tag=${tag}"
--set-string "rulesChecker.image.tag=${tag}"
)
helm template "$RELEASE_NAME" helm-chart --kube-version v1.32.5 "${ci_overrides[@]}" > artifacts-rendered-helm.yaml
mkdir -p artifacts
helm upgrade --install "$RELEASE_NAME" helm-chart --namespace "$APP_NAMESPACE" --create-namespace --wait --timeout 600s "${ci_overrides[@]}" 2>&1 | tee artifacts/helm-upgrade.log
8 changes: 8 additions & 0 deletions .github/scripts/k8s/publish-kafka-fixture.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail

kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_FIXTURE_PRODUCER_POD" -- sh -c 'timeout 120s /opt/bitnami/kafka/bin/kafka-console-producer.sh --bootstrap-server my-kafka.kafka.svc.cluster.local:9092 --topic my-docs < /tmp/test_data.json'
input_offset=$(kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-get-offsets.sh --bootstrap-server localhost:9092 --topic my-docs | awk -F: 'END { print $3 }')
expected_input_offset=$((INPUT_START_OFFSET + FIXTURE_RECORDS))
printf 'Kafka input: start=%s current=%s expected=%s\n' "$INPUT_START_OFFSET" "${input_offset:-0}" "$expected_input_offset"
[ "${input_offset:-0}" -eq "$expected_input_offset" ]
9 changes: 9 additions & 0 deletions .github/scripts/k8s/run-laravel-cluster-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail

kubectl -n "$APP_NAMESPACE" exec "$UI_POD" -c "$UI_CONTAINER" -- sh -c '
test -x ./vendor/bin/phpunit
php -d short_open_tag=off ./vendor/bin/phpunit --testsuite Cluster --list-tests --stderr | tee /tmp/cluster-test-list.txt
grep -Fqx " - Tests\\Cluster\\ClusterTest::assignUser" /tmp/cluster-test-list.txt
php -d short_open_tag=off ./vendor/bin/phpunit --do-not-cache-result --testsuite Cluster --stderr
'
29 changes: 29 additions & 0 deletions .github/scripts/k8s/start-kafka-fixture-producer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euxo pipefail

kubectl -n "$KAFKA_NAMESPACE" apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: ${KAFKA_FIXTURE_PRODUCER_POD}
labels:
app.kubernetes.io/name: kafka-fixture-producer
spec:
restartPolicy: Never
containers:
- name: producer
image: docker.io/bitnamilegacy/kafka:4.0.0-debian-12-r10@sha256:aa0b2aee8c5610dd1d18d48b4f1df0dbe3267b5d4c338d36c9af9cbf0529c0b0
command: ["sh", "-c", "sleep infinity"]
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
EOF
kubectl -n "$KAFKA_NAMESPACE" wait --for=condition=Ready "pod/${KAFKA_FIXTURE_PRODUCER_POD}" --timeout="${TIMEOUT_SECONDS}s"
kubectl -n "$KAFKA_NAMESPACE" cp dev-environment/kafka/test_data.tar.gz "${KAFKA_FIXTURE_PRODUCER_POD}:/tmp/test_data.tar.gz"
kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_FIXTURE_PRODUCER_POD" -- tar -xzf /tmp/test_data.tar.gz -C /tmp
fixture_records=$(kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_FIXTURE_PRODUCER_POD" -- sh -c 'wc -l < /tmp/test_data.json')
echo "FIXTURE_RECORDS=${fixture_records}" >> "$GITHUB_ENV"
56 changes: 56 additions & 0 deletions .github/scripts/k8s/verify-kafka-processing.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -euo pipefail

end=$(( $(date +%s) + TIMEOUT_SECONDS ))
expected_offset=$((START_OFFSET + EXPECTED_RECORDS))
next_report=0
pipeline_name=${PIPELINE#"${RELEASE_NAME}"-}
while [ "$(date +%s)" -lt "$end" ]; do
current_offset=$(kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-get-offsets.sh --bootstrap-server localhost:9092 --topic my-results | awk -F: 'END { print $3 }')
current_offset=${current_offset:-0}
if [ "$current_offset" -eq "$expected_offset" ]; then
printf 'Processed exactly %s records\n' "$EXPECTED_RECORDS"
exit 0
fi
now=$(date +%s)
if [ "$now" -ge "$next_report" ]; then
printf 'Kafka output: start=%s current=%s expected=%s\n' "$START_OFFSET" "$current_offset" "$expected_offset"
kubectl -n "$APP_NAMESPACE" get statefulset "$PIPELINE"
kubectl -n "$APP_NAMESPACE" get pods -l "name=${pipeline_name}" -o wide
for pod in $(kubectl -n "$APP_NAMESPACE" get pods -l "name=${pipeline_name}" -o name); do
for container in $(kubectl -n "$APP_NAMESPACE" get "$pod" -o jsonpath='{.spec.containers[*].name}'); do
case "$container" in
*-worker)
echo "--- Pipeline worker logs: $pod ($container), last 100 lines ---"
kubectl -n "$APP_NAMESPACE" logs "$pod" -c "$container" --tail=100 --prefix || true
;;
esac
done
done
next_report=$((now + 30))
fi
sleep 10
done
echo "Pipeline $PIPELINE did not produce offset $expected_offset within ${TIMEOUT_SECONDS}s" >&2
echo '--- Kafka topic offsets ---'
kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-get-offsets.sh --bootstrap-server localhost:9092 --topic my-docs || true
kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-get-offsets.sh --bootstrap-server localhost:9092 --topic my-results || true
echo '--- Kafka consumer group ms_test_stream ---'
kubectl -n "$KAFKA_NAMESPACE" exec "$KAFKA_POD" -c kafka -- /opt/bitnami/kafka/bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group ms_test_stream || true
kubectl -n "$APP_NAMESPACE" describe "statefulset/$PIPELINE" || true
kubectl -n "$APP_NAMESPACE" get events --sort-by=.lastTimestamp | tail -30 || true
kubectl -n "$APP_NAMESPACE" get pods -l "name=${pipeline_name}" -o wide || true
for pod in $(kubectl -n "$APP_NAMESPACE" get pods -l "name=${pipeline_name}" -o name); do
kubectl -n "$APP_NAMESPACE" describe "$pod" || true
for container in $(kubectl -n "$APP_NAMESPACE" get "$pod" -o jsonpath='{.spec.containers[*].name}'); do
case "$container" in
*-manticore|*-worker)
echo "--- Pipeline container logs: $pod ($container) ---"
kubectl -n "$APP_NAMESPACE" logs "$pod" -c "$container" --prefix || true
echo "--- Previous pipeline container logs: $pod ($container) ---"
kubectl -n "$APP_NAMESPACE" logs "$pod" -c "$container" --previous --prefix || true
;;
esac
done
done
exit 1
12 changes: 12 additions & 0 deletions .github/scripts/k8s/wait-for-application-workloads.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euxo pipefail

kubectl get namespace "$APP_NAMESPACE"
kubectl -n "$KAFKA_NAMESPACE" get pod "$KAFKA_POD"
kubectl -n "$APP_NAMESPACE" rollout status deployment/"$UI_DEPLOYMENT" --timeout="${TIMEOUT_SECONDS}s"
kubectl -n "$APP_NAMESPACE" rollout status deployment/"${RELEASE_NAME}-manticoresearch-scaler" --timeout="${TIMEOUT_SECONDS}s"
kubectl -n "$APP_NAMESPACE" rollout status statefulset/"${RELEASE_NAME}-manticoresearch-columnar" --timeout="${TIMEOUT_SECONDS}s"
kubectl -n "$APP_NAMESPACE" rollout status statefulset/"${RELEASE_NAME}-manticoresearch-ui-mysql" --timeout="${TIMEOUT_SECONDS}s"
ui_pod=$(kubectl -n "$APP_NAMESPACE" get pods -l name=manticoresearch-ui -o jsonpath='{.items[0].metadata.name}')
test -n "$ui_pod"
echo "UI_POD=$ui_pod" >> "$GITHUB_ENV"
Loading
Loading