From 2c089822538146265cf7b26fa7ca7903bed8b4f4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:19:39 +0000 Subject: [PATCH 1/5] fix: override NODE_ENV=development in functional test and add retry logic Co-authored-by: decyjphr <57544838+decyjphr@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/safe-settings/sessions/97b10121-f26e-44c0-86e6-3ede047fe176 --- .github/workflows/create-pre-release.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-pre-release.yml b/.github/workflows/create-pre-release.yml index 1f8b0df41..b81a3a7be 100644 --- a/.github/workflows/create-pre-release.yml +++ b/.github/workflows/create-pre-release.yml @@ -71,9 +71,10 @@ jobs: - name: Run Functional Tests id: functionaltest run: | - docker run --env APP_ID=${{ secrets.APP_ID }} --env PRIVATE_KEY=${{ secrets.PRIVATE_KEY }} --env WEBHOOK_SECRET=${{ secrets.WEBHOOK_SECRET }} -d -p 3000:3000 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-enterprise + CONTAINER_ID=$(docker run --env APP_ID=${{ secrets.APP_ID }} --env PRIVATE_KEY=${{ secrets.PRIVATE_KEY }} --env WEBHOOK_SECRET=${{ secrets.WEBHOOK_SECRET }} --env NODE_ENV=development -d -p 3000:3000 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-enterprise) sleep 10 - curl http://localhost:3000 + docker logs $CONTAINER_ID + curl --retry 5 --retry-delay 3 --retry-connrefused http://localhost:3000 - run: echo "${{ github.ref }}" - name: Tag a final release id: prerelease From c96b8cb4a1b8fecc0eb8914bbcffbaa401fe488f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:20:52 +0000 Subject: [PATCH 2/5] fix: add --fail to curl and || true to docker logs in functional test Co-authored-by: decyjphr <57544838+decyjphr@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/safe-settings/sessions/97b10121-f26e-44c0-86e6-3ede047fe176 --- .github/workflows/create-pre-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-pre-release.yml b/.github/workflows/create-pre-release.yml index b81a3a7be..daa2fa9f1 100644 --- a/.github/workflows/create-pre-release.yml +++ b/.github/workflows/create-pre-release.yml @@ -73,8 +73,8 @@ jobs: run: | CONTAINER_ID=$(docker run --env APP_ID=${{ secrets.APP_ID }} --env PRIVATE_KEY=${{ secrets.PRIVATE_KEY }} --env WEBHOOK_SECRET=${{ secrets.WEBHOOK_SECRET }} --env NODE_ENV=development -d -p 3000:3000 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-enterprise) sleep 10 - docker logs $CONTAINER_ID - curl --retry 5 --retry-delay 3 --retry-connrefused http://localhost:3000 + docker logs $CONTAINER_ID || true + curl --fail --retry 5 --retry-delay 3 --retry-connrefused http://localhost:3000 - run: echo "${{ github.ref }}" - name: Tag a final release id: prerelease From 94da73e0ee5f77ac25d7271fcf1ee8c81eab46de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:22:37 +0000 Subject: [PATCH 3/5] fix: migrate all octokit API calls to .rest namespace for probot v14 compatibility and revert Dockerfile ENV HOST Co-authored-by: decyjphr <57544838+decyjphr@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/safe-settings/sessions/179c9d77-8ca0-4098-9017-8a255df170f9 --- Dockerfile | 1 - index.js | 14 ++--- lib/configManager.js | 2 +- lib/plugins/archive.js | 6 +- lib/plugins/autolinks.js | 10 +-- lib/plugins/branches.js | 18 +++--- lib/plugins/collaborators.js | 20 +++--- lib/plugins/custom_properties.js | 6 +- lib/plugins/labels.js | 16 ++--- lib/plugins/milestones.js | 8 +-- lib/plugins/repository.js | 48 +++++++------- lib/plugins/teams.js | 14 ++--- lib/plugins/validator.js | 6 +- lib/settings.js | 18 +++--- test/unit/lib/plugins/archive.test.js | 26 ++++---- test/unit/lib/plugins/autolinks.test.js | 48 +++++++------- test/unit/lib/plugins/branches.test.js | 62 ++++++++++--------- test/unit/lib/plugins/collaborators.test.js | 28 +++++---- .../lib/plugins/custom_properties.test.js | 22 ++++--- test/unit/lib/plugins/labels.test.js | 50 ++++++++------- test/unit/lib/plugins/milestones.test.js | 34 +++++----- test/unit/lib/plugins/repository.test.js | 24 +++---- test/unit/lib/plugins/teams.test.js | 32 +++++----- test/unit/lib/settings.test.js | 30 +++++---- 24 files changed, 282 insertions(+), 261 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5c27ee9c4..38db6b50b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,6 @@ FROM node:22-alpine WORKDIR /opt/safe-settings ENV NODE_ENV production -ENV HOST=0.0.0.0 ## Set the Labels LABEL version="1.0" \ description="Probot app which is a modified version of Settings Probot GitHub App" \ diff --git a/index.js b/index.js index ab3237689..4707c82d0 100644 --- a/index.js +++ b/index.js @@ -199,7 +199,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) => async function createCheckRun (context, pull_request, head_sha, head_branch) { const { payload } = context // robot.log.debug(`Check suite was requested! for ${context.repo()} ${pull_request.number} ${head_sha} ${head_branch}`) - const res = await context.octokit.checks.create({ + const res = await context.octokit.rest.checks.create({ owner: payload.repository.owner.login, repo: payload.repository.name, name: 'Safe-setting validator', @@ -211,13 +211,13 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) => async function info () { const github = await robot.auth() const installations = await github.paginate( - github.apps.listInstallations.endpoint.merge({ per_page: 100 }) + github.rest.apps.listInstallations.endpoint.merge({ per_page: 100 }) ) robot.log.debug(`installations: ${JSON.stringify(installations)}`) if (installations.length > 0) { const installation = installations[0] const github = await robot.auth(installation.id) - const app = await github.apps.getAuthenticated() + const app = await github.rest.apps.getAuthenticated() appSlug = app.data.slug robot.log.debug(`Validated the app is configured properly = \n${JSON.stringify(app.data, null, 2)}`) } @@ -228,7 +228,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) => const github = await robot.auth() const installations = await github.paginate( - github.apps.listInstallations.endpoint.merge({ per_page: 100 }) + github.rest.apps.listInstallations.endpoint.merge({ per_page: 100 }) ) if (installations.length > 0) { @@ -577,11 +577,11 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) => output: { title: 'Starting NOP', summary: 'initiating...' } } robot.log.debug(`Updating check run ${JSON.stringify(params)}`) - await context.octokit.checks.update(params) + await context.octokit.rest.checks.update(params) params = Object.assign(context.repo(), { pull_number: pull_request.number }) - const changes = await context.octokit.pulls.listFiles(params) + const changes = await context.octokit.rest.pulls.listFiles(params) const files = changes.data.map(f => { return f.filename }) const settingsModified = files.includes(Settings.FILE_PATH) @@ -609,7 +609,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) => output: { title: 'No Safe-settings changes detected', summary: 'No changes detected' } } robot.log.debug(`Completing check run ${JSON.stringify(params)}`) - await context.octokit.checks.update(params) + await context.octokit.rest.checks.update(params) }) robot.on('repository.created', async context => { diff --git a/lib/configManager.js b/lib/configManager.js index 58f5bb436..7f1bb39b0 100644 --- a/lib/configManager.js +++ b/lib/configManager.js @@ -19,7 +19,7 @@ module.exports = class ConfigManager { try { const repo = { owner: this.context.repo().owner, repo: env.ADMIN_REPO } const params = Object.assign(repo, { path: filePath, ref: this.ref }) - const response = await this.context.octokit.repos.getContent(params).catch(e => { + const response = await this.context.octokit.rest.repos.getContent(params).catch(e => { this.log.error(`Error getting settings ${e}`) }) diff --git a/lib/plugins/archive.js b/lib/plugins/archive.js index f3d7c4c3a..c00c827bb 100644 --- a/lib/plugins/archive.js +++ b/lib/plugins/archive.js @@ -11,7 +11,7 @@ module.exports = class Archive { async getRepo () { try { - const { data } = await this.github.repos.get({ + const { data } = await this.github.rest.repos.get({ owner: this.repo.owner, repo: this.repo.repo }) @@ -32,13 +32,13 @@ module.exports = class Archive { return new NopCommand( this.constructor.name, this.repo, - this.github.repos.update.endpoint(this.settings), + this.github.rest.repos.update.endpoint(this.settings), change, 'INFO' ) } - const { data } = await this.github.repos.update({ + const { data } = await this.github.rest.repos.update({ owner: this.repo.owner, repo: this.repo.repo, archived diff --git a/lib/plugins/autolinks.js b/lib/plugins/autolinks.js index 128e40214..db85abff8 100644 --- a/lib/plugins/autolinks.js +++ b/lib/plugins/autolinks.js @@ -8,7 +8,7 @@ module.exports = class Autolinks extends Diffable { // } async find () { - const { data } = await this.github.repos.listAutolinks(this.repo) + const { data } = await this.github.rest.repos.listAutolinks(this.repo) return data } @@ -43,13 +43,13 @@ module.exports = class Autolinks extends Diffable { return new NopCommand( this.constructor.name, this.repo, - this.github.repos.createAutolink.endpoint(attrs), + this.github.rest.repos.createAutolink.endpoint(attrs), 'Add autolink' ) } try { - return this.github.repos.createAutolink(attrs) + return this.github.rest.repos.createAutolink(attrs) } catch (e) { if (e?.response?.data?.errors?.[0]?.code === 'already_exists') { this.log.debug(`Did not update ${key_prefix}, as it already exists`) @@ -68,10 +68,10 @@ module.exports = class Autolinks extends Diffable { return new NopCommand( this.constructor.name, this.repo, - this.github.repos.deleteAutolink.endpoint(attrs), + this.github.rest.repos.deleteAutolink.endpoint(attrs), 'Remove autolink' ) } - return this.github.repos.deleteAutolink(attrs) + return this.github.rest.repos.deleteAutolink(attrs) } } diff --git a/lib/plugins/branches.js b/lib/plugins/branches.js index d28e2f905..718691445 100644 --- a/lib/plugins/branches.js +++ b/lib/plugins/branches.js @@ -23,7 +23,7 @@ module.exports = class Branches extends ErrorStash { sync () { const resArray = [] - return this.github.repos.get(this.repo).then((currentRepo) => { + return this.github.rest.repos.get(this.repo).then((currentRepo) => { return Promise.all( this.branches .filter(branch => branch.protection !== undefined) @@ -39,12 +39,12 @@ module.exports = class Branches extends ErrorStash { const params = Object.assign({}, p) if (this.nop) { resArray.push( - new NopCommand(this.constructor.name, this.repo, this.github.repos.deleteBranchProtection.endpoint(params), 'Delete Branch Protection') + new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.deleteBranchProtection.endpoint(params), 'Delete Branch Protection') ) return Promise.resolve(resArray) } - return this.github.repos.deleteBranchProtection(params).catch(e => { return [] }) + return this.github.rest.repos.deleteBranchProtection(params).catch(e => { return [] }) } else { // Branch protection is not empty let p = Object.assign(this.repo, { branch: branch.name }) @@ -54,7 +54,7 @@ module.exports = class Branches extends ErrorStash { } // Hack to handle closures and keep params from changing const params = Object.assign({}, p) - return this.github.repos.getBranchProtection(params).then((result) => { + return this.github.rest.repos.getBranchProtection(params).then((result) => { const mergeDeep = new MergeDeep(this.log, this.github, ignorableFields) const changes = mergeDeep.compareDeep({ branch: { protection: this.reformatAndReturnBranchProtection(result.data) } }, { branch: { protection: Overrides.removeOverrides(overrides, branch.protection, result.data) } }) const results = { msg: `Followings changes will be applied to the branch protection for ${params.branch.name} branch`, additions: changes.additions, modifications: changes.modifications, deletions: changes.deletions } @@ -76,24 +76,24 @@ module.exports = class Branches extends ErrorStash { Object.assign(params, branch.protection, { headers: previewHeaders }) if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.updateBranchProtection.endpoint(params), 'Add Branch Protection')) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.updateBranchProtection.endpoint(params), 'Add Branch Protection')) return Promise.resolve(resArray) } this.log.debug(`Adding branch protection ${JSON.stringify(params)}`) - return this.github.repos.updateBranchProtection(params).then(res => this.log.debug(`Branch protection applied successfully ${JSON.stringify(res.url)}`)).catch(e => { this.logError(`Error applying branch protection ${JSON.stringify(e)}`); return [] }) + return this.github.rest.repos.updateBranchProtection(params).then(res => this.log.debug(`Branch protection applied successfully ${JSON.stringify(res.url)}`)).catch(e => { this.logError(`Error applying branch protection ${JSON.stringify(e)}`); return [] }) }).catch((e) => { if (e.status === 404) { Object.assign(params, Overrides.removeOverrides(overrides, branch.protection, {}), { headers: previewHeaders }) if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.updateBranchProtection.endpoint(params), 'Add Branch Protection')) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.updateBranchProtection.endpoint(params), 'Add Branch Protection')) return Promise.resolve(resArray) } this.log.debug(`Adding branch protection ${JSON.stringify(params)}`) - return this.github.repos.updateBranchProtection(params).then(res => this.log.debug(`Branch protection applied successfully ${JSON.stringify(res.url)}`)).catch(e => { this.logError(`Error applying branch protection ${JSON.stringify(e)}`); return [] }) + return this.github.rest.repos.updateBranchProtection(params).then(res => this.log.debug(`Branch protection applied successfully ${JSON.stringify(res.url)}`)).catch(e => { this.logError(`Error applying branch protection ${JSON.stringify(e)}`); return [] }) } else { this.logError(e) if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.updateBranchProtection.endpoint(params), `${e}`, 'ERROR')) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.updateBranchProtection.endpoint(params), `${e}`, 'ERROR')) return Promise.resolve(resArray) } } diff --git a/lib/plugins/collaborators.js b/lib/plugins/collaborators.js index f3758709a..e0b351488 100644 --- a/lib/plugins/collaborators.js +++ b/lib/plugins/collaborators.js @@ -20,8 +20,8 @@ module.exports = class Collaborators extends Diffable { // 'direct' means all collaborators with permissions to an organization-owned repository, regardless of organization membership status. (includes outside collaborators) // 'all' means all collaborators the authenticated user can see. // We are using 'direct' to avoid double listing users outside collaborators and team members. - return Promise.all([this.github.repos.listCollaborators({ repo: this.repo.repo, owner: this.repo.owner, affiliation: 'direct' }), - this.github.repos.listInvitations({ repo: this.repo.repo, owner: this.repo.owner })]) + return Promise.all([this.github.rest.repos.listCollaborators({ repo: this.repo.repo, owner: this.repo.owner, affiliation: 'direct' }), + this.github.rest.repos.listInvitations({ repo: this.repo.repo, owner: this.repo.owner })]) .then(res => { const mapCollaborator = user => { return { @@ -74,10 +74,10 @@ module.exports = class Collaborators extends Diffable { const data = Object.assign({}, attrs, this.repo) if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.repos.addCollaborator.endpoint(data), 'Add Collaborators') + new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.addCollaborator.endpoint(data), 'Add Collaborators') ]) } - return this.github.repos.addCollaborator(data) + return this.github.rest.repos.addCollaborator(data) } updateInvite (invitation_id, permissions) { @@ -89,10 +89,10 @@ module.exports = class Collaborators extends Diffable { }, this.repo) if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.repos.updateInvitation.endpoint(data), 'Update Invitation') + new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.updateInvitation.endpoint(data), 'Update Invitation') ]) } - return this.github.repos.updateInvitation(data) + return this.github.rest.repos.updateInvitation(data) } remove (existing) { @@ -100,20 +100,20 @@ module.exports = class Collaborators extends Diffable { const data = Object.assign({ invitation_id: existing.invitation_id }, this.repo) if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.repos.deleteInvitation.endpoint(data), + new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.deleteInvitation.endpoint(data), 'Delete Invitation') ]) } - return this.github.repos.deleteInvitation(data) + return this.github.rest.repos.deleteInvitation(data) } else { const data = Object.assign({ username: existing.username }, this.repo) if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.repos.removeCollaborator.endpoint(data), + new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.removeCollaborator.endpoint(data), 'Remove Collaborator') ]) } - return this.github.repos.removeCollaborator(data) + return this.github.rest.repos.removeCollaborator(data) } } } diff --git a/lib/plugins/custom_properties.js b/lib/plugins/custom_properties.js index 6b1f3ab36..5d6ab6e5b 100644 --- a/lib/plugins/custom_properties.js +++ b/lib/plugins/custom_properties.js @@ -25,7 +25,7 @@ module.exports = class CustomProperties extends Diffable { this.log.debug(`Getting all custom properties for the repo ${repoFullName}`) const customProperties = await this.github.paginate( - this.github.repos.getCustomPropertiesValues, + this.github.rest.repos.getCustomPropertiesValues, { owner, repo, @@ -82,14 +82,14 @@ module.exports = class CustomProperties extends Diffable { return new NopCommand( this.constructor.name, this.repo, - this.github.repos.createOrUpdateCustomPropertiesValues.endpoint(params), + this.github.rest.repos.createOrUpdateCustomPropertiesValues.endpoint(params), `${operation} Custom Property` ) } try { this.log.debug(`${operation} Custom Property "${name}" for the repo ${repoFullName}`) - await this.github.repos.createOrUpdateCustomPropertiesValues(params) + await this.github.rest.repos.createOrUpdateCustomPropertiesValues(params) this.log.debug(`Successfully ${operation.toLowerCase()}d Custom Property "${name}" for the repo ${repoFullName}`) } catch (e) { this.logError(`Error during ${operation} Custom Property "${name}" for the repo ${repoFullName}: ${e.message || e}`) diff --git a/lib/plugins/labels.js b/lib/plugins/labels.js index 49558cc08..6e48d8dcb 100644 --- a/lib/plugins/labels.js +++ b/lib/plugins/labels.js @@ -34,8 +34,8 @@ module.exports = class Labels extends Diffable { find () { this.log.debug(`Finding labels for ${JSON.stringify(this.wrapAttrs({ per_page: 100 }))}`) - const options = this.github.issues.listLabelsForRepo.endpoint.merge(this.wrapAttrs({ per_page: 100 })) - return this.github.repos.get(this.repo).then(() => { + const options = this.github.rest.issues.listLabelsForRepo.endpoint.merge(this.wrapAttrs({ per_page: 100 })) + return this.github.rest.repos.get(this.repo).then(() => { return this.github.paginate(options) }) .catch(e => { @@ -63,20 +63,20 @@ module.exports = class Labels extends Diffable { delete attrs.oldname if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.issues.updateLabel.endpoint(this.wrapAttrs(attrs)), 'Update label') + new NopCommand(this.constructor.name, this.repo, this.github.rest.issues.updateLabel.endpoint(this.wrapAttrs(attrs)), 'Update label') ]) } - return this.github.issues.updateLabel(this.wrapAttrs(attrs)) + return this.github.rest.issues.updateLabel(this.wrapAttrs(attrs)) } add (attrs) { if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.issues.createLabel.endpoint(this.wrapAttrs(attrs)), 'Create label') + new NopCommand(this.constructor.name, this.repo, this.github.rest.issues.createLabel.endpoint(this.wrapAttrs(attrs)), 'Create label') ]) } this.log.debug(`Creating labels for ${JSON.stringify(attrs, null, 4)}`) - return this.github.issues.createLabel(this.wrapAttrs(attrs)).catch(e => this.logError(` ${JSON.stringify(e)}`)) + return this.github.rest.issues.createLabel(this.wrapAttrs(attrs)).catch(e => this.logError(` ${JSON.stringify(e)}`)) } remove (existing) { @@ -85,10 +85,10 @@ module.exports = class Labels extends Diffable { } if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.issues.deleteLabel.endpoint(this.wrapAttrs({ name: existing.name })), 'Delete label') + new NopCommand(this.constructor.name, this.repo, this.github.rest.issues.deleteLabel.endpoint(this.wrapAttrs({ name: existing.name })), 'Delete label') ]) } - return this.github.issues.deleteLabel(this.wrapAttrs({ name: existing.name })) + return this.github.rest.issues.deleteLabel(this.wrapAttrs({ name: existing.name })) } wrapAttrs (attrs) { diff --git a/lib/plugins/milestones.js b/lib/plugins/milestones.js index 9fc93ab22..cdb242496 100644 --- a/lib/plugins/milestones.js +++ b/lib/plugins/milestones.js @@ -14,7 +14,7 @@ module.exports = class Milestones extends Diffable { } find () { - const options = this.github.issues.listMilestones.endpoint.merge(Object.assign({ per_page: 100, state: 'all' }, this.repo)) + const options = this.github.rest.issues.listMilestones.endpoint.merge(Object.assign({ per_page: 100, state: 'all' }, this.repo)) return this.github.paginate(options) } @@ -29,18 +29,18 @@ module.exports = class Milestones extends Diffable { update (existing, attrs) { const { owner, repo } = this.repo - return this.github.issues.updateMilestone(Object.assign({ milestone_number: existing.number }, attrs, { owner, repo })) + return this.github.rest.issues.updateMilestone(Object.assign({ milestone_number: existing.number }, attrs, { owner, repo })) } add (attrs) { const { owner, repo } = this.repo - return this.github.issues.createMilestone(Object.assign({}, attrs, { owner, repo })) + return this.github.rest.issues.createMilestone(Object.assign({}, attrs, { owner, repo })) } remove (existing) { const { owner, repo } = this.repo - return this.github.issues.deleteMilestone(Object.assign({ milestone_number: existing.number }, { owner, repo })) + return this.github.rest.issues.deleteMilestone(Object.assign({ milestone_number: existing.number }, { owner, repo })) } } diff --git a/lib/plugins/repository.js b/lib/plugins/repository.js index 14599f608..4fea13f8a 100644 --- a/lib/plugins/repository.js +++ b/lib/plugins/repository.js @@ -64,7 +64,7 @@ module.exports = class Repository extends ErrorStash { this.settings.name = this.settings.name || this.settings.repo // let hasChanges = false // let hasTopicChanges = false - return this.github.repos.get(this.repo) + return this.github.rest.repos.get(this.repo) .then(resp => { const mergeDeep = new MergeDeep(this.log, this.github, ignorableFields) @@ -125,23 +125,23 @@ module.exports = class Repository extends ErrorStash { const options = { template_owner: this.repo.owner, template_repo: this.template, owner: this.repo.owner, name: this.repo.repo, private: (this.settings.private ? this.settings.private : true), description: this.settings.description ? this.settings.description : '' } if (this.nop) { - this.log.debug(`Creating Repo using template ${JSON.stringify(this.github.repos.createInOrg.endpoint(this.settings))} `) - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.createUsingTemplate.endpoint(options), 'Create Repo Using Template')) + this.log.debug(`Creating Repo using template ${JSON.stringify(this.github.rest.repos.createInOrg.endpoint(this.settings))} `) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.createUsingTemplate.endpoint(options), 'Create Repo Using Template')) return Promise.resolve(resArray) } - return this.github.repos.createUsingTemplate(options) + return this.github.rest.repos.createUsingTemplate(options) } else { // https://docs.github.com/en/rest/repos/repos#create-an-organization-repository uses org instead of owner like // the API to create a repo with a template this.settings.org = this.settings.owner this.log.debug('Creating repo with settings ', this.settings) if (this.nop) { - this.log.debug(`Creating Repo ${JSON.stringify(this.github.repos.createInOrg.endpoint(this.settings))} `) + this.log.debug(`Creating Repo ${JSON.stringify(this.github.rest.repos.createInOrg.endpoint(this.settings))} `) return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.repos.createInOrg.endpoint(this.settings), 'Create Repo') + new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.createInOrg.endpoint(this.settings), 'Create Repo') ]) } - return this.github.repos.createInOrg(this.settings) + return this.github.rest.repos.createInOrg(this.settings) } } else { if (this.nop) { @@ -158,7 +158,7 @@ module.exports = class Repository extends ErrorStash { updateDefaultBranch (oldname, newname, resArray) { this.log.debug(`Checking if ${newname} is already a branch`) - return this.github.repos.getBranch({ + return this.github.rest.repos.getBranch({ owner: this.settings.owner, repo: this.settings.repo, branch: newname @@ -175,10 +175,10 @@ module.exports = class Repository extends ErrorStash { default_branch: newname } if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.update.endpoint(parms), 'Update Repo')) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.update.endpoint(parms), 'Update Repo')) } else { this.log.debug(`Updating repo with settings ${JSON.stringify(parms)}`) - return this.github.repos.update(parms) + return this.github.rest.repos.update(parms) } } }).catch(e => { @@ -200,19 +200,19 @@ module.exports = class Repository extends ErrorStash { } this.log.info(`Rename default branch repo with settings ${JSON.stringify(parms)}`) if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.renameBranch.endpoint(oldname, this.settings.default_branch), `Repo rename default branch to ${this.settings.default_branch}`)) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.renameBranch.endpoint(oldname, this.settings.default_branch), `Repo rename default branch to ${this.settings.default_branch}`)) } else { - return this.github.repos.renameBranch(parms) + return this.github.rest.repos.renameBranch(parms) } } updaterepo (resArray) { this.log.debug(`Updating repo with settings ${JSON.stringify(this.topics)} ${JSON.stringify(this.settings)}`) if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.update.endpoint(this.settings), 'Update Repo')) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.update.endpoint(this.settings), 'Update Repo')) return Promise.resolve(resArray) } - return this.github.repos.update(this.settings) + return this.github.rest.repos.update(this.settings) } updatetopics (repoData, resArray) { @@ -230,10 +230,10 @@ module.exports = class Repository extends ErrorStash { // !repoData.data?.topics.every(t => this.topics.includes(t))) { this.log.debug(`Updating repo with topics ${this.topics.join(',')}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.repos.replaceAllTopics.endpoint(parms), 'Update Topics'))) + resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.replaceAllTopics.endpoint(parms), 'Update Topics'))) return Promise.resolve(resArray) } - return this.github.repos.replaceAllTopics(parms) + return this.github.rest.repos.replaceAllTopics(parms) // } else { // this.log.debug(`no need to update topics for ${repoData.data.name}`) // if (this.nop) { @@ -251,26 +251,26 @@ module.exports = class Repository extends ErrorStash { if (this.security.enableVulnerabilityAlerts === true) { this.log.debug(`Enabling Dependabot alerts for owner: ${repoData.owner.login} and repo ${repoData.name}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.repos.enableVulnerabilityAlerts.endpoint({ + resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.enableVulnerabilityAlerts.endpoint({ owner: repoData.owner.login, repo: repoData.name }), 'Enabling Dependabot alerts'))) return Promise.resolve(resArray) } - return this.github.repos.enableVulnerabilityAlerts({ + return this.github.rest.repos.enableVulnerabilityAlerts({ owner: repoData.owner.login, repo: repoData.name }) } else { this.log.debug(`Disabling Dependabot alerts for for owner: ${repoData.owner.login} and repo ${repoData.name}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.github.repos.disableVulnerabilityAlerts.endpoint({ + resArray.push((new NopCommand(this.constructor.name, this.github.rest.repos.disableVulnerabilityAlerts.endpoint({ owner: repoData.owner.login, repo: repoData.name }), 'Disabling Dependabot alerts'))) return Promise.resolve(resArray) } - return this.github.repos.disableVulnerabilityAlerts({ + return this.github.rest.repos.disableVulnerabilityAlerts({ owner: repoData.owner.login, repo: repoData.name }) @@ -289,26 +289,26 @@ module.exports = class Repository extends ErrorStash { if (this.security.enableAutomatedSecurityFixes === true) { this.log.debug(`Enabling Dependabot security updates for owner: ${repoData.owner.login} and repo ${repoData.name}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.repos.enableAutomatedSecurityFixes.endpoint({ + resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.enableAutomatedSecurityFixes.endpoint({ owner: repoData.owner.login, repo: repoData.name }), 'Enabling Dependabot security updates'))) return Promise.resolve(resArray) } - return this.github.repos.enableAutomatedSecurityFixes({ + return this.github.rest.repos.enableAutomatedSecurityFixes({ owner: repoData.owner.login, repo: repoData.name }) } else { this.log.debug(`Disabling Dependabot security updates for owner: ${repoData.owner.login} and repo ${repoData.name}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.github.repos.disableAutomatedSecurityFixes.endpoint({ + resArray.push((new NopCommand(this.constructor.name, this.github.rest.repos.disableAutomatedSecurityFixes.endpoint({ owner: repoData.owner.login, repo: repoData.name }), 'Disabling Dependabot security updates'))) return Promise.resolve(resArray) } - return this.github.repos.disableAutomatedSecurityFixes({ + return this.github.rest.repos.disableAutomatedSecurityFixes({ owner: repoData.owner.login, repo: repoData.name }) diff --git a/lib/plugins/teams.js b/lib/plugins/teams.js index 4d7f79273..da97a2d2e 100644 --- a/lib/plugins/teams.js +++ b/lib/plugins/teams.js @@ -5,7 +5,7 @@ const teamRepoEndpoint = '/orgs/:owner/teams/:team_slug/repos/:owner/:repo' module.exports = class Teams extends Diffable { async find () { this.log.debug(`Finding teams for ${this.repo.owner}/${this.repo.repo}`) - return this.github.paginate(this.github.repos.listTeams, this.repo).then(res => { + return this.github.paginate(this.github.rest.repos.listTeams, this.repo).then(res => { this.log.debug(`Found teams ${JSON.stringify(res)}`) return this.checkSecurityManager(res) }) @@ -73,15 +73,15 @@ module.exports = class Teams extends Diffable { add (attrs) { let existing = { team_id: 1 } this.log.debug(`Getting team with the parms ${JSON.stringify(attrs)}`) - return this.github.teams.getByName({ org: this.repo.owner, team_slug: attrs.name }).then(res => { + return this.github.rest.teams.getByName({ org: this.repo.owner, team_slug: attrs.name }).then(res => { existing = res.data this.log.debug(`adding team ${attrs.name} to repo ${this.repo.repo}`) if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.teams.addOrUpdateRepoPermissionsInOrg.endpoint(this.toParams(existing, attrs)), 'Add Teams to Repo') + new NopCommand(this.constructor.name, this.repo, this.github.rest.teams.addOrUpdateRepoPermissionsInOrg.endpoint(this.toParams(existing, attrs)), 'Add Teams to Repo') ]) } - return this.github.teams.addOrUpdateRepoPermissionsInOrg(this.toParams(existing, attrs)).then(res => { + return this.github.rest.teams.addOrUpdateRepoPermissionsInOrg(this.toParams(existing, attrs)).then(res => { this.log.debug(`team added ${res}`) }).catch(e => { this.logError(`Error adding team to repo ${JSON.stringify(e)} with parms ${JSON.stringify(this.toParams(existing, attrs))}:\n`, e) @@ -98,14 +98,14 @@ module.exports = class Teams extends Diffable { this.log.debug(`Creating teams ${JSON.stringify(createParam)}`) if (this.nop) { return Promise.resolve([ - new NopCommand(this.constructor.name, this.repo, this.github.teams.create.endpoint(createParam), 'Create Team') + new NopCommand(this.constructor.name, this.repo, this.github.rest.teams.create.endpoint(createParam), 'Create Team') ]) } - return this.github.teams.create(createParam).then(res => { + return this.github.rest.teams.create(createParam).then(res => { this.log.debug(`team ${createParam.name} created`) existing = res.data this.log.debug(`adding team ${attrs.name} to repo ${this.repo.repo}`) - return this.github.teams.addOrUpdateRepoPermissionsInOrg(this.toParams(existing, attrs)) + return this.github.rest.teams.addOrUpdateRepoPermissionsInOrg(this.toParams(existing, attrs)) }).catch(e => { this.logError('Error adding team: ', e) }) diff --git a/lib/plugins/validator.js b/lib/plugins/validator.js index 8ee72af9a..25b39cfe0 100644 --- a/lib/plugins/validator.js +++ b/lib/plugins/validator.js @@ -12,7 +12,7 @@ module.exports = class Validator { sync () { try { - return this.github.repos.getAllTopics({ + return this.github.rest.repos.getAllTopics({ owner: this.repo.owner, repo: this.repo.repo, mediaType: { @@ -28,7 +28,7 @@ module.exports = class Validator { } if (res.data.names.find(x => x === 'validation-error')) { res.data.names = res.data.names.filter(x => x !== 'validation-error') - return this.github.repos.replaceAllTopics({ + return this.github.rest.repos.replaceAllTopics({ owner: this.repo.owner, repo: this.repo.repo, names: res.data.names, @@ -46,7 +46,7 @@ module.exports = class Validator { } if (!res.data.names.find(x => x === 'validation-error')) { res.data.names.push('validation-error') - return this.github.repos.replaceAllTopics({ + return this.github.rest.repos.replaceAllTopics({ owner: this.repo.owner, repo: this.repo.repo, names: res.data.names, diff --git a/lib/settings.js b/lib/settings.js index 59a615419..86ea868bb 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -140,12 +140,12 @@ class Settings { } // Use the latest commit to create the check against - return this.github.repos.listCommits({ + return this.github.rest.repos.listCommits({ owner: this.repo.owner, repo: env.ADMIN_REPO }) .then(commits => { - return this.github.checks.create( + return this.github.rest.checks.create( { owner: this.repo.owner, repo: env.ADMIN_REPO, @@ -285,7 +285,7 @@ ${this.results.reduce((x, y) => { const pullRequest = payload.check_run.check_suite.pull_requests[0] - await this.github.issues.createComment({ + await this.github.rest.issues.createComment({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: pullRequest.number, @@ -307,7 +307,7 @@ ${this.results.reduce((x, y) => { } this.log.debug(`Completing check run ${JSON.stringify(params)}`) - await this.github.checks.update(params) + await this.github.rest.checks.update(params) } async loadConfigs (repo) { @@ -555,7 +555,7 @@ ${this.results.reduce((x, y) => { async loadConfigMap (params) { try { this.log.debug(` In loadConfigMap ${JSON.stringify(params)}`) - const response = await this.github.repos.getContent(params).catch(e => { + const response = await this.github.rest.repos.getContent(params).catch(e => { this.log.debug(`Error getting settings ${JSON.stringify(params)} ${e}`) }) @@ -609,7 +609,7 @@ ${this.results.reduce((x, y) => { // get /repos directory sha to use in the getTree api const repo = { owner: this.repo.owner, repo: env.ADMIN_REPO } const params = Object.assign(repo, { path: path.posix.join(CONFIG_PATH), ref: this.ref }) - const githubDirectoryContentResponse = await this.github.repos.getContent(params).catch(e => { + const githubDirectoryContentResponse = await this.github.rest.repos.getContent(params).catch(e => { this.log.debug(`Error getting settings ${JSON.stringify(params)} ${e}`) }) @@ -629,8 +629,8 @@ ${this.results.reduce((x, y) => { // const endpoint = `/repos/${this.repo.owner}/${repo.repo}/git/trees/${repoDirInfo.sha}` // this.log.debug(`endpoint: ${endpoint}`) const treeParams = Object.assign(repo, { tree_sha: repoDirInfo.sha, recursive: 0 }) - const response = await this.github.git.getTree(treeParams).catch(e => { - this.log.debug(`Error getting settings ${JSON.stringify(this.github.git.getTree.endpoint(treeParams))} ${e}`) + const response = await this.github.rest.git.getTree(treeParams).catch(e => { + this.log.debug(`Error getting settings ${JSON.stringify(this.github.rest.git.getTree.endpoint(treeParams))} ${e}`) }) if (!response || !response.data) { @@ -853,7 +853,7 @@ ${this.results.reduce((x, y) => { } } - const response = await this.github.repos.getContent(params).catch(e => { + const response = await this.github.rest.repos.getContent(params).catch(e => { if (e.status === 304) { this.log.debug(`Cache hit for file ${filePath}`) return { diff --git a/test/unit/lib/plugins/archive.test.js b/test/unit/lib/plugins/archive.test.js index 9aa690442..0ed0f38d1 100644 --- a/test/unit/lib/plugins/archive.test.js +++ b/test/unit/lib/plugins/archive.test.js @@ -10,9 +10,11 @@ describe('Archive Plugin', () => { beforeEach(() => { github = { - repos: { - get: jest.fn(), - update: jest.fn().mockReturnValue({ data: {} }) + rest: { + repos: { + get: jest.fn(), + update: jest.fn().mockReturnValue({ data: {} }) + } } } repo = { owner: 'test-owner', repo: 'test-repo' } @@ -23,19 +25,19 @@ describe('Archive Plugin', () => { describe('getRepo', () => { it('returns repository data when found', async () => { const mockData = { archived: false } - github.repos.get.mockResolvedValue({ data: mockData }) + github.rest.repos.get.mockResolvedValue({ data: mockData }) archive = new Archive(false, github, repo, settings, log) const result = await archive.getRepo() expect(result).toEqual(mockData) - expect(github.repos.get).toHaveBeenCalledWith({ + expect(github.rest.repos.get).toHaveBeenCalledWith({ owner: repo.owner, repo: repo.repo }) }) it('returns null when repo not found and no archive state defined', async () => { - github.repos.get.mockRejectedValue({ status: 404 }) + github.rest.repos.get.mockRejectedValue({ status: 404 }) archive = new Archive(false, github, repo, settings, log) const result = await archive.getRepo() @@ -44,7 +46,7 @@ describe('Archive Plugin', () => { it('throws error for non-404 errors', async () => { const error = { status: 500 } - github.repos.get.mockRejectedValue(error) + github.rest.repos.get.mockRejectedValue(error) archive = new Archive(false, github, repo, settings, log) await expect(archive.getRepo()).rejects.toEqual(error) @@ -55,7 +57,7 @@ describe('Archive Plugin', () => { it('returns NopCommand when nop is true', async () => { archive = new Archive(true, github, repo, settings, log) const mockEndpoint = { method: 'PATCH', url: '/repos/{owner}/{repo}' } - github.repos.update.endpoint = jest.fn().mockReturnValue(mockEndpoint) + github.rest.repos.update.endpoint = jest.fn().mockReturnValue(mockEndpoint) const result = await archive.updateRepoArchiveStatus(true) expect(result).toBeInstanceOf(NopCommand) @@ -65,7 +67,7 @@ describe('Archive Plugin', () => { archive = new Archive(false, github, repo, settings, log) await archive.updateRepoArchiveStatus(true) - expect(github.repos.update).toHaveBeenCalledWith({ + expect(github.rest.repos.update).toHaveBeenCalledWith({ owner: repo.owner, repo: repo.repo, archived: true @@ -97,7 +99,7 @@ describe('Archive Plugin', () => { }) it('returns empty results when no archive changes needed', async () => { - github.repos.get.mockResolvedValue({ + github.rest.repos.get.mockResolvedValue({ data: { archived: false } }) settings.archived = false @@ -108,14 +110,14 @@ describe('Archive Plugin', () => { }) it('archives repo when shouldArchive is true', async () => { - github.repos.get.mockResolvedValue({ + github.rest.repos.get.mockResolvedValue({ data: { archived: false } }) settings.archived = true const results = await archive.sync() expect(results).toHaveLength(1) - expect(github.repos.update).toHaveBeenCalledWith({ + expect(github.rest.repos.update).toHaveBeenCalledWith({ owner: repo.owner, repo: repo.repo, archived: true diff --git a/test/unit/lib/plugins/autolinks.test.js b/test/unit/lib/plugins/autolinks.test.js index 10413cc1a..02829daa0 100644 --- a/test/unit/lib/plugins/autolinks.test.js +++ b/test/unit/lib/plugins/autolinks.test.js @@ -13,10 +13,12 @@ describe('Autolinks', () => { beforeEach(() => { github = { - repos: { - listAutolinks: jest.fn().mockResolvedValue([]), - createAutolink: jest.fn().mockResolvedValue(), - deleteAutolink: jest.fn().mockResolvedValue() + rest: { + repos: { + listAutolinks: jest.fn().mockResolvedValue([]), + createAutolink: jest.fn().mockResolvedValue(), + deleteAutolink: jest.fn().mockResolvedValue() + } } } }) @@ -35,7 +37,7 @@ describe('Autolinks', () => { { key_prefix: 'NEW_ALPHA-TRUE-', url_template: 'https://test/', is_alphanumeric: true } ]) - github.repos.listAutolinks.mockResolvedValueOnce({ + github.rest.repos.listAutolinks.mockResolvedValueOnce({ data: [ { id: '1', key_prefix: 'SAME-', url_template: 'https://test/', is_alphanumeric: true }, { id: '2', key_prefix: 'REMOVE-', url_template: 'https://test/', is_alphanumeric: true }, @@ -50,97 +52,97 @@ describe('Autolinks', () => { }) return plugin.sync().then(() => { - expect(github.repos.createAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).toHaveBeenCalledWith({ key_prefix: 'ADD-', url_template: 'https://test/', is_alphanumeric: true, ...repo }) - expect(github.repos.deleteAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).toHaveBeenCalledWith({ autolink_id: '2', ...repo }) - expect(github.repos.deleteAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).toHaveBeenCalledWith({ autolink_id: '3', ...repo }) - expect(github.repos.createAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).toHaveBeenCalledWith({ key_prefix: 'NEW_URL-', url_template: 'https://new-url/', is_alphanumeric: true, ...repo }) - expect(github.repos.deleteAutolink).not.toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).not.toHaveBeenCalledWith({ autolink_id: '4', ...repo }) - expect(github.repos.createAutolink).not.toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).not.toHaveBeenCalledWith({ key_prefix: 'SAME_ALPHA-UNDEFINED-', url_template: 'https://test/', is_alphanumeric: true, ...repo }) - expect(github.repos.deleteAutolink).not.toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).not.toHaveBeenCalledWith({ autolink_id: '5', ...repo }) - expect(github.repos.createAutolink).not.toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).not.toHaveBeenCalledWith({ key_prefix: 'SAME_ALPHA-FALSE-', url_template: 'https://test/', is_alphanumeric: false, ...repo }) - expect(github.repos.deleteAutolink).not.toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).not.toHaveBeenCalledWith({ autolink_id: '6', ...repo }) - expect(github.repos.createAutolink).not.toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).not.toHaveBeenCalledWith({ key_prefix: 'SAME_ALPHA-TRUE-', url_template: 'https://test/', is_alphanumeric: true, ...repo }) - expect(github.repos.deleteAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).toHaveBeenCalledWith({ autolink_id: '7', ...repo }) - expect(github.repos.createAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).toHaveBeenCalledWith({ key_prefix: 'NEW_ALPHA-UNDEFINED-', url_template: 'https://test/', is_alphanumeric: true, ...repo }) - expect(github.repos.deleteAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).toHaveBeenCalledWith({ autolink_id: '8', ...repo }) - expect(github.repos.createAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).toHaveBeenCalledWith({ key_prefix: 'NEW_ALPHA-FALSE-', url_template: 'https://test/', is_alphanumeric: false, ...repo }) - expect(github.repos.deleteAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.deleteAutolink).toHaveBeenCalledWith({ autolink_id: '9', ...repo }) - expect(github.repos.createAutolink).toHaveBeenCalledWith({ + expect(github.rest.repos.createAutolink).toHaveBeenCalledWith({ key_prefix: 'NEW_ALPHA-TRUE-', url_template: 'https://test/', is_alphanumeric: true, ...repo }) - expect(github.repos.deleteAutolink).toHaveBeenCalledTimes(5) - expect(github.repos.createAutolink).toHaveBeenCalledTimes(5) + expect(github.rest.repos.deleteAutolink).toHaveBeenCalledTimes(5) + expect(github.rest.repos.createAutolink).toHaveBeenCalledTimes(5) }) }) }) diff --git a/test/unit/lib/plugins/branches.test.js b/test/unit/lib/plugins/branches.test.js index 4b3683f34..450ec9939 100644 --- a/test/unit/lib/plugins/branches.test.js +++ b/test/unit/lib/plugins/branches.test.js @@ -17,19 +17,21 @@ describe('Branches', () => { beforeEach(() => { github = { - repos: { - get: jest.fn().mockResolvedValue({ - data: { - default_branch: 'main' - } - }), - getBranchProtection: jest.fn().mockResolvedValue({ - data: { - enforce_admins: { enabled: false } - } - }), - updateBranchProtection: jest.fn().mockImplementation(() => Promise.resolve('updateBranchProtection')), - deleteBranchProtection: jest.fn().mockImplementation(() => Promise.resolve('deleteBranchProtection')) + rest: { + repos: { + get: jest.fn().mockResolvedValue({ + data: { + default_branch: 'main' + } + }), + getBranchProtection: jest.fn().mockResolvedValue({ + data: { + enforce_admins: { enabled: false } + } + }), + updateBranchProtection: jest.fn().mockImplementation(() => Promise.resolve('updateBranchProtection')), + deleteBranchProtection: jest.fn().mockImplementation(() => Promise.resolve('deleteBranchProtection')) + } } } }) @@ -53,7 +55,7 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'master', @@ -80,8 +82,8 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).not.toHaveBeenCalled() - expect(github.repos.deleteBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).not.toHaveBeenCalled() + expect(github.rest.repos.deleteBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'master' @@ -100,8 +102,8 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).not.toHaveBeenCalled() - expect(github.repos.deleteBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).not.toHaveBeenCalled() + expect(github.rest.repos.deleteBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'master' @@ -120,8 +122,8 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).not.toHaveBeenCalled() - expect(github.repos.deleteBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).not.toHaveBeenCalled() + expect(github.rest.repos.deleteBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'master' @@ -140,8 +142,8 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).not.toHaveBeenCalled() - expect(github.repos.deleteBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).not.toHaveBeenCalled() + expect(github.rest.repos.deleteBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'master' @@ -159,8 +161,8 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).not.toHaveBeenCalled() - expect(github.repos.deleteBranchProtection).not.toHaveBeenCalled() + expect(github.rest.repos.updateBranchProtection).not.toHaveBeenCalled() + expect(github.rest.repos.deleteBranchProtection).not.toHaveBeenCalled() }) }) }) @@ -180,7 +182,7 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'main', @@ -196,7 +198,7 @@ describe('Branches', () => { describe('when {{EXTERNALLY_DEFINED}} is present in "required_status_checks" and status checks exist in GitHub', () => { it('it retains the status checks from GitHub', () => { - github.repos.getBranchProtection = jest.fn().mockResolvedValue({ + github.rest.repos.getBranchProtection = jest.fn().mockResolvedValue({ data: { enforce_admins: { enabled: false }, protection: { @@ -219,7 +221,7 @@ describe('Branches', () => { ) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).toHaveBeenCalledWith({ + expect(github.rest.repos.updateBranchProtection).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'main', @@ -248,7 +250,7 @@ describe('Branches', () => { ] ) - when(github.repos.getBranchProtection) + when(github.rest.repos.getBranchProtection) .calledWith(expect.objectContaining({ branch: 'other' })).mockResolvedValue({ @@ -258,9 +260,9 @@ describe('Branches', () => { }) return plugin.sync().then(() => { - expect(github.repos.updateBranchProtection).toHaveBeenCalledTimes(2) + expect(github.rest.repos.updateBranchProtection).toHaveBeenCalledTimes(2) - expect(github.repos.updateBranchProtection).toHaveBeenLastCalledWith({ + expect(github.rest.repos.updateBranchProtection).toHaveBeenLastCalledWith({ owner: 'bkeepers', repo: 'test', branch: 'other', diff --git a/test/unit/lib/plugins/collaborators.test.js b/test/unit/lib/plugins/collaborators.test.js index 359dd4614..f01007953 100644 --- a/test/unit/lib/plugins/collaborators.test.js +++ b/test/unit/lib/plugins/collaborators.test.js @@ -10,13 +10,15 @@ describe('Collaborators', () => { beforeEach(() => { github = { - repos: { - listInvitations: jest.fn().mockResolvedValue([]), - deleteInvitation: jest.fn().mockResolvedValue(), - updateInvitation: jest.fn().mockResolvedValue(), - listCollaborators: jest.fn().mockResolvedValue([]), - removeCollaborator: jest.fn().mockResolvedValue(), - addCollaborator: jest.fn().mockResolvedValue() + rest: { + repos: { + listInvitations: jest.fn().mockResolvedValue([]), + deleteInvitation: jest.fn().mockResolvedValue(), + updateInvitation: jest.fn().mockResolvedValue(), + listCollaborators: jest.fn().mockResolvedValue([]), + removeCollaborator: jest.fn().mockResolvedValue(), + addCollaborator: jest.fn().mockResolvedValue() + } } } }) @@ -30,7 +32,7 @@ describe('Collaborators', () => { { username: 'DIFFERENTcase', permission: 'push' } ]) - github.repos.listCollaborators.mockResolvedValueOnce({ + github.rest.repos.listCollaborators.mockResolvedValueOnce({ data: [ { login: 'bkeepers', permissions: { admin: true, push: true, pull: true } }, { login: 'updated-permission', permissions: { admin: false, push: false, pull: true } }, @@ -40,29 +42,29 @@ describe('Collaborators', () => { }) return plugin.sync().then(() => { - expect(github.repos.addCollaborator).toHaveBeenCalledWith({ + expect(github.rest.repos.addCollaborator).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', username: 'added-user', permission: 'push' }) - expect(github.repos.addCollaborator).toHaveBeenCalledWith({ + expect(github.rest.repos.addCollaborator).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', username: 'updated-permission', permission: 'push' }) - expect(github.repos.addCollaborator).toHaveBeenCalledTimes(2) + expect(github.rest.repos.addCollaborator).toHaveBeenCalledTimes(2) - expect(github.repos.removeCollaborator).toHaveBeenCalledWith({ + expect(github.rest.repos.removeCollaborator).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', username: 'removed-user' }) - expect(github.repos.removeCollaborator).toHaveBeenCalledTimes(1) + expect(github.rest.repos.removeCollaborator).toHaveBeenCalledTimes(1) }) }) }) diff --git a/test/unit/lib/plugins/custom_properties.test.js b/test/unit/lib/plugins/custom_properties.test.js index 429544f8a..6afc8228b 100644 --- a/test/unit/lib/plugins/custom_properties.test.js +++ b/test/unit/lib/plugins/custom_properties.test.js @@ -15,9 +15,11 @@ describe('CustomProperties', () => { beforeEach(() => { github = { paginate: jest.fn(), - repos: { - getCustomPropertiesValues: jest.fn(), - createOrUpdateCustomPropertiesValues: jest.fn() + rest: { + repos: { + getCustomPropertiesValues: jest.fn(), + createOrUpdateCustomPropertiesValues: jest.fn() + } } } @@ -42,7 +44,7 @@ describe('CustomProperties', () => { const result = await plugin.find() expect(github.paginate).toHaveBeenCalledWith( - github.repos.getCustomPropertiesValues, + github.rest.repos.getCustomPropertiesValues, { owner, repo, @@ -75,14 +77,14 @@ describe('CustomProperties', () => { return plugin.sync().then(() => { expect(github.paginate).toHaveBeenCalledWith( - github.repos.getCustomPropertiesValues, + github.rest.repos.getCustomPropertiesValues, { owner, repo, per_page: 100 } ) - expect(github.repos.createOrUpdateCustomPropertiesValues).not.toHaveBeenCalledWith({ + expect(github.rest.repos.createOrUpdateCustomPropertiesValues).not.toHaveBeenCalledWith({ owner, repo, properties: [ @@ -92,7 +94,7 @@ describe('CustomProperties', () => { } ] }) - expect(github.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ + expect(github.rest.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ owner, repo, properties: [ @@ -102,7 +104,7 @@ describe('CustomProperties', () => { } ] }) - expect(github.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ + expect(github.rest.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ owner, repo, properties: [ @@ -112,7 +114,7 @@ describe('CustomProperties', () => { } ] }) - expect(github.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ + expect(github.rest.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ owner, repo, properties: [ @@ -127,7 +129,7 @@ describe('CustomProperties', () => { // const plugin = configure([{ name: 'Test', value: 'test' }]) // await plugin.update({ name: 'test', value: 'old' }, { name: 'test', value: 'test' }) - // expect(github.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ + // expect(github.rest.repos.createOrUpdateCustomPropertiesValues).toHaveBeenCalledWith({ // owner, // repo, // properties: [ diff --git a/test/unit/lib/plugins/labels.test.js b/test/unit/lib/plugins/labels.test.js index 71eaf2c8b..1d1bd51b1 100644 --- a/test/unit/lib/plugins/labels.test.js +++ b/test/unit/lib/plugins/labels.test.js @@ -12,18 +12,20 @@ describe('Labels', () => { beforeEach(() => { github = { paginate: jest.fn().mockImplementation(() => Promise.resolve()), - repos: { - get: jest.fn().mockImplementation(() => Promise.resolve({})) - }, - issues: { - listLabelsForRepo: { - endpoint: { - merge: jest.fn().mockImplementation(() => {}) - } + rest: { + repos: { + get: jest.fn().mockImplementation(() => Promise.resolve({})) }, - createLabel: jest.fn().mockImplementation(() => Promise.resolve()), - deleteLabel: jest.fn().mockImplementation(() => Promise.resolve()), - updateLabel: jest.fn().mockImplementation(() => Promise.resolve()) + issues: { + listLabelsForRepo: { + endpoint: { + merge: jest.fn().mockImplementation(() => {}) + } + }, + createLabel: jest.fn().mockImplementation(() => Promise.resolve()), + deleteLabel: jest.fn().mockImplementation(() => Promise.resolve()), + updateLabel: jest.fn().mockImplementation(() => Promise.resolve()) + } } } log = { debug: jest.fn(), error: console.error } @@ -48,14 +50,14 @@ describe('Labels', () => { ]) return plugin.sync().then(() => { - expect(github.issues.deleteLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.deleteLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', name: 'delete-me', headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.createLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.createLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', name: 'added', @@ -63,7 +65,7 @@ describe('Labels', () => { headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.updateLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.updateLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', current_name: 'update-me', @@ -73,7 +75,7 @@ describe('Labels', () => { headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.updateLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.updateLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', current_name: 'new-color', @@ -83,7 +85,7 @@ describe('Labels', () => { headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.updateLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.updateLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', current_name: 'new-description', @@ -93,9 +95,9 @@ describe('Labels', () => { headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.deleteLabel).toHaveBeenCalledTimes(1) - expect(github.issues.updateLabel).toHaveBeenCalledTimes(3) - expect(github.issues.createLabel).toHaveBeenCalledTimes(1) + expect(github.rest.issues.deleteLabel).toHaveBeenCalledTimes(1) + expect(github.rest.issues.updateLabel).toHaveBeenCalledTimes(3) + expect(github.rest.issues.createLabel).toHaveBeenCalledTimes(1) }) }) @@ -122,14 +124,14 @@ describe('Labels', () => { }) return plugin.sync().then(() => { - expect(github.issues.deleteLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.deleteLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', name: 'delete-me', headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.updateLabel).toHaveBeenCalledWith({ + expect(github.rest.issues.updateLabel).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', current_name: 'update-me', @@ -139,9 +141,9 @@ describe('Labels', () => { headers: { accept: 'application/vnd.github.symmetra-preview+json' } }) - expect(github.issues.deleteLabel).toHaveBeenCalledTimes(1) - expect(github.issues.updateLabel).toHaveBeenCalledTimes(1) - expect(github.issues.createLabel).toHaveBeenCalledTimes(1) + expect(github.rest.issues.deleteLabel).toHaveBeenCalledTimes(1) + expect(github.rest.issues.updateLabel).toHaveBeenCalledTimes(1) + expect(github.rest.issues.createLabel).toHaveBeenCalledTimes(1) }) }) }) diff --git a/test/unit/lib/plugins/milestones.test.js b/test/unit/lib/plugins/milestones.test.js index 93cde7db4..359cd8b6f 100644 --- a/test/unit/lib/plugins/milestones.test.js +++ b/test/unit/lib/plugins/milestones.test.js @@ -10,15 +10,17 @@ describe.skip('Milestones', () => { beforeEach(() => { github = { paginate: jest.fn().mockImplementation(() => Promise.resolve()), - issues: { - listMilestonesForRepo: { - endpoint: { - merge: jest.fn().mockImplementation(() => {}) - } - }, - createMilestone: jest.fn().mockImplementation(() => Promise.resolve()), - deleteMilestone: jest.fn().mockImplementation(() => Promise.resolve()), - updateMilestone: jest.fn().mockImplementation(() => Promise.resolve()) + rest: { + issues: { + listMilestonesForRepo: { + endpoint: { + merge: jest.fn().mockImplementation(() => {}) + } + }, + createMilestone: jest.fn().mockImplementation(() => Promise.resolve()), + deleteMilestone: jest.fn().mockImplementation(() => Promise.resolve()), + updateMilestone: jest.fn().mockImplementation(() => Promise.resolve()) + } } } }) @@ -41,19 +43,19 @@ describe.skip('Milestones', () => { await plugin.sync() - expect(github.issues.deleteMilestone).toHaveBeenCalledWith({ + expect(github.rest.issues.deleteMilestone).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', milestone_number: 1 }) - expect(github.issues.createMilestone).toHaveBeenCalledWith({ + expect(github.rest.issues.createMilestone).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', title: 'added' }) - expect(github.issues.updateMilestone).toHaveBeenCalledWith({ + expect(github.rest.issues.updateMilestone).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', title: 'new-description', @@ -61,7 +63,7 @@ describe.skip('Milestones', () => { milestone_number: 2 }) - expect(github.issues.updateMilestone).toHaveBeenCalledWith({ + expect(github.rest.issues.updateMilestone).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', title: 'new-state', @@ -69,9 +71,9 @@ describe.skip('Milestones', () => { milestone_number: 4 }) - expect(github.issues.deleteMilestone).toHaveBeenCalledTimes(1) - expect(github.issues.updateMilestone).toHaveBeenCalledTimes(2) - expect(github.issues.createMilestone).toHaveBeenCalledTimes(1) + expect(github.rest.issues.deleteMilestone).toHaveBeenCalledTimes(1) + expect(github.rest.issues.updateMilestone).toHaveBeenCalledTimes(2) + expect(github.rest.issues.createMilestone).toHaveBeenCalledTimes(1) }) }) }) diff --git a/test/unit/lib/plugins/repository.test.js b/test/unit/lib/plugins/repository.test.js index fc4c453b0..75b1199fc 100644 --- a/test/unit/lib/plugins/repository.test.js +++ b/test/unit/lib/plugins/repository.test.js @@ -2,14 +2,16 @@ const Repository = require('../../../../lib/plugins/repository') describe('Repository', () => { const github = { - repos: { - get: jest.fn().mockResolvedValue({ - data: { - topics: [] - } - }), - update: jest.fn().mockResolvedValue(), - replaceAllTopics: jest.fn().mockResolvedValue() + rest: { + repos: { + get: jest.fn().mockResolvedValue({ + data: { + topics: [] + } + }), + update: jest.fn().mockResolvedValue(), + replaceAllTopics: jest.fn().mockResolvedValue() + } } } const log = jest.fn() @@ -34,7 +36,7 @@ describe('Repository', () => { topics: [] }) return plugin.sync().then(() => { - expect(github.repos.update).toHaveBeenCalledWith({ + expect(github.rest.repos.update).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', name: 'test', @@ -49,7 +51,7 @@ describe('Repository', () => { name: 'new-name' }) return plugin.sync().then(() => { - expect(github.repos.update).toHaveBeenCalledWith({ + expect(github.rest.repos.update).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', name: 'new-name', @@ -64,7 +66,7 @@ describe('Repository', () => { }) return plugin.sync().then(() => { - expect(github.repos.replaceAllTopics).toHaveBeenCalledWith({ + expect(github.rest.repos.replaceAllTopics).toHaveBeenCalledWith({ owner: 'bkeepers', repo: 'test', names: ['foo', 'bar'], diff --git a/test/unit/lib/plugins/teams.test.js b/test/unit/lib/plugins/teams.test.js index 60ef23dbc..d47113076 100644 --- a/test/unit/lib/plugins/teams.test.js +++ b/test/unit/lib/plugins/teams.test.js @@ -27,19 +27,21 @@ describe('Teams', () => { const response = await fetch() return response.data }), - teams: { - create: jest.fn().mockResolvedValue(), - getByName: jest.fn(), - addOrUpdateRepoPermissionsInOrg: jest.fn().mockResolvedValue() - }, - repos: { - listTeams: jest.fn().mockResolvedValue({ - data: [ - { id: unchangedTeamId, slug: unchangedTeamName, permission: 'push' }, - { id: removedTeamId, slug: removedTeamName, permission: 'push' }, - { id: updatedTeamId, slug: updatedTeamName, permission: 'pull' } - ] - }) + rest: { + teams: { + create: jest.fn().mockResolvedValue(), + getByName: jest.fn(), + addOrUpdateRepoPermissionsInOrg: jest.fn().mockResolvedValue() + }, + repos: { + listTeams: jest.fn().mockResolvedValue({ + data: [ + { id: unchangedTeamId, slug: unchangedTeamName, permission: 'push' }, + { id: removedTeamId, slug: removedTeamName, permission: 'push' }, + { id: updatedTeamId, slug: updatedTeamName, permission: 'pull' } + ] + }) + } }, request: jest.fn().mockResolvedValue() } @@ -53,7 +55,7 @@ describe('Teams', () => { { name: addedTeamName, permission: 'pull' } ]) - when(github.teams.getByName) + when(github.rest.teams.getByName) .defaultResolvedValue({}) .calledWith({ org: 'bkeepers', team_slug: addedTeamName }) .mockResolvedValue({ data: { id: addedTeamId } }) @@ -72,7 +74,7 @@ describe('Teams', () => { } ) - expect(github.teams.addOrUpdateRepoPermissionsInOrg).toHaveBeenCalledWith({ + expect(github.rest.teams.addOrUpdateRepoPermissionsInOrg).toHaveBeenCalledWith({ org, team_id: addedTeamId, team_slug: addedTeamName, diff --git a/test/unit/lib/settings.test.js b/test/unit/lib/settings.test.js index c65fcd1af..b36106518 100644 --- a/test/unit/lib/settings.test.js +++ b/test/unit/lib/settings.test.js @@ -52,8 +52,10 @@ repository: topics: - frontend `).toString('base64'); - mockOctokit.repos = { - getContent: jest.fn().mockResolvedValue({ data: { content } }) + mockOctokit.rest = { + repos: { + getContent: jest.fn().mockResolvedValue({ data: { content } }) + } } mockOctokit.request = { @@ -310,8 +312,10 @@ repository: Settings.fileCache = {}; stubContext = { octokit: { - repos: { - getContent: jest.fn() + rest: { + repos: { + getContent: jest.fn() + } }, request: jest.fn(), paginate: jest.fn() @@ -334,7 +338,7 @@ repository: // Given const filePath = 'path/to/file.yml'; const content = Buffer.from('key: value').toString('base64'); - jest.spyOn(settings.github.repos, 'getContent').mockResolvedValue({ + jest.spyOn(settings.github.rest.repos, 'getContent').mockResolvedValue({ data: { content }, headers: { etag: 'etag123' } }); @@ -355,14 +359,14 @@ repository: const filePath = 'path/to/file.yml'; const content = Buffer.from('key: value').toString('base64'); Settings.fileCache[`${mockRepo.owner}/${filePath}`] = { etag: 'etag123', data: { content } }; - jest.spyOn(settings.github.repos, 'getContent').mockRejectedValue({ status: 304 }); + jest.spyOn(settings.github.rest.repos, 'getContent').mockRejectedValue({ status: 304 }); // When const result = await settings.loadYaml(filePath); // Then expect(result).toEqual({ key: 'value' }); - expect(settings.github.repos.getContent).toHaveBeenCalledWith( + expect(settings.github.rest.repos.getContent).toHaveBeenCalledWith( expect.objectContaining({ headers: { 'If-None-Match': 'etag123' } }) ); }); @@ -373,7 +377,7 @@ repository: const content = Buffer.from('key: value').toString('base64'); const wrongContent = Buffer.from('wrong: content').toString('base64'); Settings.fileCache['another-org/path/to/file.yml'] = { etag: 'etag123', data: { wrongContent } }; - jest.spyOn(settings.github.repos, 'getContent').mockResolvedValue({ + jest.spyOn(settings.github.rest.repos, 'getContent').mockResolvedValue({ data: { content }, headers: { etag: 'etag123' } }); @@ -388,7 +392,7 @@ repository: it('should return null when the file path is a folder', async () => { // Given const filePath = 'path/to/folder'; - jest.spyOn(settings.github.repos, 'getContent').mockResolvedValue({ + jest.spyOn(settings.github.rest.repos, 'getContent').mockResolvedValue({ data: [] }); @@ -402,7 +406,7 @@ repository: it('should return null when the file is a symlink or submodule', async () => { // Given const filePath = 'path/to/symlink'; - jest.spyOn(settings.github.repos, 'getContent').mockResolvedValue({ + jest.spyOn(settings.github.rest.repos, 'getContent').mockResolvedValue({ data: { content: null } }); @@ -416,7 +420,7 @@ repository: it('should handle 404 errors gracefully and return null', async () => { // Given const filePath = 'path/to/nonexistent.yml'; - jest.spyOn(settings.github.repos, 'getContent').mockRejectedValue({ status: 404 }); + jest.spyOn(settings.github.rest.repos, 'getContent').mockRejectedValue({ status: 404 }); // When const result = await settings.loadYaml(filePath); @@ -428,7 +432,7 @@ repository: it('should throw an error for non-404 exceptions when not in nop mode', async () => { // Given const filePath = 'path/to/error.yml'; - jest.spyOn(settings.github.repos, 'getContent').mockRejectedValue(new Error('Unexpected error')); + jest.spyOn(settings.github.rest.repos, 'getContent').mockRejectedValue(new Error('Unexpected error')); // When / Then await expect(settings.loadYaml(filePath)).rejects.toThrow('Unexpected error'); @@ -438,7 +442,7 @@ repository: // Given const filePath = 'path/to/error.yml'; settings.nop = true; - jest.spyOn(settings.github.repos, 'getContent').mockRejectedValue(new Error('Unexpected error')); + jest.spyOn(settings.github.rest.repos, 'getContent').mockRejectedValue(new Error('Unexpected error')); jest.spyOn(settings, 'appendToResults'); // When From ff5555f132b0d7f04813ef72816b8f8ca3f32640 Mon Sep 17 00:00:00 2001 From: Yadhav Jayaraman <57544838+decyjphr@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:54:40 -0400 Subject: [PATCH 4/5] Update lib/plugins/repository.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/plugins/repository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugins/repository.js b/lib/plugins/repository.js index 4fea13f8a..6d5a209fb 100644 --- a/lib/plugins/repository.js +++ b/lib/plugins/repository.js @@ -200,7 +200,7 @@ module.exports = class Repository extends ErrorStash { } this.log.info(`Rename default branch repo with settings ${JSON.stringify(parms)}`) if (this.nop) { - resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.renameBranch.endpoint(oldname, this.settings.default_branch), `Repo rename default branch to ${this.settings.default_branch}`)) + resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.renameBranch.endpoint(parms), `Repo rename default branch to ${this.settings.default_branch}`)) } else { return this.github.rest.repos.renameBranch(parms) } From e473adf9b5cd7a7c90755c3e8c7c794e9b32e31c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 16:02:08 +0000 Subject: [PATCH 5/5] fix: address review feedback - NopCommand repo arg, milestones mock, teams test error propagation Co-authored-by: decyjphr <57544838+decyjphr@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/safe-settings/sessions/d9420b15-2cca-40a3-a30b-869df73487f1 --- lib/plugins/repository.js | 6 +++--- package.json | 3 +++ test/setup.js | 14 ++++++++++++++ test/unit/lib/plugins/milestones.test.js | 2 +- test/unit/lib/plugins/teams.test.js | 11 ++++++++--- 5 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 test/setup.js diff --git a/lib/plugins/repository.js b/lib/plugins/repository.js index 6d5a209fb..8f1a3f5dc 100644 --- a/lib/plugins/repository.js +++ b/lib/plugins/repository.js @@ -125,7 +125,7 @@ module.exports = class Repository extends ErrorStash { const options = { template_owner: this.repo.owner, template_repo: this.template, owner: this.repo.owner, name: this.repo.repo, private: (this.settings.private ? this.settings.private : true), description: this.settings.description ? this.settings.description : '' } if (this.nop) { - this.log.debug(`Creating Repo using template ${JSON.stringify(this.github.rest.repos.createInOrg.endpoint(this.settings))} `) + this.log.debug(`Creating Repo using template ${JSON.stringify(this.github.rest.repos.createUsingTemplate.endpoint(options))} `) resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.createUsingTemplate.endpoint(options), 'Create Repo Using Template')) return Promise.resolve(resArray) } @@ -264,7 +264,7 @@ module.exports = class Repository extends ErrorStash { } else { this.log.debug(`Disabling Dependabot alerts for for owner: ${repoData.owner.login} and repo ${repoData.name}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.github.rest.repos.disableVulnerabilityAlerts.endpoint({ + resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.disableVulnerabilityAlerts.endpoint({ owner: repoData.owner.login, repo: repoData.name }), 'Disabling Dependabot alerts'))) @@ -302,7 +302,7 @@ module.exports = class Repository extends ErrorStash { } else { this.log.debug(`Disabling Dependabot security updates for owner: ${repoData.owner.login} and repo ${repoData.name}`) if (this.nop) { - resArray.push((new NopCommand(this.constructor.name, this.github.rest.repos.disableAutomatedSecurityFixes.endpoint({ + resArray.push((new NopCommand(this.constructor.name, this.repo, this.github.rest.repos.disableAutomatedSecurityFixes.endpoint({ owner: repoData.owner.login, repo: repoData.name }), 'Disabling Dependabot security updates'))) diff --git a/package.json b/package.json index 50ec5073e..c8aef848e 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,9 @@ }, "jest": { "testEnvironment": "node", + "setupFilesAfterEnv": [ + "/test/setup.js" + ], "reporters": [ "default", "jest-junit" diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 000000000..3bb75c781 --- /dev/null +++ b/test/setup.js @@ -0,0 +1,14 @@ +/* eslint-disable no-undef */ +// Fail tests that produce unexpected console.error output. +// This ensures that caught-but-logged errors in production code don't +// silently slip through the test suite (e.g. TypeError inside a catch block +// that logs via this.log.error = console.error). +beforeEach(() => { + jest.spyOn(console, 'error').mockImplementation((...args) => { + throw new Error(`Unexpected console.error call in test: ${args.join(' ')}`) + }) +}) + +afterEach(() => { + jest.restoreAllMocks() +}) diff --git a/test/unit/lib/plugins/milestones.test.js b/test/unit/lib/plugins/milestones.test.js index 359cd8b6f..ebbac3ddd 100644 --- a/test/unit/lib/plugins/milestones.test.js +++ b/test/unit/lib/plugins/milestones.test.js @@ -12,7 +12,7 @@ describe.skip('Milestones', () => { paginate: jest.fn().mockImplementation(() => Promise.resolve()), rest: { issues: { - listMilestonesForRepo: { + listMilestones: { endpoint: { merge: jest.fn().mockImplementation(() => {}) } diff --git a/test/unit/lib/plugins/teams.test.js b/test/unit/lib/plugins/teams.test.js index d47113076..de16965a6 100644 --- a/test/unit/lib/plugins/teams.test.js +++ b/test/unit/lib/plugins/teams.test.js @@ -23,8 +23,11 @@ describe('Teams', () => { beforeEach(() => { github = { paginate: jest.fn() - .mockImplementation(async (fetch) => { - const response = await fetch() + .mockImplementation(async (fetch, params) => { + if (typeof fetch !== 'function') { + return [] + } + const response = await fetch(params) return response.data }), rest: { @@ -43,7 +46,9 @@ describe('Teams', () => { }) } }, - request: jest.fn().mockResolvedValue() + request: Object.assign(jest.fn().mockResolvedValue(), { + endpoint: jest.fn().mockReturnValue({}) + }) } })