diff --git a/.gitea/workflows/openapi.yml b/.gitea/workflows/openapi.yml new file mode 100644 index 000000000..0ac8d3b98 --- /dev/null +++ b/.gitea/workflows/openapi.yml @@ -0,0 +1,198 @@ +# .gitea/workflows/openapi.yml +name: OpenAPI evaluation + +on: + push: + branches: + - main + pull_request: + branches: + - main + paths: + - 'docs/*/openapi/*.yaml' + - 'docs/*/openapi/*.yml' + +jobs: + openapi: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Dump Gitea env + run: | + env | sort | grep GITEA + + - name: Get base branch name + id: base + run: | + base_ref=$(jq -r '.pull_request.base.ref' "$GITEA_PATH") + echo "base_ref=$base_ref" + echo "${{ gitea.base_ref }}" + BASE_SHA="${{ gitea.event.pull_request.base.sha }}" + echo "Base SHA: $BASE_SHA" + + - name: Get changed files other method + id: changed-files + run: | + BASE_SHA="${{ gitea.event.pull_request.base.sha }}" + echo "Base SHA: $BASE_SHA" + git fetch origin $BASE_SHA + echo "changed_files=$(git diff --name-only ${BASE_SHA}...HEAD | grep -E '^docs/[^/]+/openapi/.*\.(yaml|yml)$' | xargs)" >> $GITHUB_OUTPUT + + - name: List changed files + run: | + for file in ${{ steps.changed-files.outputs.changed_files }}; do + echo "$file was changed" + done + + - name: Get changed OpenAPI files (branch URLs) + id: changed-urls + run: | + BASE_SHA="${{ gitea.event.pull_request.base.sha }}" + git fetch origin $BASE_SHA + + # Use PR branch if available, otherwise push branch + BRANCH="${{ gitea.head_ref }}" + if [ -z "$BRANCH" ]; then + BRANCH="${{ gitea.ref_name }}" + fi + + REPO_URL="${{ gitea.server_url }}/${{ gitea.repository }}" + + # Only docs/*/openapi/*.yaml or yml + # FILES=$(git diff --name-only ${BASE_SHA}...HEAD \ + # | grep -E '^docs/[^/]+/openapi/.*\.(yaml|yml)$' || true) + + echo "changed urls" + + for file in ${{ steps.changed-files.outputs.changed_files }}; do + echo "$REPO_URL/raw/branch/$BRANCH/$file" + done + + echo "changed_urls<> $GITHUB_OUTPUT + + for file in ${{ steps.changed-files.outputs.changed_files }}; do + echo "$REPO_URL/raw/branch/$BRANCH/$file" + done >> $GITHUB_OUTPUT + + echo "EOF" >> $GITHUB_OUTPUT + + - name: List URLs + run: | + while IFS= read -r url; do + echo "$url was changed" + done <<< "${{ steps.changed-urls.outputs.changed_urls }}" + + - name: Validate OpenAPI files + show validation results + env: + INTERNAL_OPENAPI_KEY: ${{ secrets.INTERNAL_OPENAPI_KEY }} + API_URL: ${{ vars.OPENAPI_URL }} + REPORTPORTAL_URL: ${{ vars.REPORTPORTAL_URL }} + run: | + set -e + + MAX_ATTEMPTS=30 # ~5 minutes total (30 * 10s) + SLEEP_SECONDS=10 + HAS_FAILURE=0 # <-- track failures + + # --- Fetching access token --- + OPENAPI_TOKEN="$(curl -X POST "https://${API_URL}/api/token/machine" \ + -H "X-Internal-Api-Key: $INTERNAL_OPENAPI_KEY" | jq -r .access_token)" + echo "::add-mask::$OPENAPI_TOKEN" + + while IFS= read -r url; do + [ -z "$url" ] && continue + + echo "==============================" + echo "Validating: $url" + + # --- 1. trigger validation using file_content --- + VALIDATION_RESPONSE=$(curl -sS -X POST "https://${API_URL}/api/validate" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAPI_TOKEN" \ + -d "$(jq -n \ + --arg path "$url" \ + '{path: $path, export: "xml", ruleset: "default"}')") + + echo "Validation response:" + echo "$VALIDATION_RESPONSE" + + # --- 2. extract launch id --- + LAUNCH_UUID=$(echo "$VALIDATION_RESPONSE" | jq -r '.launch.id // empty') + + if [ -z "$LAUNCH_UUID" ]; then + echo "❌ Could not extract launch UUID" + HAS_FAILURE=1 + continue + fi + + echo "Launch UUID: $LAUNCH_UUID" + + # --- 3. wait until validation finishes --- + ATTEMPT=1 + STATUS="IN_PROGRESS" + + while [ "$STATUS" = "IN_PROGRESS" ] && [ $ATTEMPT -le $MAX_ATTEMPTS ]; do + echo "Checking launch status (attempt $ATTEMPT/$MAX_ATTEMPTS)..." + + LAUNCH_DETAILS=$(curl -sS \ + -H "Authorization: Bearer $OPENAPI_TOKEN" \ + "https://${API_URL}/api/reportportal?project=openapi&launchId=$LAUNCH_UUID") + + STATUS=$(echo "$LAUNCH_DETAILS" | jq -r '.status // "UNKNOWN"') + echo "Current status: $STATUS" + + if [ "$STATUS" = "IN_PROGRESS" ]; then + sleep $SLEEP_SECONDS + fi + + ATTEMPT=$((ATTEMPT+1)) + done + + if [ "$STATUS" = "IN_PROGRESS" ]; then + echo "⚠️ Timeout waiting for validation to finish" + HAS_FAILURE=1 + continue + fi + + # --- 4. extract statistics --- + STATUS=$(echo "$LAUNCH_DETAILS" | jq -r '.status') + TOTAL=$(echo "$LAUNCH_DETAILS" | jq -r '.statistics.executions.total') + PASSED=$(echo "$LAUNCH_DETAILS" | jq -r '.statistics.executions.passed') + FAILED=$(echo "$LAUNCH_DETAILS" | jq -r '.statistics.executions.failed') + SKIPPED=$(echo "$LAUNCH_DETAILS" | jq -r '.statistics.executions.skipped') + + + if [ "$STATUS" = "FAILED" ]; then + echo "❌ Validation FAILED for $url" + HAS_FAILURE=1 + fi + + # Fetch Launch ID + LAUNCH_ID=$(echo "$LAUNCH_DETAILS" | jq -r '.id') + + # fallback if API doesn't return UI link + REPORT_URL="https://${REPORTPORTAL_URL}/ui/#openapi/launches/all/$LAUNCH_ID" + + # --- 5. summary --- + echo "" + echo "📊 Validation summary" + echo "Status: $STATUS" + echo "Total: $TOTAL" + echo "Passed: $PASSED" + echo "Failed: $FAILED" + echo "Skipped: $SKIPPED" + echo "Report: $REPORT_URL" + echo "==============================" + echo + + done <<< "${{ steps.changed-urls.outputs.changed_urls }}" + + if [ "$HAS_FAILURE" -eq 1 ]; then + echo "❌ One or more OpenAPI validations failed" + exit 1 + fi