bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
156 lines
5.1 KiB
Python
156 lines
5.1 KiB
Python
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
|
|
|
import json
|
|
|
|
|
|
def normalize_team(team: dict) -> dict:
|
|
states = []
|
|
for state in (team.get("states") or {}).get("nodes", []):
|
|
states.append({
|
|
"state_id": state.get("id"),
|
|
"state_name": state.get("name"),
|
|
"type": state.get("type"),
|
|
})
|
|
return {
|
|
"team_id": team.get("id"),
|
|
"team_key": team.get("key"),
|
|
"team_name": team.get("name"),
|
|
"name": team.get("name"),
|
|
"description": team.get("description"),
|
|
"timezone": team.get("timezone"),
|
|
"updated_at": team.get("updatedAt"),
|
|
"states": states,
|
|
}
|
|
|
|
|
|
def normalize_user(user: dict) -> dict:
|
|
return {
|
|
"user_id": user.get("id"),
|
|
"name": user.get("name"),
|
|
"display_name": user.get("displayName") or user.get("name"),
|
|
"email": user.get("email"),
|
|
"is_active": user.get("active"),
|
|
"is_admin": user.get("admin"),
|
|
"updated_at": user.get("updatedAt"),
|
|
"url": user.get("url"),
|
|
}
|
|
|
|
|
|
def normalize_issue(issue: dict) -> dict:
|
|
team = issue.get("team") or {}
|
|
state = issue.get("state") or {}
|
|
project = issue.get("project") or {}
|
|
cycle = issue.get("cycle") or {}
|
|
assignee = issue.get("assignee") or {}
|
|
creator = issue.get("creator") or {}
|
|
labels = (issue.get("labels") or {}).get("nodes", [])
|
|
return {
|
|
"issue_id": issue.get("id"),
|
|
"issue_key": issue.get("identifier"),
|
|
"title": issue.get("title"),
|
|
"description": issue.get("description") or "",
|
|
"team_id": team.get("id"),
|
|
"team_key": team.get("key"),
|
|
"team_name": team.get("name"),
|
|
"project_id": project.get("id"),
|
|
"project_name": project.get("name"),
|
|
"cycle_id": cycle.get("id"),
|
|
"cycle_name": cycle.get("name"),
|
|
"cycle_number": cycle.get("number"),
|
|
"state_id": state.get("id"),
|
|
"state_name": state.get("name"),
|
|
"assignee_id": assignee.get("id"),
|
|
"assignee_email": assignee.get("email"),
|
|
"assignee_name": assignee.get("name"),
|
|
"creator_id": creator.get("id"),
|
|
"creator_email": creator.get("email"),
|
|
"creator_name": creator.get("name"),
|
|
"priority": issue.get("priority"),
|
|
"label_ids": [label.get("id") for label in labels],
|
|
"label_names": [label.get("name") for label in labels],
|
|
"created_at": issue.get("createdAt"),
|
|
"updated_at": issue.get("updatedAt"),
|
|
"url": issue.get("url"),
|
|
}
|
|
|
|
|
|
def normalize_comment(comment: dict, *, issue_id: str,
|
|
issue_key: str | None) -> dict:
|
|
user = comment.get("user") or {}
|
|
return {
|
|
"comment_id": comment.get("id"),
|
|
"issue_id": issue_id,
|
|
"issue_key": issue_key,
|
|
"user_id": user.get("id"),
|
|
"user_email": user.get("email"),
|
|
"user_name": user.get("displayName") or user.get("name"),
|
|
"body": comment.get("body") or "",
|
|
"created_at": comment.get("createdAt"),
|
|
"updated_at": comment.get("updatedAt"),
|
|
"url": comment.get("url"),
|
|
}
|
|
|
|
|
|
def normalize_project(
|
|
project: dict,
|
|
*,
|
|
team_id: str,
|
|
team_key: str | None,
|
|
team_name: str | None,
|
|
issues: list[dict],
|
|
) -> dict:
|
|
lead = project.get("lead") or {}
|
|
return {
|
|
"project_id": project.get("id"),
|
|
"team_id": team_id,
|
|
"team_key": team_key,
|
|
"team_name": team_name,
|
|
"name": project.get("name"),
|
|
"description": project.get("description"),
|
|
"state": (project.get("status") or {}).get("type"),
|
|
"lead_id": lead.get("id"),
|
|
"updated_at": project.get("updatedAt"),
|
|
"url": project.get("url"),
|
|
"issue_count": len(issues),
|
|
"issues": issues,
|
|
}
|
|
|
|
|
|
def normalize_cycle(cycle: dict, *, team_id: str) -> dict:
|
|
return {
|
|
"cycle_id": cycle.get("id"),
|
|
"team_id": team_id,
|
|
"name": cycle.get("name"),
|
|
"number": cycle.get("number"),
|
|
"starts_at": cycle.get("startsAt"),
|
|
"ends_at": cycle.get("endsAt"),
|
|
"updated_at": cycle.get("updatedAt"),
|
|
"url": cycle.get("url"),
|
|
}
|
|
|
|
|
|
def to_json_bytes(value: dict | list) -> bytes:
|
|
return json.dumps(value, ensure_ascii=False, indent=2).encode()
|
|
|
|
|
|
def to_jsonl_bytes(rows: list[dict]) -> bytes:
|
|
ordered = sorted(rows, key=lambda row: row.get("created_at") or "")
|
|
if not ordered:
|
|
return b""
|
|
text = "\n".join(
|
|
json.dumps(row, ensure_ascii=False, separators=(",", ":"))
|
|
for row in ordered)
|
|
return text.encode() + b"\n"
|