Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can’t fetch pipelines from merge requests because of mismatched ref #280

Open
shivjm opened this issue May 31, 2021 · 17 comments
Open

Can’t fetch pipelines from merge requests because of mismatched ref #280

shivjm opened this issue May 31, 2021 · 17 comments
Assignees
Labels
bug Something isn't working

Comments

@shivjm
Copy link

shivjm commented May 31, 2021

I’m not sure whether GitLab changed something recently, in the run up to version 14, but I have the exporter set up with a Webhook and it’s unable to fetch any pipelines. For example (with my project details edited):

{"ip-address":"10.244.1.187:42854","level":"debug","msg":"webhook request","time":"2021-05-31T13:46:23Z","user-agent":"GitLab/14.0.0-pre"}
{"level":"info","msg":"received a pipeline webhook from GitLab for a ref, triggering metrics pull","project-name":"my-group/my-repo","ref":"my-branch","ref-kind":"merge-request","time":"2021-05-31T13:46:23Z"}
{"level":"debug","msg":"listing project pipelines","project-name":"my-group/my-repo","ref":"my-branch","time":"2021-05-31T13:46:23Z"}
{"level":"debug","msg":"could not find any pipeline for the ref","project-name":"my-group/my-repo","ref":"my-branch","ref-kind":"merge-request","time":"2021-05-31T13:46:23Z"}

I did some debugging and what I found is that GitLab’s pipeline details (now?) use ref like this:

        "ref": "refs/merge-requests/55/head",

If you search for pipelines using the name of the branch, it returns nothing. If you use this ref, it does show up. However, it’s not possible to generate it from the Webhook request. Instead, you can take the sha from the Webhook request and retrieve pipelines based on that instead (by passing a sha parameter instead of a ref parameter). I confirmed manually that it works. No matter what the ref is, the sha will always match.

@mvisonneau mvisonneau reopened this Jun 1, 2021
@mvisonneau
Copy link
Owner

hey @shivjm, thanks for raising this issue and the associated troubleshooting. I believe this is a duplicate of #259 actually but it allowed me to figure out where to look 🙇 I believe 83ca5f2 should sort it out.

@mvisonneau mvisonneau self-assigned this Jun 1, 2021
@mvisonneau mvisonneau added the bug Something isn't working label Jun 1, 2021
@shivjm
Copy link
Author

shivjm commented Jun 1, 2021

Thank you for the speedy response! I did see #259 but it didn’t seem like the same thing. My mistake. I’m glad I helped you find the issue, at any rate.

I updated to the latest Docker image (and confirmed that the digests match), but I’m afraid I’m still seeing the same issue:

"ip-address":"10.244.1.187:57670","level":"debug","msg":"webhook request","time":"2021-06-01T10:48:23Z","user-agent":"GitLab/14.0.0-pre"}
{"level":"info","msg":"received a pipeline webhook from GitLab for a ref, triggering metrics pull","project-name":"my-group/my-project","ref":"my-branch","ref-kind":"merge-request","time":"2021-06-01T10:48:23Z"}
{"level":"debug","msg":"listing project pipelines","project-name":"my-group/my-project","ref":"refs/merge-requests/my-branch/head","time":"2021-06-01T10:48:23Z"}
{"level":"debug","msg":"could not find any pipeline for the ref","project-name":"my-group/my-project","ref":"my-branch","ref-kind":"merge-request","time":"2021-06-01T10:48:23Z"}

@mpickering
Copy link

I don't think this is fixed still. See my comment - 83ca5f2#r51677228

@mvisonneau
Copy link
Owner

mvisonneau commented Jun 3, 2021

@shivjm indeed, there were further changes required, 436f91f should fix it 🤞

@mpickering
Copy link

I still think something isn't quite right.. with the latest change I get

time="2021-06-03T11:39:29-04:00" level=info msg="ref not configured in the exporter, ignoring pipeline webhook" project-name=ghc/ghc ref=5882 ref-kind=merge-request

Before the patch I would get

