Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ rg -n "(shutil.rmtree|os.remove|Path.unlink|rm -rf|rimraf)" -S
- "🔍 Code Quality & Security"
- "Unit Tests (3.11)"
- "Unit Tests (3.12)"
- "Unit Tests md-heavy (3.11)"
- "Unit Tests md-heavy (3.12)"

### נוספים
- אין `paths-ignore` על `.cursorrules` – שינוי בו מריץ CI
Expand Down
6 changes: 4 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ EOF
| בדיקה | תיאור |
|-------|--------|
| 🔍 **Code Quality & Security** | בדיקת איכות קוד ופרצות אבטחה |
| 🧪 **Unit Tests (3.11)** | טסטים על Python 3.11 |
| 🧪 **Unit Tests (3.12)** | טסטים על Python 3.12 |
| 🧪 **Unit Tests (3.11)** | כל הטסטים חוץ מ-`md_heavy`, על Python 3.11 |
| 🧪 **Unit Tests (3.12)** | כל הטסטים חוץ מ-`md_heavy`, על Python 3.12 |
| 🧪 **Unit Tests md-heavy (3.11)** | טסטי ה-Markdown הכבדים (`md_heavy`), על Python 3.11 |
| 🧪 **Unit Tests md-heavy (3.12)** | טסטי ה-Markdown הכבדים (`md_heavy`), על Python 3.12 |

---

Expand Down
4 changes: 4 additions & 0 deletions .github/agents/my-agent.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pull_request_template: |
- 🔍 Code Quality & Security
- Unit Tests (3.11)
- Unit Tests (3.12)
- Unit Tests md-heavy (3.11)
- Unit Tests md-heavy (3.12)

## 📝 סוג שינוי
- [ ] feat: פיצ'ר חדש
Expand Down Expand Up @@ -134,6 +136,8 @@ guards:
- "🔍 Code Quality & Security"
- "Unit Tests (3.11)"
- "Unit Tests (3.12)"
- "Unit Tests md-heavy (3.11)"
- "Unit Tests md-heavy (3.12)"
description: "כל ה-Required Checks חייבים להיות ירוקים"

style_guide:
Expand Down
4 changes: 3 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<li>סיכוני Rollback אם יש</li>
<li>קישור ל-Docs Preview אם רלוונטי</li>
<li>השפעה על Deploy (אם יש)</li>
<li>CI Required Checks: 🔍 Code Quality & Security; Unit Tests (3.11); Unit Tests (3.12)</li>
<li>CI Required Checks: 🔍 Code Quality & Security; Unit Tests (3.11); Unit Tests (3.12); Unit Tests md-heavy (3.11); Unit Tests md-heavy (3.12)</li>
<li>אין סודות/PII בקוד</li>
<li>אין מחיקות מסוכנות (ראו .cursorrules)</li>
</ul>
Expand Down Expand Up @@ -44,6 +44,8 @@
- 🔍 Code Quality & Security
- Unit Tests (3.11)
- Unit Tests (3.12)
- Unit Tests md-heavy (3.11)
- Unit Tests md-heavy (3.12)

## 📝 סוג שינוי
- [ ] feat: פיצ'ר חדש
Expand Down
65 changes: 48 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,20 +165,39 @@ jobs:
});

