1e5378da94
Adds audit:rebuild-chain --partition=<name> --from-id=<n> [--force] to MUTATING_RE regex group. Required to rebuild hash chain on 2 broken partitions (activity_log_y2026_m05 from id=599, balance_transactions_y2026_m05 from id=462) after F1 advisory-lock migration applied. Ref: docs/superpowers/plans/2026-05-29-audit-chain-race-fix.md Step 3.3
120 lines
4.9 KiB
YAML
120 lines
4.9 KiB
YAML
name: Run artisan command on liderra.ru
|
||
|
||
# Universal artisan-runner для прод-команд пока прямой SSH с dev-машины
|
||
# заблокирован YC backbone-фильтром. Заказчик пишет команду строкой в
|
||
# workflow_dispatch input, workflow проверяет её по whitelist, выполняет на
|
||
# проде под sudo -u www-data, выводит результат в job summary.
|
||
#
|
||
# Whitelist охватывает read-only / dry-run / status команды без подтверждения
|
||
# плюс несколько mutating команд с обязательным confirm_apply=true.
|
||
#
|
||
# Любая команда вне whitelist'а → fail before SSH.
|
||
#
|
||
# Использует тот же LIDERRA_SSH_KEY что и deploy.yml/ssh-diagnose.yml.
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
command:
|
||
description: 'artisan-команда (например: supplier:rekey-orphans --dry-run)'
|
||
required: true
|
||
type: string
|
||
confirm_apply:
|
||
description: 'Подтверждаю выполнение mutating-команды (обязательно true для команд без --dry-run)'
|
||
required: false
|
||
default: false
|
||
type: boolean
|
||
|
||
jobs:
|
||
run:
|
||
name: ${{ github.event.inputs.command }}
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 15
|
||
|
||
env:
|
||
LIDERRA_HOST: 111.88.246.137
|
||
LIDERRA_USER: ubuntu
|
||
CMD: ${{ github.event.inputs.command }}
|
||
CONFIRM: ${{ github.event.inputs.confirm_apply }}
|
||
|
||
steps:
|
||
- name: Whitelist check
|
||
run: |
|
||
set -euo pipefail
|
||
CMD_TRIM=$(echo "$CMD" | sed 's/^ *//;s/ *$//')
|
||
echo "Requested: '$CMD_TRIM'"
|
||
|
||
# Group 1 — read-only / dry-run / inspection: всегда разрешены
|
||
READ_ONLY_RE='^(migrate:status|route:list|schedule:list|queue:listen --help|about|env:show|config:show|cache:table|view:cache|optimize:status|snapshot:backfill( --date=20[2-9][0-9]-[0-1][0-9]-[0-3][0-9])?|scheduler:check-heartbeats|incidents:watch-failures( --threshold-spike=[0-9]+)?( --threshold-daily=[0-9]+)?( --persistent-hours=[0-9]+)?|supplier:rekey-orphans --dry-run|audit:verify-chains)( *)$'
|
||
|
||
# Group 2 — mutating: требуют confirm_apply=true
|
||
MUTATING_RE='^(supplier:rekey-orphans|cache:clear|view:clear|config:clear|route:clear|optimize:clear|optimize|queue:restart|partitions:create-months( --months=[0-9]+)?|partitions:drop-old|audit:rebuild-chain --partition=[a-z_0-9]+ --from-id=[0-9]+( --force)?)( *)$'
|
||
|
||
if [[ "$CMD_TRIM" =~ $READ_ONLY_RE ]]; then
|
||
echo "::notice::Command in read-only whitelist — proceeding."
|
||
exit 0
|
||
fi
|
||
|
||
if [[ "$CMD_TRIM" =~ $MUTATING_RE ]]; then
|
||
if [[ "$CONFIRM" != "true" ]]; then
|
||
echo "::error::Mutating command '$CMD_TRIM' requires confirm_apply=true. Re-run with confirm_apply checked."
|
||
exit 1
|
||
fi
|
||
echo "::warning::Mutating command authorized via confirm_apply=true."
|
||
exit 0
|
||
fi
|
||
|
||
echo "::error::Command '$CMD_TRIM' is NOT in whitelist. Allowed read-only patterns: $READ_ONLY_RE. Allowed mutating: $MUTATING_RE. Add to whitelist if needed."
|
||
exit 1
|
||
|
||
- name: Setup SSH key
|
||
run: |
|
||
mkdir -p ~/.ssh
|
||
echo "${{ secrets.LIDERRA_SSH_KEY }}" > ~/.ssh/liderra_deploy
|
||
chmod 600 ~/.ssh/liderra_deploy
|
||
ssh-keyscan -H ${{ env.LIDERRA_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||
|
||
- name: Run artisan on prod
|
||
run: |
|
||
set -o pipefail
|
||
CMD_B64=$(printf '%s' "$CMD" | base64 -w0)
|
||
ssh -i ~/.ssh/liderra_deploy ${{ env.LIDERRA_USER }}@${{ env.LIDERRA_HOST }} \
|
||
"CMD_B64='$CMD_B64' bash -s" <<'REMOTE' | tee /tmp/artisan-output.log
|
||
set +e
|
||
CMD=$(echo "$CMD_B64" | base64 -d)
|
||
cd /var/www/liderra/app
|
||
echo "=== Running: php artisan $CMD on $(hostname) at $(date -u) ==="
|
||
sudo -u www-data php artisan $CMD 2>&1
|
||
RC=$?
|
||
echo
|
||
echo "=== Exit code: $RC ==="
|
||
exit $RC
|
||
REMOTE
|
||
|
||
- name: Print summary
|
||
if: always()
|
||
run: |
|
||
{
|
||
echo "## artisan \`$CMD\`"
|
||
echo
|
||
echo "- Host: $LIDERRA_HOST"
|
||
echo "- Confirm: $CONFIRM"
|
||
echo "- Triggered by: ${{ github.actor }}"
|
||
echo
|
||
echo '```'
|
||
cat /tmp/artisan-output.log 2>/dev/null || echo "(no output captured)"
|
||
echo '```'
|
||
} >> "$GITHUB_STEP_SUMMARY"
|
||
|
||
- name: Upload output as artifact
|
||
if: always()
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: artisan-output
|
||
path: /tmp/artisan-output.log
|
||
retention-days: 30
|
||
|
||
- name: Cleanup SSH key
|
||
if: always()
|
||
run: rm -f ~/.ssh/liderra_deploy
|