Skip to content

[Integration][Github] Added selector for first commit enrichment in PR exporter#3068

Open
omby8888 wants to merge 9 commits intomainfrom
github_enrich_pr_first_commit
Open

[Integration][Github] Added selector for first commit enrichment in PR exporter#3068
omby8888 wants to merge 9 commits intomainfrom
github_enrich_pr_first_commit

Conversation

@omby8888
Copy link
Copy Markdown
Contributor

@omby8888 omby8888 commented Apr 9, 2026

Description

What - Adds an optional selector for pull requests when using the GraphQL API: the query can request the first commit on the branch (oid, committedDate), and the exporter attaches that payload as a firstCommit object on each normalized PR. The behavior is controlled by a new selector field enrichWithFirstCommit.

Why - Lets you measure lead time from the first commit on the PR branch through review and merge.

Type of change

Please leave one option from the following and delete the rest:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • New Integration (non-breaking change which adds a new integration)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Non-breaking change (fix of existing functionality that will not change current behavior)
  • Documentation (added/updated documentation)

All tests should be run against the port production environment(using a testing org).

Core testing checklist

  • Integration able to create all default resources from scratch
  • Resync finishes successfully
  • Resync able to create entities
  • Resync able to update entities
  • Resync able to detect and delete entities
  • Scheduled resync able to abort existing resync and start a new one
  • Tested with at least 2 integrations from scratch
  • Tested with Kafka and Polling event listeners
  • Tested deletion of entities that don't pass the selector

Integration testing checklist

  • Integration able to create all default resources from scratch
  • Completed a full resync from a freshly installed integration and it completed successfully
  • Resync able to create entities
  • Resync able to update entities
  • Resync able to detect and delete entities
  • Resync finishes successfully
  • If new resource kind is added or updated in the integration, add example raw data, mapping and expected result to the examples folder in the integration directory.
  • If resource kind is updated, run the integration with the example data and check if the expected result is achieved
  • If new resource kind is added or updated, validate that live-events for that resource are working as expected
  • Docs PR link here

Preflight checklist

  • Handled rate limiting
  • Handled pagination
  • Implemented the code in async
  • Support Multi account

Screenshots

Include screenshots from your environment showing how the resources of the integration will look.

API Documentation

Provide links to the API documentation used for this integration.

@github-actions github-actions bot added the size/L label Apr 9, 2026
@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add first commit enrichment for GraphQL pull requests

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add optional first commit enrichment for GraphQL pull requests
• Implement dynamic GraphQL query generation based on selector options
• Create PullRequestGraphQLOptions dataclass for managing optional selections
• Extend PR options with enrich_with_first_commit boolean field
• Add comprehensive tests for first commit enrichment functionality
Diagram
flowchart LR
  A["PR Selector Config"] -->|enrich_with_first_commit| B["PullRequestGraphQLOptions"]
  B -->|generate_pr_fields| C["Dynamic GraphQL Query"]
  C -->|execute| D["GraphQL API"]
  D -->|response with commits| E["_normalize_pr_node"]
  E -->|_enrich_with_first_commit| F["Normalized PR with firstCommit"]
Loading

Grey Divider

File Changes

1. integrations/github/github/core/exporters/pull_request_exporter/core.py ✨ Enhancement +73/-25

Implement dynamic GraphQL queries with first commit enrichment

• Refactor GraphQL query imports to use generator functions instead of static strings
• Add PullRequestGraphQLOptions parameter to all PR fetching methods
• Implement _enrich_with_first_commit() method to extract first commit data
• Update _normalize_pr_node() to conditionally enrich with first commit based on options
• Pass gql_options through all code paths (single resource, paginated open/closed PRs)

integrations/github/github/core/exporters/pull_request_exporter/core.py


2. integrations/github/github/core/options.py ✨ Enhancement +2/-0

Add first commit enrichment option to PR options

• Add enrich_with_first_commit: NotRequired[bool] field to SinglePullRequestOptions
• Add enrich_with_first_commit: NotRequired[bool] field to ListPullRequestOptions

integrations/github/github/core/options.py


3. integrations/github/github/helpers/gql_queries.py ✨ Enhancement +96/-51

Refactor GraphQL queries to support dynamic options

• Create PullRequestGraphQLOptions dataclass with from_mapping() factory method
• Convert static PR_FIELDS string to generate_pr_fields() function
• Split commits query into PR_COMMITS_TOTAL_ONLY and PR_COMMITS_WITH_FIRST fragments
• Convert LIST_PULL_REQUESTS_GQL to generate_list_pull_requests_gql() function
• Convert PULL_REQUEST_DETAILS_GQL to generate_pull_request_details_gql() function
• Conditionally include first commit node data based on enrich_with_first_commit option

integrations/github/github/helpers/gql_queries.py


View more (5)
4. integrations/github/integration.py ⚙️ Configuration changes +11/-1

Add first commit enrichment selector to configuration

• Add enrich_with_first_commit boolean field to GithubPullRequestSelector
• Set field alias to enrichWithFirstCommit for configuration mapping
• Add descriptive help text explaining lead time measurement use case
• Import validator from pydantic (for potential future validation)

integrations/github/integration.py


5. integrations/github/main.py ✨ Enhancement +1/-0

Wire first commit enrichment through resync workflow

