Layout_engine #5307
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# File: .github/workflows/validate.yml | |
# Workflow: v0.7.1 – Changes (Validate) | |
name: v0.7.1 - Changes (Validate) | |
on: | |
pull_request: | |
paths: | |
- 'pkgs/**' | |
workflow_dispatch: | |
jobs: | |
detect-changed-files: | |
if: ${{ !cancelled() }} | |
runs-on: [testing] | |
outputs: | |
matrix: ${{ steps.detect.outputs.matrix }} | |
steps: | |
# ────────────────────────────────────────────────────────────────────────── | |
# Step: Check out code ─ (uses: actions/checkout@v4) | |
# ────────────────────────────────────────────────────────────────────────── | |
- name: Check out code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # fetch full history for diffing | |
# ────────────────────────────────────────────────────────────────────────── | |
# Step: Get changed files (id=files) | |
# ────────────────────────────────────────────────────────────────────────── | |
- name: Get changed files | |
id: files | |
run: | | |
set -eo pipefail | |
echo "Collecting changed files …" | |
git diff --name-only \ | |
"${{ github.event.pull_request.base.sha }}" \ | |
"${{ github.event.pull_request.head.sha }}" > changed_files.txt | |
cat changed_files.txt | |
# ────────────────────────────────────────────────────────────────────────── | |
# Step: Detect changes and generate package matrix (id=detect) | |
# Function: find_pyproject_root (Bash function) | |
# ────────────────────────────────────────────────────────────────────────── | |
- name: Detect changes and generate test matrix | |
id: detect | |
run: | | |
echo "Detecting changed packages …" | |
# Exclude the monorepo root pyproject.toml as it does not represent | |
# a real package and will always fail validation. | |
CHANGED_FILES=$(grep '^pkgs/' changed_files.txt | grep -v '^pkgs/pyproject.toml$' || true) | |
if [ -z "$CHANGED_FILES" ]; then | |
echo "No changes in pkgs/. Exiting." | |
echo 'matrix=[]' >> "$GITHUB_OUTPUT" | |
exit 0 | |
fi | |
declare -A PACKAGE_SET # <package_path> ⇒ 1 | |
# ── Function: find_pyproject_root ──────────────────────────────────── | |
find_pyproject_root() { | |
local path="$1" | |
while true; do | |
[[ -f "$path/pyproject.toml" ]] && { echo "$path"; return; } | |
[[ "$path" == "." ]] && { echo ""; return; } | |
path="$(dirname "$path")" | |
done | |
} | |
# ───────────────────────────────────────────────────────────────────── | |
for FILE in $CHANGED_FILES; do | |
DIR=$(dirname "$FILE") | |
PKG_ROOT=$(find_pyproject_root "$DIR") | |
if [[ -z "$PKG_ROOT" || "$PKG_ROOT" == "pkgs" ]]; then | |
continue | |
fi | |
PKG_PATH="${PKG_ROOT#pkgs/}" # strip leading pkgs/ | |
PACKAGE_SET["$PKG_PATH"]=1 # record the package | |
done | |
# Build JSON matrix | |
MATRIX="[" | |
for PKG in "${!PACKAGE_SET[@]}"; do | |
MATRIX+='{"package_path":"'"$PKG"'","tests":""},' | |
done | |
MATRIX="${MATRIX%,}]" | |
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" | |
echo "Final test matrix: $MATRIX" | |
# ───────────────────────────────────────────────────────────────────────────── | |
# Job: run-tests – executes once per package reported in matrix | |
# ───────────────────────────────────────────────────────────────────────────── | |
run-tests: | |
needs: detect-changed-files | |
if: ${{ !cancelled() && needs.detect-changed-files.outputs.matrix != '[]' }} | |
runs-on: [testing] | |
strategy: | |
fail-fast: false | |
matrix: | |
package_tests: ${{ fromJSON(needs.detect-changed-files.outputs.matrix) }} | |
env: | |
UNIQUE_VENV_PATH: "${{ github.workspace }}/.venv_core_${{ github.run_id }}" | |
steps: | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Check out code ─ (uses: actions/checkout@v4) | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Check out code | |
uses: actions/checkout@v4 | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Set up Python ─ (uses: actions/setup-python@v5) | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.12' | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Create & activate venv | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Create and activate virtual environment | |
run: | | |
python -m venv "$UNIQUE_VENV_PATH" | |
source "$UNIQUE_VENV_PATH/bin/activate" | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Install dependencies | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Install dependencies | |
run: | | |
source "$UNIQUE_VENV_PATH/bin/activate" | |
python -m pip install --upgrade pip | |
pip install uv poetry toml | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Ruff Format (package_path only) | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Ruff Format | |
run: | | |
source "$UNIQUE_VENV_PATH/bin/activate" | |
PKG_PATH="${{ matrix.package_tests.package_path }}" | |
echo "Running ruff format on pkgs/$PKG_PATH" | |
cd pkgs | |
PACKAGE_NAME=$(python -c "import toml, pathlib, sys; print(toml.load(pathlib.Path('$PKG_PATH')/'pyproject.toml')['project']['name'])") | |
uv run --directory "$PKG_PATH" --package "$PACKAGE_NAME" --isolated --active ruff format . | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Ruff Check (package_path only) | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Ruff Check | |
run: | | |
source "$UNIQUE_VENV_PATH/bin/activate" | |
PKG_PATH="${{ matrix.package_tests.package_path }}" | |
echo "Running ruff check on pkgs/$PKG_PATH" | |
cd pkgs | |
PACKAGE_NAME=$(python -c "import toml, pathlib, sys; print(toml.load(pathlib.Path('$PKG_PATH')/'pyproject.toml')['project']['name'])") | |
uv run --directory "$PKG_PATH" --package "$PACKAGE_NAME" --isolated --active ruff check . --fix | |
# ──────────────────────────────────────────────────────────────────────── | |
# Step: Run Pytests (run all tests in package) | |
# ──────────────────────────────────────────────────────────────────────── | |
- name: Run Pytests | |
run: | | |
set -o pipefail | |
source "$UNIQUE_VENV_PATH/bin/activate" | |
PKG_PATH="${{ matrix.package_tests.package_path }}" | |
echo "Running pytest in pkgs/$PKG_PATH" | |
cd pkgs | |
PACKAGE_NAME=$(python -c "import toml, pathlib, sys; print(toml.load(pathlib.Path('$PKG_PATH')/'pyproject.toml')['project']['name'])") | |
export PKG_PATH PACKAGE_NAME | |
set +e | |
uv run --directory "$PKG_PATH" --package "$PACKAGE_NAME" --isolated --active pytest -vvv | tee pytest.log | |
STATUS=${PIPESTATUS[0]} | |
set -e | |
python - <<'PY' | |
import os, re, pathlib | |
pkg_name = os.environ.get("PACKAGE_NAME", "unknown") | |
pkg_path = os.environ.get("PKG_PATH", "") | |
log = pathlib.Path('pytest.log').read_text().splitlines()[-1] | |
patterns = { | |
'passed': r'(\d+) passed', | |
'failed': r'(\d+) failed', | |
'xfailed': r'(\d+) xfailed', | |
'xpassed': r'(\d+) xpassed', | |
'skipped': r'(\d+) skipped', | |
'warnings': r'(\d+) warnings?', | |
'errors': r'(\d+) errors?' | |
} | |
counts = {k: 0 for k in patterns} | |
for key, pat in patterns.items(): | |
m = re.search(pat, log) | |
if m: | |
counts[key] = int(m.group(1)) | |
summary = " ".join(f"{k}={v}" for k, v in counts.items()) | |
print(f"::notice title=pytest summary ({pkg_name})::pkg_path={pkg_path} {summary}") | |
PY | |
exit $STATUS |