run.sh (7462B)
1 #!/bin/bash 2 set -euo pipefail 3 4 # 06-sub-pipelines: Run CI steps only for parts of the monorepo that changed. 5 # 6 # Detects which top-level folders were modified in the latest commit and 7 # launches the matching sub-pipeline (python / js / go). When no diff is 8 # available (e.g. the very first commit) every pipeline runs. 9 10 cd "$JCI_REPO_ROOT" 11 12 # ── Detect changed folders ─────────────────────────────────────────── 13 changed_files=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) 14 15 run_python=false 16 run_js=false 17 run_go=false 18 19 if [ -z "$changed_files" ]; then 20 echo "No diff detected (first commit or shallow clone) — running all sub-pipelines." 21 run_python=true 22 run_js=true 23 run_go=true 24 else 25 echo "Changed files:" 26 echo "$changed_files" | sed 's/^/ /' 27 echo 28 29 if echo "$changed_files" | grep -q '^06-sub-pipelines/python-app/'; then 30 run_python=true 31 fi 32 if echo "$changed_files" | grep -q '^06-sub-pipelines/js-app/'; then 33 run_js=true 34 fi 35 if echo "$changed_files" | grep -q '^06-sub-pipelines/go-app/'; then 36 run_go=true 37 fi 38 fi 39 40 pipelines_ran=0 41 summary="" 42 43 # ── Python sub-pipeline ────────────────────────────────────────────── 44 if $run_python; then 45 echo "═══ Python sub-pipeline ═══" 46 result_file="$JCI_OUTPUT_DIR/python-results.txt" 47 { 48 echo "Python sub-pipeline results" 49 echo "Commit: $JCI_COMMIT" 50 echo "Run at: $(date -u +%Y-%m-%dT%H:%M:%SZ)" 51 echo 52 53 # Lint 54 echo "── Lint ──" 55 if [ -d 06-sub-pipelines/python-app ] && command -v python3 &>/dev/null; then 56 if command -v ruff &>/dev/null; then 57 echo "Running: ruff check 06-sub-pipelines/python-app/" 58 ruff check 06-sub-pipelines/python-app/ 2>&1 && echo "Lint: PASS" || echo "Lint: FAIL" 59 elif command -v flake8 &>/dev/null; then 60 echo "Running: flake8 06-sub-pipelines/python-app/" 61 flake8 06-sub-pipelines/python-app/ 2>&1 && echo "Lint: PASS" || echo "Lint: FAIL" 62 else 63 echo "No Python linter found (ruff/flake8) — checking syntax only." 64 find 06-sub-pipelines/python-app -name '*.py' -exec python3 -m py_compile {} + 2>&1 \ 65 && echo "Syntax check: PASS" || echo "Syntax check: FAIL" 66 fi 67 else 68 echo "06-sub-pipelines/python-app/ directory or python3 not found — skipped." 69 fi 70 echo 71 72 # Tests 73 echo "── Tests ──" 74 if [ -d 06-sub-pipelines/python-app ] && command -v python3 &>/dev/null; then 75 if [ -f 06-sub-pipelines/python-app/requirements.txt ]; then 76 echo "Installing dependencies…" 77 pip install -q -r 06-sub-pipelines/python-app/requirements.txt 2>&1 || true 78 fi 79 echo "Running: python3 -m pytest 06-sub-pipelines/python-app/" 80 python3 -m pytest 06-sub-pipelines/python-app/ 2>&1 && echo "Tests: PASS" || echo "Tests: FAIL" 81 else 82 echo "06-sub-pipelines/python-app/ directory or python3 not found — skipped." 83 fi 84 } | tee "$result_file" 85 86 pipelines_ran=$((pipelines_ran + 1)) 87 summary="${summary} ✔ python-app\n" 88 echo 89 fi 90 91 # ── JS sub-pipeline ────────────────────────────────────────────────── 92 if $run_js; then 93 echo "═══ JS sub-pipeline ═══" 94 result_file="$JCI_OUTPUT_DIR/js-results.txt" 95 { 96 echo "JS sub-pipeline results" 97 echo "Commit: $JCI_COMMIT" 98 echo "Run at: $(date -u +%Y-%m-%dT%H:%M:%SZ)" 99 echo 100 101 # Lint 102 echo "── Lint ──" 103 if [ -d 06-sub-pipelines/js-app ]; then 104 if [ -f 06-sub-pipelines/js-app/package.json ] && command -v npm &>/dev/null; then 105 echo "Installing dependencies…" 106 (cd 06-sub-pipelines/js-app && npm ci --ignore-scripts 2>&1) || true 107 if [ -x 06-sub-pipelines/js-app/node_modules/.bin/eslint ]; then 108 echo "Running: eslint 06-sub-pipelines/js-app/" 109 06-sub-pipelines/js-app/node_modules/.bin/eslint 06-sub-pipelines/js-app/ 2>&1 \ 110 && echo "Lint: PASS" || echo "Lint: FAIL" 111 else 112 echo "eslint not installed — listing JS files instead." 113 find 06-sub-pipelines/js-app -name '*.js' -o -name '*.ts' | head -20 114 echo "Lint: SKIPPED" 115 fi 116 else 117 echo "No package.json or npm not available — checking syntax with node." 118 if command -v node &>/dev/null; then 119 find 06-sub-pipelines/js-app -name '*.js' -exec node --check {} \; 2>&1 \ 120 && echo "Syntax check: PASS" || echo "Syntax check: FAIL" 121 else 122 echo "node not found — skipped." 123 fi 124 fi 125 else 126 echo "06-sub-pipelines/js-app/ directory not found — skipped." 127 fi 128 } | tee "$result_file" 129 130 pipelines_ran=$((pipelines_ran + 1)) 131 summary="${summary} ✔ js-app\n" 132 echo 133 fi 134 135 # ── Go sub-pipeline ────────────────────────────────────────────────── 136 if $run_go; then 137 echo "═══ Go sub-pipeline ═══" 138 result_file="$JCI_OUTPUT_DIR/go-results.txt" 139 { 140 echo "Go sub-pipeline results" 141 echo "Commit: $JCI_COMMIT" 142 echo "Run at: $(date -u +%Y-%m-%dT%H:%M:%SZ)" 143 echo 144 145 # Build & test 146 echo "── Build & Test ──" 147 if [ -d 06-sub-pipelines/go-app ]; then 148 if command -v go &>/dev/null; then 149 echo "Running: go build ./06-sub-pipelines/go-app/..." 150 (cd 06-sub-pipelines/go-app && go build ./...) 2>&1 && echo "Build: PASS" || echo "Build: FAIL" 151 echo 152 echo "Running: go test ./06-sub-pipelines/go-app/..." 153 (cd 06-sub-pipelines/go-app && go test ./...) 2>&1 && echo "Test: PASS" || echo "Test: FAIL" 154 else 155 echo "go not found — skipped." 156 fi 157 else 158 echo "06-sub-pipelines/go-app/ directory not found — skipped." 159 fi 160 } | tee "$result_file" 161 162 pipelines_ran=$((pipelines_ran + 1)) 163 summary="${summary} ✔ go-app\n" 164 echo 165 fi 166 167 # ── Summary ────────────────────────────────────────────────────────── 168 echo "═══════════════════════════════════════" 169 echo "Sub-pipeline summary ($pipelines_ran ran)" 170 echo "═══════════════════════════════════════" 171 172 if [ $pipelines_ran -eq 0 ]; then 173 echo " No sub-pipelines matched the changed files." 174 else 175 printf "$summary" 176 fi 177 178 echo 179 echo "Result files in $JCI_OUTPUT_DIR:" 180 ls -1 "$JCI_OUTPUT_DIR"/*.txt 2>/dev/null || echo " (none)"