Skip to content

Commit

Permalink
Merge pull request #980 from repository-settings/esm-again
Browse files Browse the repository at this point in the history
Reapply "Revert "ESM support (#569)" (#587)"
  • Loading branch information
travi authored Jul 17, 2024
2 parents 2d36c8c + 220c602 commit 8da2063
Show file tree
Hide file tree
Showing 31 changed files with 527 additions and 49 deletions.
File renamed without changes.
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const mergeArrayByName = require('./lib/mergeArrayByName')
import mergeArrayByName from './lib/mergeArrayByName.js'
import SettingsApp from './lib/settings.js'

/**
* @param {import('probot').Probot} robot
*/
module.exports = (robot, _, Settings = require('./lib/settings')) => {
export default (robot, _, Settings = SettingsApp) => {
async function syncSettings (context, repo = context.repo()) {
const config = await context.config('settings.yml', {}, { arrayMerge: mergeArrayByName })
return Settings.sync(context.octokit, repo, config)
Expand Down
6 changes: 2 additions & 4 deletions lib/mergeArrayByName.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// https://github.com/KyleAMathews/deepmerge#arraymerge

const merge = require('deepmerge')
import merge from 'deepmerge'

function findMatchingIndex (sourceItem, target) {
if (Object.prototype.hasOwnProperty.call(sourceItem, 'name')) {
Expand All @@ -10,7 +10,7 @@ function findMatchingIndex (sourceItem, target) {
}
}

function mergeByName (target, source, options) {
export default function mergeByName (target, source, options) {
const destination = target.slice()

source.forEach(sourceItem => {
Expand All @@ -24,5 +24,3 @@ function mergeByName (target, source, options) {

return destination
}

module.exports = mergeByName
2 changes: 1 addition & 1 deletion lib/plugins/branches.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const previewHeaders = {
'application/vnd.github.hellcat-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.zzzax-preview+json'
}

module.exports = class Branches {
export default class Branches {
constructor (github, repo, settings) {
this.github = github
this.repo = repo
Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/collaborators.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Diffable = require('./diffable')
import Diffable from './diffable.js'

module.exports = class Collaborators extends Diffable {
export default class Collaborators extends Diffable {
constructor (...args) {
super(...args)

Expand Down
2 changes: 1 addition & 1 deletion lib/plugins/diffable.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// remove(existing) {
// }
// }
module.exports = class Diffable {
export default class Diffable {
constructor (github, repo, entries) {
this.github = github
this.repo = repo
Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/environments.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const Diffable = require('./diffable')
import Diffable from './diffable.js'

const environmentRepoEndpoint = '/repos/:org/:repo/environments/:environment_name'

Expand Down Expand Up @@ -60,7 +60,7 @@ function deploymentBranchPolicyHasChanged (existing, attrs) {
)
}

module.exports = class Environments extends Diffable {
export default class Environments extends Diffable {
constructor (...args) {
super(...args)

Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/labels.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Diffable = require('./diffable')
import Diffable from './diffable.js'
const previewHeaders = { accept: 'application/vnd.github.symmetra-preview+json' }

module.exports = class Labels extends Diffable {
export default class Labels extends Diffable {
constructor (...args) {
super(...args)

Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/milestones.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Diffable = require('./diffable')
import Diffable from './diffable.js'

module.exports = class Milestones extends Diffable {
export default class Milestones extends Diffable {
constructor (...args) {
super(...args)

Expand Down
2 changes: 1 addition & 1 deletion lib/plugins/repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const enableVulnerabilityAlerts = ({ github, settings, enabled }) => {
return github.repos[methodName](args)
}

module.exports = class Repository {
export default class Repository {
constructor (github, repo, settings) {
this.github = github
this.settings = Object.assign({ mediaType: { previews: ['baptiste'] } }, settings, repo)
Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/teams.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const Diffable = require('./diffable')
import Diffable from './diffable.js'

// it is necessary to use this endpoint until GitHub Enterprise supports
// the modern version under /orgs
const teamRepoEndpoint = '/teams/:team_id/repos/:owner/:repo'

module.exports = class Teams extends Diffable {
export default class Teams extends Diffable {
find () {
return this.github.repos.listTeams(this.repo).then(res => res.data)
}
Expand Down
26 changes: 16 additions & 10 deletions lib/settings.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
class Settings {
import Repository from './plugins/repository.js'
import Labels from './plugins/labels.js'
import Collaborators from './plugins/collaborators.js'
import Teams from './plugins/teams.js'
import Milestones from './plugins/milestones.js'
import Branches from './plugins/branches.js'
import Environments from './plugins/environments.js'

export default class Settings {
static sync (github, repo, config) {
return new Settings(github, repo, config).update()
}
Expand Down Expand Up @@ -35,13 +43,11 @@ class Settings {
Settings.FILE_NAME = '.github/settings.yml'

Settings.PLUGINS = {
repository: require('./plugins/repository'),
labels: require('./plugins/labels'),
collaborators: require('./plugins/collaborators'),
environments: require('./plugins/environments'),
teams: require('./plugins/teams'),
milestones: require('./plugins/milestones'),
branches: require('./plugins/branches')
repository: Repository,
labels: Labels,
collaborators: Collaborators,
teams: Teams,
milestones: Milestones,
branches: Branches,
environments: Environments
}

module.exports = Settings
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"version": "0.0.0-semantically-released",
"description": "Pull Requests for GitHub repository settings",
"repository": "github:repository-settings/app",
"main": "index.js",
"type": "module",
"main": "./index.js",
"exports": "./index.js",
"scripts": {
"dev": "nodemon",
"start": "probot run ./index.js",
Expand All @@ -14,7 +16,7 @@
"lint:engines": "ls-engines",
"lint:peer": "npm ls >/dev/null",
"lint:publish": "publint --strict",
"test:unit": "jest 'test/unit/'",
"test:unit": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest 'test/unit/'",
"test:unit:watch": "npm run test:unit -- --watch",
"test:integration": "run-s 'test:integration:base -- --profile noWip'",
"test:integration:base": "NODE_OPTIONS=--enable-source-maps DEBUG=any cucumber-js test/integration",
Expand Down
File renamed without changes.
76 changes: 76 additions & 0 deletions test/integration/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Probot } from 'probot'
import nock from 'nock'
import any from '@travi/any'
import settingsBot from '../../index'
import settings from '../../lib/settings'

nock.disableNetConnect()

const repository = {
default_branch: 'master',
name: 'botland',
owner: {
name: 'bkeepers-inc',
login: 'bkeepers-inc',
email: null
}
}

function loadInstance () {
const probot = new Probot({ appId: 1, privateKey: 'test', githubToken: 'test' })
probot.load(settingsBot)

return probot
}

function initializeNock () {
return nock('https://api.github.com')
}

function teardownNock (githubScope) {
expect(githubScope.pendingMocks()).toStrictEqual([])

nock.cleanAll()
}

function buildPushEvent () {
return {
name: 'push',
payload: {
ref: 'refs/heads/master',
repository,
commits: [{ modified: [settings.FILE_NAME], added: [] }]
}
}
}

function buildRepositoryEditedEvent () {
return {
name: 'repository.edited',
payload: {
changes: { default_branch: { from: any.word() } },
repository
}
}
}

function buildRepositoryCreatedEvent () {
return {
name: 'repository.created',
payload: { repository }
}
}

function buildTriggerEvent () {
return any.fromList([buildPushEvent(), buildRepositoryCreatedEvent(), buildRepositoryEditedEvent()])
}

export {
loadInstance,
initializeNock,
teardownNock,
buildTriggerEvent,
buildRepositoryCreatedEvent,
buildRepositoryEditedEvent,
repository
}
45 changes: 45 additions & 0 deletions test/integration/plugins/collaborators.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import fs from 'fs'
import { CREATED, NO_CONTENT, OK } from 'http-status-codes'
import Settings from '../../../lib/settings'
import { buildTriggerEvent, initializeNock, loadInstance, repository, teardownNock } from '../common'

describe('collaborators plugin', function () {
let probot, githubScope

beforeEach(() => {
githubScope = initializeNock()
probot = loadInstance()
})

afterEach(() => {
teardownNock(githubScope)
})

it('syncs collaborators', async () => {
const pathToConfig = new URL('../../fixtures/collaborators-config.yml', import.meta.url)
const configFile = Buffer.from(fs.readFileSync(pathToConfig, 'utf8'))
const config = configFile.toString()
githubScope
.get(`/repos/${repository.owner.name}/${repository.name}/contents/${encodeURIComponent(Settings.FILE_NAME)}`)
.reply(OK, config)
githubScope.get(`/repos/${repository.owner.name}/${repository.name}/collaborators?affiliation=direct`).reply(OK, [
{ login: 'travi', permissions: { admin: true } },
{ login: 'bkeepers', permissions: { push: true } }
])
githubScope
.put(`/repos/${repository.owner.name}/${repository.name}/collaborators/hubot`, body => {
expect(body).toMatchObject({ permission: 'pull' })
return true
})
.reply(CREATED)
githubScope
.put(`/repos/${repository.owner.name}/${repository.name}/collaborators/octokit-bot`, body => {
expect(body).toMatchObject({ permission: 'triage' })
return true
})
.reply(CREATED)
githubScope.delete(`/repos/${repository.owner.name}/${repository.name}/collaborators/travi`).reply(NO_CONTENT)

await probot.receive(buildTriggerEvent())
})
})
64 changes: 64 additions & 0 deletions test/integration/plugins/milestones.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import fs from 'fs'
import { CREATED, NO_CONTENT, OK } from 'http-status-codes'
import Settings from '../../../lib/settings'
import { buildTriggerEvent, initializeNock, loadInstance, repository, teardownNock } from '../common'

describe('milestones plugin', function () {
let probot, githubScope

beforeEach(() => {
githubScope = initializeNock()
probot = loadInstance()
})

afterEach(() => {
teardownNock(githubScope)
})

it('syncs milestones', async () => {
const pathToConfig = new URL('../../fixtures/milestones-config.yml', import.meta.url)
const configFile = Buffer.from(fs.readFileSync(pathToConfig, 'utf8'))
const config = configFile.toString()
githubScope
.get(`/repos/${repository.owner.name}/${repository.name}/contents/${encodeURIComponent(Settings.FILE_NAME)}`)
.reply(OK, config)
githubScope.patch(`/repos/${repository.owner.name}/${repository.name}`).reply(200)
githubScope.get(`/repos/${repository.owner.name}/${repository.name}/milestones?per_page=100&state=all`).reply(OK, [
{
number: 42,
title: 'existing-milestone',
description: 'this milestone should get updated',
state: 'open'
},
{
number: 8,
title: 'old-milestone',
description: 'this milestone should get deleted',
state: 'closed'
}
])
githubScope
.post(`/repos/${repository.owner.name}/${repository.name}/milestones`, body => {
expect(body).toMatchObject({
title: 'new-milestone',
description: 'this milestone should get added',
state: 'open'
})
return true
})
.reply(CREATED)
githubScope
.patch(`/repos/${repository.owner.name}/${repository.name}/milestones/42`, body => {
expect(body).toMatchObject({
title: 'existing-milestone',
description: 'this milestone should get updated',
state: 'closed'
})
return true
})
.reply(OK)
githubScope.delete(`/repos/${repository.owner.name}/${repository.name}/milestones/8`).reply(NO_CONTENT)

await probot.receive(buildTriggerEvent())
})
})
Loading

0 comments on commit 8da2063

Please sign in to comment.