Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-workflows-empty-results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"grafana-github-datasource": patch
---

Fix empty results in Workflows query type. Added nil check for CreatedAt/UpdatedAt timestamps and added "None" option to Time Field dropdown (default) to return all workflows without time filtering.
8 changes: 7 additions & 1 deletion docs/sources/query/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -554,10 +554,16 @@ List GitHub Actions workflows defined in a repository.
| ---------- | -------------------------------------------------- | -------- |
| owner | GitHub user or organization that owns the repository | Yes |
| repository | Name of the repository | Yes |
| Time Field | The time field to filter the responses on, can be: `CreatedAt` or `UpdatedAt` | Yes |
| Time Field | The time field to filter the responses on, can be: `None` (returns all workflows), `CreatedAt`, or `UpdatedAt` | Yes |

##### Sample queries

Show all workflows in the `grafana/grafana` repository:

- Owner: `grafana`
- Repository: `grafana`
- Time Field: `None`

Show all workflows created within the `grafana/grafana` repository within the current time range:

- Owner: `grafana`
Expand Down
43 changes: 37 additions & 6 deletions pkg/github/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ func GetWorkflows(ctx context.Context, client models.Client, opts models.ListWor
return nil, fmt.Errorf("listing workflows: opts=%+v %w", opts, err)
}

// If time field is None, return all workflows without filtering
if opts.TimeField == models.WorkflowTimeFieldNone {
return WorkflowsWrapper(data.Workflows), nil
}

// Otherwise, apply time filtering based on the selected time field
workflows, err := keepWorkflowsInTimeRange(data.Workflows, opts.TimeField, timeRange)
if err != nil {
return nil, fmt.Errorf("filtering workflows by time range: timeField=%d timeRange=%+v %w", opts.TimeField, timeRange, err)
Expand All @@ -72,27 +78,52 @@ func GetWorkflows(ctx context.Context, client models.Client, opts models.ListWor
}

func keepWorkflowsInTimeRange(workflows []*googlegithub.Workflow, timeField models.WorkflowTimeField, timeRange backend.TimeRange) ([]*googlegithub.Workflow, error) {
// If time range is empty/unset, return all workflows (similar to Tags, Releases, etc.)
if timeRange.From.Unix() <= 0 && timeRange.To.Unix() <= 0 {
return workflows, nil
}

out := make([]*googlegithub.Workflow, 0)
nilCount := 0
excludedCount := 0

for _, workflow := range workflows {
var shouldInclude bool

switch timeField {
case models.WorkflowCreatedAt:
if workflow.CreatedAt.Before(timeRange.From) || workflow.CreatedAt.After(timeRange.To) {
if workflow.CreatedAt == nil {
// If filtering by CreatedAt but CreatedAt is nil, exclude the workflow
nilCount++
continue
}
// Include if CreatedAt is within the time range (inclusive)
createdAtTime := workflow.CreatedAt.Time
shouldInclude = !createdAtTime.Before(timeRange.From) && !createdAtTime.After(timeRange.To)
if !shouldInclude {
excludedCount++
}

case models.WorkflowUpdatedAt:
if workflow.UpdatedAt != nil {
if workflow.UpdatedAt.Before(timeRange.From) || workflow.UpdatedAt.After(timeRange.To) {
continue
}
if workflow.UpdatedAt == nil {
// If filtering by UpdatedAt but UpdatedAt is nil, exclude the workflow
nilCount++
continue
}
// Include if UpdatedAt is within the time range (inclusive)
updatedAtTime := workflow.UpdatedAt.Time
shouldInclude = !updatedAtTime.Before(timeRange.From) && !updatedAtTime.After(timeRange.To)
if !shouldInclude {
excludedCount++
}

default:
return nil, backend.DownstreamError(fmt.Errorf("unexpected time field: %d", timeField))
}

out = append(out, workflow)
if shouldInclude {
out = append(out, workflow)
}
}

return out, nil
Expand Down
4 changes: 3 additions & 1 deletion pkg/models/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import "time"
type WorkflowTimeField uint32

const (
// WorkflowTimeFieldNone indicates no time filtering should be applied
WorkflowTimeFieldNone WorkflowTimeField = iota
// WorkflowCreatedAt is used when filtering when an workflow was created
WorkflowCreatedAt WorkflowTimeField = iota
WorkflowCreatedAt
// WorkflowUpdatedAt is used when filtering when an Workflow was updated
WorkflowUpdatedAt
)
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export enum IssueTimeField {
}

export enum WorkflowsTimeField {
None,
CreatedAt,
UpdatedAt,
}
Expand Down
6 changes: 3 additions & 3 deletions src/views/QueryEditorWorkflows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@
};
});

const defaultTimeField = 0 as WorkflowsTimeField;
const defaultTimeField = WorkflowsTimeField.None;

const QueryEditorWorkflows = (props: Props) => {
return (
<>
<InlineField
labelWidth={LeftColumnWidth * 2}
label="Time Field"
tooltip="The time field to filter on the time range"
tooltip="Select 'None' to return all workflows, or choose a time field to filter by the dashboard time range"
>
<Select

Check warning on line 31 in src/views/QueryEditorWorkflows.tsx

View workflow job for this annotation

GitHub Actions / CI / Test and build plugin

`Select` is deprecated. Use Combobox component instead
width={RightColumnWidth}
options={timeFieldOptions}
value={props.timeField || defaultTimeField}
value={props.timeField !== undefined ? props.timeField : defaultTimeField}
onChange={(opt) => {
props.onChange({
...props,
Expand Down
Loading