mvisonneau / gitlab-ci-pipelines-exporter

Prometheus / OpenMetrics exporter for GitLab CI pipelines insights
Apache License 2.0
1.21k stars 238 forks source link

No metrics for merged results pipelines #534

Open jimmy0012 opened 1 year ago

jimmy0012 commented 1 year ago

https://docs.gitlab.com/ee/ci/pipelines/merged_results_pipelines.html

It looks like metrics for merged results pipelines are never collected

mj3c commented 6 months ago

This is due to the regex used when checking whether a retrieved ref matches the expected pattern for merge request pipelines. Here's the line: https://github.com/mvisonneau/gitlab-ci-pipelines-exporter/blob/0687efd1075d33283c3762a135aa24de94ffe21c/pkg/schemas/ref.go#L13

The /head at the end of the ref there is only available for "regular" merge request pipelines. For merge results pipelines the ref has a /merge at the end instead.

Here's a patch that makes the code work for all MR pipelines (regular and merge results ones):

diff --git a/pkg/controller/pipelines.go b/pkg/controller/pipelines.go
index 8173434..71e94b2 100644
--- a/pkg/controller/pipelines.go
+++ b/pkg/controller/pipelines.go
@@ -36,7 +36,7 @@ func (c *Controller) PullRefMetrics(ctx context.Context, ref schemas.Ref) error
        // We need a different syntax if the ref is a merge-request
        var refName string
        if ref.Kind == schemas.RefKindMergeRequest {
-               refName = fmt.Sprintf("refs/merge-requests/%s/head", ref.Name)
+               refName = fmt.Sprintf("refs/merge-requests/%s", ref.Name)
        } else {
                refName = ref.Name
        }
diff --git a/pkg/gitlab/pipelines.go b/pkg/gitlab/pipelines.go
index 4557c7a..8c74721 100644
--- a/pkg/gitlab/pipelines.go
+++ b/pkg/gitlab/pipelines.go
@@ -236,6 +236,10 @@ func (c *Client) GetRefsFromPipelines(ctx context.Context, p schemas.Project, re
                        }

                        if refKind == schemas.RefKindMergeRequest {
+                               // We split the ref into pieces and save the last element to figure out the type of this MR pipeline.
+                               // The last element will be "/head" for regular MR pipelines, and "/merge" for merge results pipelines.
+                               refParts := strings.Split(refName, "/")
+
                                if refName, err = schemas.GetMergeRequestIIDFromRefName(refName); err != nil {
                                        log.WithContext(ctx).
                                                WithField("ref", refName).
@@ -244,6 +248,9 @@ func (c *Client) GetRefsFromPipelines(ctx context.Context, p schemas.Project, re

                                        continue
                                }
+
+                               // We attach the MR pipeline type ("/head" or "/merge") to the refName.
+                               refName = refName + "/" + refParts[len(refParts)-1]
                        }

                        ref := schemas.NewRef(
diff --git a/pkg/schemas/ref.go b/pkg/schemas/ref.go
index 8f403a8..1731410 100644
--- a/pkg/schemas/ref.go
+++ b/pkg/schemas/ref.go
@@ -10,7 +10,7 @@ import (
 )

 const (
-       mergeRequestRegexp string = `^((\d+)|refs/merge-requests/(\d+)/head)$`
+       mergeRequestRegexp string = `^((\d+)|refs/merge-requests/(\d+)/(?:head|merge))$`

        // RefKindBranch refers to a branch.
        RefKindBranch RefKind = "branch"

Note that the ref name that will be exported now includes a suffix. For example for a merge request with ID 15, the ref name will be 15/head or 15/merge depending the type of the MR pipeline.