msg="received a pipeline webhook from GitLab for a ref, triggering metrics pull" project-name=ghc/ghc ref=wip/adinapoli-issue-19923 ref-kind=merge-request
 msg="listing project pipelines" project-name=ghc/ghc ref=refs/merge-requests/wip/adinapoli-issue-19923/head
 msg="could not find any pipeline for the ref" project-name=ghc/ghc ref=wip/adinapoli-issue-19923 ref-kind=merge-request

@mvisonneau
Copy link
Owner

@mpickering, indeed this is following some breaking changes I am about to release as part of v0.5.0, you can already read about them in the CHANGELOG.

basically you will now need to set the following to get it to work with merge requests refs:

project_defaults:
  pull:
    refs:
      merge_requests:
        enabled: true

@mpickering
Copy link

I tried making that change. Still the same result, here is the config.

gitlab:
  token: <>
  url: 'https://gitlab.haskell.org'
projects:
  - name: ghc/ghc
    pull:
      refs:
        merge_requests:
          enabled: true
        regexp: .*
pull:
  environments_from_projects:
    on_init: false
    scheduled: false
  metrics:
    on_init: false
    scheduled: false
  projects_from_wildcards:
    on_init: false
    scheduled: false
  refs:
    regexp: .*
  refs_from_projects:
    on_init: false
    scheduled: false
server:
  listen_address: ':9887'
  webhook:
    enabled: true
    secret_token: <>
wildcards:
  - {}

@mvisonneau
Copy link
Owner

@mpickering can you give it a try with the following config?

---
server:
  listen_address: ':9887'
  webhook:
    enabled: true
    secret_token: <>

gitlab:
  token: <>
  url: 'https://gitlab.haskell.org'

projects_defaults:
  pull:
    refs:
      branches:
        regexp: .*    
      merge_requests:
        enabled: true

pull:
  environments_from_projects:
    on_init: false
    scheduled: false
  metrics:
    on_init: false
    scheduled: false
  projects_from_wildcards:
    on_init: false
    scheduled: false
  refs_from_projects:
    on_init: false
    scheduled: false

wildcards: [{}]

@mpickering
Copy link

Still seems broken on all MRs for me. There are now no errors in the log but no metrics are populating the DB.

INFO[2021-06-03T17:43:16-04:00] configured                                    gitlab-endpoint="https://gitlab.haskell.org" gitlab-rate-limit=1rps
INFO[2021-06-03T17:43:16-04:00] pull projects from wildcards                  on-init=no scheduled=no
INFO[2021-06-03T17:43:16-04:00] pull environments from projects               on-init=no scheduled=no
INFO[2021-06-03T17:43:16-04:00] pull refs from projects                       on-init=no scheduled=no
INFO[2021-06-03T17:43:16-04:00] pull metrics                                  on-init=no scheduled=no
INFO[2021-06-03T17:43:16-04:00] garbage collect projects                      on-init=no scheduled="every 14400s"
INFO[2021-06-03T17:43:16-04:00] garbage collect environments                  on-init=no scheduled="every 14400s"
INFO[2021-06-03T17:43:16-04:00] garbage collect refs                          on-init=no scheduled="every 1800s"
INFO[2021-06-03T17:43:16-04:00] garbage collect metrics                       on-init=no scheduled="every 300s"
DEBU[2021-06-03T17:43:16-04:00] task scheduled                                interval_seconds=14400 task=GarbageCollectProjects
DEBU[2021-06-03T17:43:16-04:00] task scheduled                                interval_seconds=14400 task=GarbageCollectEnvironments
DEBU[2021-06-03T17:43:16-04:00] task scheduled                                interval_seconds=1800 task=GarbageCollectRefs
DEBU[2021-06-03T17:43:16-04:00] task scheduled                                interval_seconds=300 task=GarbageCollectMetrics
INFO[2021-06-03T17:43:16-04:00] http server started                           listen-address=":9887" metrics-endpoint-enabled=true openmetrics-encoding-enabled=false pprof-endpoint-enabled=false webhook-endpoint-enabled=true
DEBU[2021-06-03T17:43:27-04:00] webhook request                               ip-address="127.0.0.1:55480" user-agent=GitLab/13.12.2-ee
DEBU[2021-06-03T17:43:53-04:00] webhook request                               ip-address="127.0.0.1:55488" user-agent=GitLab/13.12.2-ee
INFO[2021-06-03T17:48:16-04:00] starting 'metrics' garbage collection        
INFO[2021-06-03T17:48:16-04:00] ending 'metrics' garbage collection          
INFO[2021-06-03T17:53:16-04:00] starting 'metrics' garbage collection        
INFO[2021-06-03T17:53:16-04:00] ending 'metrics' garbage collection          
INFO[2021-06-03T17:58:16-04:00] starting 'metrics' garbage collection        
INFO[2021-06-03T17:58:16-04:00] ending 'metrics' garbage collection          
INFO[2021-06-03T18:03:16-04:00] starting 'metrics' garbage collection        
INFO[2021-06-03T18:03:16-04:00] ending 'metrics' garbage collection          
DEBU[2021-06-03T18:06:44-04:00] webhook request                               ip-address="127.0.0.1:57544" user-agent=GitLab/13.12.2-ee
DEBU[2021-06-03T18:06:45-04:00] webhook request                               ip-address="127.0.0.1:57548" user-agent=GitLab/13.12.2-ee
INFO[2021-06-03T18:08:16-04:00] starting 'metrics' garbage collection        
INFO[2021-06-03T18:08:16-04:00] ending 'metrics' garbage collection   

