Scanverra
CI/CD Integration

أدلة

التكامل مع CI/CD

تقبل كل نقطة طرفية للماسح مفتاح API، لذا يمكن تشغيل أيٍّ منها كخطوة ضمن خط الأنابيب. تتناول هذه الصفحة معنى مخرجات كل أداة، وكيفية تحويلها إلى بوابة نجاح/فشل، وأمثلة عملية لأربع منصات CI.

أساس احتساب النتائج لكل أداة

ما تُعيده كل نقطة طرفية، وما الذي ينبغي تحديد حد أدنى له.

الأداةالمخرجاتالأساسبوابة مدمجة
تدقيق الموقع الإلكتروني4 نتائج من 0 إلى 100: performance وseo وaccessibility وbestPracticesنتائج Lighthouse الخام. المعيار: 90 فأكثر جيدة، من 50 إلى 89 بحاجة إلى تحسين، أقل من 50 ضعيفة.لا توجد بوابة مدمجة — اختر الحد الأدنى الخاص بك لكل نتيجة.
فحص الأمانriskScore من 0 إلى 100 (كلما ارتفعت القيمة، زادت السلامة)100 مطروحًا منها خصومات مرجّحة حسب الشدة ومحدودة لكل فئة. درجات التقييم: A+ 90 فأكثر … F أقل من 30.لا توجد بوابة مدمجة — اختر الحد الأدنى الخاص بك.
اختبار المتصفحمصفوفات: jsErrors وbrokenLinks وformIssues وimgIssues (لكل منها severity: "error" | "warning")لا توجد نتيجة إجمالية.بوابة تعتمد على عدد المشكلات، مثل وجود أي severity === "error".
ماسح المستودعاتscore من 0 إلى 100 + qualityGate: "passed" | "failed"100 مطروحًا منها خصومات مرجّحة حسب الشدة، محدودة لكل فئة.بوابة مدمجة — تفشل تلقائيًا عند وجود أي مشكلة حرجة أو نتيجة أقل من 60.

إيقاف خط الأنابيب

آلية عمل CI واحدة بغض النظر عن المنصة: أي خطوة تخرج برمز غير صفري تُفشل المهمة. لمنع طلب سحب (PR) أو طلب دمج فعليًا من الدمج، أضف هذه المهمة كـ فحص مطلوب/إلزامي ضمن إعدادات حماية الفرع أو موافقات طلبات الدمج في مضيف المستودع لديك — فشل خطوة واحدة بمفرده يظهر باللون الأحمر فقط، ولا يمنع الدمج من تلقاء نفسه.

أمثلة على خطوط الأنابيب

الفحوصات الأربعة نفسها — التدقيق، وفحص الأمان، واختبار المتصفح، وفحص المستودع — مكتوبة لأربع منصات. اختر نظام CI الخاص بك أدناه.

name: Scanverra checks
on: [pull_request]

jobs:
  scanverra:
    runs-on: ubuntu-latest
    env:
      API_KEY: ${{ secrets.SCANVERRA_API_KEY }}
      TARGET_URL: https://staging.example.com   # your deployed preview URL
    steps:
      - name: Website Audit (perf/SEO/a11y)
        run: |
          RES=$(curl -sf -X POST https://www.scanverra.com/api/audit \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$TARGET_URL\"}")
          echo "$RES" | jq .
          PERF=$(echo "$RES" | jq '.scores.performance')
          A11Y=$(echo "$RES" | jq '.scores.accessibility')
          if (( $(echo "$PERF < 50" | bc -l) )) || (( $(echo "$A11Y < 90" | bc -l) )); then
            echo "::error::Audit failed thresholds (perf=$PERF, a11y=$A11Y)"
            exit 1
          fi

      - name: Security Scan
        run: |
          RES=$(curl -sf -X POST https://www.scanverra.com/api/security-scan \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$TARGET_URL\"}")
          RISK=$(echo "$RES" | jq '.riskScore')
          echo "riskScore=$RISK"
          [ "$RISK" -lt 70 ] && { echo "::error::Security risk score too low ($RISK)"; exit 1; }
          true

      - name: Browser Test (JS errors, broken links)
        run: |
          RES=$(curl -sf -X POST https://www.scanverra.com/api/browser-test \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$TARGET_URL\"}")
          ERRORS=$(echo "$RES" | jq '[.jsErrors[]? | select(.severity=="error")] | length')
          [ "$ERRORS" -gt 0 ] && { echo "::error::$ERRORS JS errors found"; exit 1; }
          true

      - name: Repo Scan (SAST, secrets, deps, quality gate)
        run: |
          SCAN_ID=$(curl -sf -X POST https://www.scanverra.com/api/repo/scan \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d '{"owner":"your-org","repo":"your-repo","branch":"${{ github.head_ref }}"}' | jq -r .scanId)

          for i in $(seq 1 30); do
            RESULT=$(curl -sf "https://www.scanverra.com/api/repo/result?id=$SCAN_ID" -H "X-API-Key: $API_KEY")
            STATUS=$(echo "$RESULT" | jq -r .status)
            [ "$STATUS" != "running" ] && break
            sleep 10
          done

          echo "$RESULT" | jq '{score, qualityGate}'
          GATE=$(echo "$RESULT" | jq -r .qualityGate)
          [ "$GATE" = "failed" ] && { echo "::error::Repo quality gate failed"; exit 1; }
          true

أين تُخزَّن مفتاح API كسرّ (secret)، حسب المنصة:

  • GitHub Actions: سرّ على مستوى المستودع — Settings ← Secrets and variables ← Actions.
  • GitLab CI: متغيّر CI/CD مُخفى (masked) — Settings ← CI/CD ← Variables.
  • Azure Pipelines: متغيّر خط أنابيب سرّي (أيقونة القفل) أو مجموعة متغيرات (Variable Group) ضمن Pipelines ← Library.
  • Jenkins: بيانات اعتماد نصية سرية (Secret text credential) — Manage Jenkins ← Credentials — يُشار إليها عبر credentials(). تحتاج صورة الوكيل (agent image) أيضًا إلى تثبيت curl وjq وbc؛ تتضمنها مسبقًا أدوات التشغيل ubuntu-latest المستضافة على GitHub وAzure، بينما لا تتضمنها صورة alpine في GitLab (ومن هنا تأتي خطوة apk add).

تحتاج خطوة ماسح المستودعات إلى ربط حساب GitHub/Bitbucket/Azure الخاص بك مسبقًا في إعدادات Scanverra — فهي تفحص باستخدام الرمز (token) المخزَّن هناك، وليس رمزًا يُرسَل مع كل طلب.

ملاحظة حول الحصة: يخضع مفتاح API الخاص بالخطة المجانية لحدود الحصة نفسها التي يخضع لها حساب الويب المجاني — لا تزال عمليات تشغيل CI تُحتسب ضمن حد الفحص الشهري الخاص بك ويمكن أن تستنفده بسرعة إذا كنت تُجري الفحص مع كل طلب سحب. مفاتيح API الخاصة بخطط Pro وTeam وEnterprise غير مقيدة بحصة. راجع الحدود والسلوك.

ماسح المستودعات فقط هو من يُعيد حقل qualityGate الجاهز. أما بالنسبة للأدوات الثلاث الأخرى، فحدّد حدودك الخاصة مسبقًا وحافظ على ثباتها عبر جميع البيئات (على سبيل المثال، لا تقارن نتيجة أمان عنوان URL خاص ببيئة تجريبية بحد ضُبط لبيئة الإنتاج).