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
3 changes: 2 additions & 1 deletion benchpark-bridge/scripts/ci_generator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ ${job_prefix}_send:
script:
- echo \"Checking CI variables\"
- test -n \"\$RESULT_SERVER\" && echo \"RESULT_SERVER is set\" || echo \"RESULT_SERVER is NOT set\"
- test -n \"\$RESULT_SERVER_KEY\" && echo \"RESULT_SERVER_KEY is set\" || echo \"RESULT_SERVER_KEY is NOT set\"
- test -n \"\$RESULT_SERVER_CLIENT_CERT\" && echo \"RESULT_SERVER_CLIENT_CERT is set\" || echo \"RESULT_SERVER_CLIENT_CERT is NOT set\"
- test -n \"\$RESULT_SERVER_CLIENT_KEY\" && echo \"RESULT_SERVER_CLIENT_KEY is set\" || echo \"RESULT_SERVER_CLIENT_KEY is NOT set\"
- echo \"Sending results to server\"
- bash scripts/result_server/send_results.sh

Expand Down
4 changes: 2 additions & 2 deletions docs/guides/add-site.md
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ NewSystem,NewSystem,Example CPU,2,64,Example GPU,4,512GB,10
5. `result0.json` が作られること
- `scripts/result.sh` が Result JSON を組み立てられることを確認します。
6. `send_results` まで通ること
- API key、Result Server 接続、`results/result*.json` の配置を確認します。
- mTLS client certificate/key、Result Server 接続、`results/result*.json` の配置を確認します。

最初の動作確認では、既存アプリで最小の 1 条件だけ `list.csv` に足して `scripts/test_submit.sh` で試すのが安全です。

Expand All @@ -709,7 +709,7 @@ NewSystem,NewSystem,Example CPU,2,64,Example GPU,4,512GB,10
| build | `module load` の typo、コンパイラ不一致、依存ライブラリ不足 | `programs/<code>/build.sh` |
| run | `mpirun` / `srun` の引数、affinity、ノード側環境差異 | `programs/<code>/run.sh`, scheduler log |
| result 生成 | `results/result` がない、FOM 出力形式が違う、`bk_emit_*` 未使用 | `scripts/result.sh`, `scripts/bk_functions.sh` |
| send_results | API key、Result Server 接続、JSON 不足 | `scripts/result_server/send_results.sh`, Result Server log |
| send_results | mTLS client certificate/key、Result Server 接続、JSON 不足 | `scripts/result_server/send_results.sh`, Result Server log |

CI ログでは、まず「どの stage まで進んだか」を見ると切り分けが早くなります。`get_sources` 前、build 前、run 前、send_results 前で原因の層がかなり絞れます。

Expand Down
9 changes: 7 additions & 2 deletions docs/guides/developer-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ The supported baseline is that contributors can add apps, sites, and estimation
- detailed result and estimate pages
- usage reporting
- TOTP-based authentication
- admin pages for user management
- admin pages for user management, execution profile governance, Portal-managed
GitLab trigger submission, trigger-runner observations, and related operation
history

### Main Route Groups

Expand All @@ -100,7 +102,8 @@ The supported baseline is that contributors can add apps, sites, and estimation
- `result_server/routes/auth.py`
Login, setup, logout, and TOTP flow.
- `result_server/routes/admin.py`
Admin-only user management.
Admin-only user management, execution profile registry, manual GitLab trigger
submission, trigger definitions, trigger run history, and runner observations.

### Main API Endpoints

Expand Down Expand Up @@ -143,6 +146,8 @@ Data or `*.ncu-rep`.
TOTP setup page.
- `result_server/templates/admin_users.html`
Admin user management page.
- `result_server/templates/admin_execution_profiles.html`
Admin execution profile, trigger definition, trigger run, and observation page.

## CI Pipeline Structure

Expand Down
76 changes: 76 additions & 0 deletions result_server/tests/test_profile_usage_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,82 @@ def test_profile_usage_overview_links_profile_triggers_results_and_node_hours(tm
assert row["latest_result"]["environment_snapshot"]["allocation_project_id"] == "rkp00010"


def test_profile_usage_overview_does_not_scope_match_triggered_results_to_other_profiles(tmp_path):
db_path = tmp_path / "cx_portal.sqlite3"
received_dir = tmp_path / "received"
received_dir.mkdir()

store = ExecutionProfileStore(str(db_path))
store.upsert_profile(_profile(id="qws-fugaku"), actor="admin@test.com")
store.upsert_profile(
_profile(
id="qws-test",
system=["Fugaku", "MiyabiG"],
allocation_project_id="",
),
actor="admin@test.com",
)
store.upsert_trigger_definition(_trigger(profile_id="qws-fugaku"), actor="admin@test.com")
(received_dir / "result_20260810_170000_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee.json").write_text(
json.dumps(
{
"code": "qws",
"system": "Fugaku",
"Exp": "CASE0",
"node_count": "1",
"execution_mode": "cross",
"pipeline_timing": {"run_time": 3600},
"execution_trigger": {
"id": "qws-fugaku-time",
"type": "scheduled",
"reason": "cron:0 14 * * *",
},
}
),
encoding="utf-8",
)
(received_dir / "result_20260810_180000_cccccccc-dddd-eeee-ffff-000000000000.json").write_text(
json.dumps(
{
"code": "qws",
"system": "Fugaku",
"Exp": "CASE0",
"node_count": "1",
"execution_mode": "cross",
"pipeline_timing": {"run_time": 900},
"execution_trigger": {
"id": "qws-fugaku",
"type": "manual_button",
"reason": "manual_button:qws-fugaku",
},
}
),
encoding="utf-8",
)
(received_dir / "result_20260809_170000_bbbbbbbb-cccc-dddd-eeee-ffffffffffff.json").write_text(
json.dumps(
{
"code": "qws",
"system": "Fugaku",
"Exp": "CASE0",
"node_count": "1",
"execution_mode": "cross",
"pipeline_timing": {"run_time": 1800},
}
),
encoding="utf-8",
)

overview = build_profile_usage_overview(str(received_dir), str(db_path))

rows = {row["profile_id"]: row for row in overview["rows"]}
assert rows["qws-fugaku"]["result_count"] == 3
assert rows["qws-fugaku"]["node_hours"] == 1.75
assert rows["qws-test"]["result_count"] == 1
assert rows["qws-test"]["node_hours"] == 0.5
assert rows["qws-test"]["latest_result"]["timestamp"] == "2026-08-09 17:00:00"


def test_profile_usage_overview_handles_missing_db(tmp_path):
overview = build_profile_usage_overview(str(tmp_path), None)

Expand Down
4 changes: 2 additions & 2 deletions result_server/utils/profile_usage_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ def _result_matches_profile(
trigger_ids: set[str],
) -> bool:
trigger_id = extract_execution_trigger(result)["id"]
if trigger_id and trigger_id in trigger_ids:
return True
if trigger_id:
return trigger_id == profile.get("id") or trigger_id in trigger_ids
return (
_scope_matches(profile.get("code", []), result.get("code"))
and _scope_matches(profile.get("system", []), result.get("system"))
Expand Down
Loading