imbi-plugin-github 2.34.0__py3-none-any.whl → 2.35.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,11 +19,11 @@ backfill: there is no push payload, so the GitHub host is read from
19
19
  it walks the full default-branch history and the complete tag list rather
20
20
  than a single push delta.
21
21
 
22
- Commit / tag rows are written to the shared ClickHouse ``commits`` /
23
- ``tags`` tables via :func:`imbi.common.clickhouse.insert`. Writes are
24
- best-effort: a storage failure is logged and swallowed so an analytics
25
- hiccup never 5xxs the webhook, exactly as the gateway's own event
26
- recording behaves.
22
+ Commit / tag rows are published via :func:`imbi.common.iggy.publish` to
23
+ the ``commits`` / ``tags`` streams, which the ClickHouse sink drains into
24
+ the tables of the same name. Writes are best-effort: a publish failure is
25
+ logged and swallowed so an analytics hiccup never 5xxs the webhook,
26
+ exactly as the gateway's own event recording behaves.
27
27
  """
28
28
 
29
29
  from __future__ import annotations
@@ -40,7 +40,7 @@ import httpx
40
40
  import jsonpointer
41
41
  import pydantic
42
42
 
43
- from imbi.common import cache, clickhouse
43
+ from imbi.common import cache, clickhouse, iggy
44
44
  from imbi.common.json_pointer import JsonPointer
45
45
  from imbi.common.models import CommitRecord, TagRecord
46
46
  from imbi.common.plugins.base import (
@@ -67,6 +67,9 @@ from imbi.plugins.github.deployment import (
67
67
 
68
68
  LOGGER = logging.getLogger(__name__)
69
69
 
70
+ #: The Iggy topic every row this plugin publishes goes to.
71
+ _TOPIC = 'github'
72
+
70
73
  _HTTP_TIMEOUT_SECONDS = 10.0
71
74
  _ZERO_SHA = '0' * 40
72
75
  # GitHub's compare endpoint caps ``commits[]`` at 250 per page and
@@ -903,25 +906,26 @@ async def _fetch_commits_since(
903
906
  return out
904
907
 
905
908
 
906
- async def _insert_best_effort(
907
- table: str, records: list[pydantic.BaseModel], project_id: str
909
+ async def _publish_best_effort(
910
+ stream: str, records: list[pydantic.BaseModel], project_id: str
908
911
  ) -> int:
909
- """Insert ``records`` into ``table``; return rows written (0 on fail).
912
+ """Publish ``records`` to ``stream``; return rows sent (0 on fail).
910
913
 
911
- ``imbi.common.clickhouse.insert`` rejects an empty list, so an empty
912
- set short-circuits to 0. A storage failure is logged and swallowed,
914
+ The stream is named for the ClickHouse table the sink lands it in.
915
+ ``imbi.common.iggy.publish`` rejects an empty list, so an empty set
916
+ short-circuits to 0. A publish failure is logged and swallowed,
913
917
  mirroring the webhook actions -- an analytics hiccup must not fail the
914
918
  sync.
915
919
  """
916
920
  if not records:
917
921
  return 0
918
922
  try:
919
- await clickhouse.insert(table, records)
923
+ await iggy.publish(stream, _TOPIC, records)
920
924
  except Exception:
921
925
  LOGGER.exception(
922
926
  'github-commit-sync: failed to record %d %s rows for project %s',
923
927
  len(records),
924
- table,
928
+ stream,
925
929
  project_id,
926
930
  )
927
931
  return 0
