This workflow corresponds to n8n.io template #7985 — we link there as the canonical source.
This workflow follows the Google Sheets → 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 →
{
"id": "Ozg0c8uxCru2a79p",
"name": "Catalog Android (Kotlin/Java) feature flags and sweep dead flags vs LaunchDarkly (weekly) \u2192 Sheets + Jira + PR + Slack",
"tags": [],
"nodes": [
{
"id": "edcaa1e6-4fd2-4b06-93b5-b9219bbba407",
"name": "Check Dead Flags",
"type": "n8n-nodes-base.if",
"position": [
40,
1680
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{$json.deadFlag !== undefined}}",
"operation": "notEqual"
}
]
}
},
"typeVersion": 1
},
{
"id": "e603fbcb-275a-4356-acbf-d70a219f975c",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-420,
1360
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtHour": 10
}
]
}
},
"typeVersion": 1.2
},
{
"id": "70dfcf7f-3d82-44d6-9ea2-ef550b5496f4",
"name": "GitLab",
"type": "n8n-nodes-base.gitlab",
"position": [
-200,
1360
],
"parameters": {
"owner": "",
"resource": "",
"operation": "",
"repository": "",
"authentication": ""
},
"credentials": {
"gitlabOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "13799fe3-a8d0-4dc2-924f-a5c53c17dea5",
"name": "Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
-180,
1680
],
"parameters": {
"sheetName": {
"__rl": true,
"mode": "list",
"value": ""
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "958b3c35-f1ea-4ef4-8c7c-3a69869e4eb1",
"name": "Slack",
"type": "n8n-nodes-base.slack",
"position": [
260,
1760
],
"parameters": {
"otherOptions": {}
},
"typeVersion": 2.3
},
{
"id": "ecc1b21c-e3b0-40ae-9e21-9b09f69db3cf",
"name": "Jira Software",
"type": "n8n-nodes-base.jira",
"position": [
260,
1600
],
"parameters": {
"project": {
"__rl": true,
"mode": "list",
"value": ""
},
"summary": "=Dead feature flag: {{$json.deadFlag}}",
"issueType": {
"__rl": true,
"mode": "list",
"value": ""
},
"additionalFields": {}
},
"typeVersion": 1
},
{
"id": "566e7571-2423-4e4b-9edf-dea23b9e8fae",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
240,
1360
],
"parameters": {
"url": "https://app.launchdarkly.com/api/v2/flags/default",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "",
"value": ""
}
]
}
},
"typeVersion": 4.2,
"alwaysOutputData": false
},
{
"id": "afb07c42-6687-423b-9ccb-739768aa0c4f",
"name": "Find dead flags",
"type": "n8n-nodes-base.code",
"position": [
-420,
1680
],
"parameters": {
"jsCode": "// 1. Extract LaunchDarkly flags array from input\nconst ldItems = $input.all()[0]?.json?.items || [];\n\n// 2. Extract code flags from another input node named 'Code Flags'\nconst codeFlags = $('Detect flags').all().map(item => item.json.flag);\n\n// 3. Filter dead flags from LD\nconst deadFlags = ldItems.filter(ldFlag => {\n const isUsedInCode = codeFlags.includes(ldFlag.key);\n\n if (isUsedInCode) return false;\n\n const prod = ldFlag.environments?.production || {};\n const test = ldFlag.environments?.test || {};\n\n const archivedEverywhere = prod.archived && test.archived;\n const offInProd = prod.on === false;\n\n return archivedEverywhere || offInProd;\n});\n\n// 4. Return as array\nreturn deadFlags.map(flag => ({\n json: {\n deadFlag: flag.key,\n reason: flag.environments?.production?.archived\n ? 'Archived'\n : 'Off in Production'\n }\n}));\n"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "75abe5e7-051f-4b87-8329-d10d87ce2b93",
"name": "Detect flags",
"type": "n8n-nodes-base.code",
"position": [
20,
1360
],
"parameters": {
"jsCode": "const pattern = /(ENABLE_[A-Z0-9_]+)/g;\nconst flags = new Set();\n\nfor (const item of $input.all()) {\n const content = item.json.content || ''; // Assumes content was previously fetched\n let match;\n while ((match = pattern.exec(content)) !== null) {\n flags.add(match[1]);\n }\n}\n\nreturn Array.from(flags).map(flag => ({ json: { flag } }));"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "82ee43c2-85c4-4e36-b0ca-0c848266c6de",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1020,
1240
],
"parameters": {
"width": 500,
"height": 700,
"content": "**Purpose:**\nAutomatically find unused (\u201cdead\u201d) feature flags in an Android Kotlin/Java codebase and notify the team.\n\n**Core Logic:**\n\n1. **Weekly trigger** runs the check.\n2. **GitLab** \u2192 fetch code & extract used flags.\n3. **LaunchDarkly API** \u2192 fetch all flags & statuses.\n4. Compare lists \u2192 identify flags not in code and either archived or off in production.\n5. Save results to **Google Sheets**.\n6. If dead flags found \u2192 create **Jira tickets** + send **Slack alerts**.\n\n\n**Outcome:**\nKeeps feature flags clean, reduces technical debt, and informs the team automatically.\n"
},
"typeVersion": 1
},
{
"id": "ce6edc27-0f97-45a9-b36d-ad294963cfac",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-500,
1240
],
"parameters": {
"color": 4,
"width": 960,
"height": 700,
"content": "## Catalog Android (Kotlin/Java) feature flags and sweep dead flags vs LaunchDarkly (weekly) \u2192 Sheets + Jira + PR + Slack"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "97e8bc6b-a717-4a64-a148-620c2991a8fc",
"connections": {
"GitLab": {
"main": [
[
{
"node": "Detect flags",
"type": "main",
"index": 0
}
]
]
},
"Detect flags": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Find dead flags",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets": {
"main": [
[
{
"node": "Check Dead Flags",
"type": "main",
"index": 0
}
]
]
},
"Find dead flags": {
"main": [
[
{
"node": "Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Check Dead Flags": {
"main": [
[
{
"node": "Jira Software",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "GitLab",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gitlabOAuth2ApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n automation detects unused (“dead”) feature flags in an Android Kotlin/Java codebase by comparing your GitLab repository code against LaunchDarkly’s feature flag list.
Source: https://n8n.io/workflows/7985/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Simplify financial oversight with this automated n8n workflow. Triggered daily, it fetches cash flow and expense data from a Google Sheet, analyzes inflows and outflows, validates records, and generat
Use cases are many: send recurring market updates to investors, distribute new listings context to buyers, or push periodic area snapshots to your client base — all without touching it manually after
Automated garden and farm irrigation system that uses weather forecasts and evapotranspiration calculations to determine optimal watering schedules, preventing water waste while maintaining healthy pl
This workflow automatically monitors competitor affiliate programs twice daily using Bright Data's web scraping API to extract commission rates, cookie durations, average order values, and payout term