diff --git a/docs/github-settings/6. deployment-environments.md b/docs/github-settings/6. deployment-environments.md index 4bb33c48..f4024c70 100644 --- a/docs/github-settings/6. deployment-environments.md +++ b/docs/github-settings/6. deployment-environments.md @@ -18,6 +18,20 @@ collaborators: - username: KalEl permission: write environments: + - name: dev + wait_timer: 0 + prevent_self_review: true + reviewers: + - type: Team + id: 1234647 + deployment_branch_policy: + protected_branches: false + custom_branch_policies: + - old-way-branch-pattern-only + - name: new-way-branch-pattern/* + type: branch + - name: v-* + type: tag - name: production wait_timer: 0 prevent_self_review: true diff --git a/lib/plugins/environments.js b/lib/plugins/environments.js index 4ceaa9ff..38782494 100644 --- a/lib/plugins/environments.js +++ b/lib/plugins/environments.js @@ -1,363 +1,383 @@ +/* eslint-disable camelcase */ const Diffable = require('./diffable') -const MergeDeep = require('../mergeDeep') const NopCommand = require('../nopcommand') module.exports = class Environments extends Diffable { - constructor(...args) { - super(...args) - - if (this.entries) { - // Force all names to lowercase to avoid comparison issues. - this.entries.forEach(environment => { - environment.name = environment.name.toLowerCase(); - if(environment.variables) { - environment.variables.forEach(variable => { - variable.name = variable.name.toLowerCase(); - }); + constructor (...args) { + super(...args) + + if (this.entries) { + this.entries.forEach(environment => { + // Fix to allow old format of: + // - my-branch policy + // to + // - name: my-branch-policy + // type: branch + // + // and also allow: + // - name: my-tag + // type: tag + if (environment.deployment_branch_policy && environment.deployment_branch_policy.custom_branch_policies) { + if (environment.deployment_branch_policy.custom_branch_policies.length > 0) { + const newArray = [] + environment.deployment_branch_policy.custom_branch_policies.forEach(policy => { + if (typeof policy === 'string') { + newArray.push({ + name: policy, + type: 'branch' + }) + } else { + newArray.push(policy) } }) + environment.deployment_branch_policy.custom_branch_policies = newArray + } } - } - async find() { - const { data: { environments } } = await this.github.request('GET /repos/:org/:repo/environments', { - org: this.repo.owner, - repo: this.repo.repo - }); - - let environments_mapped = []; - - for(let environment of environments) { - const mapped = { - name: environment.name.toLowerCase(), - repo: this.repo.repo, - wait_timer: (environment.protection_rules.find(rule => rule.type === 'wait_timer') || { wait_timer: 0 }).wait_timer, - prevent_self_review: (environment.protection_rules.find(rule => rule.type === 'required_reviewers') || { prevent_self_review: false }).prevent_self_review, - reviewers: (environment.protection_rules.find(rule => rule.type === 'required_reviewers') || { reviewers: [] }).reviewers.map(reviewer => ({id: reviewer.reviewer.id, type: reviewer.type})), - deployment_branch_policy: environment.deployment_branch_policy === null ? null : { - protected_branches: (environment.deployment_branch_policy || { protected_branches: false }).protected_branches, - custom_branch_policies: (environment.deployment_branch_policy || { custom_branch_policies: false }).custom_branch_policies && (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: environment.name - })).data.branch_policies.map(policy => ({ - name: policy.name - })) - }, - variables: (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/variables', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: environment.name - })).data.variables.map(variable => ({name: variable.name.toLowerCase(), value: variable.value})), - deployment_protection_rules: (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: environment.name - })).data.custom_deployment_protection_rules.map(rule => ({ - app_id: rule.app.id, - id: rule.id - })) - } - environments_mapped.push(mapped); - //console.log(mapped); + // Force all names to lowercase to avoid comparison issues. + environment.name = environment.name.toLowerCase() + if (environment.variables) { + environment.variables.forEach(variable => { + variable.name = variable.name.toLowerCase() + }) } - - return environments_mapped; + }) } - - comparator(existing, attrs) { - return existing.name === attrs.name + } + + async find () { + const { data: { environments } } = await this.github.request('GET /repos/:org/:repo/environments', { + org: this.repo.owner, + repo: this.repo.repo + }) + + const environments_mapped = [] + + for (const environment of environments) { + const mapped = { + name: environment.name.toLowerCase(), + repo: this.repo.repo, + wait_timer: (environment.protection_rules.find(rule => rule.type === 'wait_timer') || { wait_timer: 0 }).wait_timer, + prevent_self_review: (environment.protection_rules.find(rule => rule.type === 'required_reviewers') || { prevent_self_review: false }).prevent_self_review, + reviewers: (environment.protection_rules.find(rule => rule.type === 'required_reviewers') || { reviewers: [] }).reviewers.map(reviewer => ({id: reviewer.reviewer.id, type: reviewer.type})), + deployment_branch_policy: environment.deployment_branch_policy === null ? null : { + protected_branches: (environment.deployment_branch_policy || { protected_branches: false }).protected_branches, + custom_branch_policies: (environment.deployment_branch_policy || { custom_branch_policies: false }).custom_branch_policies && (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: environment.name + })).data.branch_policies.map(policy => ({ + name: policy.name, + type: policy.type + })) + }, + variables: (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/variables', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: environment.name + })).data.variables.map(variable => ({ name: variable.name.toLowerCase(), value: variable.value })), + deployment_protection_rules: (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: environment.name + })).data.custom_deployment_protection_rules.map(rule => ({ + app_id: rule.app.id, + id: rule.id + })) + } + environments_mapped.push(mapped) + // console.log(mapped); } - - getChanged(existing, 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 = []; - - 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(); - } - let attrs_custom_branch_policies = attrs.deployment_branch_policy === null ? null : attrs.deployment_branch_policy.custom_branch_policies; - if(typeof(attrs_custom_branch_policies) === 'object' && attrs_custom_branch_policies !== null) { - attrs_custom_branch_policies = attrs_custom_branch_policies.sort(); - } - let deployment_branch_policy; - if(existing.deployment_branch_policy === attrs.deployment_branch_policy) { - deployment_branch_policy = false; - } - else { - deployment_branch_policy = ( - (existing.deployment_branch_policy === null && attrs.deployment_branch_policy !== null) || - (existing.deployment_branch_policy !== null && attrs.deployment_branch_policy === null) || - (existing.deployment_branch_policy.protected_branches !== attrs.deployment_branch_policy.protected_branches) || - (JSON.stringify(existing_custom_branch_policies) !== JSON.stringify(attrs_custom_branch_policies)) - ); - } - - const variables = JSON.stringify(existing.variables.sort((x1, x2) => x1.name - x2.name)) !== JSON.stringify(attrs.variables.sort((x1, x2) => x1.name - x2.name)); - const deployment_protection_rules = JSON.stringify(existing.deployment_protection_rules.map(x => ({app_id: x.app_id})).sort((x1, x2) => x1.app_id - x2.app_id)) !== JSON.stringify(attrs.deployment_protection_rules.map(x => ({app_id: x.app_id})).sort((x1, x2) => x1.app_id - x2.app_id)); - - return {wait_timer, prevent_self_review, reviewers, deployment_branch_policy, variables, deployment_protection_rules}; + return environments_mapped + } + + comparator (existing, attrs) { + return existing.name === attrs.name + } + + getChanged (existing, 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 = [] + + 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() } - changed(existing, attrs) { - const {wait_timer, prevent_self_review, reviewers, deployment_branch_policy, variables, deployment_protection_rules} = this.getChanged(existing, attrs); - - return wait_timer || prevent_self_review || reviewers || deployment_branch_policy || variables || deployment_protection_rules; + let attrs_custom_branch_policies = attrs.deployment_branch_policy === null ? null : attrs.deployment_branch_policy.custom_branch_policies + if (typeof (attrs_custom_branch_policies) === 'object' && attrs_custom_branch_policies !== null) { + attrs_custom_branch_policies = attrs_custom_branch_policies.sort() } - async update(existing, attrs) { - const {wait_timer, prevent_self_review, reviewers, deployment_branch_policy, variables, deployment_protection_rules} = this.getChanged(existing, attrs); - - if(wait_timer || prevent_self_review || reviewers || deployment_branch_policy) { - await this.github.request(`PUT /repos/:org/:repo/environments/:environment_name`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - wait_timer: attrs.wait_timer, - prevent_self_review: attrs.prevent_self_review, - reviewers: attrs.reviewers, - deployment_branch_policy: attrs.deployment_branch_policy === null ? null : { - protected_branches: attrs.deployment_branch_policy.protected_branches, - custom_branch_policies: !!attrs.deployment_branch_policy.custom_branch_policies - } - }) - } + let deployment_branch_policy + if (existing.deployment_branch_policy === attrs.deployment_branch_policy) { + deployment_branch_policy = false + } else { + deployment_branch_policy = ( + (existing.deployment_branch_policy === null && attrs.deployment_branch_policy !== null) || + (existing.deployment_branch_policy !== null && attrs.deployment_branch_policy === null) || + (existing.deployment_branch_policy.protected_branches !== attrs.deployment_branch_policy.protected_branches) || + (JSON.stringify(existing_custom_branch_policies) !== JSON.stringify(attrs_custom_branch_policies)) + ) + } - if(deployment_branch_policy && attrs.deployment_branch_policy && attrs.deployment_branch_policy.custom_branch_policies) { - const existingPolicies = (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name - })).data.branch_policies; - - for(let policy of existingPolicies) { - await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name/deployment-branch-policies/:branch_policy_id', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - branch_policy_id: policy.id - }); - } + const variables = JSON.stringify(existing.variables.sort((x1, x2) => x1.name - x2.name)) !== JSON.stringify(attrs.variables.sort((x1, x2) => x1.name - x2.name)) + const deployment_protection_rules = JSON.stringify(existing.deployment_protection_rules.map(x => ({ app_id: x.app_id })).sort((x1, x2) => x1.app_id - x2.app_id)) !== JSON.stringify(attrs.deployment_protection_rules.map(x => ({app_id: x.app_id})).sort((x1, x2) => x1.app_id - x2.app_id)); - for(let policy of attrs.deployment_branch_policy.custom_branch_policies) { - await this.github.request('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - name: policy - }); - } - } + return { wait_timer, prevent_self_review, reviewers, deployment_branch_policy, variables, deployment_protection_rules } + } - if(variables) { - let existingVariables = [...existing.variables]; - - for(let variable of attrs.variables) { - const existingVariable = existingVariables.find((_var) => _var.name === variable.name); - if(existingVariable) { - existingVariables = existingVariables.filter(_var => _var.name !== variable.name); - if(existingVariable.value !== variable.value) { - await this.github.request(`PATCH /repos/:org/:repo/environments/:environment_name/variables/:variable_name`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - variable_name: variable.name, - value: variable.value - }); - } - } - else { - await this.github.request(`POST /repos/:org/:repo/environments/:environment_name/variables`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - name: variable.name, - value: variable.value - }); - } - } + changed (existing, attrs) { + const { wait_timer, prevent_self_review, reviewers, deployment_branch_policy, variables, deployment_protection_rules } = this.getChanged(existing, attrs) - for(let variable of existingVariables) { - await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name/variables/:variable_name', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - variable_name: variable.name - }); - } - } + return wait_timer || prevent_self_review || reviewers || deployment_branch_policy || variables || deployment_protection_rules + } - if(deployment_protection_rules) { - let existingRules = [...existing.deployment_protection_rules]; + async update (existing, attrs) { + const { wait_timer, prevent_self_review, reviewers, deployment_branch_policy, variables, deployment_protection_rules } = this.getChanged(existing, attrs) - for(let rule of attrs.deployment_protection_rules) { - const existingRule = existingRules.find((_rule) => _rule.id === rule.id); + if (wait_timer || prevent_self_review || reviewers || deployment_branch_policy) { + await this.github.request('PUT /repos/:org/:repo/environments/:environment_name', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + wait_timer: attrs.wait_timer, + prevent_self_review: attrs.prevent_self_review, + reviewers: attrs.reviewers, + deployment_branch_policy: attrs.deployment_branch_policy === null ? null : { + protected_branches: attrs.deployment_branch_policy.protected_branches, + custom_branch_policies: !!attrs.deployment_branch_policy.custom_branch_policies + } + }) + } - if(!existingRule) { - await this.github.request(`POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - integration_id: rule.app_id - }); - } - } + if (deployment_branch_policy && attrs.deployment_branch_policy && attrs.deployment_branch_policy.custom_branch_policies) { + const existingPolicies = (await this.github.request('GET /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name + })).data.branch_policies + + for (const policy of existingPolicies) { + await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name/deployment-branch-policies/:branch_policy_id', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + branch_policy_id: policy.id + }) + } - for(let rule of existingRules) { - await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name/deployment_protection_rules/:rule_id', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - rule_id: rule.id - }); - } - } + for (const policy of attrs.deployment_branch_policy.custom_branch_policies) { + await this.github.request('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + name: policy.name, + type: policy.type + }) + } } - async add(attrs) { - await this.github.request(`PUT /repos/:org/:repo/environments/:environment_name`, { + if (variables) { + let existingVariables = [...existing.variables] + + for (const variable of attrs.variables) { + const existingVariable = existingVariables.find((_var) => _var.name === variable.name) + if (existingVariable) { + existingVariables = existingVariables.filter(_var => _var.name !== variable.name) + if (existingVariable.value !== variable.value) { + await this.github.request('PATCH /repos/:org/:repo/environments/:environment_name/variables/:variable_name', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + variable_name: variable.name, + value: variable.value + }) + } + } else { + await this.github.request('POST /repos/:org/:repo/environments/:environment_name/variables', { org: this.repo.owner, repo: this.repo.repo, environment_name: attrs.name, - wait_timer: attrs.wait_timer, - prevent_self_review: attrs.prevent_self_review, - reviewers: attrs.reviewers, - deployment_branch_policy: attrs.deployment_branch_policy == null ? null : { - protected_branches: !!attrs.deployment_branch_policy.protected_branches, - custom_branch_policies: !!attrs.deployment_branch_policy.custom_branch_policies - } - }); - - if(attrs.deployment_branch_policy && attrs.deployment_branch_policy.custom_branch_policies) { - - for(let policy of attrs.deployment_branch_policy.custom_branch_policies) { - await this.github.request('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - name: policy.name - }); - } - + name: variable.name, + value: variable.value + }) } + } - if(attrs.variables) { - - for(let variable of attrs.variables) { - await this.github.request(`POST /repos/:org/:repo/environments/:environment_name/variables`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - name: variable.name, - value: variable.value - }); - } - - } + for (const variable of existingVariables) { + await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name/variables/:variable_name', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + variable_name: variable.name + }) + } + } - if(attrs.deployment_protection_rules) { + if (deployment_protection_rules) { + const existingRules = [...existing.deployment_protection_rules] - for(let rule of attrs.deployment_protection_rules) { - await this.github.request(`POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: attrs.name, - integration_id: rule.app_id - }); - } + for (const rule of attrs.deployment_protection_rules) { + const existingRule = existingRules.find((_rule) => _rule.id === rule.id) + if (!existingRule) { + await this.github.request('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + integration_id: rule.app_id + }) } + } + + for (const rule of existingRules) { + await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name/deployment_protection_rules/:rule_id', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + rule_id: rule.id + }) + } + } + } + + async add (attrs) { + await this.github.request('PUT /repos/:org/:repo/environments/:environment_name', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + wait_timer: attrs.wait_timer, + prevent_self_review: attrs.prevent_self_review, + reviewers: attrs.reviewers, + deployment_branch_policy: attrs.deployment_branch_policy == null ? null : { + protected_branches: !!attrs.deployment_branch_policy.protected_branches, + custom_branch_policies: !!attrs.deployment_branch_policy.custom_branch_policies + } + }) + + if (attrs.deployment_branch_policy && attrs.deployment_branch_policy.custom_branch_policies) { + for (const policy of attrs.deployment_branch_policy.custom_branch_policies) { + await this.github.request('POST /repos/:org/:repo/environments/:environment_name/deployment-branch-policies', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + name: policy.name, + type: policy.type + }) + } } - async remove(existing) { - await this.github.request(`DELETE /repos/:org/:repo/environments/:environment_name`, { - org: this.repo.owner, - repo: this.repo.repo, - environment_name: existing.name - }); + if (attrs.variables) { + for (const variable of attrs.variables) { + await this.github.request('POST /repos/:org/:repo/environments/:environment_name/variables', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + name: variable.name, + value: variable.value + }) + } } - sync () { - const resArray = [] - if (this.entries) { - let filteredEntries = this.filterEntries() - return this.find().then(existingRecords => { - - // Remove any null or undefined values from the diffables (usually comes 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] - } + if (attrs.deployment_protection_rules) { + for (const rule of attrs.deployment_protection_rules) { + await this.github.request('POST /repos/:org/:repo/environments/:environment_name/deployment_protection_rules', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: attrs.name, + integration_id: rule.app_id + }) + } + } + } + + async remove (existing) { + await this.github.request('DELETE /repos/:org/:repo/environments/:environment_name', { + org: this.repo.owner, + repo: this.repo.repo, + environment_name: existing.name + }) + } + + sync () { + const resArray = [] + if (this.entries) { + const filteredEntries = this.filterEntries() + return this.find().then(existingRecords => { + // Remove any null or undefined values from the diffables (usually comes 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] } } - // For environments, we want to keep the entries with only name defined. - - 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) - } - }) + } + // For environments, we want to keep the entries with only name defined. + + const changes = [] - filteredEntries.forEach(attrs => { - const existing = existingRecords.find(record => { - return this.comparator(record, attrs) + 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) + } + }) - 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) - } + filteredEntries.forEach(attrs => { + const existing = existingRecords.find(record => { + return this.comparator(record, attrs) }) - if (this.nop) { - return Promise.resolve(resArray) + 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) } - 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) - } + }) + + 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 { - this.logError(`Error ${e} in ${this.constructor.name} for repo: ${JSON.stringify(this.repo)} entries ${JSON.stringify(this.entries)}`) + 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)}`) + } + }) } - + } }