grafana / grafana/github-datasource
Bug: Workflow_Runs query type consistently returns 0 rows when same URL+token directly returns data
- Dominant language
- Go
- Stars
- 310
- Forks
- 70
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 3
Description
# Bug: `Workflow_Runs` query type returns 0 rows when the same URL+token directly returns the expected data
## What you expected to happen
A `Workflow_Runs` query against a valid `owner` / `repository` / `workflow` should return the workflow runs visible to the configured credentials, like:
```
GET /repos/{owner}/{repo}/actions/workflows/{workflow}/runs?created=..
```
would return when called directly.
## What actually happened
The plugin returns `status: 200` with a valid frame schema (14 fields: `id`, `name`, `head_branch`, …) but **all field value arrays are empty** (`[]`). Other query types (`Workflows`, `Issues`, `Pull_Requests`, `Repositories`, `Commits`) against the same datasource work correctly and return populated data.
## Steps to reproduce
1. Configure the datasource against an org with at least one repo and one workflow that has recent runs.
2. Add a panel with query:
```json
{
"queryType": "Workflow_Runs",
"options": {
"owner": "",
"repository": "",
"workflow": ".yml"
}
}
```
3. Set the dashboard time range to a window that contains real runs.
4. Inspect the panel. The query returns no rows.
For reference, the same underlying API endpoint called directly with the exact `created=..` filter the plugin would construct (using either an App installation token or a PAT) returns the expected runs:
```bash
curl -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos///actions/workflows/.yml/runs?created=..&per_page=100"
# → total_count: 12, returns 12 runs
```
## Query inspector evidence
Request body sent by the plugin (captured via Grafana's query inspector):
```json
{
"queries": [{
"refId": "A",
"datasource": { "type": "grafana-github-datasource", "uid": "..." },
"queryType": "Workflow_Runs",
"options": {
"owner": "",
"repository": "",
"workflow": ".yml"
},
"datasourceId": 62,
"intervalMs": 600000,
"maxDataPoints": 1180
}],
"from": "1781300092199",
"to": "1781904892199"
}
```
Plugin response:
```json
{
"results": {
"A": {
"status": 200,
"frames": [{
"schema": {
"name": "workflow_run",
"fields": [
{ "name": "id", "type": "number", ... },
{ "name": "name", "type": "string", ... },
{ "name": "head_branch", ... },
{ "name": "head_sha", ... },
{ "name": "created_at", "type": "time", ... },
{ "name": "updated_at", ... },
{ "name": "run_started_at", ... },
{ "name": "html_url", ... },
{ "name": "url", ... },
{ "name": "status", ... },
{ "name": "conclusion", ... },
{ "name": "event", ... },
{ "name": "workflow_id", ... },
{ "name": "run_number", ... }
]
},
"data": { "values": [[], [], [], [], [], [], [], [], [], [], [], [], [], []] }
}]
}
}
}
```
Schema is correct; values are empty for every field.
## What we ruled out during debugging
We spent a few hours narrowing this down. The matrix of combinations that all produced the same `0 rows` result:
| Variable | Tested | Result |
|---|---|---|
| Plugin version | v2.3.0, v2.5.1, v2.6.0, v2.8.0 | All: 0 rows |
| Auth | GitHub App (ghinstallation) + Personal Access Token | Both: 0 rows |
| Workflow `workflow` value | basename (`x.yml`), numeric ID (``), full path (`.github/workflows/x.yml`) | Basename and ID: 0 rows. Full path: `workflow not found` error (expected). |
| Workflow choice | several different workflows in the same repo | All: 0 rows |
| Repository choice | several different repos in the same org | All: 0 rows |
| Time range | `now-7d`, `now-30d`, explicit epoch ms covering known-good runs | All: 0 rows |
| Direct API call with the same install token / PAT | Same URL the plugin would construct, same `created=..` filter | **Returns the expected runs** (12 in our test) |
App permissions used (verified by minting an installation token via JWT and inspecting `/app/installations/{id}/access_tokens` response):
```json
"permissions": {
"actions": "read",
"contents": "read",
"issues": "read",
"metadata": "read",
"pull_requests": "read"
}
```
`repository_selection: "all"`.
## Environment
- Grafana: `12.1.1`
- Plugin: confirmed across `2.3.0`, `2.5.1`, `2.6.0`, `2.8.0`
- Auth tested: GitHub App (with valid permissions including `actions: read`) and Personal Access Token (with `repo, workflow, read:org` scopes)
- Cluster: EKS, plugin running in the official Grafana Helm chart deployment
- Other query types from this plugin against the same datasource all work: `Workflows` (lists workflows), `Issues`, `Pull_Requests`, `Repositories`, `Commits`
## Possible related fix
PR #526 (fixes #503) addressed a similar "0 rows" problem in the `Workflows` query type — root cause was in `pkg/models/workflows.go` / `pkg/github/workflows.go` around `CreatedAt`/`UpdatedAt` time filtering with nil-handling and the addition of a `None` time field option.
`Workflow_Runs` does not expose a similar `None` option (the time filter is always applied based on the dashboard time range, constructed inside `pkg/github/client/client.go` as `created=..`). It's plausible the same underlying issue with time filter construction affects this query type but is not covered by #526's fix.
## Hypothesis
The fact that:
- The plugin returns HTTP 200 (so the call to GitHub succeeded)
- The schema is fully populated (14 expected fields)
- Yet `data.values` arrays are all empty
- And a manual curl with the exact same URL+token returns runs
…suggests something between the GitHub response and the frame serialization is dropping rows. The fact that PR #526's fix on the `Workflows` query type added "improve time filtering logic with better nil handling" makes me suspect the same neighborhood — perhaps the response is being parsed and rows are filtered out by some predicate that shouldn't apply.
I'd be happy to add more diagnostic information (debug-level logs from the plugin, network trace) if useful — please indicate what would help most.
## Workaround
For now we removed the `Workflow_Runs`-based panels from our dashboard and use only the query types that work (`Workflows`, `Issues`, `Pull_Requests`, `Repositories`). Workflow-run metrics remain unavailable to us via this plugin.
---
Contributor guide
Research direction
Trace the Workflow_Runs query from its handler into pkg/github/client/client.go, then compare the time-filtering and response handling with pkg/models/workflows.go and pkg/github/workflows.go, which are implicated by PR #526. Reproduce the empty frame using the supplied query and compare the constructed request with the successful curl; done means known runs populate all 14 fields for the selected dashboard range.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github, go
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100