unit-tests:
name: "Unit Tests (${{ matrix.python-version }})"
# שני מסלולים לכל גרסת פייתון, שרצים במקביל. ``main`` מריץ את כל הטסטים חוץ
# מאלה שמסומנים ``md_heavy`` (הרישום ב-``pytest.ini``), ו-``md-heavy`` מריץ רק
# אותם. הם במסלול משלהם כי הם מפרסרים קלט ענק בתקרות של פרסר ה-Markdown, וכך
# הם אינם מאריכים את המסלול שכל PR מחכה לו. ראו docs/ci-cd.rst.
#
# כל מסלול מדווח סטטוס חובה משלו בשם ``<label> (<python-version>)``. שמות
# הסטטוסים כתובים גם ברשימות של בדיקות החובה בתיעוד ובתבניות, ו-
# ``tests/test_required_checks_are_listed.py`` משווה אותן למטריצה הזו.
name: "${{ matrix.label }} (${{ matrix.python-version }})"
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
python-version: [ '3.11', '3.12' ]
suite: ['main', 'md-heavy']
include:
- suite: main
label: 'Unit Tests'
marker: 'not md_heavy'
- suite: md-heavy
label: 'Unit Tests md-heavy'
marker: 'md_heavy'
services:
# המסלול ``md-heavy`` אינו צריך מסד: ``image`` ריק אומר ל-runner לא להרים את
# השירות (``jobs.<job_id>.services.<service_id>.image`` בתיעוד של GitHub
# Actions).
mongodb:
# 8.0 ולא 6.0, כי הפרודקשן רץ על MongoDB Atlas 8.0 — בדיקה שרצה מול
# מסד אמיתי צריכה לבדוק את אותו מנוע. בפרט ``queryShapeHash`` בפלט של
# ``explain`` קיים רק מ-8.0 ומעלה, ו-tests/test_profiler_projection_mongo.py
# נשען עליו. ראו docs/testing.rst.
image: mongo:8.0
image: ${{ matrix.suite == 'main' && 'mongo:8.0' || '' }}
Comment thread
amirbiron marked this conversation as resolved.
env:
MONGO_INITDB_ROOT_USERNAME: test
MONGO_INITDB_ROOT_PASSWORD: test123
Expand All @@ -189,7 +208,7 @@ jobs:
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
image: ${{ matrix.suite == 'main' && 'redis:7-alpine' || '' }}
# Avoid host port binding; job connects via service hostname
options: >-
--health-cmd "redis-cli ping"
Expand Down Expand Up @@ -217,6 +236,10 @@ jobs:
- name: 🔎 Dependency integrity (pip check)
run: pip check || true

# שם הסטטוס נבנה מהמטריצה, באותה צורה כמו ``name`` של הג'וב, כך שכל מסלול
# כותב רק לסטטוס שלו. GitHub קובע את מצב הסטטוס לפי הדיווח האחרון לכל שם
# (REST, "Commit statuses"), ולכן שני מסלולים שכותבים לאותו שם היו דורסים זה
# את זה — והצלחה של אחד הייתה מסתירה כשל של השני.
- name: Report required status (pending)
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
Expand All @@ -225,19 +248,20 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const sha = context.payload.pull_request ? context.payload.pull_request.head.sha : context.sha;
const ver = process.env.PYV || '${{ matrix.python-version }}';
await github.request('POST /repos/{owner}/{repo}/statuses/{sha}', {
owner: context.repo.owner,
repo: context.repo.repo,
sha,
state: 'pending',
context: `Unit Tests (${ver})`,
context: process.env.STATUS_CONTEXT,
description: 'Job queued/running',
target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
});
env:
PYV: ${{ matrix.python-version }}
STATUS_CONTEXT: "${{ matrix.label }} (${{ matrix.python-version }})"
# בדיקת תחביר על כל הריפו — לא תלויה במסלול, ולכן רצה פעם אחת לכל גרסה.
- name: 🧪 Smoke compile (exclude .restore)
if: matrix.suite == 'main'
run: |
find . -type f -name "*.py" -not -path "./.restore/*" -print0 | xargs -0 -n1 -P 4 python -m py_compile
- name: 🧪 Run Tests
Expand Down Expand Up @@ -267,8 +291,15 @@ jobs:
REQUESTS_RETRIES: '0'
REQUESTS_RETRY_BACKOFF: '0'
AIOHTTP_TIMEOUT_TOTAL: '6'
# ``-m`` בוחר את הטסטים של המסלול (``matrix.marker``). מסלול שלא נבחר בו אף
# טסט נכשל ולא עובר בשקט: pytest יוצא בקוד 5 כשלא נאסף אף טסט, גם כשכולם
# סוננו ב-``-m`` (נמדד ב-pytest 8.4.2, עם ``-n`` ובלעדיו). כך שם סימון ששונה
# כאן ולא בטסטים, או בכל הטסטים ולא כאן, מפיל את המסלול ``md-heavy``. טסט בודד
# שהסימון שלו חסר או שגוי פשוט רץ במסלול הרגיל. את קוד היציאה, ואת זה ששני
# הביטויים משלימים זה את זה, מקבע ``tests/test_required_checks_are_listed.py``.
run: |
pytest -n auto --dist=loadscope -v -o addopts="" --cov=. --cov-report=xml --cov-report=term \
pytest -n auto --dist=loadscope -v -o addopts="" -m "${{ matrix.marker }}" \
Comment thread
amirbiron marked this conversation as resolved.
--cov=. --cov-report=xml --cov-report=term \
--durations=0 --json-report --json-report-file=unit-durations.json