@@ -1094,7 +1098,7 @@ async def sync_commits(
1094
1098
  if not records:
1095
1099
  return
1096
1100
  try:
1097
- await clickhouse.insert('commits', records)
1101
+ await iggy.publish('commits', _TOPIC, records)
1098
1102
  except Exception:
1099
1103
  LOGGER.exception(
1100
1104
  'github-commit-sync: failed to record %d commits for project %s',
@@ -1464,7 +1468,7 @@ async def sync_tags(
1464
1468
  if not records:
1465
1469
  return # every tag in this delivery was unpeelable (warned above)
1466
1470
  try:
1467
- await clickhouse.insert('tags', records)
1471
+ await iggy.publish('tags', _TOPIC, records)
1468
1472
  except Exception:
1469
1473
  LOGGER.exception(
1470
1474
  'github-commit-sync: failed to record %d tags for project %s',
@@ -1478,7 +1482,8 @@ sync_commits_descriptor = ActionDescriptor(
1478
1482
  label='Sync Commit History',
1479
1483
  description=(
1480
1484
  'Fetch the full set of commits in a push (via the GitHub compare '
1481
- 'API) and record them in the ClickHouse commits table.'
1485
+ 'API) and publish them to the stream that lands in the ClickHouse '
1486
+ 'commits table.'
1482
1487
  ),
1483
1488
  callable=typing.cast(
1484
1489
  'typing.Any', 'imbi.plugins.github.commits:sync_commits'
@@ -1492,8 +1497,8 @@ sync_tags_descriptor = ActionDescriptor(
1492
1497
  name='sync_tags',
1493
1498
  label='Sync Tag History',
1494
1499
  description=(
1495
- 'Record the pushed tag (and, when reconcile_all is set, the full '
1496
- 'tag list) in the ClickHouse tags table.'
1500
+ 'Publish the pushed tag (and, when reconcile_all is set, the full '
1501
+ 'tag list) to the stream that lands in the ClickHouse tags table.'
1497
1502
  ),
1498
1503
  callable=typing.cast(
1499
1504
  'typing.Any', 'imbi.plugins.github.commits:sync_tags'
@@ -1625,10 +1630,10 @@ class GitHubCommitSync(CommitSyncCapability):
1625
1630
  for item in raw_commits
1626
1631
  if item.get('sha')
1627
1632
  ]
1628
- commits_recorded = await _insert_best_effort(
1633
+ commits_recorded = await _publish_best_effort(
1629
1634
  'commits', commit_records, ctx.project_id
1630
1635
  )
1631
- tags_recorded = await _insert_best_effort(
1636
+ tags_recorded = await _publish_best_effort(
1632
1637
  'tags', list(tags), ctx.project_id
1633
1638
  )
1634
1639
  return commits_recorded, tags_recorded
@@ -1724,7 +1729,7 @@ class GitHubCommitSync(CommitSyncCapability):
1724
1729
  )
1725
1730
  if record is None:
1726
1731
  return 0 # unpeelable (warned by _tag_record)
1727
- return await _insert_best_effort('tags', [record], ctx.project_id)
1732
+ return await _publish_best_effort('tags', [record], ctx.project_id)
1728
1733
 
1729
1734
  async def sync_new_commits(
1730
1735
  self,
@@ -1791,7 +1796,7 @@ class GitHubCommitSync(CommitSyncCapability):
1791
1796
  for item in raw
1792
1797
  if item.get('sha')
1793
1798
  ]
1794
- return await _insert_best_effort('commits', records, ctx.project_id)
1799
+ return await _publish_best_effort('commits', records, ctx.project_id)
1795
1800
 
1796
1801
  async def _fetch_new_commits(
1797
1802
  self,
@@ -13,10 +13,11 @@ GitHub's list-PRs API omits per-file diff stats
13
13
  (``additions``/``deletions``/``changed_files``), so backfill rows
14
14
  store ``0`` for those fields; they are accurate on webhook-driven rows.
15
15
 
16
- PR rows are written to the shared ClickHouse ``pull_requests`` table via
17
- :func:`imbi.common.clickhouse.insert`. Writes are best-effort: a storage
18
- failure is logged and swallowed so an analytics hiccup never 5xxs the
19
- webhook, exactly as the gateway's own event recording behaves.
16
+ PR rows are published via :func:`imbi.common.iggy.publish` to the
17
+ ``pull_requests`` stream, which the ClickHouse sink drains into the table
18
+ of the same name. Writes are best-effort: a publish failure is logged and
19
+ swallowed so an analytics hiccup never 5xxs the webhook, exactly as the
20
+ gateway's own event recording behaves.
20
21
  """
21
22
 
22
23
  from __future__ import annotations
@@ -29,7 +30,7 @@ import httpx
29
30
  import jsonpointer
30
31
  import pydantic
31
32
 
32
- from imbi.common import clickhouse
33
+ from imbi.common import iggy
33
34
  from imbi.common.json_pointer import JsonPointer
34
35
  from imbi.common.models import PullRequestRecord
35
36
  from imbi.common.plugins.base import (
@@ -43,7 +44,7 @@ from imbi.plugins.github._repos import resolve_owner_repo
43
44
  from imbi.plugins.github.commits import (
44
45
  _BACKFILL_MAX_WAIT_SECONDS, # pyright: ignore[reportPrivateUsage]
45
46
  _client, # pyright: ignore[reportPrivateUsage]
46
- _insert_best_effort, # pyright: ignore[reportPrivateUsage]
47
+ _publish_best_effort, # pyright: ignore[reportPrivateUsage]
47
48
  _request, # pyright: ignore[reportPrivateUsage]
48
49
  _resolve, # pyright: ignore[reportPrivateUsage]
49
50
  _resolve_bearer, # pyright: ignore[reportPrivateUsage]
@@ -237,7 +238,7 @@ async def sync_pull_requests(
237
238
  )
238
239
  return
239
240
  try:
240
- await clickhouse.insert('pull_requests', [record])
241
+ await iggy.publish('pull_requests', 'github', [record])
241
242
  except Exception:
242
243
  LOGGER.exception(
243
244
  'github-pr-sync: failed to record PR #%d for project %s',
@@ -356,6 +357,6 @@ class GitHubPullRequestSync(PullRequestSyncCapability):
356
357
  record = _pr_record(pr, project_id=ctx.project_id)
357
358
  if record is not None:
358
359
  records.append(record)
359
- return await _insert_best_effort(
360
+ return await _publish_best_effort(
360
361
  'pull_requests', records, ctx.project_id
361
362
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: imbi-plugin-github
3
- Version: 2.34.0
3
+ Version: 2.35.0
4
4
  Summary: GitHub identity plugin for Imbi (github.com / GHEC / GHES)
5
5
  Author-email: "Gavin M. Roy" <gavinr@aweber.com>
6
6
  License-Expression: BSD-3-Clause
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.14
13
13
  Requires-Python: >=3.14
14
14
  Requires-Dist: httpx>=0.27
15
- Requires-Dist: imbi-common[databases]==2.34.0
15
+ Requires-Dist: imbi-common[databases]==2.35.0
16
16
  Requires-Dist: pydantic>=2
17
17
  Requires-Dist: pyjwt[crypto]>=2.8
18
18
  Description-Content-Type: text/markdown
@@ -3,14 +3,14 @@ imbi/plugins/github/__init__.py,sha256=L_5_kr22VkjJob6SVLVzCkIvnWddxi54GIrM2cNs2
3
3
  imbi/plugins/github/_app_auth.py,sha256=Fte_3Tohxw6xBl1U2AB3uatVfTxfl9xPEc8M0lmVCpc,18420
4
4
  imbi/plugins/github/_hosts.py,sha256=sYuE3f7934125VZ6GGTqm8t3sVa3m0DNt3jL9Hb8nM0,4014
5
5
  imbi/plugins/github/_repos.py,sha256=BeSwrpzQnFBtlUGW-eP7v6_gAcSaSkqObq-vhj5wcYA,6575
6
- imbi/plugins/github/commits.py,sha256=crLHw9qrVXM14iNYtUocVMptmSRb01h1RMO-6y18lPc,71608
6
+ imbi/plugins/github/commits.py,sha256=wHs_NUl4cmhfvD3WrnOCmqaaJS-Eku-E-lOMh6Cb8IU,71882
7
7
  imbi/plugins/github/deployment.py,sha256=sx7xyK7MbOCXgt52RcHvsaNJ2aA9fMCNYZBUdRbsTbA,110360
8
8
  imbi/plugins/github/doctor.py,sha256=9pSXnpMTihhBrJ6OsLFFq2V6mpyqRRnvG1U94RL79L4,27156
9
9
  imbi/plugins/github/identity.py,sha256=9t_e-_jUbQ1iL0Vb6vaK2d7bT1ki6pw9aWwc4ics6gI,10354
10
10
  imbi/plugins/github/lifecycle.py,sha256=KJSzB36zFqetQBY5HNXLsRGRoIwGhrBJ-I1mA8G9H_Q,37711
11
11
  imbi/plugins/github/plugin.py,sha256=V1BzHPR5a0gGr1ttSqo_yTVdK5ShKs26AcReX2N-eOg,15531
12
- imbi/plugins/github/pull_requests.py,sha256=nnftzzQhOf0x-rt0ud3V3Mv4OW2LYmf1Hvs75WW3FR4,13463
12
+ imbi/plugins/github/pull_requests.py,sha256=FiHbjdGqghJ2Q1--d15XfOtpUe_KZE7hYRb8JLQ5U1I,13510
13
13
  imbi/plugins/github/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- imbi_plugin_github-2.34.0.dist-info/METADATA,sha256=V65mRKNIwkak_dQjDR_URxG-dWrqLB_QGoO9_0srk14,7618
15
- imbi_plugin_github-2.34.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
16
- imbi_plugin_github-2.34.0.dist-info/RECORD,,
14
+ imbi_plugin_github-2.35.0.dist-info/METADATA,sha256=D5Tl4UHk3dD8dD1PeBAP9Bh2NTm0wkGD5bSKpsUjp2E,7618
15
+ imbi_plugin_github-2.35.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
16
+ imbi_plugin_github-2.35.0.dist-info/RECORD,,