{
  "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
          }
        ]
      ]
    }
  }
}