- name: Upload coverage to Codecov
Expand All @@ -285,7 +316,10 @@ jobs:
if: always()
uses: actions/upload-artifact@v4
with:
name: unit-durations-${{ matrix.python-version }}-${{ github.run_id }}
# שם ייחודי לכל מסלול: ``upload-artifact@v4`` אינו מאפשר שתי העלאות לאותו
# שם. הקידומת ``unit-durations-`` נשארת, כי ``notify-post-merge-issue.yml``
# מחפש לפיה את הדוחות שבהם נספרים טסטים שנכשלו.
name: unit-durations-${{ matrix.suite }}-${{ matrix.python-version }}-${{ github.run_id }}
path: |
unit-durations.json
if-no-files-found: ignore
Expand All @@ -298,18 +332,17 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const sha = context.payload.pull_request ? context.payload.pull_request.head.sha : context.sha;
const ver = process.env.PYV || '${{ matrix.python-version }}';
await github.request('POST /repos/{owner}/{repo}/statuses/{sha}', {
owner: context.repo.owner,
repo: context.repo.repo,
sha,
state: 'success',
context: `Unit Tests (${ver})`,
context: process.env.STATUS_CONTEXT,
description: 'Tests passed',
target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
});
env:
PYV: ${{ matrix.python-version }}
STATUS_CONTEXT: "${{ matrix.label }} (${{ matrix.python-version }})"

- name: Report required status (failure)
if: ${{ failure() }}
Expand All @@ -319,18 +352,17 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const sha = context.payload.pull_request ? context.payload.pull_request.head.sha : context.sha;
const ver = process.env.PYV || '${{ matrix.python-version }}';
await github.request('POST /repos/{owner}/{repo}/statuses/{sha}', {
owner: context.repo.owner,
repo: context.repo.repo,
sha,
state: 'failure',
context: `Unit Tests (${ver})`,
context: process.env.STATUS_CONTEXT,
description: 'Tests failed',
target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
});
env:
PYV: ${{ matrix.python-version }}
STATUS_CONTEXT: "${{ matrix.label }} (${{ matrix.python-version }})"

- name: Report required status (cancelled)
if: ${{ cancelled() }}
Expand All @@ -340,18 +372,17 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const sha = context.payload.pull_request ? context.payload.pull_request.head.sha : context.sha;
const ver = process.env.PYV || '${{ matrix.python-version }}';
await github.request('POST /repos/{owner}/{repo}/statuses/{sha}', {
owner: context.repo.owner,
repo: context.repo.repo,
sha,
state: 'failure',
context: `Unit Tests (${ver})`,
context: process.env.STATUS_CONTEXT,
description: 'Job cancelled',
target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
});
env:
PYV: ${{ matrix.python-version }}
STATUS_CONTEXT: "${{ matrix.label }} (${{ matrix.python-version }})"

js-tests:
name: "JS Tests (node)"
Expand Down
10 changes: 3 additions & 7 deletions docs/auto-updates-and-auto-merge.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,7 @@
- סמן:
- Require a pull request before merging
- Require status checks to pass before merging
- בחר את הסטטוסים שמגיעים מ־ci.yml:
- "Unit Tests (3.9)"
- "Unit Tests (3.10)"
- "Unit Tests (3.11)"
- "🔍 Code Quality & Security"
- בחר את הסטטוסים הנדרשים שמגיעים מ־ci.yml. הרשימה נמצאת ב-`docs/ci-cd.rst`, ולא מועתקת לכאן כדי שלא תתיישן.
- מומלץ: Require branches to be up to date before merging
- Require conversation resolution before merging (מומלץ)

