@@ -20,15 +20,16 @@ WORKDIR="${RUNNER_TEMP:-$(mktemp -d)}/csubst_smoke"
2020mkdir -p " $WORKDIR "
2121cd " $WORKDIR "
2222
23+ # アーティファクト置き場
24+ ART=" $WORKDIR /_artifacts_cmd"
25+ mkdir -p " $ART "
26+
2327# 最小データが無ければ生成
2428if [ ! -s alignment.fa ]; then
2529 csubst dataset --name PGK
2630fi
2731test -s alignment.fa && test -s tree.nwk && test -s foreground.txt
2832
29- # 便利関数:直近生成ファイルの列挙
30- newer_files () { find . -maxdepth 1 -type f -newer " $1 " -printf " %f\n" || true ; }
31-
3233# --- analyze(既定=ECM系) ---
3334rm -f alignment.fa.{iqtree,log,rate,state,treefile} || true
3435MARKER=$( mktemp) ; sleep 1; touch " $MARKER "
@@ -67,12 +68,12 @@ MARKER=$(mktemp); sleep 1; touch "$MARKER"
6768
6869# ログを保存しつつ終了コードを保持
6970set +e
70- env PYTHONOPTIMIZE=1 OMP_NUM_THREADS=1 ${MPLBACKEND : +env MPLBACKEND= $MPLBACKEND } csubst site \
71+ env PYTHONOPTIMIZE=1 OMP_NUM_THREADS=1 csubst site \
7172 --alignment_file alignment.fa \
7273 --rooted_tree_file tree.nwk \
7374 --cb_file " $CBFILE " \
7475 --branch_id fg \
75- --threads 1 2>&1 | tee site.log
76+ --threads 1 2>&1 | tee " $ART / site.log"
7677rc=${PIPESTATUS[0]}
7778set -e
7879
@@ -84,26 +85,25 @@ if [ $rc -ne 0 ]; then
8485 [ -n " $combo " ] || { echo " ERROR: cb テーブルから枝IDを取得できませんでした" ; exit 1; }
8586
8687 set +e
87- env PYTHONOPTIMIZE=1 OMP_NUM_THREADS=1 ${MPLBACKEND : +env MPLBACKEND= $MPLBACKEND } csubst site \
88+ env PYTHONOPTIMIZE=1 OMP_NUM_THREADS=1 csubst site \
8889 --alignment_file alignment.fa \
8990 --rooted_tree_file tree.nwk \
9091 --branch_id " $combo " \
91- --threads 1 2>&1 | tee site.log
92+ --threads 1 2>&1 | tee " $ART / site.log"
9293 rc=${PIPESTATUS[0]}
9394 set -e
9495fi
9596
9697[ $rc -eq 0 ] || { echo " ERROR: csubst site が非0終了" ; exit 1; }
9798
9899# ---- 成功判定:ログ+中間ファイル(.mmap を必須にしない) ----
99- grep -E " csubst site end|Generating memory map" site.log > /dev/null || {
100+ grep -E " csubst site end|Generating memory map" " $ART / site.log" > /dev/null || {
100101 echo " ERROR: site.log に実行完了の痕跡がありません" ; exit 1; }
101102
102103# IQ-TREEの中間が直近でできていること(少なくとも state/rate)
103104test -s alignment.fa.state && test -s alignment.fa.rate || {
104105 echo " ERROR: alignment.fa.state / .rate が見つかりません" ; exit 1; }
105- # 実行後に更新されたかを軽く確認(無理ならスキップしてOK)
106- if [ -n " $( find . -maxdepth 1 -name ' alignment.fa.state' -newer " $MARKER " -print -quit) " ]; then
106+ if find . -maxdepth 1 -name ' alignment.fa.state' -newer " $MARKER " | head -n1 | grep -q . ; then
107107 echo " OK: site 再計算で state/rate を生成/更新"
108108else
109109 echo " NOTE: site は既存の IQ-TREE 中間を再利用した可能性があります"
113113SITE_TSV=($( find . -maxdepth 1 -type f -name " csubst_site*.tsv" -newer " $MARKER " -print) )
114114[ ${# SITE_TSV[@]} -ge 1 ] && echo " NOTE: site TSV: ${SITE_TSV[*]} "
115115
116- # アーティファクト収集に site.log も追加
117- ART=" $WORKDIR /_artifacts_cmd"
118- mkdir -p " $ART "
119- cp -v site.log " $ART " || true
120-
121116echo " OK: site finished (verified by logs and IQ-TREE intermediates)"
122117
123- # --- round-trip: simulate の出力を analyze へ ---
118+ # --- simulate(pyvolve の存在を確認してから) ---
119+ python - << 'PY '
120+ import sys
121+ try:
122+ import pyvolve # noqa: F401
123+ except Exception as e:
124+ print("FATAL: pyvolve import failed:", e)
125+ sys.exit(1)
126+ print("OK: pyvolve import")
127+ PY
128+
129+ # simulate 実行(ログ保存)
124130MARKER=$( mktemp) ; sleep 1; touch " $MARKER "
125-
126- env PYTHONOPTIMIZE=1 csubst simulate \
131+ set -o pipefail
132+ csubst simulate \
127133 --alignment_file alignment.fa \
128134 --rooted_tree_file tree.nwk \
129135 --foreground foreground.txt \
130- --threads 1
136+ --iqtree_model GY+F3x4+R2 \
137+ --threads 1 | tee " $ART /simulate.log"
138+ sim_ec=${PIPESTATUS[0]}
139+ set +o pipefail
131140
141+ # 合否判定:終了コード + ログマーカー
142+ if [[ $sim_ec -ne 0 ]]; then
143+ echo " ERROR: simulate failed (exit $sim_ec )" ; exit 1
144+ fi
145+ grep -q " csubst simulate start" " $ART /simulate.log" || { echo " ERROR: simulate log missing 'start' mark" ; exit 1; }
146+ grep -q " Time elapsed" " $ART /simulate.log" || { echo " ERROR: simulate log missing 'Time elapsed'" ; exit 1; }
147+ echo " OK: simulate finished (verified by exit code and log markers)"
148+
149+ # --- round-trip: simulate の出力を analyze へ ---
132150SIM_ALN=" $( find . -maxdepth 1 -type f \( -name " *.fa" -o -name " *.fasta" -o -name " *.phy" \) -newer " $MARKER " | head -n1) "
133151[ -s " ${SIM_ALN:- } " ] || { echo " ERROR: simulate 出力の配列ファイルが見つかりません" ; exit 1; }
134152
@@ -138,13 +156,13 @@ env PYTHONOPTIMIZE=1 OMP_NUM_THREADS=1 csubst analyze \
138156 --rooted_tree_file tree.nwk \
139157 --foreground foreground.txt \
140158 --threads 1
141-
142159NEW_TSV2=($( find . -maxdepth 1 -type f -name " csubst_*.tsv" -newer " $MARKER2 " -print) )
143160[ ${# NEW_TSV2[@]} -ge 1 ] || { echo " ERROR: simulate→analyze で TSV が生成されていません" ; exit 1; }
144161echo " OK: round-trip simulate→analyze(created): ${NEW_TSV2[*]} "
145162
146163echo " Command tests OK"
147164
165+ # サマリ
148166{
149167 echo " # csubst CI Summary"
150168 echo
0 commit comments