@mvisonneau
Copy link
Owner

INFO[2021-06-03T23:44:05+01:00] configured                                    gitlab-endpoint="https://git.example.com" gitlab-rate-limit=25rps
INFO[2021-06-03T23:44:05+01:00] pull projects from wildcards                  on-init=no scheduled=no
INFO[2021-06-03T23:44:05+01:00] pull environments from projects               on-init=no scheduled=no
INFO[2021-06-03T23:44:05+01:00] pull refs from projects                       on-init=no scheduled=no
INFO[2021-06-03T23:44:05+01:00] pull metrics                                  on-init=no scheduled=no
INFO[2021-06-03T23:44:05+01:00] garbage collect projects                      on-init=no scheduled="every 14400s"
INFO[2021-06-03T23:44:05+01:00] garbage collect environments                  on-init=no scheduled="every 14400s"
INFO[2021-06-03T23:44:05+01:00] garbage collect refs                          on-init=no scheduled="every 1800s"
INFO[2021-06-03T23:44:05+01:00] garbage collect metrics                       on-init=no scheduled="every 300s"
DEBU[2021-06-03T23:44:05+01:00] task scheduled                                interval_seconds=14400 task=GarbageCollectProjects
DEBU[2021-06-03T23:44:05+01:00] task scheduled                                interval_seconds=14400 task=GarbageCollectEnvironments
DEBU[2021-06-03T23:44:05+01:00] task scheduled                                interval_seconds=1800 task=GarbageCollectRefs
DEBU[2021-06-03T23:44:05+01:00] task scheduled                                interval_seconds=300 task=GarbageCollectMetrics
INFO[2021-06-03T23:44:05+01:00] http server started                           listen-address=":5000" metrics-endpoint-enabled=true openmetrics-encoding-enabled=false pprof-endpoint-enabled=false webhook-endpoint-enabled=true
DEBU[2021-06-03T23:44:14+01:00] webhook request                               ip-address="127.0.0.1:40074" user-agent=GitLab/13.12.1-ee
INFO[2021-06-03T23:44:14+01:00] project ref not currently exported but its configuration matches a wildcard, triggering a pull of the projects from this wildcard  project-name=foo/bar ref=1234 ref-kind=merge-request
INFO[2021-06-03T23:44:14+01:00] done looking up for wildcards matching the project ref  project-name=foo/bar ref=1234 ref-kind=merge-request
DEBU[2021-06-03T23:44:14+01:00] listing all projects from wildcard            wildcard-archived=false wildcard-owner-include-subgroups=false wildcard-owner-kind= wildcard-owner-name= wildcard-search=
[..]