Expand Down Expand Up @@ -86,7 +82,7 @@
### פתרון תקלות
- "No checks have been added" בכללי ההגנה:
- ודא שיש לפחות ריצה אחת של ה־CI על PR (גם Draft מספיק).
- רענן את העמוד ואז בחר את 4 הסטטוסים מרשימת ה־checks (Unit Tests 3 גרסאות + Code Quality).
- רענן את העמוד ואז בחר את הסטטוסים הנדרשים מרשימת ה־checks (הרשימה ב-`docs/ci-cd.rst`).

- "There isn’t anything to compare" כשפותחים PR:
- ודא שה־base הוא `main` וה־compare הוא הענף שלך.
Expand All @@ -100,7 +96,7 @@


### צ'ק־ליסט מהיר
- [ ] הגדרת Branch protection ל־`main` עם 4 הסטטוסים מ־ci.yml
- [ ] הגדרת Branch protection ל־`main` עם הסטטוסים הנדרשים מ־ci.yml (הרשימה ב-`docs/ci-cd.rst`)
- [ ] הפעלת "Allow auto‑merge" (Settings → General → Pull requests)
- [ ] הוספת Secret: `DEPENDABOT_AUTOMERGE`=true (כשרוצים אוטומרג׳ ל־patch)
- [ ] לשקול כיבוי זמני של Auto Deploy ב־Render לפני מיזוגים ל־`main`
Expand Down
4 changes: 1 addition & 3 deletions docs/branch-protection-and-pr-rules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ Branch Protection & PR Rules

CI – Required Checks
--------------------
- "🔍 Code Quality & Security"
- "Unit Tests (3.11)"
- "Unit Tests (3.12)"
- אילו סטטוסים ה-PR חייב לעבור, ומתי סטטוס חדש מתחיל לחסום מיזוג — ב-:doc:`ci-cd`. העמוד הזה מפנה לשם במקום להחזיק עותק של הרשימה.

קישורים
-------
Expand Down
8 changes: 7 additions & 1 deletion docs/ci-cd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@ CI/CD Guide
- 🔍 Code Quality & Security
- Unit Tests (3.11)
- Unit Tests (3.12)
- Unit Tests md-heavy (3.11)
- Unit Tests md-heavy (3.12)

שמות הסטטוסים של ``Unit Tests`` נבנים מהמטריצה של הג'וב ``unit-tests`` ב-``.github/workflows/ci.yml`` (``label`` ו-``python-version``). אותם שמות כתובים ביד גם בקבצים אחרים בריפו, ו-``tests/test_required_checks_are_listed.py`` משווה למטריצה כל קובץ כזה שרשום בו (``LISTS``), כולל העמוד הזה. הוא נכשל גם כשעותק מופיע בקובץ שאינו רשום בו, אלא אם הקובץ מסומן שם כתמונת מצב ולא כרשימה שפועלים לפיה (``SNAPSHOTS``). עמוד שרק צריך להזכיר את הרשימה מפנה לכאן במקום להעתיק אותה.

**סטטוס חדש אינו חוסם מיזוג עד שמסמנים אותו כבדיקת חובה** בכלל שמגן על ``main`` בהגדרות של GitHub (Require status checks to pass before merging). GitHub מציע לבחירה רק בדיקה שעברה בהצלחה בריפו בשבעת הימים האחרונים (GitHub Docs, "Troubleshooting required status checks"), ולכן מסמנים אותה אחרי שה-CI של ה-PR שהוסיף אותה עבר.

ריכוז CI (Overview)
--------------------

