AutomationFlowsWeb Scraping › Generate Your Gitlab Year-in-review Wrapped Report Automatically

Generate Your Gitlab Year-in-review Wrapped Report Automatically

ByJannik Lehmann @jnnklhmnn on n8n.io

✨ Automatically generate your personalized GitLab Wrapped, a stunning year-in-review of your contributions, activity, and stats.

Event trigger★★★★☆ complexity23 nodesForm TriggerHTTP Request
Web Scraping Trigger: Event Nodes: 23 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #12394 — we link there as the canonical source.

This workflow follows the Form Trigger → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "vYXacrHS3dDuVhDm",
  "name": "GitLab Wrapped Workflow",
  "tags": [],
  "nodes": [
    {
      "id": "8e0b0b30-e1af-43a8-9024-7080102a795a",
      "name": "GitLab Wrapped Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        3008,
        -176
      ],
      "parameters": {
        "options": {
          "appendAttribution": false
        },
        "formTitle": "GitLab Wrapped 2024",
        "formFields": {
          "values": [
            {
              "fieldLabel": "user",
              "requiredField": true
            },
            {
              "fieldLabel": "token",
              "requiredField": true
            },
            {
              "fieldLabel": "url",
              "placeholder": "https://gitlab.com",
              "defaultValue": "https://gitlab.com"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Year",
              "placeholder": "2025",
              "defaultValue": "2025"
            }
          ]
        },
        "formDescription": "Generate your personalized GitLab Wrapped for 2024"
      },
      "typeVersion": 2.3
    },
    {
      "id": "14751144-3de8-457c-9fd7-b3c9e4dc4781",
      "name": "Workflow Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        3232,
        -176
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "name",
              "type": "string",
              "value": "={{ $json.user }}"
            },
            {
              "id": "id-2",
              "name": "apiToken",
              "type": "string",
              "value": "={{ $json.token }}"
            },
            {
              "id": "id-3",
              "name": "gitlabUrl",
              "type": "string",
              "value": "={{ $json.url }}"
            },
            {
              "id": "id-4",
              "name": "year",
              "type": "string",
              "value": "2024"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "0715a87d-c26f-4ffe-a585-e3cc2d88b54a",
      "name": "Wait for CI/CD",
      "type": "n8n-nodes-base.wait",
      "position": [
        5472,
        -80
      ],
      "parameters": {
        "unit": "minutes",
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "79f41700-fdee-4d9c-99ec-13b1460e57cd",
      "name": "Check Pipeline Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5696,
        -160
      ],
      "parameters": {
        "url": "=https://gitlab.com/api/v4/projects/{{ $('set ProjectId').item.json.projectId }}/pipelines?ref=main&per_page=1\n",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "95b44757-5e9e-4697-a51c-0ae3de2ad675",
      "name": "Pipeline Complete?",
      "type": "n8n-nodes-base.if",
      "position": [
        5920,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.status}}",
              "rightValue": "success"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c2a6222f-4581-4b9a-9802-04a3007610fd",
      "name": "Set token env var",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        4576,
        -80
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.gitlabUrl }}/api/v4/projects/{{ $json.projectId }}/variables",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"key\": \"GITLAB_TOKEN\",\n  \"value\": \"{{ $('Workflow Configuration').first().json.apiToken }}\",\n  \"masked\": true,\n  \"protected\": true,\n  \"environment_scope\": \"*\"\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "4d5f41e1-088d-4bc6-8155-2cd5755058f7",
      "name": "Set Username env var",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        4800,
        -80
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.gitlabUrl }}/api/v4/projects/{{ $('set ProjectId').item.json.projectId }}/variables",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"key\": \"GITLAB_USERNAME\",\n  \"value\": \"{{ $('Workflow Configuration').first().json.user }}\",\n  \"masked\": false,\n  \"protected\": false,\n  \"environment_scope\": \"*\"\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "26f9a830-821a-44eb-89c9-49a2f41fde29",
      "name": "Set Year env var",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        5024,
        -80
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.gitlabUrl }}/api/v4/projects/{{ $('set ProjectId').item.json.projectId }}/variables\n",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"key\": \"GITLAB_YEAR\",\n  \"value\": \"2025\",\n  \"masked\": false,\n  \"protected\": false,\n  \"environment_scope\": \"*\"\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "82137f38-5ea2-43e1-831c-9c932c83d541",
      "name": "Trigger Pipeline",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5248,
        -80
      ],
      "parameters": {
        "url": "=https://gitlab.com/api/v4/projects/{{ $('set ProjectId').item.json.projectId }}/pipeline?ref=main\n",
        "method": "POST",
        "options": {},
        "jsonBody": "={}\n\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "740583df-1b32-432f-ac64-1170c3b62261",
      "name": "Search Existing Fork",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        3904,
        16
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.gitlabUrl }}/api/v4/projects?owned=true&search=gitlab-wrapped",
        "options": {},
        "jsonBody": "={\n  \"key\": \"GITLAB_TOKEN\",\n  \"value\": \"{{ $('Workflow Configuration').first().json.apiToken }}\",\n  \"masked\": true,\n  \"protected\": true,\n  \"environment_scope\": \"*\"\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "c282e0d5-d6e4-4cae-80a6-c72374c53e5e",
      "name": "Try to fork",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        3904,
        -176
      ],
      "parameters": {
        "url": "https://gitlab.com/api/v4/projects/michaelangelorivera%2Fgitlab-wrapped/fork",
        "method": "POST",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.token }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "c581d68c-3cc4-4dbf-85ca-0e814b4497ed",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        4128,
        -80
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "a0b6d183-78b7-46ae-a4d5-5b798838aa86",
      "name": "set ProjectId",
      "type": "n8n-nodes-base.code",
      "position": [
        4352,
        -80
      ],
      "parameters": {
        "jsCode": "return [{projectId: $('Search Existing Fork').first().json.id}]"
      },
      "typeVersion": 2
    },
    {
      "id": "4ac34498-8995-486f-a39d-aa4210328b63",
      "name": "Validate PAT Owner",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        3456,
        -176
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.gitlabUrl }}/api/v4/user/",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "PRIVATE-TOKEN",
              "value": "={{ $('Workflow Configuration').first().json.apiToken }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "9d3928ea-ba95-478f-a764-55c47cdd0578",
      "name": "Is PAT Owner invalid?",
      "type": "n8n-nodes-base.if",
      "position": [
        3680,
        -176
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.username }}",
              "rightValue": "={{ $('Workflow Configuration').item.json.user }}"
            },
            {
              "id": "ef14cc76-f887-4ba1-a1de-818fb1500ba8",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b2b2f532-f906-4e23-ad26-bcc0a5a3710a",
      "name": "No Operation, to not leak private Projects",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3840,
        -512
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ef29d97b-77f3-4c1e-822b-05aab38763a9",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2528,
        -720
      ],
      "parameters": {
        "color": 4,
        "width": 400,
        "height": 820,
        "content": "### How it works\nThis workflow generates your personalized GitLab Wrapped, a year-in-review of your GitLab contributions.\n\nPowered by https://gitlab.com/michaelangelorivera/gitlab-wrapped by https://gitlab.com/michaelangelorivera\n\nWhen you submit the form, the workflow:\n1. Checks that the PAT does NOT belong to the username you entered. If they DO match, the workflow stops to prevent unauthorized access to private projects.\n2. Forks (or finds your existing fork of) the gitlab-wrapped project\n3. Configures CI/CD variables with your credentials and settings\n4. Triggers the GitLab pipeline to generate your wrapped report\n5. Monitors the pipeline until completion\n\n### Setup steps\n1. **Create a GitLab PAT** with `api`, `read_repository`, and `write_repository` scopes\n2. Fill in the form with:\n   - Your GitLab username\n   - Your PAT token\n   - GitLab instance URL (default: https://gitlab.com)\n   - Year for your wrapped report\n\n**\ud83c\udf89 Your wrapped will be available at:**\n**`https://YOUR-USERNAME.gitlab.io/gitlab-wrapped`**\n\nReplace `YOUR-USERNAME` with your GitLab username.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "dbbda209-5390-4517-9e61-61e1a60c04ac",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2992,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 340,
        "height": 140,
        "content": "## \ud83d\udccb Form Input\nCollects user credentials and preferences to generate the wrapped report."
      },
      "typeVersion": 1
    },
    {
      "id": "1a562656-c126-4e87-8f47-cc3264996f01",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3488,
        -336
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 140,
        "content": "## \ud83d\udd10 Security Validation\nEnsures the PAT token does not belong to the specified user to prevent unauthorized access to private projects."
      },
      "typeVersion": 1
    },
    {
      "id": "78f6dc4b-2c55-48fa-8545-790ffda55d91",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3824,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 308,
        "height": 120,
        "content": "## \ud83c\udf74 Fork Setup\nCreates or finds your fork of the gitlab-wrapped project to run the generation pipeline."
      },
      "typeVersion": 1
    },
    {
      "id": "b67d65ba-dbed-4ef5-a877-ec9dc892680b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4624,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 540,
        "height": 140,
        "content": "## \u2699\ufe0f CI/CD Configuration\nConfigures environment variables in your fork to pass settings to the pipeline."
      },
      "typeVersion": 1
    },
    {
      "id": "86a72ddd-6207-4d79-b8f1-52919305fe68",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5504,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 104,
        "content": "## \ud83d\ude80 Pipeline Execution\nTriggers the wrapped generation pipeline and monitors it until completion (polls every 2 minutes)."
      },
      "typeVersion": 1
    },
    {
      "id": "5a1e5e5d-c397-492c-aeb2-130dc2583bf4",
      "name": "Wrapped available at https://YOUR_USERNAME.gitlab.io/gitlab-wrapped",
      "type": "n8n-nodes-base.noOp",
      "position": [
        6144,
        -80
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6a2a807d-e0ce-4b3e-b0c7-629c9f33016a",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "set ProjectId",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Try to fork": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "set ProjectId": {
      "main": [
        [
          {
            "node": "Set token env var",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for CI/CD": {
      "main": [
        [
          {
            "node": "Check Pipeline Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Year env var": {
      "main": [
        [
          {
            "node": "Trigger Pipeline",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Pipeline": {
      "main": [
        [
          {
            "node": "Wait for CI/CD",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set token env var": {
      "main": [
        [
          {
            "node": "Set Username env var",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pipeline Complete?": {
      "main": [
        [
          {
            "node": "Wrapped available at https://YOUR_USERNAME.gitlab.io/gitlab-wrapped",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for CI/CD",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate PAT Owner": {
      "main": [
        [
          {
            "node": "Is PAT Owner invalid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitLab Wrapped Form": {
      "main": [
        [
          {
            "node": "Workflow Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Existing Fork": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Set Username env var": {
      "main": [
        [
          {
            "node": "Set Year env var",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Pipeline Status": {
      "main": [
        [
          {
            "node": "Pipeline Complete?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is PAT Owner invalid?": {
      "main": [
        [
          {
            "node": "No Operation, to not leak private Projects",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Search Existing Fork",
            "type": "main",
            "index": 0
          },
          {
            "node": "Try to fork",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Configuration": {
      "main": [
        [
          {
            "node": "Validate PAT Owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

✨ Automatically generate your personalized GitLab Wrapped, a stunning year-in-review of your contributions, activity, and stats.

Source: https://n8n.io/workflows/12394/ — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

This workflow allows you to import any workflow from a file or another n8n instance and map the credentials easily. A multi-form setup guides you through the entire process At the beginning you have t

Execute Command, Read Write File, HTTP Request +3
Web Scraping

[n8n] Advanced URL Parsing and Shortening Workflow - Switchy.io Integration. Uses splitInBatches, stickyNote, httpRequest, html. Event-driven trigger; 56 nodes.

HTTP Request, GitHub, Stop And Error +1
Web Scraping

[](https://youtu.be/c7yCZhmMjtI)

HTTP Request, GitHub, Stop And Error +1
Web Scraping

N8n recently introduced folders and it has been a big improvement on workflow management on top of the tags.

HTTP Request, n8n, Form Trigger +1
Web Scraping

This workflow automates the creation of press releases for music artists releasing a new single. Upload your MP3, fill in basic info, and receive a publication-ready press release saved as a Google Do

Form Trigger, HTTP Request, Google Docs