From 76dfd3b3c092dc7a9bbfca155e0d0d1a83cbb68a Mon Sep 17 00:00:00 2001 From: Claude BM Date: Tue, 28 Apr 2026 14:44:22 +0000 Subject: [PATCH] Add tag-targeted test runs to CI runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ci-runner.sh now accepts optional 4th parameter for pytest markers: ci-runner.sh mfg abc123 claude genlab → runs only genlab tests ci-runner.sh mfg abc123 claude heavy → runs full heavy suite ci-runner.sh mfg abc123 claude → runs full light suite (default) Changes: - TAG parameter parsed from $4 - pytest -m flag applied when tag provided - RUN_MODE shown in Telegram notification (light/heavy/tag:name) - Baseline check only enforced on full light suite runs - Comments noting tags need periodic updates as features change Co-Authored-By: Claude Opus 4.6 (1M context) --- ci-runner.sh | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/ci-runner.sh b/ci-runner.sh index ed40afa..6a10925 100755 --- a/ci-runner.sh +++ b/ci-runner.sh @@ -3,6 +3,17 @@ # Runs tests, feature manifests, and package checks against TSHARPS worktrees. # READ-ONLY — never writes, commits, or pushes to TSHARPS. # Same checks for ALL branches — no branch-specific logic. +# +# Usage: +# ci-runner.sh [tag] +# +# Optional [tag] parameter runs only tests with that pytest marker: +# ci-runner.sh mfg abc123 claude genlab → runs only genlab-tagged tests +# ci-runner.sh mfg abc123 claude → runs full light suite (default) +# ci-runner.sh mfg abc123 claude heavy → runs full heavy suite +# +# NOTE: Feature tags (genlab, scheduling, auth, etc.) need updating from time +# to time as features change. See pytest.ini for the current list of markers. set -o pipefail @@ -11,6 +22,7 @@ CONFIG="$SCRIPT_DIR/ci-config.json" BRANCH="$1" COMMIT="$2" ACTOR="${3:-unknown}" +TAG="${4:-}" START_TIME=$(date +%s) # Load config @@ -83,7 +95,21 @@ if $PYTHON -c "import pytest_timeout" 2>/dev/null; then TIMEOUT_FLAG="--timeout=$TIMEOUT" fi -TEST_OUTPUT=$($PYTHON -m pytest "$WORKTREE/backend/tests/" --tb=line -q $TIMEOUT_FLAG 2>&1) +# Build pytest command — use tag filter if provided +TAG_FLAG="" +RUN_MODE="light" +if [ -n "$TAG" ]; then + if [ "$TAG" = "heavy" ]; then + TAG_FLAG="" + RUN_MODE="heavy" + export RUN_HEAVY_TESTS=1 + else + TAG_FLAG="-m $TAG" + RUN_MODE="tag:$TAG" + fi +fi + +TEST_OUTPUT=$($PYTHON -m pytest "$WORKTREE/backend/tests/" --tb=line -q $TIMEOUT_FLAG $TAG_FLAG 2>&1) TEST_EXIT=$? PASS_COUNT=$(echo "$TEST_OUTPUT" | grep -oP '\d+ passed' | grep -oP '\d+' || echo 0) @@ -115,8 +141,9 @@ if [ "$ERROR_COUNT" != "0" ] && [ "$ERROR_COUNT" != "" ]; then fi # ─── Test Count Baseline Check ─── +# Baseline check only applies to full suite runs (light), not tag-targeted runs BASELINE=$(python3 -c "import json; print(json.load(open('$CONFIG')).get('test_count_baseline', 0))") -if [ "$BASELINE" -gt 0 ] && [ "$PASS_COUNT" -lt "$BASELINE" ]; then +if [ "$RUN_MODE" = "light" ] && [ "$BASELINE" -gt 0 ] && [ "$PASS_COUNT" -lt "$BASELINE" ]; then OVERALL="fail" echo "TEST COUNT REGRESSION: expected >= $BASELINE passed, got $PASS_COUNT" fi @@ -151,7 +178,13 @@ SUMMARY="${PASS_COUNT} passed, ${FAIL_COUNT} failed, ${SKIP_COUNT} skipped" TAGS_USED=$(grep -rhoP 'pytest\.mark\.\K\w+' "$WORKTREE/backend/tests/test_"*.py 2>/dev/null | \ sort -u | grep -vxE 'skipif|skip|parametrize|fixture|unit|integration|pipeline|e2e|slow|heavy' | \ tr '\n' ', ' | sed 's/,$//') -SUITE_INFO="Tags: ${TAGS_USED} | ${DESELECTED_COUNT} not in scope" +if [ "$RUN_MODE" = "light" ]; then + SUITE_INFO="Mode: light (full) | Tags: ${TAGS_USED} | ${DESELECTED_COUNT} not in scope" +elif [ "$RUN_MODE" = "heavy" ]; then + SUITE_INFO="Mode: heavy (all tests) | Tags: ${TAGS_USED}" +else + SUITE_INFO="Mode: ${RUN_MODE} | ${DESELECTED_COUNT} not in scope" +fi echo "" echo "========================="