- **Code Quality & Security** – בדיקות סטטיות ואבטחה
- **Unit Tests (3.11/3.12)** – טסטי יחידה במטריצת גרסאות
- **Unit Tests (3.11/3.12)** ו-**Unit Tests md-heavy (3.11/3.12)** – טסטי היחידה, בשני מסלולים לכל גרסת פייתון שרצים במקביל. ``Unit Tests`` מריץ את כל הטסטים חוץ מאלה שמסומנים ``md_heavy``, ו-``Unit Tests md-heavy`` מריץ רק אותם: טסטי פרסר ה-Markdown הכבדים (ראו :doc:`testing`). כל מסלול מדווח סטטוס חובה משלו, והמסלול ``md-heavy`` אינו מרים את MongoDB ואת Redis (``services`` של ``unit-tests``).
- **JS Tests (node)** – טסטי הצד-לקוח שב-``tests/*.test.js``. כל קובץ הוא סקריפט עצמאי שמריץ את עצמו ויוצא עם קוד שגיאה בכשל, בלי רץ טסטים חיצוני. ``repo-history.test.js`` מדולג במפורש: הוא כתוב בסגנון ``describe``/``it`` ואין בפרויקט רץ שמספק אותם. **אינו סטטוס נדרש** – הכשל מופיע ב-PR אך אינו חוסם מיזוג.
- **Performance Tests** – טסטי ביצועים (ברירת מחדל: הכל; Draft + ``perf-light``: רק קלים). דוחות זמני ריצה נשמרים כארטיפקטים.

Expand Down
22 changes: 21 additions & 1 deletion docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,27 @@ Mocking HTTP ב‑github_menu_handler
CI נתמך
-------

- ה‑PR חייב לעבור סטטוסים: "🔍 Code Quality & Security", "Unit Tests (3.11)", "Unit Tests (3.12)".
- אילו ג'ובים רצים על PR ואילו סטטוסים הוא חייב לעבור — ב-:doc:`ci-cd`. העמוד הזה מפנה לשם במקום להחזיק עותק של הרשימה.

טסטי Markdown כבדים (``md_heavy``)
-----------------------------------

**טסטים שמסומנים ``md_heavy`` רצים ב-CI במסלול משלהם, במקביל לשאר הטסטים.** אלה טסטי פרסר ה-Markdown שעיקר העבודה שלהם הוא החישוב עצמו: השוואה לאורקל cmark-gfm (``tests/test_md_parser_oracle.py``), קלט ענק בתקרות של הפרסר, והטסטים של סקריפטי המדידה (``scripts/md_parser_upgrade_zero_diff.py`` ו-``scripts/measure_md_parse_cost.py``). הסימון רשום ב-``pytest.ini``. הוא מונח על הקובץ כולו (``pytestmark``) כשכל הקובץ מהסוג הזה, ועל טסט בודד כשרק הוא כזה — כמו שני טסטי התקרה ב-``tests/test_md_parser.py``.

- ``pytest`` בלי ``-m`` מריץ את כולם, כולל ``md_heavy``. כדי להריץ רק חלק אחד:

.. code-block:: bash

# רק הכבדים — מה שהמסלול md-heavy מריץ ב-CI
pytest -m md_heavy

# כל השאר — מה שהמסלול הרגיל מריץ ב-CI
pytest -m "not md_heavy"

- ב-CI הג'וב ``unit-tests`` ב-``.github/workflows/ci.yml`` רץ בשני מסלולים לכל גרסת פייתון, וכל מסלול מדווח סטטוס חובה משלו (ראו :doc:`ci-cd`).
- **מתי מסמנים טסט חדש:** כשהוא מאותו סוג — השוואה לאורקל, קלט בתקרות של הפרסר, או סקריפט מדידה. טסט איטי מסוג אחר אינו שייך לכאן: המסלול הזה אינו מקום לכל מה שאיטי.
- **אין קשר ל-``heavy``.** ``heavy`` שייך לטסטי הביצועים (``-m performance``), ראו :doc:`performance-tests`.
- **מסלול שלא נבחר בו אף טסט נכשל ואינו עובר בשקט:** pytest יוצא בקוד 5 כשלא נאסף אף טסט, גם כשכולם סוננו ב-``-m`` (נמדד ב-pytest 8.4.2). לכן שם סימון ששונה ב-``ci.yml`` בלי הטסטים, או בכל הטסטים בלי ``ci.yml``, מפיל את המסלול ``md-heavy``. טסט בודד שהסימון שלו חסר או שגוי אינו נתפס כך: הוא עובר למסלול הרגיל ורץ שם, לאט יותר. ``tests/test_required_checks_are_listed.py`` מקבע את קוד היציאה, ובודק שהביטויים של שני המסלולים משלימים זה את זה, כך שכל טסט נבחר במסלול אחד בדיוק.

בדיקות דפדפן, ותקרת הזמן
-------------------------
Expand Down
Loading
Loading