• Pass enrich_with_first_commit from selector config to ListPullRequestOptions
• Enable first commit enrichment in resync pull requests workflow

integrations/github/main.py


6. integrations/github/github/webhook/webhook_processors/pull_request_webhook_processor.py ✨ Enhancement +1/-0

Wire first commit enrichment through webhook processor

• Pass enrich_with_first_commit from config selector to SinglePullRequestOptions
• Enable first commit enrichment in webhook event handling

integrations/github/github/webhook/webhook_processors/pull_request_webhook_processor.py


7. integrations/github/tests/github/core/exporters/test_pull_request_exporter.py 🧪 Tests +260/-8

Add comprehensive tests for first commit enrichment

• Update existing test to use generate_pull_request_details_gql() with options
• Add test_get_resource_enrich_with_first_commit() to verify first commit extraction
• Add test_get_paginated_resources_passes_enriched_query_when_enabled() for paginated enrichment
• Add test_normalize_pr_node_enriches_and_flattens() to verify normalization with first commit
• Add test_normalize_pr_node_skips_first_commit_fields_when_disabled() for disabled case
• Add test_normalize_pr_node_no_commits() to handle empty commits edge case
• Update mock calls to use generated query functions with options

integrations/github/tests/github/core/exporters/test_pull_request_exporter.py


8. integrations/github/tests/github/webhook/webhook_processors/test_pull_request_webhook_processor.py 🧪 Tests +1/-0

Update webhook processor tests for enrichment option

• Update webhook processor test to include enrich_with_first_commit=False in assertions
• Verify webhook event handling passes enrichment option correctly

integrations/github/tests/github/webhook/webhook_processors/test_pull_request_webhook_processor.py


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Apr 9, 2026

Code Review by Qodo

🐞 Bugs (1)   📘 Rule violations (0)   📎 Requirement gaps (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (1)

Grey Divider


Remediation recommended

1. REST ignores enrichment flag 🐞
Description
enrichWithFirstCommit can be enabled while api=rest, but the REST pull request exporter never
uses this option, so PRs will not include firstCommit despite the selector being enabled. This is
a silent misconfiguration path (no validation/warning), making the feature appear broken to users.
Code

integrations/github/integration.py[R222-231]

+    enrich_with_first_commit: bool = Field(
+        title="Enrich with first commit",
+        alias="enrichWithFirstCommit",
+        default=False,
+        description=(
+            "When the api selector is set to graphql and this option is enabled, each pull request is enriched with the "
+            "first commit on the branch (OID and committed timestamp in UTC). Use this to measure "
+            "lead time from the initial commit through review and merge."
+        ),
+    )
Evidence
The selector description states the option applies when the API selector is GraphQL, but the webhook
and resync code pass the flag regardless of API type, and the REST exporter has no logic to enrich
or attach firstCommit based on the flag.

integrations/github/integration.py[217-231]
integrations/github/main.py[403-437]
integrations/github/github/webhook/webhook_processors/pull_request_webhook_processor.py[75-88]
integrations/github/github/core/exporters/pull_request_exporter/core.py[24-82]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`enrichWithFirstCommit` can be enabled while `api=rest`, but REST exporting does not (and cannot, in this PR) attach `firstCommit`. This yields silent, user-visible missing data.

## Issue Context
The selector text says the option only applies when API is GraphQL. Both resync and webhook code paths pass the flag regardless of API type.

## Fix Focus Areas
- integrations/github/integration.py[198-237]
- integrations/github/main.py[403-437]
- integrations/github/github/webhook/webhook_processors/pull_request_webhook_processor.py[75-88]

## Suggested fix
Implement a Pydantic validator on `GithubPullRequestSelector` to enforce: if `enrich_with_first_commit` is true, `api` must be `graphql` (raise a clear validation error). Optionally, also guard at call sites to only pass `enrich_with_first_commit=True` when `is_graphql_api` is true (or emit a warning when REST is selected).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

2. Unused Callable import🐞
Description
Callable is imported in gql_queries.py but is not used, adding noise and suggesting incomplete
refactoring. This can be safely removed.
Code

integrations/github/github/helpers/gql_queries.py[R3-4]

+from collections.abc import Callable, Mapping
+from dataclasses import dataclass
Evidence
The file imports Callable alongside Mapping, but only Mapping is used for from_mapping
typing; there are no other references to Callable in the module.

integrations/github/github/helpers/gql_queries.py[1-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Callable` is imported but unused in `gql_queries.py`.

## Issue Context
Keeping unused imports increases clutter and can confuse future maintainers.

## Fix Focus Areas
- integrations/github/github/helpers/gql_queries.py[1-5]

## Suggested fix
Remove `Callable` from the `collections.abc` import list (keep `Mapping`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@emekanwaoma
Copy link
Copy Markdown
Contributor

I see a misconfiguration gap where enrichWithFirstCommit is configurable even when api=rest, but the REST exporter won’t populate firstCommit. That’s a “looks enabled but doesn’t work” footgun.

Can we add a field validator on GithubPullRequestSelector.enrich_with_first_commit in integrations.py to enforce GraphQL?

omby8888 and others added 3 commits April 9, 2026 18:22
Made-with: Cursor

# Conflicts:
#	integrations/github/CHANGELOG.md
#	integrations/github/pyproject.toml
Copy link
Copy Markdown
Contributor

@emekanwaoma emekanwaoma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants