feat: choose initial owner during issue filing
This commit is contained in:
1 parent
322f025794
commit
6449ead83d
13 files changed
+383
-38
No files matched your search
+4
-2
@@ -1452,8 +1452,10 @@ async def create_issue(
|
||||
for item in assignees
|
||||
if isinstance(item, dict) and isinstance(item.get("login"), str)
|
||||
]
|
||||
if assignee not in confirmed_assignees:
|
||||
raise ValueError("Gitea did not confirm issue self-assignment")
|
||||
if confirmed_assignees != [assignee]:
|
||||
raise ValueError(
|
||||
"Gitea did not confirm self-assignment or exact issue assignment"
|
||||
)
|
||||
labels_value = issue.get("labels")
|
||||
labels = labels_value if isinstance(labels_value, list) else []
|
||||
milestone_value = issue.get("milestone")
|
||||
|
||||
+47
-2
@@ -714,6 +714,9 @@ def _validate_binary_attachment(filename: str, content_type: str, content: bytes
|
||||
class IssueCreation(BaseModel):
|
||||
title: str = Field(min_length=1, max_length=255)
|
||||
body: str = Field(default="", max_length=10_000)
|
||||
assignee: str | None = Field(
|
||||
default=None, pattern=r"^[A-Za-z0-9_.-]+$", max_length=255
|
||||
)
|
||||
label_ids: list[int] = Field(default_factory=list, max_length=20)
|
||||
milestone_id: PositiveInt | None = None
|
||||
due_date: str | None = Field(
|
||||
@@ -4525,6 +4528,36 @@ async def repository_labels(owner: str, repo: str):
|
||||
)
|
||||
|
||||
|
||||
@app.get("/api/v1/repos/{owner}/{repo}/issue-assignees")
|
||||
async def repository_issue_assignees(owner: str, repo: str):
|
||||
repository = f"{owner}/{repo}"
|
||||
|
||||
async def load_assignees():
|
||||
if await gitea_proxy.repository_access(repository) is None:
|
||||
raise HTTPException(status_code=404, detail="Repository not found")
|
||||
candidates = [
|
||||
item
|
||||
for item in await gitea_proxy.issue_handoff_candidates(repository)
|
||||
if isinstance(item, dict)
|
||||
and isinstance(item.get("login"), str)
|
||||
and re.fullmatch(r"[A-Za-z0-9_.-]+", item["login"])
|
||||
][:25]
|
||||
return JSONResponse(candidates, headers={"Cache-Control": "no-store"})
|
||||
|
||||
try:
|
||||
return await asyncio.wait_for(
|
||||
load_assignees(), timeout=ISSUE_ACTION_TIMEOUT_SECONDS
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception:
|
||||
return JSONResponse(
|
||||
{"error": "Owners could not be loaded. You can still assign the issue to yourself."},
|
||||
status_code=503,
|
||||
headers={"Retry-After": "1"},
|
||||
)
|
||||
|
||||
|
||||
@app.post("/api/v1/repos/{owner}/{repo}/issues", status_code=201)
|
||||
async def create_assigned_issue(
|
||||
creation: IssueCreation,
|
||||
@@ -4541,6 +4574,17 @@ async def create_assigned_issue(
|
||||
login = user.get("login") if isinstance(user, dict) else None
|
||||
if not login or accessible is None:
|
||||
raise HTTPException(status_code=404, detail="Repository not found")
|
||||
assignee = login
|
||||
if creation.assignee and creation.assignee != login:
|
||||
eligible = {
|
||||
item["login"]
|
||||
for item in await gitea_proxy.issue_handoff_candidates(repository)
|
||||
}
|
||||
if creation.assignee not in eligible:
|
||||
raise HTTPException(
|
||||
status_code=422, detail="Selected owner is no longer eligible"
|
||||
)
|
||||
assignee = creation.assignee
|
||||
if creation.label_ids:
|
||||
available_labels = await gitea_proxy.repo_labels(repository)
|
||||
valid_label_ids = {
|
||||
@@ -4566,13 +4610,13 @@ async def create_assigned_issue(
|
||||
repository,
|
||||
creation.title,
|
||||
creation.body,
|
||||
login,
|
||||
assignee,
|
||||
creation.label_ids,
|
||||
creation.milestone_id,
|
||||
creation.due_date,
|
||||
)
|
||||
return await gitea_proxy.create_issue(
|
||||
repository, creation.title, creation.body, login, creation.label_ids
|
||||
repository, creation.title, creation.body, assignee, creation.label_ids
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -4584,6 +4628,7 @@ async def create_assigned_issue(
|
||||
repository,
|
||||
creation.title,
|
||||
creation.body,
|
||||
creation.assignee,
|
||||
tuple(creation.label_ids),
|
||||
creation.milestone_id,
|
||||
creation.due_date,
|
||||
|
||||
Reference in new issue
Block a user