Skip to content

Commit 53aab47

Browse files
committed
Collect workflow content + generate jobs/steps
1 parent 37716c2 commit 53aab47

1 file changed

Lines changed: 54 additions & 9 deletions

File tree

src/openhound_github/resources/organization.py

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import base64
2+
import binascii
13
from dataclasses import dataclass, field
24
from datetime import datetime
35
from typing import Any, Iterator
46

7+
import dlt
58
from dlt.sources.helpers import requests
69
from dlt.sources.helpers.rest_client.client import RESTClient
710
from dlt.sources.helpers.rest_client.paginators import (
@@ -61,6 +64,8 @@
6164
TeamRole,
6265
User,
6366
Workflow,
67+
WorkflowJob,
68+
WorkflowStep,
6469
)
6570
from openhound_github.models.repo_role_assignment import TEAM_PERMISSION_MAP
6671
from openhound_github.models.repository_role import DEFAULT_REPO_ROLES
@@ -388,7 +393,6 @@ def teams(ctx: SourceContext):
388393
"query": TEAMS_QUERY,
389394
"variables": {"login": org_name, "count": 100, "after": None},
390395
}
391-
392396
for page_data in client.paginate(
393397
"/graphql",
394398
method="POST",
@@ -452,6 +456,10 @@ def team_members(team: Team, ctx: SourceContext):
452456
)
453457

454458
if team.members.page_info.has_next_page:
459+
if not team.members.page_info.end_cursor:
460+
raise RuntimeError(
461+
f"GitHub team {team.org_login}/{team.slug} has more members but no endCursor"
462+
)
455463
client = _client_for_org(ctx, team.org_login)
456464
data = {
457465
"query": TEAM_MEMBERS_OVERFLOW_QUERY,
@@ -846,19 +854,52 @@ def workflows(repo: Repository, ctx: SourceContext):
846854
Yields:
847855
Workflow (Workflow): An active workflow record.
848856
"""
857+
858+
@dlt.defer
859+
def _workflow_file_contents(
860+
client: RESTClient, repo: Repository, workflow: dict[str, Any]
861+
) -> dict | None:
862+
path = workflow.get("path")
863+
if not path:
864+
return None
865+
866+
params = {"ref": repo.default_branch} if repo.default_branch else None
867+
response = client.get(
868+
f"/repos/{repo.full_name}/contents/{path}", params=params
869+
).json()
870+
871+
content = response.get("content")
872+
if not content:
873+
return None
874+
875+
return {
876+
**workflow,
877+
"contents": content,
878+
"branch": repo.default_branch,
879+
"repository_name": repo.name,
880+
"repository_node_id": repo.node_id,
881+
"org_login": repo.org_login,
882+
}
883+
849884
client = _client_for_org(ctx, repo.org_login)
850885
for page in client.paginate(
851886
f"/repos/{repo.full_name}/actions/workflows", params={"per_page": 100}
852887
):
853888
for workflow in page:
854-
# TODO: Check if we should only store active workflows
855889
if workflow.get("state") == "active":
856-
yield {
857-
**workflow,
858-
"repository_name": repo.name,
859-
"repository_node_id": repo.node_id,
860-
"org_login": repo.org_login,
861-
}
890+
yield _workflow_file_contents(client, repo, workflow)
891+
892+
893+
@app.transformer(name="workflow_jobs", columns=WorkflowJob, parallelized=True)
894+
def workflow_jobs(workflow: Workflow):
895+
for row in workflow.workflow_job_rows():
896+
yield row
897+
898+
899+
@app.transformer(name="workflow_steps", columns=WorkflowStep, parallelized=True)
900+
def workflow_steps(workflow: Workflow):
901+
for row in workflow.workflow_step_rows():
902+
yield row
862903

863904

864905
@app.transformer(name="environments", columns=Environment, parallelized=True)
@@ -1451,6 +1492,7 @@ def external_identities(ctx: SourceContext):
14511492
cursor_variable="after",
14521493
cursor_field="endCursor",
14531494
has_next_field="hasNextPage",
1495+
allow_missing_page_info=True,
14541496
)
14551497
data = {
14561498
"query": SAML_IDENTITIES_QUERY,
@@ -1511,6 +1553,7 @@ def organization_resources(ctx: SourceContext):
15111553
roles_resource = org_roles(ctx)
15121554
repo_roles_base = list(repository_roles_base(ctx))
15131555
repos_resource = repositories(ctx)
1556+
workflows_resource = repos_resource | workflows(ctx)
15141557
environments_resource = repos_resource | environments(ctx)
15151558
personal_access_tokens_resource = personal_access_tokens(ctx)
15161559

@@ -1535,7 +1578,9 @@ def organization_resources(ctx: SourceContext):
15351578
actions_permissions(ctx),
15361579
repos_resource,
15371580
repos_resource | repository_roles(repo_roles_base),
1538-
repos_resource | workflows(ctx),
1581+
workflows_resource,
1582+
workflows_resource | workflow_jobs(),
1583+
workflows_resource | workflow_steps(),
15391584
repos_resource | repo_runners(ctx),
15401585
repos_resource | repository_secrets(ctx),
15411586
repos_resource | repository_variables(ctx),

0 commit comments

Comments
 (0)