Skip to content

Commit

Permalink
feat(collaborators): listen to member changes (#382)
Browse files Browse the repository at this point in the history
* fix(ConfigManager): add missing log property

* feat(collaborators): listen to member changes

Add listeners for repository collaborator events:

- member
- team

Synchronizes settings when users or teams are added, removed, and when
permissions for a member is changed.

* fix(mergedeep): hasChanges for empty source and non-empty target

Fix for empty collaborators config not removing excess members.
Using config `collaborators: []` this fix makes sure that manually
added collaborators are removed.
  • Loading branch information
anderssonjohan authored Feb 14, 2023
1 parent e2ffb51 commit b6d0029
Show file tree
Hide file tree
Showing 10 changed files with 698 additions and 33 deletions.
51 changes: 25 additions & 26 deletions app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ default_events:
# - issues
# - label
# - milestone
# - member
- member
# - membership
# - org_block
# - organization
Expand All @@ -42,10 +42,10 @@ default_events:
- repository
# - repository_import
# - status
# - team
- team
# - team_add
# - watch

# The set of permissions needed by the GitHub App. The format of the object uses
# the permission name for the key (for example, issues) and the access type for
# the value (for example, write).
Expand All @@ -54,86 +54,85 @@ default_permissions:
# Repository creation, deletion, settings, teams, and collaborators.
# https://developer.github.com/v3/apps/permissions/#permission-on-administration
administration: write

# Checks on code.
# https://developer.github.com/v3/apps/permissions/#permission-on-checks
checks: write

# Repository contents, commits, branches, downloads, releases, and merges.
# https://developer.github.com/v3/apps/permissions/#permission-on-contents
contents: write

# Deployments and deployment statuses.
# https://developer.github.com/v3/apps/permissions/#permission-on-deployments
# deployments: read

# Issues and related comments, assignees, labels, and milestones.
# https://developer.github.com/v3/apps/permissions/#permission-on-issues
issues: write

# Search repositories, list collaborators, and access repository metadata.
# https://developer.github.com/v3/apps/permissions/#metadata-permissions
metadata: read

# Retrieve Pages statuses, configuration, and builds, as well as create new builds.
# https://developer.github.com/v3/apps/permissions/#permission-on-pages
# pages: read

# Pull requests and related comments, assignees, labels, milestones, and merges.
# https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
pull_requests: write

# Manage the post-receive hooks for a repository.
# https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
# repository_hooks: read

# Manage repository projects, columns, and cards.
# https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects
# repository_projects: read

# Retrieve security vulnerability alerts.
# https://developer.github.com/v4/object/repositoryvulnerabilityalert/
# vulnerability_alerts: read

# Commit statuses.
# https://developer.github.com/v3/apps/permissions/#permission-on-statuses
statuses: write

# Organization members and teams.
# https://developer.github.com/v3/apps/permissions/#permission-on-members
members: write

# View and manage users blocked by the organization.
# https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking
# organization_user_blocking: read

# Manage organization projects, columns, and cards.
# https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects
# organization_projects: read

# Manage team discussions and related comments.
# https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions
# team_discussions: read

# Manage the post-receive hooks for an organization.
# https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks
# organization_hooks: read

# Get notified of, and update, content references.
# https://developer.github.com/v3/apps/permissions/
organization_administration: write


# The name of the GitHub App. Defaults to the name specified in package.json
name: Safe Settings

# The homepage of your GitHub App.
url: https://github.com/github/safe-settings

# A description of the GitHub App.
# description: A description of my awesome app

# Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app.
# Default: true
public: false

18 changes: 18 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,24 @@ module.exports = (robot, _, Settings = require('./lib/settings')) => {
return syncSettings(false, context)
})

