From 79bf7de4f23803b758738c734bb5cc9242cf5d82 Mon Sep 17 00:00:00 2001 From: Aleksey Sabilin Date: Tue, 14 Jul 2026 23:41:01 +0300 Subject: [PATCH] fix(admin): IFT smoke credentials from stand .env via SSH. Refs EventHub/EventHubFrontAdmin#33 #39 --- .gitea/workflows/e2e-ift.yml | 46 +++++++++++++++++++++++++++--------- e2e/TESTIDS.md | 17 +++++++------ e2e/tests/ift/smoke.spec.ts | 23 ++++++++++++++---- 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/.gitea/workflows/e2e-ift.yml b/.gitea/workflows/e2e-ift.yml index e72f0ed..8f694b2 100644 --- a/.gitea/workflows/e2e-ift.yml +++ b/.gitea/workflows/e2e-ift.yml @@ -1,8 +1,9 @@ name: E2E IFT smoke (admin) # После успешного Deploy IFT — smoke против живого IFT (без API-моков). -# Secrets (repo EventHubFrontAdmin): E2E_ADMIN_EMAIL, E2E_ADMIN_PASSWORD; -# опционально E2E_IFT_BASE_URL (default https://admin-ui.ift.eventhub.local). +# Учётки берутся с хоста IFT из /opt/eventhub-ift/.env +# (SMOKE_ADMIN_* → fallback ADMIN_SUPER_*; см. EventHubDevOps/ift/.env.example). +# Опц. secret E2E_IFT_BASE_URL (default https://admin-ui.ift.eventhub.local). on: workflow_run: workflows: ["Deploy IFT (admin)"] @@ -34,19 +35,42 @@ jobs: - name: Install Playwright browser run: npx playwright install --with-deps chromium + - name: Load smoke credentials from IFT .env + env: + SSH_HOST: ${{ secrets.IFT_SSH_HOST }} + SSH_USER: ${{ secrets.IFT_SSH_USER }} + SSH_KEY: ${{ secrets.IFT_SSH_PRIVATE_KEY }} + run: | + set -euo pipefail + KEY=$(mktemp) + printf '%s\n' "$SSH_KEY" > "$KEY" + chmod 600 "$KEY" + # Источник истины — env на стенде (не отдельные Gitea E2E secrets). + REMOTE=$(ssh -i "$KEY" -o BatchMode=yes -o StrictHostKeyChecking=accept-new \ + "${SSH_USER}@${SSH_HOST}" \ + "grep -E '^(SMOKE_ADMIN_EMAIL|SMOKE_ADMIN_PASSWORD|ADMIN_SUPER_EMAIL|ADMIN_SUPER_PASSWORD)=' /opt/eventhub-ift/.env || true") + rm -f "$KEY" + EMAIL=$(printf '%s\n' "$REMOTE" | sed -n 's/^SMOKE_ADMIN_EMAIL=//p' | head -1) + PASS=$(printf '%s\n' "$REMOTE" | sed -n 's/^SMOKE_ADMIN_PASSWORD=//p' | head -1) + if [ -z "$EMAIL" ]; then + EMAIL=$(printf '%s\n' "$REMOTE" | sed -n 's/^ADMIN_SUPER_EMAIL=//p' | head -1) + fi + if [ -z "$PASS" ]; then + PASS=$(printf '%s\n' "$REMOTE" | sed -n 's/^ADMIN_SUPER_PASSWORD=//p' | head -1) + fi + if [ -z "$EMAIL" ] || [ -z "$PASS" ]; then + echo "::error::В /opt/eventhub-ift/.env нет SMOKE_ADMIN_* / ADMIN_SUPER_*" + exit 1 + fi + echo "SMOKE_ADMIN_EMAIL=${EMAIL}" >> "$GITHUB_ENV" + echo "SMOKE_ADMIN_PASSWORD=${PASS}" >> "$GITHUB_ENV" + echo "Loaded smoke admin email: ${EMAIL}" + - name: IFT smoke env: E2E_TARGET: ift - E2E_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL }} - E2E_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD }} E2E_IFT_BASE_URL: ${{ secrets.E2E_IFT_BASE_URL }} - run: | - set -euo pipefail - if [ -z "${E2E_ADMIN_EMAIL:-}" ] || [ -z "${E2E_ADMIN_PASSWORD:-}" ]; then - echo "::error::Нужны secrets E2E_ADMIN_EMAIL и E2E_ADMIN_PASSWORD" - exit 1 - fi - npm run test:e2e:ift + run: npm run test:e2e:ift - name: Upload Playwright report if: failure() diff --git a/e2e/TESTIDS.md b/e2e/TESTIDS.md index acf45ec..ea91c2f 100644 --- a/e2e/TESTIDS.md +++ b/e2e/TESTIDS.md @@ -31,12 +31,15 @@ Helper: `src/lib/testid.ts`. | `npm run test:e2e` | mock-suite (CI / PR), API через Playwright route | | `npm run test:e2e:ift` | IFT smoke (живой API), см. ниже | -### IFT secrets (Gitea → Settings → Secrets) +### IFT / stage учётки -| Secret | Обязателен | Назначение | -|--------|------------|------------| -| `E2E_ADMIN_EMAIL` | да | логин smoke-админа на IFT | -| `E2E_ADMIN_PASSWORD` | да | пароль | -| `E2E_IFT_BASE_URL` | нет | default `https://admin-ui.ift.eventhub.local` | +Источник истины — env стенда (`EventHubDevOps/ift/.env`, `EventHubDevOps/stage/.env` → на хосте `/opt/eventhub-{ift,stage}/.env`): -Workflow `e2e-ift.yml` стартует после успешного `Deploy IFT (admin)`. +| Переменная | Назначение | +|------------|------------| +| `SMOKE_ADMIN_EMAIL` / `SMOKE_ADMIN_PASSWORD` | предпочтительно для smoke/E2E | +| `ADMIN_SUPER_EMAIL` / `ADMIN_SUPER_PASSWORD` | fallback, если `SMOKE_ADMIN_*` пустые | + +Локально: `set -a && source /path/to/ift/.env && set +a && npm run test:e2e:ift`. + +Workflow `e2e-ift.yml` после Deploy IFT читает те же ключи по SSH с `/opt/eventhub-ift/.env` (нужны уже имеющиеся `IFT_SSH_*`). Опц. secret `E2E_IFT_BASE_URL`. diff --git a/e2e/tests/ift/smoke.spec.ts b/e2e/tests/ift/smoke.spec.ts index ee47fe9..d6befb3 100644 --- a/e2e/tests/ift/smoke.spec.ts +++ b/e2e/tests/ift/smoke.spec.ts @@ -1,16 +1,29 @@ import { test, expect } from '@playwright/test'; /** - * IFT smoke — заполняется секретами E2E_ADMIN_EMAIL / E2E_ADMIN_PASSWORD. - * Запуск: `npm run test:e2e:ift` (без моков). + * IFT smoke — учётки из DevOps env (`EventHubDevOps/ift/.env`): + * `SMOKE_ADMIN_EMAIL` / `SMOKE_ADMIN_PASSWORD` (fallback `ADMIN_SUPER_*`). + * Локально: `set -a && source …/.env && set +a && npm run test:e2e:ift` */ +function smokeEmail(): string | undefined { + return process.env.SMOKE_ADMIN_EMAIL || process.env.ADMIN_SUPER_EMAIL || process.env.E2E_ADMIN_EMAIL; +} + +function smokePassword(): string | undefined { + return ( + process.env.SMOKE_ADMIN_PASSWORD || + process.env.ADMIN_SUPER_PASSWORD || + process.env.E2E_ADMIN_PASSWORD + ); +} + test.describe('IFT smoke', () => { - test.skip(!process.env.E2E_ADMIN_EMAIL || !process.env.E2E_ADMIN_PASSWORD, 'E2E_ADMIN_* secrets required'); + test.skip(!smokeEmail() || !smokePassword(), 'SMOKE_ADMIN_* (или ADMIN_SUPER_*) из IFT/stage .env required'); test('login → dashboard → logout', async ({ page }) => { await page.goto('/login'); - await page.getByLabel(/email/i).fill(process.env.E2E_ADMIN_EMAIL!); - await page.getByLabel(/пароль|password/i).fill(process.env.E2E_ADMIN_PASSWORD!); + await page.getByLabel(/email/i).fill(smokeEmail()!); + await page.getByLabel(/пароль|password/i).fill(smokePassword()!); await page.getByTestId('btn-login').click(); await expect(page.getByTestId('layout-shell')).toBeVisible({ timeout: 30_000 }); await page.getByTestId('menu-user').click();