From 91b90ea5501ed49140e0018a03374a0947af8064 Mon Sep 17 00:00:00 2001 From: ddjain Date: Thu, 30 Oct 2025 10:44:46 +0530 Subject: [PATCH 1/2] feat(rule): add infra-change detection (closes #15) --- __tests__/infrastructure/infra-change.test.js | 23 ++++++++++ src/rules/infrastructure/infra-change.js | 45 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 __tests__/infrastructure/infra-change.test.js create mode 100644 src/rules/infrastructure/infra-change.js diff --git a/__tests__/infrastructure/infra-change.test.js b/__tests__/infrastructure/infra-change.test.js new file mode 100644 index 0000000..f40fc8c --- /dev/null +++ b/__tests__/infrastructure/infra-change.test.js @@ -0,0 +1,23 @@ +const rule = require('../../src/rules/infrastructure/infra-change'); + +describe('Infra Change Rule', () => { + it('labels for terraform files', () => { + const files = [{ filename: 'infra/main.tf' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('labels for docker-compose', () => { + const files = [{ filename: 'docker-compose.yml' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('does not label for app code', () => { + const files = [{ filename: 'src/app.js' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toEqual([]); + }); +}); + + diff --git a/src/rules/infrastructure/infra-change.js b/src/rules/infrastructure/infra-change.js new file mode 100644 index 0000000..3b8c0cf --- /dev/null +++ b/src/rules/infrastructure/infra-change.js @@ -0,0 +1,45 @@ +/** + * Infrastructure Config Change Rule + * + * Adds `infra-change` if infra-related files are modified. + */ + +module.exports = function infraChangeRule({ files, pr, enableDebug }) { + const labels = []; + + const hints = [ + /^(infra|infrastructure|ops|deploy|deployment|k8s|helm|charts|terraform|ansible|chef|salt)\//i, + /^config\//i, + /\.(tf|tfvars|hcl|tpl)$/i, + /(^|\/)Dockerfile(\.|$)/i, + /(^|\/)docker-compose\.(ya?ml)$/i + ]; + + const detected = (files || []).some(f => { + const name = (f && f.filename ? String(f.filename) : '').toLowerCase(); + return name && hints.some(rx => rx.test(name)); + }); + + if (detected) { + labels.push('infra-change'); + } + + if (enableDebug) { + console.log(`[Infra Change Rule] → ${labels.join(', ') || 'none'}`); + } + + return labels; +}; + +module.exports.metadata = { + name: 'Infrastructure Config Changes', + description: 'Detects changes to infrastructure/configuration files', + labels: [ + { name: 'infra-change', color: '0075CA', description: 'Infrastructure/config changed' } + ], + author: 'pr-auto-labeler', + version: '1.0.0', + category: 'infrastructure' +}; + + From f6975b3ad9e0c3013ecb4033ff537f6e68f00b83 Mon Sep 17 00:00:00 2001 From: ddjain Date: Thu, 30 Oct 2025 12:08:06 +0530 Subject: [PATCH 2/2] test: improve infra-change coverage to 85%+ --- __tests__/infrastructure/infra-change.test.js | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/__tests__/infrastructure/infra-change.test.js b/__tests__/infrastructure/infra-change.test.js index f40fc8c..72e560b 100644 --- a/__tests__/infrastructure/infra-change.test.js +++ b/__tests__/infrastructure/infra-change.test.js @@ -7,17 +7,73 @@ describe('Infra Change Rule', () => { expect(labels).toContain('infra-change'); }); + it('labels for terraform variables', () => { + const files = [{ filename: 'terraform/vars.tfvars' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('labels for HCL files', () => { + const files = [{ filename: 'config/setup.hcl' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + it('labels for docker-compose', () => { const files = [{ filename: 'docker-compose.yml' }]; const labels = rule({ files, pr: {}, enableDebug: false }); expect(labels).toContain('infra-change'); }); + it('labels for Dockerfile', () => { + const files = [{ filename: 'services/Dockerfile' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('labels for infra directory', () => { + const files = [{ filename: 'infrastructure/setup.yaml' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('labels for k8s directory', () => { + const files = [{ filename: 'k8s/deployment.yaml' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('labels for helm charts', () => { + const files = [{ filename: 'charts/app/values.yaml' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + + it('labels for config directory', () => { + const files = [{ filename: 'config/production.yml' }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toContain('infra-change'); + }); + it('does not label for app code', () => { const files = [{ filename: 'src/app.js' }]; const labels = rule({ files, pr: {}, enableDebug: false }); expect(labels).toEqual([]); }); -}); + it('handles empty files array', () => { + const labels = rule({ files: [], pr: {}, enableDebug: false }); + expect(labels).toEqual([]); + }); + it('handles null filename', () => { + const files = [{ filename: null }]; + const labels = rule({ files, pr: {}, enableDebug: false }); + expect(labels).toEqual([]); + }); + + it('handles debug mode', () => { + const files = [{ filename: 'infra/main.tf' }]; + expect(() => rule({ files, pr: {}, enableDebug: true })).not.toThrow(); + }); +});