gabriel / musehub public
test_wire_presign_push.py python
683 lines 22.7 KB
Raw
sha256:bb2baaabdd19320bde50cb69d447fd1c1e571467df729be1a23b5e93064b046a feat(intel): standardize headers, gauge icon, velocity card… Sonnet 4.6 minor ⚠ breaking 142 days ago
1 """TDD — R2 presigned push path.
2
3 Problem
4 -------
5 Cloudflare times out streaming POSTs after ~100 seconds. Repos with
6 more than ~500 objects (e.g. the muse repo at 6905 objects / 191 MB raw)
7 fail mid-upload. The fix: for large pushes the client calls
8 ``POST /push/presign`` first, PUTs objects directly to R2 (bypassing CF),
9 then sends a compressed H+C+E stream with zero O frames. The server's
10 existing referential integrity check (lines 1758-1786 of musehub_wire.py)
11 already handles objects that arrive pre-stored.
12
13 Test plan
14 ---------
15 P1 wire_push_presign — LocalBackend: missing objects land in stream_these,
16 already-stored objects land in already_stored, presigned_urls is empty.
17
18 P2 wire_push_presign — mocked S3Backend: missing objects get presigned PUT
19 URLs; already-stored objects land in already_stored.
20
21 P3 wire_push_presign — empty object list returns all-empty response.
22
23 P4 push/stream with zero O frames and all objects pre-stored in the DB
24 finalises the commit successfully (referential integrity passes).
25
26 P5 push/stream with zero O frames but objects NOT in storage returns 422
27 (referential integrity rejects the push).
28
29 P6 Full round-trip: presign → store objects via backend.put → push stream
30 with zero O frames → /refs reflects the new head.
31
32 P7 S3Backend.presign_batch generates correctly-keyed URLs for a batch of
33 object IDs (mocked boto3; no real AWS call).
34
35 Confirm step (missing from initial implementation — discovered via staging test)
36 --------------------------------------------------------------------------------
37 The presigned PUT goes directly to R2, bypassing the server entirely. The
38 server therefore has no DB record for those objects, so the referential
39 integrity check on the zero-O-frame push/stream rejects with 422.
40
41 Fix: the client calls ``POST /push/confirm`` after all R2 PUTs succeed.
42 The server inserts a ``musehub_objects`` row (using ``backend.uri_for(oid)``)
43 and a ``musehub_object_refs`` row for each confirmed object, then the zero-O
44 push/stream passes the integrity check.
45
46 P9 wire_push_confirm inserts DB rows for confirmed objects; subsequent
47 push/stream with zero O frames succeeds.
48 P10 wire_push_confirm is idempotent — confirming the same object twice
49 does not duplicate rows or raise.
50 P11 Full end-to-end: presign → R2 PUT → confirm → zero-O push/stream →
51 commit is accessible via wire_refs.
52 """
53 from __future__ import annotations
54 from collections.abc import AsyncIterator
55
56 import asyncio
57 import zlib
58 from datetime import datetime, timezone
59 from unittest.mock import AsyncMock, MagicMock, patch
60
61 import msgpack
62 import pytest
63 from sqlalchemy.dialects.postgresql import insert as pg_insert
64 from sqlalchemy.ext.asyncio import AsyncSession
65
66 from muse.core.types import blob_id, fake_id
67 from musehub.db import musehub_models as db
68 from musehub.models.wire import (
69 SFRAME_COMMIT_PACK,
70 SFRAME_END,
71 SFRAME_HEADER,
72 SFRAME_OBJECT,
73 )
74 from muse.core.mpack import MuseWireFrameWriter
75 from musehub.types.json_types import JSONObject
76 from tests.factories import create_repo
77
78 _fw = MuseWireFrameWriter()
79
80
81 # ---------------------------------------------------------------------------
82 # Helpers
83 # ---------------------------------------------------------------------------
84
85 def _now() -> datetime:
86 return datetime.now(tz=timezone.utc)
87
88
89 def _uid(seed: str) -> str:
90 return fake_id(seed)
91
92
93 def _pack(data: JSONObject) -> bytes:
94 return msgpack.packb(data, use_bin_type=True)
95
96
97 def _wrap(ft: str, data: JSONObject) -> bytes:
98 return _fw.wrap(frame_type=ft, payload=_pack(data))
99
100
101 def _header_frame(
102 n_objects: int = 0,
103 n_commits: int = 1,
104 branch: str = "main",
105 force: bool = True,
106 ) -> bytes:
107 return _wrap(SFRAME_HEADER, {
108 "t": SFRAME_HEADER,
109 "branch": branch,
110 "force": force,
111 "n_objects": n_objects,
112 "n_commits": n_commits,
113 })
114
115
116 def _end_frame(n_objects: int = 0, n_commits: int = 1) -> bytes:
117 return _wrap(SFRAME_END, {
118 "t": SFRAME_END,
119 "n_objects": n_objects,
120 "n_commits": n_commits,
121 })
122
123
124 def _commit_pack_frame(commits: list[dict], snapshots: list[dict] | None = None) -> bytes:
125 return _wrap(SFRAME_COMMIT_PACK, {
126 "t": SFRAME_COMMIT_PACK,
127 "commits": commits,
128 "snapshots": snapshots or [],
129 })
130
131
132 def _o_frame(oid: str, content: bytes, path: str = "file.py") -> bytes:
133 return _wrap(SFRAME_OBJECT, {
134 "t": SFRAME_OBJECT,
135 "id": oid,
136 "path": path,
137 "content": zlib.compress(content, level=1),
138 "enc": "zlib",
139 "size": len(content),
140 })
141
142
143 async def _store_object(session: AsyncSession, repo_id: str, oid: str, content: bytes) -> None:
144 """Insert object directly into DB + local storage (bypasses wire protocol)."""
145 from musehub.services.musehub_wire import get_backend
146 backend = get_backend()
147 uri = await backend.put(oid, content)
148 await session.execute(
149 pg_insert(db.MusehubObject)
150 .values(
151 object_id=oid,
152 path="",
153 size_bytes=len(content),
154 disk_path=uri.replace("local://", ""),
155 storage_uri=uri,
156 )
157 .on_conflict_do_nothing(index_elements=["object_id"])
158 )
159 await session.execute(
160 pg_insert(db.MusehubObjectRef)
161 .values(repo_id=repo_id, object_id=oid)
162 .on_conflict_do_nothing()
163 )
164 await session.commit()
165
166
167 async def _make_commit_and_snapshot(
168 session: AsyncSession,
169 repo_id: str,
170 *,
171 manifest: dict[str, str],
172 commit_seed: str = "c1",
173 parent_ids: list[str] | None = None,
174 ) -> tuple[db.MusehubCommit, db.MusehubSnapshot]:
175 snap_id = _uid(f"snap-{commit_seed}")
176 snap = db.MusehubSnapshot(
177 snapshot_id=snap_id,
178 repo_id=repo_id,
179 directories=[],
180 manifest_blob=msgpack.packb(manifest, use_bin_type=True),
181 entry_count=len(manifest),
182 created_at=_now(),
183 )
184 session.add(snap)
185 commit_id = _uid(f"commit-{commit_seed}")
186 commit = db.MusehubCommit(
187 commit_id=commit_id,
188 repo_id=repo_id,
189 branch="main",
190 parent_ids=parent_ids or [],
191 message=f"commit {commit_seed}",
192 author="gabriel",
193 timestamp=_now(),
194 snapshot_id=snap_id,
195 )
196 session.add(commit)
197 await session.commit()
198 return commit, snap
199
200
201 async def _collect_frames(gen: AsyncIterator[bytes]) -> list[JSONObject]:
202 chunks: list[bytes] = []
203 async for chunk in gen:
204 chunks.append(chunk)
205 unpacker = msgpack.Unpacker(raw=False)
206 for chunk in chunks:
207 unpacker.feed(chunk)
208 return list(unpacker)
209
210
211 async def _body_iter(raw: bytes) -> None:
212 yield raw
213
214
215 # ---------------------------------------------------------------------------
216 # P1 — LocalBackend: missing → stream_these, present → already_stored
217 # ---------------------------------------------------------------------------
218
219 @pytest.mark.asyncio
220 async def test_p1_local_backend_missing_goes_to_stream_these(
221 db_session: AsyncSession,
222 ) -> None:
223 """LocalBackend.presign_batch returns {} → missing oids land in stream_these."""
224 from musehub.services.musehub_wire import wire_push_presign
225
226 repo = await create_repo(db_session, owner="gabriel")
227 repo_id = str(repo.repo_id)
228
229 content_a = b"object-A content for presign test"
230 content_b = b"object-B content for presign test"
231 oid_a = blob_id(content_a)
232 oid_b = blob_id(content_b)
233
234 # Pre-store A so it lands in already_stored.
235 await _store_object(db_session, repo_id, oid_a, content_a)
236
237 result = await wire_push_presign(
238 db_session,
239 repo_id,
240 [oid_a, oid_b],
241 )
242
243 assert oid_a in result["already_stored"]
244 assert oid_b not in result["already_stored"]
245 # LocalBackend returns no presigned URLs.
246 assert result["presigned_urls"] == {}
247 # Missing object with no presigned URL goes to stream_these.
248 assert oid_b in result["stream_these"]
249 assert oid_a not in result["stream_these"]
250
251
252 # ---------------------------------------------------------------------------
253 # P2 — S3Backend: missing → presigned_urls
254 # ---------------------------------------------------------------------------
255
256 @pytest.mark.asyncio
257 async def test_p2_s3_backend_missing_gets_presigned_url(
258 db_session: AsyncSession,
259 ) -> None:
260 """S3Backend.presign_batch is called for missing objects; URLs are returned."""
261 from musehub.services.musehub_wire import wire_push_presign
262
263 repo = await create_repo(db_session, owner="gabriel")
264 repo_id = str(repo.repo_id)
265
266 content = b"object content for s3 presign test"
267 oid = blob_id(content)
268 fake_url = f"https://r2.example.com/objects/{oid}?X-Amz-Signature=abc"
269
270 mock_backend = MagicMock()
271 mock_backend.presign_batch = AsyncMock(return_value={oid: fake_url})
272
273 with patch("musehub.services.musehub_wire.get_backend", return_value=mock_backend):
274 result = await wire_push_presign(
275 db_session,
276 repo_id,
277 [oid],
278 )
279
280 assert result["presigned_urls"] == {oid: fake_url}
281 assert result["already_stored"] == []
282 assert result["stream_these"] == []
283 mock_backend.presign_batch.assert_called_once_with([oid], "put", 3600)
284
285
286 # ---------------------------------------------------------------------------
287 # P3 — empty object list → all-empty response
288 # ---------------------------------------------------------------------------
289
290 @pytest.mark.asyncio
291 async def test_p3_empty_object_list(db_session: AsyncSession) -> None:
292 from musehub.services.musehub_wire import wire_push_presign
293
294 repo = await create_repo(db_session, owner="gabriel")
295
296 result = await wire_push_presign(db_session, str(repo.repo_id), [])
297
298 assert result["presigned_urls"] == {}
299 assert result["already_stored"] == []
300 assert result["stream_these"] == []
301
302
303 # ---------------------------------------------------------------------------
304 # P4 — zero O frames, all objects pre-stored → commit finalises
305 # ---------------------------------------------------------------------------
306
307 @pytest.mark.asyncio
308 async def test_p4_zero_o_frames_all_prestored_commit_finalises(
309 db_session: AsyncSession,
310 ) -> None:
311 """H + C + E with n_objects=0 succeeds when snapshot objects are in the DB."""
312 from musehub.services.musehub_wire import wire_push_stream
313
314 repo = await create_repo(db_session, owner="gabriel")
315 repo_id = str(repo.repo_id)
316
317 content = b"pre-stored object content p4"
318 oid = blob_id(content)
319 await _store_object(db_session, repo_id, oid, content)
320
321 snap_id = _uid("snap-p4")
322 commit_id = _uid("commit-p4")
323
324 commit_wire = {
325 "commit_id": commit_id,
326 "parent_ids": [],
327 "message": "presign round-trip",
328 "author": "gabriel",
329 "timestamp": _now().isoformat(),
330 "snapshot_id": snap_id,
331 "branch": "main",
332 }
333 snap_wire = {
334 "snapshot_id": snap_id,
335 "manifest": {"file.py": oid},
336 "directories": [],
337 "created_at": _now().isoformat(),
338 }
339
340 raw = (
341 _header_frame(n_objects=0, n_commits=1)
342 + _commit_pack_frame([commit_wire], [snap_wire])
343 + _end_frame(n_objects=0, n_commits=1)
344 )
345
346 frames = await _collect_frames(
347 wire_push_stream(db_session, repo_id, _body_iter(raw), "gabriel")
348 )
349
350 # No error frames.
351 errors = [f for f in frames if f.get("t") == "X"]
352 assert errors == [], f"unexpected error frames: {errors}"
353
354 # Commit exists in DB.
355 from sqlalchemy import select
356 row = (await db_session.execute(
357 select(db.MusehubCommit).where(db.MusehubCommit.commit_id == commit_id)
358 )).scalar_one_or_none()
359 assert row is not None
360
361
362 # ---------------------------------------------------------------------------
363 # P5 — zero O frames, objects NOT stored → 422
364 # ---------------------------------------------------------------------------
365
366 @pytest.mark.asyncio
367 async def test_p5_zero_o_frames_missing_objects_yields_422(
368 db_session: AsyncSession,
369 ) -> None:
370 """H + C + E with n_objects=0 but snapshot references absent objects → 422."""
371 from musehub.services.musehub_wire import wire_push_stream
372
373 repo = await create_repo(db_session, owner="gabriel")
374 repo_id = str(repo.repo_id)
375
376 # This oid is NOT stored anywhere.
377 oid = blob_id(b"ghost object never uploaded")
378
379 snap_id = _uid("snap-p5")
380 commit_id = _uid("commit-p5")
381
382 commit_wire = {
383 "commit_id": commit_id,
384 "parent_ids": [],
385 "message": "should fail",
386 "author": "gabriel",
387 "timestamp": _now().isoformat(),
388 "snapshot_id": snap_id,
389 "branch": "main",
390 }
391 snap_wire = {
392 "snapshot_id": snap_id,
393 "manifest": {"missing.py": oid},
394 "directories": [],
395 "created_at": _now().isoformat(),
396 }
397
398 raw = (
399 _header_frame(n_objects=0, n_commits=1)
400 + _commit_pack_frame([commit_wire], [snap_wire])
401 + _end_frame(n_objects=0, n_commits=1)
402 )
403
404 frames = await _collect_frames(
405 wire_push_stream(db_session, repo_id, _body_iter(raw), "gabriel")
406 )
407
408 error_frames = [f for f in frames if f.get("t") == "X"]
409 assert error_frames, "expected an error frame for missing objects"
410 assert error_frames[0].get("code") == 422
411
412
413 # ---------------------------------------------------------------------------
414 # P6 — full round-trip: presign → store → push stream → /refs reflects head
415 # ---------------------------------------------------------------------------
416
417 @pytest.mark.asyncio
418 async def test_p6_full_round_trip_presign_store_push(
419 db_session: AsyncSession,
420 ) -> None:
421 """presign returns oids to upload; after manual storage, zero-O-frame push works."""
422 from musehub.services.musehub_wire import wire_push_presign, wire_push_stream
423
424 repo = await create_repo(db_session, owner="gabriel")
425 repo_id = str(repo.repo_id)
426
427 content = b"p6 round-trip object bytes"
428 oid = blob_id(content)
429
430 # Step 1: Ask presign endpoint what to upload.
431 presign_result = await wire_push_presign(db_session, repo_id, [oid])
432 assert oid in presign_result["stream_these"] # LocalBackend → no presigned URL
433
434 # Step 2: Client "uploads" directly to storage (simulates R2 PUT via presigned URL).
435 await _store_object(db_session, repo_id, oid, content)
436
437 # Step 3: Now presign endpoint sees it as already_stored.
438 presign_result2 = await wire_push_presign(db_session, repo_id, [oid])
439 assert oid in presign_result2["already_stored"]
440 assert presign_result2["stream_these"] == []
441
442 # Step 4: Push H + C + E with zero O frames.
443 snap_id = _uid("snap-p6")
444 commit_id = _uid("commit-p6")
445 commit_wire = {
446 "commit_id": commit_id,
447 "parent_ids": [],
448 "message": "p6 round-trip",
449 "author": "gabriel",
450 "timestamp": _now().isoformat(),
451 "snapshot_id": snap_id,
452 "branch": "main",
453 }
454 snap_wire = {
455 "snapshot_id": snap_id,
456 "manifest": {"round_trip.py": oid},
457 "directories": [],
458 "created_at": _now().isoformat(),
459 }
460 raw = (
461 _header_frame(n_objects=0, n_commits=1)
462 + _commit_pack_frame([commit_wire], [snap_wire])
463 + _end_frame(n_objects=0, n_commits=1)
464 )
465 frames = await _collect_frames(
466 wire_push_stream(db_session, repo_id, _body_iter(raw), "gabriel")
467 )
468
469 errors = [f for f in frames if f.get("t") == "X"]
470 assert errors == [], f"push failed: {errors}"
471
472 # Step 5: Verify commit is in the DB.
473 from sqlalchemy import select
474 row = (await db_session.execute(
475 select(db.MusehubCommit).where(db.MusehubCommit.commit_id == commit_id)
476 )).scalar_one_or_none()
477 assert row is not None
478 assert row.branch == "main"
479
480
481 # ---------------------------------------------------------------------------
482 # P7 — S3Backend.presign_batch produces correctly-keyed URLs
483 # ---------------------------------------------------------------------------
484
485 @pytest.mark.asyncio
486 async def test_p7_s3_backend_presign_batch_url_format() -> None:
487 """S3Backend.presign_batch calls boto3 with the right key format per oid."""
488 from musehub.storage.backends import S3Backend
489
490 oid = blob_id(b"test object for presign key format")
491 expected_key = f"objects/{oid.replace(':', '_').replace('/', '_')}"
492 fake_url = f"https://bucket.r2.cloudflarestorage.com/{expected_key}?sig=abc"
493
494 mock_client = MagicMock()
495 mock_client.generate_presigned_url.return_value = fake_url
496
497 backend = S3Backend(
498 bucket="test-bucket",
499 region="auto",
500 endpoint_url="https://r2.example.com",
501 access_key_id="key",
502 secret_access_key="secret",
503 )
504 backend._client = mock_client
505
506 result = await backend.presign_batch([oid], "put", 3600)
507
508 assert result == {oid: fake_url}
509 mock_client.generate_presigned_url.assert_called_once_with(
510 "put_object",
511 Params={"Bucket": "test-bucket", "Key": expected_key},
512 ExpiresIn=3600,
513 )
514
515
516 # ---------------------------------------------------------------------------
517 # P9 — confirm inserts DB rows; zero-O push/stream then succeeds
518 # ---------------------------------------------------------------------------
519
520 @pytest.mark.asyncio
521 async def test_p9_confirm_registers_objects_and_push_succeeds(
522 db_session: AsyncSession,
523 ) -> None:
524 """wire_push_confirm creates DB records; referential integrity check passes."""
525 from musehub.services.musehub_wire import wire_push_confirm, wire_push_stream
526
527 repo = await create_repo(db_session, owner="gabriel")
528 repo_id = str(repo.repo_id)
529
530 content = b"p9 object bytes confirm test"
531 oid = blob_id(content)
532
533 # Simulate: client PUT raw bytes to R2 (storage has bytes but no DB row).
534 from musehub.services.musehub_wire import get_backend
535 backend = get_backend()
536 await backend.put(oid, content) # bytes in storage, no DB record yet
537
538 # Confirm step: server registers the object.
539 await wire_push_confirm(
540 db_session,
541 repo_id,
542 objects=[{"object_id": oid, "size_bytes": len(content), "path": "p9.py"}],
543 )
544
545 # Now zero-O push/stream should pass referential integrity.
546 snap_id = _uid("snap-p9")
547 commit_id = _uid("commit-p9")
548 commit_wire = {
549 "commit_id": commit_id,
550 "parent_ids": [],
551 "message": "p9 confirm test",
552 "author": "gabriel",
553 "timestamp": _now().isoformat(),
554 "snapshot_id": snap_id,
555 "branch": "main",
556 }
557 snap_wire = {
558 "snapshot_id": snap_id,
559 "manifest": {"p9.py": oid},
560 "directories": [],
561 "created_at": _now().isoformat(),
562 }
563 raw = (
564 _header_frame(n_objects=0, n_commits=1)
565 + _commit_pack_frame([commit_wire], [snap_wire])
566 + _end_frame(n_objects=0, n_commits=1)
567 )
568 frames = await _collect_frames(
569 wire_push_stream(db_session, repo_id, _body_iter(raw), "gabriel")
570 )
571 errors = [f for f in frames if f.get("t") == "X"]
572 assert errors == [], f"push failed after confirm: {errors}"
573
574 from sqlalchemy import select
575 row = (await db_session.execute(
576 select(db.MusehubCommit).where(db.MusehubCommit.commit_id == commit_id)
577 )).scalar_one_or_none()
578 assert row is not None
579
580
581 # ---------------------------------------------------------------------------
582 # P10 — confirm is idempotent
583 # ---------------------------------------------------------------------------
584
585 @pytest.mark.asyncio
586 async def test_p10_confirm_is_idempotent(db_session: AsyncSession) -> None:
587 """Confirming the same object twice does not raise or duplicate rows."""
588 from musehub.services.musehub_wire import wire_push_confirm
589 from musehub.services.musehub_wire import get_backend
590
591 repo = await create_repo(db_session, owner="gabriel")
592 repo_id = str(repo.repo_id)
593
594 content = b"p10 idempotent confirm bytes"
595 oid = blob_id(content)
596 backend = get_backend()
597 await backend.put(oid, content)
598
599 obj_entry = [{"object_id": oid, "size_bytes": len(content), "path": "p10.py"}]
600
601 await wire_push_confirm(db_session, repo_id, obj_entry)
602 await wire_push_confirm(db_session, repo_id, obj_entry) # second call must not raise
603
604 from sqlalchemy import select, func
605 count = (await db_session.execute(
606 select(func.count()).where(db.MusehubObject.object_id == oid)
607 )).scalar()
608 assert count == 1
609
610
611 # ---------------------------------------------------------------------------
612 # P11 — full end-to-end: presign → R2 PUT → confirm → zero-O stream → refs
613 # ---------------------------------------------------------------------------
614
615 @pytest.mark.asyncio
616 async def test_p11_full_end_to_end_with_confirm(db_session: AsyncSession) -> None:
617 """presign → backend.put (simulate R2) → confirm → push/stream → commit in refs."""
618 from musehub.services.musehub_wire import (
619 wire_push_presign,
620 wire_push_confirm,
621 wire_push_stream,
622 )
623 from musehub.services.musehub_wire import get_backend
624
625 repo = await create_repo(db_session, owner="gabriel")
626 repo_id = str(repo.repo_id)
627
628 content = b"p11 end to end object bytes"
629 oid = blob_id(content)
630
631 # Step 1: presign → object is missing, goes to stream_these (LocalBackend)
632 presign_result = await wire_push_presign(db_session, repo_id, [oid])
633 assert oid in presign_result["stream_these"]
634
635 # Step 2: client "PUT" to R2 (simulate by calling backend.put directly)
636 backend = get_backend()
637 await backend.put(oid, content)
638
639 # Step 3: confirm — registers DB row
640 await wire_push_confirm(
641 db_session,
642 repo_id,
643 objects=[{"object_id": oid, "size_bytes": len(content), "path": "p11.py"}],
644 )
645
646 # Step 4: presign now shows object as already_stored
647 presign_result2 = await wire_push_presign(db_session, repo_id, [oid])
648 assert oid in presign_result2["already_stored"]
649
650 # Step 5: zero-O push/stream
651 snap_id = _uid("snap-p11")
652 commit_id = _uid("commit-p11")
653 commit_wire = {
654 "commit_id": commit_id,
655 "parent_ids": [],
656 "message": "p11 end to end",
657 "author": "gabriel",
658 "timestamp": _now().isoformat(),
659 "snapshot_id": snap_id,
660 "branch": "main",
661 }
662 snap_wire = {
663 "snapshot_id": snap_id,
664 "manifest": {"p11.py": oid},
665 "directories": [],
666 "created_at": _now().isoformat(),
667 }
668 raw = (
669 _header_frame(n_objects=0, n_commits=1)
670 + _commit_pack_frame([commit_wire], [snap_wire])
671 + _end_frame(n_objects=0, n_commits=1)
672 )
673 frames = await _collect_frames(
674 wire_push_stream(db_session, repo_id, _body_iter(raw), "gabriel")
675 )
676 errors = [f for f in frames if f.get("t") == "X"]
677 assert errors == [], f"end-to-end push failed: {errors}"
678
679 from sqlalchemy import select
680 commit_row = (await db_session.execute(
681 select(db.MusehubCommit).where(db.MusehubCommit.commit_id == commit_id)
682 )).scalar_one_or_none()
683 assert commit_row is not None
File History 1 commit
sha256:bb2baaabdd19320bde50cb69d447fd1c1e571467df729be1a23b5e93064b046a feat(intel): standardize headers, gauge icon, velocity card… Sonnet 4.6 minor 142 days ago