hmm interesting, I cannot manage to reproduce 🤔 I added some further logging details in 366cd92 if you feel like trying it out.

@mpickering
Copy link

DEBU[2021-06-04T03:36:31-04:00] webhook request                               ip-address="127.0.0.1:59408" user-agent=GitLab/13.12.2-ee
DEBU[2021-06-04T03:36:31-04:00] project ref not matching wildcard, skipping..  project-name=ghc/ghc ref=5897 ref-kind=merge-request
INFO[2021-06-04T03:36:31-04:00] done looking up for wildcards matching the project ref  project-name=ghc/ghc ref=5897 ref-kind=merge-request

@mvisonneau
Copy link
Owner

and you confirm the wildcard is a global one (wildcards: [{}])?

@mpickering
Copy link

The issue was the config you gave me had projects_defaults rather than project_defaults. Would it be possible to add some validation to the config to catch errors like this?

@mvisonneau
Copy link
Owner

ah right! my bad 🤦 yep that would be great 👍

@davidtlascelles
Copy link

I'm still seeing this issue on 0.5.2-39-g287e04c

Here's a log from a webhook request:

time="2022-01-31T14:59:12Z" level=debug msg="webhook request" ip-address="127.0.0.1:49140" user-agent=GitLab/14.6.1-ee
time="2022-01-31T14:59:12Z" level=info msg="received a pipeline webhook from GitLab for a ref, triggering metrics pull" project-name=path/to/project ref=3467 ref-kind=merge-request
time="2022-01-31T14:59:12Z" level=trace msg="listing project pipelines" page=1 project-name=path/to/projec ref=refs/merge-requests/3467/head
time="2022-01-31T14:59:12Z" level=debug msg="could not find any pipeline for the ref" project-name=path/to/projec ref=3467 ref-kind=merge-request

Here's my config.yml:

log:
  level: trace
server:
  listen_address: ':8080'
  webhook:
    enabled: true
    secret_token: <>
gitlab:
  url: http://gitlab:80
  token: <>
  health_url: http://gitlab:80/-/health
pull:
  environments_from_projects:
    on_init: false
    scheduled: false
  metrics:
    on_init: false
    scheduled: false
  projects_from_wildcards:
    on_init: false
    scheduled: false
  refs_from_projects:
    on_init: false
    scheduled: false
project_defaults:
  output_sparse_status_metrics: false
  pull:
    refs:
      branches:
        regexp: ".*"
        max_age_seconds: 1209600
        exclude_deleted: false
      tags:
        enabled: false
      merge_requests:
        enabled: true
        max_age_seconds: 1209600
    pipeline:
      jobs:
        enabled: true
      variables:
        enabled: true
projects:
  - name: path/to/project
wildcards: [{}]

Any progress on this bug?

@davidtlascelles
Copy link

Hey @mvisonneau, I've dug through the code a bit to try to help. I think the issue is related to GitLab's weird refs related to merge-requests, and the implementation for fetching a pipeline based on the ref. I'm not experienced with Go, but here's how I understand the execution flow, what I suspect is the problem, and my proposed solution.

