diff --git a/.changeset/fix-workflows-empty-results.md b/.changeset/fix-workflows-empty-results.md new file mode 100644 index 00000000..e6b66f6d --- /dev/null +++ b/.changeset/fix-workflows-empty-results.md @@ -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. diff --git a/docs/sources/query/_index.md b/docs/sources/query/_index.md index 760da1c7..c0c9b9c5 100644 --- a/docs/sources/query/_index.md +++ b/docs/sources/query/_index.md @@ -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` diff --git a/pkg/github/workflows.go b/pkg/github/workflows.go index f41c2996..e239ea84 100644 --- a/pkg/github/workflows.go +++ b/pkg/github/workflows.go @@ -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) @@ -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 diff --git a/pkg/models/workflows.go b/pkg/models/workflows.go index 6afdaccf..4f96431b 100644 --- a/pkg/models/workflows.go +++ b/pkg/models/workflows.go @@ -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 ) diff --git a/src/constants.ts b/src/constants.ts index bbd2d559..4f86d8ef 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -49,6 +49,7 @@ export enum IssueTimeField { } export enum WorkflowsTimeField { + None, CreatedAt, UpdatedAt, } diff --git a/src/views/QueryEditorWorkflows.tsx b/src/views/QueryEditorWorkflows.tsx index d8103be9..128c05c9 100644 --- a/src/views/QueryEditorWorkflows.tsx +++ b/src/views/QueryEditorWorkflows.tsx @@ -18,7 +18,7 @@ const timeFieldOptions: Array> = Object.keys }; }); -const defaultTimeField = 0 as WorkflowsTimeField; +const defaultTimeField = WorkflowsTimeField.None; const QueryEditorWorkflows = (props: Props) => { return ( @@ -26,12 +26,12 @@ const QueryEditorWorkflows = (props: Props) => {