const member_change_events = [
'member',
'team.added_to_repository',
'team.removed_from_repository',
'team.edited'
]
robot.on(member_change_events, async context => {
const { payload } = context
const { sender } = payload
robot.log.debug('Repository member edited by ', JSON.stringify(sender))
if (sender.type === 'Bot') {
robot.log.debug('Repository member edited by Bot')
return
}
robot.log.debug('Repository member edited by a Human')
return syncSettings(false, context)
})

robot.on('repository.edited', async context => {
const { payload } = context
const { changes, repository, sender } = payload
Expand Down
1 change: 1 addition & 0 deletions lib/configManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = class ConfigManager {
constructor (context, ref) {
this.context = context
this.ref = ref
this.log = context.log
}

/**
Expand Down
5 changes: 4 additions & 1 deletion lib/mergeDeep.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,10 @@ class MergeDeep {
modifications = this.removeEmptyAndNulls(modifications, key)
additions = this.removeEmptyAndNulls(additions, key)
}
return ({ additions, modifications, hasChanges: !this.isEmpty(additions) || !this.isEmpty(modifications) })
let hasChanges = !this.isEmpty(additions) || !this.isEmpty(modifications)
// Indicate changes when source is empty and target is not
hasChanges |= this.isEmpty(source) && !this.isEmpty(target)
return ({ additions, modifications, hasChanges })
}

validateOverride (key, baseconfig, overrideconfig) {
Expand Down
134 changes: 134 additions & 0 deletions test/fixtures/events/member.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{
"action": "edited",
"member": {
"login": "bkeepers",
"id": 173,
"avatar_url": "https://avatars.githubusercontent.com/u/173?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/bkeepers",
"html_url": "https://github.com/bkeepers",
"followers_url": "https://api.github.com/users/bkeepers/followers",
"following_url": "https://api.github.com/users/bkeepers/following{/other_user}",
"gists_url": "https://api.github.com/users/bkeepers/gists{/gist_id}",
"starred_url": "https://api.github.com/users/bkeepers/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/bkeepers/subscriptions",
"organizations_url": "https://api.github.com/users/bkeepers/orgs",
"repos_url": "https://api.github.com/users/bkeepers/repos",
"events_url": "https://api.github.com/users/bkeepers/events{/privacy}",
"received_events_url": "https://api.github.com/users/bkeepers/received_events",
"type": "User",
"site_admin": true
},
"changes": { "permission": { "from": "triage", "to": "read" } },
"repository": {
"id": 68308403,
"name": "botland",
"full_name": "bkeepers-inc/botland",
"owner": {
"name": "bkeepers-inc",
"email": null
},
"private": true,
"html_url": "https://github.com/bkeepers-inc/botland",
"description": "Playground for testing bots.",
"fork": false,
"url": "https://github.com/bkeepers-inc/botland",
"forks_url": "https://api.github.com/repos/bkeepers-inc/botland/forks",
"keys_url": "https://api.github.com/repos/bkeepers-inc/botland/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/bkeepers-inc/botland/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/bkeepers-inc/botland/teams",
"hooks_url": "https://api.github.com/repos/bkeepers-inc/botland/hooks",
"issue_events_url": "https://api.github.com/repos/bkeepers-inc/botland/issues/events{/number}",
"events_url": "https://api.github.com/repos/bkeepers-inc/botland/events",
"assignees_url": "https://api.github.com/repos/bkeepers-inc/botland/assignees{/user}",
"branches_url": "https://api.github.com/repos/bkeepers-inc/botland/branches{/branch}",
"tags_url": "https://api.github.com/repos/bkeepers-inc/botland/tags",
"blobs_url": "https://api.github.com/repos/bkeepers-inc/botland/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/bkeepers-inc/botland/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/bkeepers-inc/botland/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/bkeepers-inc/botland/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/bkeepers-inc/botland/statuses/{sha}",
"languages_url": "https://api.github.com/repos/bkeepers-inc/botland/languages",
"stargazers_url": "https://api.github.com/repos/bkeepers-inc/botland/stargazers",
"contributors_url": "https://api.github.com/repos/bkeepers-inc/botland/contributors",
"subscribers_url": "https://api.github.com/repos/bkeepers-inc/botland/subscribers",
"subscription_url": "https://api.github.com/repos/bkeepers-inc/botland/subscription",
"commits_url": "https://api.github.com/repos/bkeepers-inc/botland/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/bkeepers-inc/botland/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/bkeepers-inc/botland/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/bkeepers-inc/botland/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/bkeepers-inc/botland/contents/{+path}",
"compare_url": "https://api.github.com/repos/bkeepers-inc/botland/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/bkeepers-inc/botland/merges",
"archive_url": "https://api.github.com/repos/bkeepers-inc/botland/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/bkeepers-inc/botland/downloads",
"issues_url": "https://api.github.com/repos/bkeepers-inc/botland/issues{/number}",
"pulls_url": "https://api.github.com/repos/bkeepers-inc/botland/pulls{/number}",
"milestones_url": "https://api.github.com/repos/bkeepers-inc/botland/milestones{/number}",
"notifications_url": "https://api.github.com/repos/bkeepers-inc/botland/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/bkeepers-inc/botland/labels{/name}",
"releases_url": "https://api.github.com/repos/bkeepers-inc/botland/releases{/id}",
"deployments_url": "https://api.github.com/repos/bkeepers-inc/botland/deployments",
"created_at": 1473954711,
"updated_at": "2016-12-19T19:41:29Z",
"pushed_at": 1484891974,
"git_url": "git://github.com/bkeepers-inc/botland.git",
"ssh_url": "git@github.com:bkeepers-inc/botland.git",
"clone_url": "https://github.com/bkeepers-inc/botland.git",
"svn_url": "https://github.com/bkeepers-inc/botland",
"homepage": "",
"size": 1,
"stargazers_count": 0,
"watchers_count": 0,
"language": "JavaScript",
"has_issues": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 0,
"mirror_url": null,
"open_issues_count": 6,
"forks": 0,
"open_issues": 6,
"watchers": 0,
"default_branch": "master",
"stargazers": 0,
"master_branch": "master",
"organization": "bkeepers-inc"
},
"organization": {
"login": "bkeepers-inc",
"id": 11724939,
"url": "https://api.github.com/orgs/bkeepers-inc",
"repos_url": "https://api.github.com/orgs/bkeepers-inc/repos",
"events_url": "https://api.github.com/orgs/bkeepers-inc/events",
"hooks_url": "https://api.github.com/orgs/bkeepers-inc/hooks",
"issues_url": "https://api.github.com/orgs/bkeepers-inc/issues",
"members_url": "https://api.github.com/orgs/bkeepers-inc/members{/member}",
"public_members_url": "https://api.github.com/orgs/bkeepers-inc/public_members{/member}",
"avatar_url": "https://avatars.githubusercontent.com/u/11724939?v=3",
"description": null
},
"sender": {
"login": "bkeepers",
"id": 173,
"avatar_url": "https://avatars.githubusercontent.com/u/173?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/bkeepers",
"html_url": "https://github.com/bkeepers",
"followers_url": "https://api.github.com/users/bkeepers/followers",
"following_url": "https://api.github.com/users/bkeepers/following{/other_user}",
"gists_url": "https://api.github.com/users/bkeepers/gists{/gist_id}",
"starred_url": "https://api.github.com/users/bkeepers/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/bkeepers/subscriptions",
"organizations_url": "https://api.github.com/users/bkeepers/orgs",
"repos_url": "https://api.github.com/users/bkeepers/repos",
"events_url": "https://api.github.com/users/bkeepers/events{/privacy}",
"received_events_url": "https://api.github.com/users/bkeepers/received_events",
"type": "User",
"site_admin": true
},
"installation": {
"id": 6274
}
}
Loading

0 comments on commit b6d0029

Please sign in to comment.