11import asyncio
2- import os
3- from datetime import datetime
4- from typing import Optional
52
63import httpx
74import turbopuffer as tpuf
85from prefect import task
96from prefect .blocks .system import Secret
107from pretty_mod import display_signature
118from pretty_mod .explorer import ModuleTreeExplorer
12- from pydantic import BaseModel , Field , field_validator
139from raggy .vectorstores .tpuf import multi_query_tpuf
1410
15- import marvin
16- from marvin .utilities .logging import get_logger
11+ from slackbot .github import GitHubIssue , _get_token
1712from slackbot .settings import settings
1813from slackbot .strings import slice_tokens
1914
@@ -60,6 +55,7 @@ def review_common_3x_gotchas() -> list[str]:
6055 "futures returned by .map can be resolved together, like integers = double.map(range(10)).result()" ,
6156 "futures must be resolved by passing them to another task, returning them or manually calling .result() or .wait()" ,
6257 "agents are replaced by workers in prefect 3.x, work pools replace the infra blocks from prefect.infrastructure" ,
58+ "the `prefect.infrastructure` IS COMPLETELY REMOVED IN 3.x, see work pools instead" ,
6359 "prefect 3.x uses pydantic 2 and server data from prefect 2.x is not compatible with 3.x" ,
6460 "Deployment.build_from_flow() IS COMPLETELY REMOVED IN 3.x, use some_flow.from_source(...).deploy(...) instead." ,
6561 "`prefect deployment build ...` IS COMPLETELY REMOVED IN 3.x, use `prefect deploy ...` instead" ,
@@ -133,68 +129,6 @@ def get_latest_prefect_release_notes() -> str:
133129 return release_notes
134130
135131
136- async def _get_token () -> str :
137- try :
138- from prefect .blocks .system import Secret
139-
140- return (await Secret .aload (name = "github-token" )).get ()
141- except (ImportError , ValueError ) as exc :
142- getattr (get_logger ("marvin" ), "debug_kv" )(
143- (
144- "Prefect Secret for GitHub token not retrieved. "
145- f"{ exc .__class__ .__name__ } : { exc } "
146- "red"
147- ),
148- )
149-
150- try :
151- return getattr (marvin .settings , "github_token" )
152- except AttributeError :
153- pass
154-
155- if token := os .environ .get ("MARVIN_GITHUB_TOKEN" , "" ):
156- return token
157-
158- raise RuntimeError ("GitHub token not found" )
159-
160-
161- class GitHubUser (BaseModel ):
162- """GitHub user."""
163-
164- login : Optional [str ] = None
165-
166-
167- class GitHubComment (BaseModel ):
168- """GitHub comment."""
169-
170- body : str = Field (default = "" )
171- user : GitHubUser = Field (default_factory = GitHubUser )
172-
173-
174- class GitHubLabel (BaseModel ):
175- """GitHub label."""
176-
177- name : str = Field (default = "" )
178-
179-
180- class GitHubIssue (BaseModel ):
181- """GitHub issue."""
182-
183- created_at : datetime = Field (...)
184- html_url : str = Field (...)
185- number : int = Field (...)
186- title : str = Field (default = "" )
187- body : str | None = Field (default = "" )
188- labels : list [GitHubLabel ] = Field (default_factory = GitHubLabel )
189- user : GitHubUser = Field (default_factory = GitHubUser )
190-
191- @field_validator ("body" )
192- def validate_body (cls , v : str ) -> str :
193- if not v :
194- return ""
195- return v
196-
197-
198132@task (task_run_name = "Reading {n} issues from {repo} given query: {query}" )
199133def read_github_issues (query : str , repo : str = "prefecthq/prefect" , n : int = 3 ) -> str :
200134 """
@@ -207,7 +141,6 @@ def read_github_issues(query: str, repo: str = "prefecthq/prefect", n: int = 3)
207141 - repo: prefecthq/prefect
208142 - query: label:bug is:open AttributeError
209143 """
210- # Load GitHub token synchronously
211144 github_token = Secret .load (settings .github_token_secret_name , _sync = True ).get () # type: ignore
212145 return asyncio .run (
213146 search_github_issues (query , repo = repo , n = n , api_token = github_token )
@@ -230,6 +163,7 @@ async def search_github_issues(
230163 - repo: prefecthq/prefect
231164 - query: label:bug is:open AttributeError
232165 """
166+ TOKEN_LIMIT = 1500
233167 headers = {"Accept" : "application/vnd.github.v3+json" }
234168
235169 headers ["Authorization" ] = f"Bearer { api_token or await _get_token ()} "
@@ -248,11 +182,10 @@ async def search_github_issues(
248182
249183 issues_data = response .json ()["items" ]
250184
251- # enforce 1000 token limit per body
252185 for issue in issues_data :
253186 if not issue ["body" ]:
254187 continue
255- issue ["body" ] = slice_tokens (issue ["body" ], 1000 )
188+ issue ["body" ] = slice_tokens (issue ["body" ], TOKEN_LIMIT )
256189
257190 issues = [GitHubIssue (** issue ) for issue in issues_data ]
258191
0 commit comments