Start
This commit is contained in:
1 parent
fdbd3b0fcb
commit
7494563885
2 files changed
+132
No files matched your search
+47
@@ -0,0 +1,47 @@
|
||||
name: 'Finite State Machine (FSM) Action'
|
||||
description: 'Лёгкий конечный автомат на чистом Bash без Docker'
|
||||
author: '4ma.su community'
|
||||
inputs:
|
||||
states:
|
||||
description: 'JSON с переходами (обязательно)'
|
||||
required: true
|
||||
initial:
|
||||
description: 'Начальное состояние'
|
||||
required: true
|
||||
event:
|
||||
description: 'Событие для обработки'
|
||||
required: true
|
||||
context:
|
||||
description: 'JSON-контекст для подстановки в действия ${{ var }}'
|
||||
required: false
|
||||
default: '{}'
|
||||
debug:
|
||||
description: 'Включить отладку'
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
outputs:
|
||||
next_state:
|
||||
description: 'Следующее состояние'
|
||||
value: ${{ steps.fsm.outputs.next_state }}
|
||||
executed_actions:
|
||||
description: 'Массив выполненных действий'
|
||||
value: ${{ steps.fsm.outputs.executed_actions }}
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- id: fsm
|
||||
name: Run FSM
|
||||
shell: bash
|
||||
env:
|
||||
INPUT_STATES: ${{ inputs.states }}
|
||||
INPUT_INITIAL: ${{ inputs.initial }}
|
||||
INPUT_EVENT: ${{ inputs.event }}
|
||||
INPUT_CONTEXT: ${{ inputs.context }}
|
||||
INPUT_DEBUG: ${{ inputs.debug }}
|
||||
run: ${{ github.action_path }}/fsm.sh
|
||||
|
||||
branding:
|
||||
icon: 'activity'
|
||||
color: 'blue'
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# fsm.sh — лёгкий конечный автомат для GitHub Actions (composite)
|
||||
set -euo pipefail
|
||||
|
||||
DEBUG="${INPUT_DEBUG:-false}"
|
||||
[[ "$DEBUG" == "true" ]] && set -x
|
||||
|
||||
log() { echo "::notice::$1"; }
|
||||
debug() { [[ "$DEBUG" == "true" ]] && echo "::debug::$1"; }
|
||||
error() { echo "::error::$1"; exit 1; }
|
||||
|
||||
# Установка jq, если его нет (работает на всех официальных runner-ах)
|
||||
if ! command -v jq &>/dev/null; then
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk add --no-cache jq
|
||||
elif [[ -f /etc/debian_version ]]; then
|
||||
sudo apt-get update && sudo apt-get install -y jq
|
||||
elif [[ "$RUNNER_OS" == "macOS" ]]; then
|
||||
brew install jq
|
||||
elif [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||
choco install jq -y
|
||||
else
|
||||
error "Не удалось установить jq на $RUNNER_OS"
|
||||
fi
|
||||
fi
|
||||
|
||||
STATES_JSON="$INPUT_STATES"
|
||||
CURRENT="$INPUT_INITIAL"
|
||||
EVENT="$INPUT_EVENT"
|
||||
CONTEXT_JSON="${INPUT_CONTEXT:-{}}"
|
||||
|
||||
debug "States: $STATES_JSON"
|
||||
debug "From: $CURRENT → Event: $EVENT"
|
||||
debug "Context: $CONTEXT_JSON"
|
||||
|
||||
# Ищем подходящий переход (поддержка wildcard события *)
|
||||
TRANSITION=$(echo "$STATES_JSON" | jq -r --arg from "$CURRENT" --arg event "$EVENT" '
|
||||
.transitions // [] |
|
||||
.[] |
|
||||
select(.from == $from and (.event == $event or .event == "*")) |
|
||||
{
|
||||
to: .to,
|
||||
action: (.action // "")
|
||||
} | @json
|
||||
' | head -n1)
|
||||
|
||||
[[ -z "$TRANSITION" || "$TRANSITION" == "null" ]] && \
|
||||
error "Нет перехода из состояния '$CURRENT' по событию '$EVENT'"
|
||||
|
||||
NEXT_STATE=$(echo "$TRANSITION" | jq -r '.to')
|
||||
ACTION=$(echo "$TRANSITION" | jq -r '.action')
|
||||
|
||||
log "Переход: $CURRENT --[$EVENT]--> $NEXT_STATE"
|
||||
|
||||
EXECUTED=()
|
||||
|
||||
if [[ -n "$ACTION" && "$ACTION" != "null" ]]; then
|
||||
log "Выполняется действие: $ACTION"
|
||||
|
||||
# Подстановка переменных вида ${{ var }} из контекста + env
|
||||
ACTION_EXP=$(echo "$ACTION" | CONTEXT="$CONTEXT_JSON" jq -r '
|
||||
reduce paths(scalars) as $p (.;
|
||||
setpath($p; getpath($p) |
|
||||
if type == "string" then
|
||||
gsub("\\$\\{\\{[ \\t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \\t]*\\}\\}" ;
|
||||
(capture("\\$\\{\\{[ \\t]*(?<v>[a-zA-Z_][a-zA-Z0-9_]*)[ \\t]*\\}\\}") |.v) as $var |
|
||||
($ENV.CONTEXT | fromjson | .[$var] // env[$var] // "")
|
||||
)
|
||||
else .
|
||||
end
|
||||
)
|
||||
)
|
||||
')
|
||||
|
||||
debug "Расширенная команда: $ACTION_EXP"
|
||||
eval "$ACTION_EXP"
|
||||
EXECUTED+=("$ACTION")
|
||||
fi
|
||||
|
||||
# Выводим outputs
|
||||
echo "next_state=$NEXT_STATE" >> "$GITHUB_OUTPUT"
|
||||
echo "executed_actions=$(jq -c --null-input '$EXECUTED')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
log "Новое состояние: $NEXT_STATE"
|
||||
[[ ${#EXECUTED[@]} -gt 0 ]] && log "Выполнено действий: ${#EXECUTED[@]}"
|
||||
Reference in new issue
Block a user