From 658e3e3126e50bbceae38826f17e4158d2ec7055 Mon Sep 17 00:00:00 2001 From: Brad Abrams Date: Tue, 14 May 2024 15:36:30 -0400 Subject: [PATCH 1/4] decompose unit tests, patch sync for environments --- lib/plugins/environments.js | 84 +- test/unit/lib/plugins/environments.test.js | 911 +++++++++++++++------ 2 files changed, 753 insertions(+), 242 deletions(-) diff --git a/lib/plugins/environments.js b/lib/plugins/environments.js index 3435388e..299f3407 100644 --- a/lib/plugins/environments.js +++ b/lib/plugins/environments.js @@ -1,4 +1,5 @@ const Diffable = require('./diffable') +const MergeDeep = require('../mergeDeep') module.exports = class Environments extends Diffable { constructor(...args) { @@ -78,7 +79,7 @@ module.exports = class Environments extends Diffable { const wait_timer = existing.wait_timer !== attrs.wait_timer; const prevent_self_review = existing.prevent_self_review !== attrs.prevent_self_review; const reviewers = JSON.stringify(existing.reviewers.sort((x1, x2) => x1.id - x2.id)) !== JSON.stringify(attrs.reviewers.sort((x1, x2) => x1.id - x2.id)); - + let existing_custom_branch_policies = existing.deployment_branch_policy === null ? null : existing.deployment_branch_policy.custom_branch_policies; if(typeof(existing_custom_branch_policies) === 'object' && existing_custom_branch_policies !== null) { existing_custom_branch_policies = existing_custom_branch_policies.sort(); @@ -243,7 +244,7 @@ module.exports = class Environments extends Diffable { }); } } - + for(let variable of attrs.variables) { await this.github.request(`POST /repos/:org/:repo/environments/:environment_name/variables`, { @@ -272,4 +273,81 @@ module.exports = class Environments extends Diffable { environment_name: existing.name }); } -} \ No newline at end of file + + sync () { + const resArray = [] + if (this.entries) { + let filteredEntries = this.filterEntries() + // this.log.debug(`filtered entries are ${JSON.stringify(filteredEntries)}`) + return this.find().then(existingRecords => { + this.log.debug(` ${JSON.stringify(existingRecords, null, 2)} \n\n ${JSON.stringify(filteredEntries, null, 2)} `) + + // Filter out all empty entries (usually from repo override) + for (const entry of filteredEntries) { + for (const key of Object.keys(entry)) { + if (entry[key] === null || entry[key] === undefined) { + delete entry[key] + } + } + } + filteredEntries = filteredEntries.filter(entry => Object.keys(entry).filter(key => !MergeDeep.NAME_FIELDS.includes(key)).length !== 0) + + const changes = [] + + existingRecords.forEach(x => { + if (!filteredEntries.find(y => this.comparator(x, y))) { + const change = this.remove(x).then(res => { + if (this.nop) { + return resArray.push(res) + } + return res + }) + changes.push(change) + } + }) + + filteredEntries.forEach(attrs => { + const existing = existingRecords.find(record => { + return this.comparator(record, attrs) + }) + + if (!existing) { + const change = this.add(attrs).then(res => { + if (this.nop) { + return resArray.push(res) + } + return res + }) + changes.push(change) + } else if (this.changed(existing, attrs)) { + const change = this.update(existing, attrs).then(res => { + if (this.nop) { + return resArray.push(res) + } + return res + }) + changes.push(change) + } + }) + + if (this.nop) { + return Promise.resolve(resArray) + } + return Promise.all(changes) + }).catch(e => { + if (this.nop) { + if (e.status === 404) { + // Ignore 404s which can happen in dry-run as the repo may not exist. + return Promise.resolve(resArray) + } else { + resArray.push(new NopCommand(this.constructor.name, this.repo, null, `error ${e} in ${this.constructor.name} for repo: ${JSON.stringify(this.repo)} entries ${JSON.stringify(this.entries)}`, 'ERROR')) + return Promise.resolve(resArray) + } + } else { + this.logError(`Error ${e} in ${this.constructor.name} for repo: ${JSON.stringify(this.repo)} entries ${JSON.stringify(this.entries)}`) + } + }) + } + } + +} diff --git a/test/unit/lib/plugins/environments.test.js b/test/unit/lib/plugins/environments.test.js index e826e005..e7e214df 100644 --- a/test/unit/lib/plugins/environments.test.js +++ b/test/unit/lib/plugins/environments.test.js @@ -1,274 +1,707 @@ const { when } = require('jest-when') const Environments = require('../../../../lib/plugins/environments') -describe('Environments', () => { - let github - const org = 'bkeepers' - const repo = 'test' - - function fillEnvironment(attrs) { - if (!attrs.wait_timer) attrs.wait_timer = 0; - if (!attrs.prevent_self_review) attrs.prevent_self_review = false; - if (!attrs.reviewers) attrs.reviewers = []; - if (!attrs.deployment_branch_policy) attrs.deployment_branch_policy = null; - if(!attrs.variables) attrs.variables = []; - if(!attrs.deployment_protection_rules) attrs.deployment_protection_rules = []; - if(!attrs.protection_rules) attrs.protection_rules = []; - - return attrs; +describe('Environments Plugin test suite', () => { + let github + let environment_name = '' + const org = 'bkeepers' + const repo = 'test' + const AllEnvironmentNamesBeingTested = ['wait-timer_environment', 'wait-timer_2_environment', 'reviewers_environment', 'prevent-self-review_environment', 'deployment-branch-policy_environment', 'deployment-branch-policy-custom_environment', 'variables_environment', 'deployment-protection-rules_environment'] + const log = jest.fn() + log.debug = jest.fn() + log.error = jest.fn() + + function fillEnvironment(attrs) { + if (!attrs.wait_timer) attrs.wait_timer = 0; + if (!attrs.prevent_self_review) attrs.prevent_self_review = false; + if (!attrs.reviewers) attrs.reviewers = []; + if (!attrs.deployment_branch_policy) attrs.deployment_branch_policy = null; + if (!attrs.variables) attrs.variables = []; + if (!attrs.deployment_protection_rules) attrs.deployment_protection_rules = []; + if (!attrs.protection_rules) attrs.protection_rules = []; + + return attrs; + } + + beforeEach(() => { + //arrange for all + github = { + request: jest.fn(() => Promise.resolve(true)) + } + + AllEnvironmentNamesBeingTested.forEach((environment_name) => { + when(github.request) + .calledWith('GET /repos/:org/:repo/environments/:environment_name/variables', { org, repo, environment_name }) + .mockResolvedValue({ + data: { + variables: [] + } + }) } + ); - beforeAll(() => { - github = { - request: jest.fn().mockReturnValue(Promise.resolve(true)) + AllEnvironmentNamesBeingTested.forEach((environment_name) => { + when(github.request) + .calledWith('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { org, repo, environment_name }) + .mockResolvedValue({ + data: { + custom_deployment_protection_rules: [] + } + }) + } + ); + + when(github.request) + .calledWith('GET /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { org, repo, environment_name: 'deployment-branch-policy-custom_environment' }) + .mockResolvedValue({ + data: { + branch_policies: [] + } } + ); + + when(github.request) + .calledWith('DELETE /repos/:org/:repo/environments/:environment_name/deployment-branch-policies/:branch_policy_id') + .mockResolvedValue({}); + + when(github.request) + .calledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies') + .mockResolvedValue({}); + + when(github.request) + .calledWith('PUT /repos/:org/:repo/environments/:environment_name') + .mockResolvedValue({}); + + when(github.request) + .calledWith('POST /repos/:org/:repo/environments/:environment_name/variables') + .mockResolvedValue({}); + + when(github.request) + .calledWith('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules') + .mockResolvedValue({}); + + when(github.request) + .calledWith('DELETE /repos/:org/:repo/environments/:environment_name/deployment_protection_rules/:rule_id') + .mockResolvedValue({}); + + }) + + afterEach(() => { + // every test should have included the retrieval of the existing GitHub configuration for the environment, variables, and deployment protection rules. + expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments', { org, repo }); + expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments/:environment_name/variables', { org, repo, environment_name }); + expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { org, repo, environment_name }); + jest.clearAllMocks(); + }); + + // start individual tests + + // wait-timer + describe('When the existing wait-timer is 0 and the config is set to 1', () => { + it('detect divergence and set wait-timer to 1', async () => { + //arrange + environment_name = 'wait-timer_environment' + // represent config with a wait timer of 1 + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + wait_timer: 1 + } + ], { + debug: function () { } + }); + + //model an existing environment with a wait timer of 0 + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + wait_timer: 0 + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update to the wait timer was requested with value 1 + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + wait_timer: 1 + })); + }) }) + }) - it('sync', () => { - const plugin = new Environments(undefined, github, {owner: org, repo}, [ - { - name: 'wait-timer', - wait_timer: 1 - }, + // add reviewers + describe('When there are no existing reviewers and config calls for a user and a team', () => { + it('detect divergence and set reviewers', async () => { + //arrange + environment_name = 'reviewers_environment' + // represent config with a reviewers being a user and a team + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + reviewers: [ { - name: 'reviewers', - reviewers: [ - { + type: 'User', + id: 1 + } + ] + } + ], { + debug: function () { } + }); + + //model an existing environment with no reviewers + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + protection_rules: [ + { + type: 'required_reviewers', + reviewers: [ + { type: 'User', - id: 1 - }, - { - type: 'Team', - id: 2 - } + reviewer: { + id: 56, + type: 'User' + } + } + ] + } ] - }, - { - name: 'prevent-self-review', - prevent_self_review: true - }, + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update the reviewers + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + reviewers: [ { - name: 'deployment-branch-policy', - deployment_branch_policy: { - protected_branches: true, - custom_branch_policies: false - } - }, + type: 'User', + id: 1 + } + ] + })); + }) + }) + }) + + // prevent self review + describe('When prevent self review is false, and the config calls for it to be true', () => { + it('detect divergence and set prevent self review to true', async () => { + //arrange + environment_name = 'prevent-self-review_environment' + // + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + prevent_self_review: true + } + ], { + debug: function () { } + }); + + //model an existing environment with prevent self review false + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + prevent_self_review: false + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update the prevent self review boolean + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + prevent_self_review: true + })); + }) + }) + }) + + // deployment branch policy + describe('When there is no existing deployment branch policy and the config sets a policy', () => { + it('detect divergence and set the deployment branch policy from the config', async () => { + //arrange + environment_name = 'deployment-branch-policy_environment' + // represent config with a reviewers being a user and a team + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + deployment_branch_policy: { + protected_branches: true, + custom_branch_policies: false + } + } + ], { + debug: function () { } + }); + + //model an existing environment with prevent self review false + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + deployment_branch_policy: null + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update branch policy + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + deployment_branch_policy: { + protected_branches: true, + custom_branch_policies: false + } + })); + }) + }) + }) + + // custom deployment branch policy + describe('When there is no existing deployment branch policy and the config sets a custom policy', () => { + it('detect divergence and set the custom deployment branch policy from the config', async () => { + //arrange + environment_name = 'deployment-branch-policy-custom_environment' + // represent config with a custom branch policy + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + deployment_branch_policy: { + protected_branches: false, + custom_branch_policies: [ + 'master', + 'dev' + ] + } + } + ], { + debug: function () { } + }); + + //model an existing environment with no branch policies + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + deployment_branch_policy: null + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update the custom branch policies + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + deployment_branch_policy: { + protected_branches: false, + custom_branch_policies: true + } + })); + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + name: 'master' + })); + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + name: 'dev' + })); + }) + }) + }) + + // add variable + describe('When there are no existing variables and config calls for one', () => { + it('detect divergence and add the variable', async () => { + //arrange + environment_name = 'variables_environment' + // represent config with a reviewers being a user and a team + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + variables: [ { - name: 'deployment-branch-policy-custom', - deployment_branch_policy: { - protected_branches: false, - custom_branch_policies: [ - 'master', - 'dev' - ] - } - }, + name: 'test', + value: 'test' + } + ] + } + ], { + debug: function () { } + }); + + //model an existing environment with no reviewers + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + variables: [] + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update the variables + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/variables', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + name: 'test', + value: 'test' + })); + }) + }) + }) + + // add deployment protection rules + describe('When there are no existing deployment protection rules, but config calls for one', () => { + it('detect divergence and add the deployment protection rule', async () => { + //arrange + environment_name = 'deployment-protection-rules_environment' + // represent config with a deployment protection rule + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + deployment_protection_rules: [ { - name: 'variables', - variables: [ - { - name: 'test', - value: 'test' - } + app_id: 1 + } + ] + } + ], { + debug: function () { } + }); + + //model an existing environment with no deployment protection rules + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + deployment_protection_rules: [] + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update the deployment protection rules + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + integration_id: 1 // weird that this is integration_id, but above it's app_id + })); + }) + }) + }) + + // wait-timer unchanged + describe('When the existing wait-timer is 2 and the config is set to 2', () => { + it('detect that the value is unchanged, and do nothing', async () => { + //arrange + environment_name = 'wait-timer_2_environment' + // represent config with a wait timer of 2 + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: environment_name, + wait_timer: 2 + } + ], { + debug: function () { } + }); + + //model an existing environment with no reviewers + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: environment_name, + protection_rules: [ + { + type: 'wait_timer', + wait_timer: 2 + } ] + }) + ] + } + }); + + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update to the wait timer was requested with value 2 + expect(github.request).not.toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: environment_name, + wait_timer: 2 + })); + }) + }) + }) + + // original 7 changes all combined together test + describe('When there are changes across 7 environments', () => { + it('detect and apply all changes', async () => { + //arrange + environment_name = 'wait-timer_environment' //used in afterEach() + // represent 7 environments and their desired settings + const plugin = new Environments(undefined, github, { owner: org, repo }, [ + { + name: 'wait-timer_environment', + wait_timer: 1 + }, + { + name: 'reviewers_environment', + reviewers: [ + { + type: 'User', + id: 1 }, { - name: 'deployment-protection-rules', - deployment_protection_rules: [ - { - app_id: 1 - } - ] + type: 'Team', + id: 2 } - ], { - debug: function() {} - }); + ] + }, + { + name: 'prevent-self-review_environment', + prevent_self_review: true + }, + { + name: 'deployment-branch-policy_environment', + deployment_branch_policy: { + protected_branches: true, + custom_branch_policies: false + } + }, + { + name: 'deployment-branch-policy-custom_environment', + deployment_branch_policy: { + protected_branches: false, + custom_branch_policies: [ + 'master', + 'dev' + ] + } + }, + { + name: 'variables_environment', + variables: [ + { + name: 'test', + value: 'test' + } + ] + }, + { + name: 'deployment-protection-rules_environment', + deployment_protection_rules: [ + { + app_id: 1 + } + ] + } + ], { + debug: function () { } + }); - when(github.request) - .calledWith('GET /repos/:org/:repo/environments', { org, repo }) - .mockResolvedValue({ - data: { - environments: [ - fillEnvironment({ - name: 'wait-timer', - wait_timer: 0 - }), - fillEnvironment({ - name: 'reviewers', - reviewers: [] - }), - fillEnvironment({ - name: 'prevent-self-review', - prevent_self_review: false - }), - fillEnvironment({ - name: 'deployment-branch-policy', - deployment_branch_policy: null - }), - fillEnvironment({ - name: 'deployment-branch-policy-custom', - deployment_branch_policy: null - }), - fillEnvironment({ - name: 'variables', - variables: [] - }), - fillEnvironment({ - name: 'deployment-protection-rules', - deployment_protection_rules: [] - }) - ] - } - }); - - ['wait-timer', 'reviewers', 'prevent-self-review', 'deployment-branch-policy', 'deployment-branch-policy-custom', 'variables', 'deployment-protection-rules'].forEach((environment_name) => { - when(github.request) - .calledWith('GET /repos/:org/:repo/environments/:environment_name/variables', { org, repo, environment_name }) - .mockResolvedValue({ - data: { - variables: [] - } - }) + // model 7 existing environments and their settings + // note: wait-timer, required_reviewers, and branch_policy are modeled incorrectly here as they are not wrapped by protection_rules[] + // the test succeeds anyway because it so happens that the defaults assigned for missing values, coincidentally match the values below + when(github.request) + .calledWith('GET /repos/:org/:repo/environments', { org, repo }) + .mockResolvedValue({ + data: { + environments: [ + fillEnvironment({ + name: 'wait-timer_environment', + wait_timer: 0 + }), + fillEnvironment({ + name: 'reviewers_environment', + reviewers: [] + }), + fillEnvironment({ + name: 'prevent-self-review_environment', + prevent_self_review: false + }), + fillEnvironment({ + name: 'deployment-branch-policy_environment', + deployment_branch_policy: null + }), + fillEnvironment({ + name: 'deployment-branch-policy-custom_environment', + deployment_branch_policy: null + }), + fillEnvironment({ + name: 'variables_environment', + variables: [] + }), + fillEnvironment({ + name: 'deployment-protection-rules_environment', + deployment_protection_rules: [] + }) + ] + } }); - ['wait-timer', 'reviewers', 'prevent-self-review', 'deployment-branch-policy', 'deployment-branch-policy-custom', 'variables', 'deployment-protection-rules'].forEach((environment_name) => { - when(github.request) - .calledWith('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { org, repo, environment_name }) - .mockResolvedValue({ - data: { - custom_deployment_protection_rules: [] - } - }) - }); + //act - run sync() in environments.js + await plugin.sync().then(() => { + //assert - update to the wait timer was requested with value 2 - when(github.request) - .calledWith('GET /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { org, repo, environment_name: 'deployment-branch-policy-custom' }) - .mockResolvedValue({ - data: { - branch_policies: [] - } - }); + expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments', { org, repo }); - when(github.request) - .calledWith('DELETE /repos/:org/:repo/environments/:environment_name/deployment-branch-policies/:branch_policy_id') - .mockResolvedValue({}); + ['wait-timer_environment', 'reviewers_environment', 'prevent-self-review_environment', 'deployment-branch-policy_environment', 'deployment-branch-policy-custom_environment', 'variables_environment', 'deployment-protection-rules_environment'].forEach((environment_name) => { + expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments/:environment_name/variables', { org, repo, environment_name }); - when(github.request) - .calledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies') - .mockResolvedValue({}); + expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { org, repo, environment_name }); + }); - when(github.request) - .calledWith('PUT /repos/:org/:repo/environments/:environment_name') - .mockResolvedValue({}); + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: 'wait-timer_environment', + wait_timer: 1 + })); - when(github.request) - .calledWith('POST /repos/:org/:repo/environments/:environment_name/variables') - .mockResolvedValue({}); + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: 'reviewers_environment', + reviewers: [ + { + type: 'User', + id: 1 + }, + { + type: 'Team', + id: 2 + } + ] + })); - when(github.request) - .calledWith('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules') - .mockResolvedValue({}); + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: 'prevent-self-review_environment', + prevent_self_review: true + })); - when(github.request) - .calledWith('DELETE /repos/:org/:repo/environments/:environment_name/deployment_protection_rules/:rule_id') - .mockResolvedValue({}); + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: 'prevent-self-review_environment', + prevent_self_review: true + })); + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: 'deployment-branch-policy_environment', + deployment_branch_policy: { + protected_branches: true, + custom_branch_policies: false + } + })); - return plugin.sync().then(() => { - expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments', { org, repo }); + expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ + org, + repo, + environment_name: 'deployment-branch-policy-custom_environment', + deployment_branch_policy: { + protected_branches: false, + custom_branch_policies: true + } + })); - ['wait-timer', 'reviewers', 'prevent-self-review', 'deployment-branch-policy', 'deployment-branch-policy-custom', 'variables', 'deployment-protection-rules'].forEach((environment_name) => { - expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments/:environment_name/variables', { org, repo, environment_name }); + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', expect.objectContaining({ + org, + repo, + environment_name: 'deployment-branch-policy-custom_environment', + name: 'master' + })); - expect(github.request).toHaveBeenCalledWith('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { org, repo, environment_name }); - }); + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', expect.objectContaining({ + org, + repo, + environment_name: 'deployment-branch-policy-custom_environment', + name: 'dev' + })); - expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ - org, - repo, - environment_name: 'wait-timer', - wait_timer: 1 - })); + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/variables', expect.objectContaining({ + org, + repo, + environment_name: 'variables_environment', + name: 'test', + value: 'test' + })); - expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ - org, - repo, - environment_name: 'reviewers', - reviewers: [ - { - type: 'User', - id: 1 - }, - { - type: 'Team', - id: 2 - } - ] - })); - - expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ - org, - repo, - environment_name: 'prevent-self-review', - prevent_self_review: true - })); - - expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ - org, - repo, - environment_name: 'prevent-self-review', - prevent_self_review: true - })); - - expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ - org, - repo, - environment_name: 'deployment-branch-policy', - deployment_branch_policy: { - protected_branches: true, - custom_branch_policies: false - } - })); - - expect(github.request).toHaveBeenCalledWith('PUT /repos/:org/:repo/environments/:environment_name', expect.objectContaining({ - org, - repo, - environment_name: 'deployment-branch-policy-custom', - deployment_branch_policy: { - protected_branches: false, - custom_branch_policies: true - } - })); - - expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', expect.objectContaining({ - org, - repo, - environment_name: 'deployment-branch-policy-custom', - name: 'master' - })); - - expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', expect.objectContaining({ - org, - repo, - environment_name: 'deployment-branch-policy-custom', - name: 'dev' - })); - - expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/variables', expect.objectContaining({ - org, - repo, - environment_name: 'variables', - name: 'test', - value: 'test' - })); - - expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', expect.objectContaining({ - org, - repo, - environment_name: 'deployment-protection-rules', - integration_id: 1 - })); - }) + expect(github.request).toHaveBeenCalledWith('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', expect.objectContaining({ + org, + repo, + environment_name: 'deployment-protection-rules_environment', + integration_id: 1 + })); + }) }) -}) \ No newline at end of file + }) + +}) From e8e7e53531e2549bc4247d5076b376a5e27952bf Mon Sep 17 00:00:00 2001 From: Brad Abrams Date: Wed, 15 May 2024 13:49:52 -0400 Subject: [PATCH 2/4] remove logging, combine loops as per review comments --- lib/plugins/environments.js | 2 -- test/unit/lib/plugins/environments.test.js | 8 ++------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/plugins/environments.js b/lib/plugins/environments.js index 299f3407..bfdd0f10 100644 --- a/lib/plugins/environments.js +++ b/lib/plugins/environments.js @@ -278,9 +278,7 @@ module.exports = class Environments extends Diffable { const resArray = [] if (this.entries) { let filteredEntries = this.filterEntries() - // this.log.debug(`filtered entries are ${JSON.stringify(filteredEntries)}`) return this.find().then(existingRecords => { - this.log.debug(` ${JSON.stringify(existingRecords, null, 2)} \n\n ${JSON.stringify(filteredEntries, null, 2)} `) // Filter out all empty entries (usually from repo override) for (const entry of filteredEntries) { diff --git a/test/unit/lib/plugins/environments.test.js b/test/unit/lib/plugins/environments.test.js index e7e214df..18ca7f7e 100644 --- a/test/unit/lib/plugins/environments.test.js +++ b/test/unit/lib/plugins/environments.test.js @@ -37,18 +37,14 @@ describe('Environments Plugin test suite', () => { variables: [] } }) - } - ); - - AllEnvironmentNamesBeingTested.forEach((environment_name) => { - when(github.request) + when(github.request) .calledWith('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { org, repo, environment_name }) .mockResolvedValue({ data: { custom_deployment_protection_rules: [] } }) - } + } ); when(github.request) From cf3fa7208e4123c59eeb379e18d4d179fca10ca3 Mon Sep 17 00:00:00 2001 From: Brad Abrams Date: Thu, 20 Jun 2024 16:57:09 -0400 Subject: [PATCH 3/4] Add NopCommand, log.error, and errors --- lib/plugins/environments.js | 1 + test/unit/lib/plugins/environments.test.js | 41 ++++++---------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/lib/plugins/environments.js b/lib/plugins/environments.js index bfdd0f10..fc602210 100644 --- a/lib/plugins/environments.js +++ b/lib/plugins/environments.js @@ -1,5 +1,6 @@ const Diffable = require('./diffable') const MergeDeep = require('../mergeDeep') +const NopCommand = require('../nopcommand') module.exports = class Environments extends Diffable { constructor(...args) { diff --git a/test/unit/lib/plugins/environments.test.js b/test/unit/lib/plugins/environments.test.js index 18ca7f7e..e89b4fbb 100644 --- a/test/unit/lib/plugins/environments.test.js +++ b/test/unit/lib/plugins/environments.test.js @@ -7,9 +7,8 @@ describe('Environments Plugin test suite', () => { const org = 'bkeepers' const repo = 'test' const AllEnvironmentNamesBeingTested = ['wait-timer_environment', 'wait-timer_2_environment', 'reviewers_environment', 'prevent-self-review_environment', 'deployment-branch-policy_environment', 'deployment-branch-policy-custom_environment', 'variables_environment', 'deployment-protection-rules_environment'] - const log = jest.fn() - log.debug = jest.fn() - log.error = jest.fn() + log = { debug: jest.fn(), error: console.error } + const errors = [] function fillEnvironment(attrs) { if (!attrs.wait_timer) attrs.wait_timer = 0; @@ -103,9 +102,7 @@ describe('Environments Plugin test suite', () => { name: environment_name, wait_timer: 1 } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with a wait timer of 0 when(github.request) @@ -150,9 +147,7 @@ describe('Environments Plugin test suite', () => { } ] } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with no reviewers when(github.request) @@ -210,9 +205,7 @@ describe('Environments Plugin test suite', () => { name: environment_name, prevent_self_review: true } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with prevent self review false when(github.request) @@ -255,9 +248,7 @@ describe('Environments Plugin test suite', () => { custom_branch_policies: false } } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with prevent self review false when(github.request) @@ -306,9 +297,7 @@ describe('Environments Plugin test suite', () => { ] } } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with no branch policies when(github.request) @@ -368,9 +357,7 @@ describe('Environments Plugin test suite', () => { } ] } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with no reviewers when(github.request) @@ -415,9 +402,7 @@ describe('Environments Plugin test suite', () => { } ] } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with no deployment protection rules when(github.request) @@ -457,9 +442,7 @@ describe('Environments Plugin test suite', () => { name: environment_name, wait_timer: 2 } - ], { - debug: function () { } - }); + ], log, errors); //model an existing environment with no reviewers when(github.request) @@ -555,9 +538,7 @@ describe('Environments Plugin test suite', () => { } ] } - ], { - debug: function () { } - }); + ], log, errors); // model 7 existing environments and their settings // note: wait-timer, required_reviewers, and branch_policy are modeled incorrectly here as they are not wrapped by protection_rules[] From caa7d04041f78632575a36abfee4f4e63c9ba841 Mon Sep 17 00:00:00 2001 From: Brad Abrams Date: Thu, 20 Jun 2024 17:06:07 -0400 Subject: [PATCH 4/4] const log --- test/unit/lib/plugins/environments.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/lib/plugins/environments.test.js b/test/unit/lib/plugins/environments.test.js index e89b4fbb..ba8938db 100644 --- a/test/unit/lib/plugins/environments.test.js +++ b/test/unit/lib/plugins/environments.test.js @@ -7,7 +7,7 @@ describe('Environments Plugin test suite', () => { const org = 'bkeepers' const repo = 'test' const AllEnvironmentNamesBeingTested = ['wait-timer_environment', 'wait-timer_2_environment', 'reviewers_environment', 'prevent-self-review_environment', 'deployment-branch-policy_environment', 'deployment-branch-policy-custom_environment', 'variables_environment', 'deployment-protection-rules_environment'] - log = { debug: jest.fn(), error: console.error } + const log = { debug: jest.fn(), error: console.error } const errors = [] function fillEnvironment(attrs) {