| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| name: server-start |
| description: Start Iggy server and wait for readiness |
| inputs: |
| mode: |
| description: "How to run the server: cargo|bin" |
| required: false |
| default: "cargo" |
| cargo-bin: |
| description: "Cargo binary name (when mode=cargo)" |
| required: false |
| default: "iggy-server" |
| cargo-profile: |
| description: "Cargo profile: release|debug" |
| required: false |
| default: "debug" |
| bin: |
| description: "Path to server binary (when mode=bin)" |
| required: false |
| default: "" |
| working-directory: |
| description: "Working directory for building/running" |
| required: false |
| default: "." |
| tcp_address: |
| description: "TCP address (host:port)" |
| required: false |
| default: "127.0.0.1:8090" |
| http_address: |
| description: "HTTP address (host:port)" |
| required: false |
| default: "127.0.0.1:3000" |
| wait-timeout-seconds: |
| description: "Max seconds to wait until the server is ready" |
| required: false |
| default: "45" |
| log-file: |
| description: "Where to write server logs" |
| required: false |
| default: "" |
| pid-file: |
| description: "Where to write the PID" |
| required: false |
| default: "" |
| fail-if-busy: |
| description: "Fail if port is already in use" |
| required: false |
| default: "true" |
| outputs: |
| pid: |
| description: "PID of the background server process" |
| value: ${{ steps.out.outputs.pid }} |
| pid_file: |
| description: "Path to PID file" |
| value: ${{ steps.out.outputs.pid_file }} |
| log_file: |
| description: "Path to log file" |
| value: ${{ steps.out.outputs.log_file }} |
| tcp_address: |
| description: "TCP address used" |
| value: ${{ inputs.tcp_address }} |
| http_address: |
| description: "HTTP address used" |
| value: ${{ inputs.http_address }} |
| runs: |
| using: "composite" |
| steps: |
| - id: prep |
| shell: bash |
| run: | |
| set -euo pipefail |
| : "${RUNNER_TEMP:?}" |
| LOG_FILE="${{ inputs.log-file || '' }}" |
| PID_FILE="${{ inputs.pid-file || '' }}" |
| [ -n "$LOG_FILE" ] || LOG_FILE="$RUNNER_TEMP/iggy-server.log" |
| [ -n "$PID_FILE" ] || PID_FILE="$RUNNER_TEMP/iggy-server.pid" |
| echo "LOG_FILE=$LOG_FILE" >> "$GITHUB_ENV" |
| echo "PID_FILE=$PID_FILE" >> "$GITHUB_ENV" |
| |
| - id: resolve-bin |
| shell: bash |
| working-directory: ${{ inputs.working-directory }} |
| run: | |
| set -euo pipefail |
| MODE="${{ inputs.mode }}" |
| BIN_PATH="" |
| if [[ "$MODE" == "cargo" ]]; then |
| PROFILE="${{ inputs.cargo-profile }}" |
| NAME="${{ inputs.cargo-bin }}" |
| if [[ "$PROFILE" == "release" ]]; then |
| OUT="target/release/$NAME" |
| else |
| OUT="target/debug/$NAME" |
| fi |
| if [[ ! -x "$OUT" ]]; then |
| echo "Building $NAME with cargo ($PROFILE)…" |
| cargo build --locked --bin "$NAME" $([[ "$PROFILE" == "release" ]] && echo "--release") |
| fi |
| BIN_PATH="$OUT" |
| else |
| BIN_PATH="${{ inputs.bin }}" |
| [[ -x "$BIN_PATH" ]] || { echo "Binary not found or not executable: $BIN_PATH"; exit 1; } |
| fi |
| echo "bin=$BIN_PATH" >> "$GITHUB_OUTPUT" |
| |
| - id: busy |
| shell: bash |
| run: | |
| set -euo pipefail |
| TCP_ADDRESS="${{ inputs.tcp_address }}" |
| HOST="${TCP_ADDRESS%:*}" |
| PORT="${TCP_ADDRESS##*:}" |
| # true if socket is already open |
| if command -v nc >/dev/null 2>&1; then |
| if nc -z "$HOST" "$PORT" 2>/dev/null; then busy=1; else busy=0; fi |
| else |
| if timeout 1 bash -lc ":</dev/tcp/$HOST/$PORT" 2>/dev/null; then busy=1; else busy=0; fi |
| fi |
| echo "BUSY=$busy" >> "$GITHUB_ENV" |
| |
| - if: env.BUSY == '1' && inputs.fail-if-busy == 'true' |
| shell: bash |
| run: | |
| echo "Port ${{ inputs.tcp_address }} is already in use." >&2 |
| exit 1 |
| |
| - name: Start server |
| shell: bash |
| working-directory: ${{ inputs.working-directory }} |
| run: | |
| set -euo pipefail |
| export IGGY_TCP_ADDRESS="${{ inputs.tcp_address }}" |
| export IGGY_HTTP_ADDRESS="${{ inputs.http_address }}" |
| export IGGY_ROOT_USERNAME="iggy" |
| export IGGY_ROOT_PASSWORD="iggy" |
| nohup "${{ steps.resolve-bin.outputs.bin }}" >"$LOG_FILE" 2>&1 & |
| echo $! > "$PID_FILE" |
| echo "Started server PID $(cat "$PID_FILE") → logs: $LOG_FILE" |
| echo "Server configured with TCP=$IGGY_TCP_ADDRESS, HTTP=$IGGY_HTTP_ADDRESS" |
| |
| - name: Wait for readiness |
| shell: bash |
| run: | |
| set -euo pipefail |
| TCP_ADDRESS="${{ inputs.tcp_address }}" |
| HOST="${TCP_ADDRESS%:*}" |
| PORT="${TCP_ADDRESS##*:}" |
| DEADLINE=$(( $(date +%s) + ${{ inputs.wait-timeout-seconds }} )) |
| until (( $(date +%s) > DEADLINE )); do |
| if command -v nc >/dev/null 2>&1; then |
| nc -z "$HOST" "$PORT" 2>/dev/null && ready=1 || ready=0 |
| else |
| timeout 1 bash -lc ":</dev/tcp/$HOST/$PORT" 2>/dev/null && ready=1 || ready=0 |
| fi |
| if [[ "$ready" == "1" ]]; then |
| echo "Server is ready on $TCP_ADDRESS" |
| break |
| fi |
| sleep 1 |
| done |
| if [[ "${ready:-0}" != "1" ]]; then |
| echo "Server did not become ready within ${{ inputs.wait-timeout-seconds }}s." >&2 |
| echo "---- last 100 lines of log ----" |
| tail -n 100 "$LOG_FILE" || true |
| kill "$(cat "$PID_FILE")" 2>/dev/null || true |
| exit 1 |
| fi |
| |
| - id: out |
| shell: bash |
| run: | |
| echo "pid=$(cat "$PID_FILE")" >> "$GITHUB_OUTPUT" |
| echo "pid_file=$PID_FILE" >> "$GITHUB_OUTPUT" |
| echo "log_file=$LOG_FILE" >> "$GITHUB_OUTPUT" |