Execution flow

  1. Webhook request is sent. Example payload:
{
  "object_kind": "pipeline",
  "object_attributes": {
    "id": 1864,
    "ref": "MR/usr/branchName",
    "tag": false,
    "sha": "1234567890",
    "before_sha": "0987654321",
    "source": "merge_request_event",
    "status": "running",
    "detailed_status": "running",
    "stages": [
      "prechecks",
      "build",
      "test"
    ],
    "created_at": "2022-02-01 9:00:00 UTC",
    "finished_at": null,
    "duration": null,
    "queued_duration": 9,
    "variables": []
  },
  "merge_request": {
    "id": 6302,
    "iid": 3340,
    "title": "Merge Request Title",
    "source_branch": "MR/usr/branchName",
    "source_project_id": 123,
    "target_branch": "master",
    "target_project_id": 123,
    "state": "opened",
    "merge_status": "can_be_merged",
    "url": "https://gitlab_url/path/to/project/-/merge_requests/3340"
  },
  "user": {
    "..."
  },
  "project": {
    "id": 123,
    "name": "project",
    "...",
    "path_with_namespace": "path/to/project",
    "default_branch": "master",
    "..."
  },
  "commit": {
    "..."
  }
},
"builds": [
  {
    "..."
  1. Webhook received by WebhookHandler() ( pkg/controller/handlers.go )

    • Log generated: level=debug msg="webhook request"
  2. I think the object_kind property of the webhook payload is parsed, triggering processPipelineEvent() ( pkg/controller/webhooks.go )

  3. triggerRefMetricsPull() is called ( pkg/controller/webhooks.go )

    • Task scheduled to pull metrics
      c.ScheduleTask(context.TODO(), schemas.TaskTypePullRefMetrics, string(ref.Key()), ref)
    • Log generated: level=info msg="received a pipeline webhook from GitLab for a ref, triggering metrics pull"
  4. Task is handled by TaskHandlerPullRefMetrics() ( pkg/controller/scheduler.go )

  5. PullRefMetrics() is called to get metrics about the pipeline ( pkg/controller/pipelines.go )

  6. GetProjectPipelines() is called to list pipelines matching the ref ( pkg/gitlab/pipelines.go )

    • Log generated: level=trace msg="listing project pipelines"
  7. ListProjectPipelines() is called to query the GitLab API ( goGitlab/pipelines.go )

  8. No pipelines found with that ref, so PullRefMetrics() fails when len(pipelines) == 0

    • Log generated level=debug msg="could not find any pipeline for the ref"
  9. If GetProjectPipelines() was successful, the next step would be to call GetRefPipeline() using pipelines[0].ID, assigning the first (and only) pipeline in the pipelines list to the pipeline value.

Problem

If you can't find the pipeline from the ref using the ListProjectPipelines() function, the code fails. I think the merge-request ref isn't pure git, so it behaves a bit strange. I tried manually querying the API using the merge-request ref and it worked, but I suspect something strange is happening with the goGitlab dependency. Ultimately I think using merge-request refs aren't a good idea.

Proposed Solution

Modify the condition on /pkg/controller/pipelines.go, lines 26-54. The idea is instead of reformatting the refName string, just call GetRefPipeline() directly to populate the pipeline value. Something like:

// We need to handle merge-request refs differently
if ref.Kind == schemas.RefKindMergeRequest {
  // Get the pipeline directly using the pipeline ID from the Webhook payload
  pipeline, err := c.Gitlab.GetRefPipeline(ref, pipelineIdFromWebhookPayload)
    if err != nil {
      return err
    }
} else {
  // Otherwise get the pipeline using the list approach
  pipelines, _, err := c.Gitlab.GetProjectPipelines(ref.Project.Name, &goGitlab.ListProjectPipelinesOptions{
    ListOptions: goGitlab.ListOptions{
      PerPage: 1,
      Page:    1,
    },
    Ref: ref.Name, // Don't need the refName value anymore. 
  })
  {. . .} // handle errors
  // Get pipeline from list
  pipeline, err := c.Gitlab.GetRefPipeline(ref, pipelines[0].ID)
  if err != nil {
    return err
  }
}

I'm not sure if this would break functionality for the non-webhook data fetching or not. it seems like it would require some re-work for fetch events too.

@shivjm
Copy link
Author

shivjm commented Sep 25, 2022

I’ve got my stack up and running again. Sorry for leaving this in a state of limbo for so long. Unfortunately, though @davidtlascelles’s detailed comments are extremely helpful, I had to move away from the webhook approach for unrelated reasons, and as such am unable to test either the current version or the proposed solution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants