This workflow corresponds to n8n.io template #daily-maintenance — we link there as the canonical source.
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 →
{
"name": "Daily Maintenance - Scheduled Quality Checks",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24,
"triggerAtHour": 8
}
]
}
},
"id": "schedule-trigger",
"name": "Daily Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
250,
300
]
},
{
"parameters": {
"jsCode": "// Configuration - Update these for your repository\nconst config = {\n owner: $env.GITHUB_OWNER || 'YOUR_USERNAME',\n repo: $env.GITHUB_REPO || 'YOUR_REPO',\n checks: {\n phpcs: true,\n dependencies: true,\n coverage: true\n }\n};\n\nreturn {\n json: {\n config,\n started_at: new Date().toISOString(),\n checks_to_run: Object.entries(config.checks)\n .filter(([_, enabled]) => enabled)\n .map(([name]) => name)\n }\n};"
},
"id": "init-config",
"name": "Initialize Config",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
470,
300
]
},
{
"parameters": {
"batchSize": 1,
"options": {}
},
"id": "split-checks",
"name": "Split Checks",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
690,
300
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.checks_to_run[$json.currentIndex] }}",
"operation": "equals",
"value2": "phpcs"
}
]
}
},
"id": "route-phpcs",
"name": "Is PHPCS?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
910,
200
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.checks_to_run[$json.currentIndex] }}",
"operation": "equals",
"value2": "dependencies"
}
]
}
},
"id": "route-deps",
"name": "Is Dependencies?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
910,
400
]
},
{
"parameters": {
"jsCode": "// Simulate PHPCS check results\n// In production, this would call a GitHub Action or SSH to server\n\nconst config = $input.first().json.config;\n\n// Mock PHPCS results - replace with actual check\nconst phpcsResults = {\n check_type: 'phpcs',\n tier: 'T1',\n label: 'routine',\n tool: 'Copilot',\n violations: [\n {\n file: 'includes/class-example.php',\n line: 42,\n message: 'Missing PHPDoc for function',\n severity: 'warning'\n }\n ],\n total_violations: 1,\n status: 'violations_found'\n};\n\n// Return empty if no violations\nif (phpcsResults.violations.length === 0) {\n return { json: { ...phpcsResults, status: 'clean', skip_issue: true } };\n}\n\nreturn {\n json: {\n ...phpcsResults,\n config,\n issue_title: `[T1] Fix ${phpcsResults.total_violations} PHPCS violation(s)`,\n issue_body: `## PHPCS Violations Detected\\n\\n**Total**: ${phpcsResults.total_violations} violation(s)\\n\\n### Violations\\n\\n${phpcsResults.violations.map(v => \n \\`- \\\\\\`${v.file}:${v.line}\\\\\\` - ${v.message} (${v.severity})\\`\n ).join('\\n')}\\n\\n## Recommended Action\\n\\nUse **Copilot** to fix these violations:\\n\\n1. Open each file in your editor\\n2. Use Copilot to suggest fixes\\n3. Run \\\\\\`composer phpcs\\\\\\` to verify\\n\\n---\\n*Generated by n8n daily maintenance*`\n }\n};"
},
"id": "check-phpcs",
"name": "Run PHPCS Check",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1130,
100
]
},
{
"parameters": {
"jsCode": "// Simulate dependency check results\n// In production, this would call npm outdated or composer outdated\n\nconst config = $input.first().json.config;\n\n// Mock outdated deps - replace with actual check\nconst depResults = {\n check_type: 'dependencies',\n tier: 'T2',\n label: 'analytical',\n tool: 'Cursor/ChatGPT',\n outdated: [\n {\n package: 'example/package',\n current: '1.0.0',\n latest: '2.0.0',\n type: 'composer'\n }\n ],\n total_outdated: 1,\n status: 'outdated_found'\n};\n\n// Return empty if all up to date\nif (depResults.outdated.length === 0) {\n return { json: { ...depResults, status: 'up_to_date', skip_issue: true } };\n}\n\nreturn {\n json: {\n ...depResults,\n config,\n issue_title: `[T2] Review ${depResults.total_outdated} outdated dependency(ies)`,\n issue_body: `## Outdated Dependencies Detected\\n\\n**Total**: ${depResults.total_outdated} package(s) need review\\n\\n### Packages\\n\\n| Package | Current | Latest | Type |\\n|---------|---------|--------|------|\\n${depResults.outdated.map(d => \n \\`| ${d.package} | ${d.current} | ${d.latest} | ${d.type} |\\`\n ).join('\\n')}\\n\\n## Recommended Action\\n\\nUse **Cursor/ChatGPT** to analyze:\\n\\n1. Check changelogs for breaking changes\\n2. Review compatibility with WordPress version\\n3. Test in staging environment\\n4. Update if safe\\n\\n---\\n*Generated by n8n daily maintenance*`\n }\n};"
},
"id": "check-deps",
"name": "Run Dependency Check",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1130,
300
]
},
{
"parameters": {
"jsCode": "// Simulate coverage check results\n// In production, this would parse coverage reports\n\nconst config = $input.first().json.config;\n\n// Mock coverage results - replace with actual check\nconst coverageResults = {\n check_type: 'coverage',\n tier: 'T2',\n label: 'analytical',\n tool: 'Cursor/ChatGPT',\n current_coverage: 45.2,\n previous_coverage: 48.5,\n coverage_change: -3.3,\n uncovered_files: [\n 'includes/class-new-feature.php',\n 'includes/helpers.php'\n ],\n status: 'coverage_dropped'\n};\n\n// Return empty if coverage is stable or improved\nif (coverageResults.coverage_change >= 0) {\n return { json: { ...coverageResults, status: 'coverage_stable', skip_issue: true } };\n}\n\nreturn {\n json: {\n ...coverageResults,\n config,\n issue_title: `[T2] Investigate test coverage drop (${coverageResults.coverage_change.toFixed(1)}%)`,\n issue_body: `## Test Coverage Dropped\\n\\n| Metric | Value |\\n|--------|-------|\\n| Previous | ${coverageResults.previous_coverage}% |\\n| Current | ${coverageResults.current_coverage}% |\\n| Change | ${coverageResults.coverage_change.toFixed(1)}% |\\n\\n### Uncovered Files\\n\\n${coverageResults.uncovered_files.map(f => \\`- \\\\\\`${f}\\\\\\`\\`).join('\\n')}\\n\\n## Recommended Action\\n\\nUse **Cursor/ChatGPT** to analyze:\\n\\n1. Identify which changes reduced coverage\\n2. Determine if new code needs tests\\n3. Create T1 tasks for test writing\\n\\n---\\n*Generated by n8n daily maintenance*`\n }\n};"
},
"id": "check-coverage",
"name": "Run Coverage Check",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1130,
500
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.skip_issue }}",
"value2": true
}
]
}
},
"id": "filter-skip",
"name": "Has Issues?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1350,
300
]
},
{
"parameters": {
"authentication": "oAuth2",
"resource": "issue",
"operation": "create",
"owner": "={{ $json.config.owner }}",
"repository": "={{ $json.config.repo }}",
"title": "={{ $json.issue_title }}",
"body": "={{ $json.issue_body }}",
"labels": [
"={{ $json.tier.toLowerCase() }}",
"maintenance"
]
},
"id": "create-issue",
"name": "Create GitHub Issue",
"type": "n8n-nodes-base.github",
"typeVersion": 1,
"position": [
1570,
200
],
"credentials": {
"githubOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Collect all results for summary\nconst items = $input.all();\n\nconst summary = {\n completed_at: new Date().toISOString(),\n checks_run: items.length,\n issues_created: items.filter(i => !i.json.skip_issue).length,\n issues_skipped: items.filter(i => i.json.skip_issue).length,\n details: items.map(i => ({\n check: i.json.check_type,\n status: i.json.status,\n issue_created: !i.json.skip_issue\n }))\n};\n\nreturn { json: summary };"
},
"id": "summarize",
"name": "Summarize Results",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1790,
300
]
},
{
"parameters": {},
"id": "no-op-skip",
"name": "Skip (No Issues)",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
1570,
400
]
}
],
"connections": {
"Daily Schedule": {
"main": [
[
{
"node": "Initialize Config",
"type": "main",
"index": 0
}
]
]
},
"Initialize Config": {
"main": [
[
{
"node": "Split Checks",
"type": "main",
"index": 0
}
]
]
},
"Split Checks": {
"main": [
[
{
"node": "Is PHPCS?",
"type": "main",
"index": 0
},
{
"node": "Is Dependencies?",
"type": "main",
"index": 0
}
]
]
},
"Is PHPCS?": {
"main": [
[
{
"node": "Run PHPCS Check",
"type": "main",
"index": 0
}
],
[
{
"node": "Run Coverage Check",
"type": "main",
"index": 0
}
]
]
},
"Is Dependencies?": {
"main": [
[
{
"node": "Run Dependency Check",
"type": "main",
"index": 0
}
]
]
},
"Run PHPCS Check": {
"main": [
[
{
"node": "Has Issues?",
"type": "main",
"index": 0
}
]
]
},
"Run Dependency Check": {
"main": [
[
{
"node": "Has Issues?",
"type": "main",
"index": 0
}
]
]
},
"Run Coverage Check": {
"main": [
[
{
"node": "Has Issues?",
"type": "main",
"index": 0
}
]
]
},
"Has Issues?": {
"main": [
[
{
"node": "Skip (No Issues)",
"type": "main",
"index": 0
}
],
[
{
"node": "Create GitHub Issue",
"type": "main",
"index": 0
}
]
]
},
"Create GitHub Issue": {
"main": [
[
{
"node": "Summarize Results",
"type": "main",
"index": 0
}
]
]
},
"Skip (No Issues)": {
"main": [
[
{
"node": "Summarize Results",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"meta": {
"templateId": "daily-maintenance"
},
"tags": [
{
"name": "tiered-agents"
},
{
"name": "maintenance"
},
{
"name": "scheduled"
}
]
}
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.
githubOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
Ensure your codebase remains robust and error-free with automated daily quality checks that run essential scans on your GitHub repositories, saving developers hours of manual oversight and preventing small issues from escalating. This workflow is ideal for software teams maintaining PHP projects, where consistent code hygiene boosts reliability and speeds up deployments. It kicks off on a scheduled trigger each day, then branches to execute targeted checks like PHPCS for coding standards, dependency audits, and test coverage analysis, all integrated seamlessly with GitHub for repository access and results logging.
Use this workflow for routine maintenance in active development environments, particularly when your team relies on GitHub for version control and needs proactive issue detection without constant monitoring. Avoid it for non-PHP codebases or infrequent updates, as the specialised checks won't apply effectively. Common variations include adjusting the cron schedule for weekly runs or adding notifications via email for failed checks to alert the team immediately.
About this workflow
Daily Maintenance - Scheduled Quality Checks. Uses github. Scheduled trigger; 12 nodes.
Source: https://github.com/courtneyr-dev/wp-dev-prompts/blob/3513351d4837bca7008f7a37d2a2a5c0f3c18401/templates/n8n/daily-maintenance.json — 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.
Who is this for? This template is ideal for n8n administrators, automation engineers, and DevOps teams who want to maintain bidirectional synchronization between their n8n workflows and GitHub reposit
Display Project Data On A Smashing Dashboard. Uses httpRequest, github. Scheduled trigger; 24 nodes.
This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.
Automatically back up and sync your n8n workflows to GitHub with unlimited version control. This workflow ensures your repository always reflects the latest state of your n8n instance by creating, upd