From 2a93caef540fc75b3c9c40754312a3bf9bde1387 Mon Sep 17 00:00:00 2001 From: Nick Walters Date: Wed, 15 Nov 2023 12:05:47 +0000 Subject: [PATCH] Remove full org member code from repository (#106) * Commit changes made by code formatters --------- Co-authored-by: Operations Engineering Bot --- README.md | 10 +- lib/constants.rb | 44 +- lib/github_collaborators.rb | 45 +- .../archived_repositories.rb | 33 -- lib/github_collaborators/full_org_member.rb | 367 ---------------- .../full_org_member_expired.rb | 48 --- .../full_org_member_expires_soon.rb | 48 --- .../odd_full_org_members.rb | 33 -- lib/github_collaborators/organization.rb | 206 +-------- .../outside_collaborators.rb | 250 +---------- lib/github_collaborators/terraform_files.rb | 168 +------- lib/helper_module.rb | 375 +---------------- locals.tf | 2 +- spec/archived_repositories_spec.rb | 25 -- spec/close_expired_issues_spec.rb | 90 +--- spec/create_pr_from_issue_spec.rb | 8 +- spec/full_org_member_expired_spec.rb | 50 --- spec/full_org_member_expires_soon_spec.rb | 50 --- spec/full_org_member_spec.rb | 394 ------------------ spec/helper_module_spec.rb | 358 +--------------- spec/odd_full_org_members_spec.rb | 25 -- spec/organization_members_spec.rb | 65 --- spec/organization_spec.rb | 237 ----------- spec/outside_collaborators_spec.rb | 374 +---------------- spec/slack_notifier_spec.rb | 6 +- spec/terraform_block_spec.rb | 58 +-- spec/terraform_file_spec.rb | 99 ++--- spec/terraform_files_spec.rb | 58 --- spec/test_constants.rb | 7 +- spec/test_helper_module.rb | 39 -- 30 files changed, 111 insertions(+), 3461 deletions(-) delete mode 100644 lib/github_collaborators/archived_repositories.rb delete mode 100644 lib/github_collaborators/full_org_member.rb delete mode 100644 lib/github_collaborators/full_org_member_expired.rb delete mode 100644 lib/github_collaborators/full_org_member_expires_soon.rb delete mode 100644 lib/github_collaborators/odd_full_org_members.rb delete mode 100644 spec/archived_repositories_spec.rb delete mode 100644 spec/full_org_member_expired_spec.rb delete mode 100644 spec/full_org_member_expires_soon_spec.rb delete mode 100644 spec/full_org_member_spec.rb delete mode 100644 spec/odd_full_org_members_spec.rb delete mode 100644 spec/organization_members_spec.rb diff --git a/README.md b/README.md index 9925fc3..1bc06f0 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,6 @@ If you are not confident working with Terraform, you can raise an issue using th > PRs from forks do NOT work with the current automated process, please only create PRs from a branch. -## Full Org Members who are Collaborators - -Certain Collaborators need full MoJ GitHub Organization membership so that they can be added to a GitHub team for various reasons. These users still need to be tracked within this repository. Once the collaborator is added to one .tf file in the terraform folder the application will detect that the user is both a collaborator and a full Org member. The application will track which repositories the user has access to and create either a pull request to add or remove the collaborator from the matching .tf file in the terraform folder. - -These pull requests can be automatically approved by a member of the team because access has already been granted via a team or access has been revoked for the team. When a pull request to add a user to a .tf is merged in and tf apply is executed, Terraform adds the collaborator to the repository as a direct user. This means the user will have direct access and access via a team to the repository. - -A member of the team **must** manually remove the users direct access to the repository after tf apply has finished. Failure to remove the user will result in the Operations-Engineering repository automation moving that user into a new or existing repository autogenerated team. This will mean the user will be added to the repository via two teams. If the user is removed from the original team then the application will not be able to tell that the user's original access has been reverted and their access in the .tf file should be revoked as well. Full Org members still have a review date. When the review date is ready for renewal a PR to remove the user will be created one week before. This is time to review whether the user still requires access to the repository and full Org membership. - ## Background Sometimes we need to grant access to one of more of our GitHub repositories to people who are not part of the "moj-analytical-services" GitHub organisation. This often happens when we engage third-party suppliers to carry out work on our behalf. @@ -101,7 +93,7 @@ Here's an example: email = "name@acme.com" org = "Acme. Corp." reason = "Acme are building some stuff for us" - added_by = "Team Name " + added_by = "team-name@digital.justice.gov.uk" review_after = "2021-11-26" }, ] diff --git a/lib/constants.rb b/lib/constants.rb index d33e668..1ab3d79 100644 --- a/lib/constants.rb +++ b/lib/constants.rb @@ -9,20 +9,14 @@ module Constants # Name of the repository REPO_NAME = "github-outside-collaborators" - # Operations Engineering Bot account email address - ADDED_BY_EMAIL = "opseng-bot@digital.justice.gov.uk" - # GitHub Bot account email address GITHUB_BOT_EMAIL = "github-actions[bot]@users.noreply.github.com" # Operations Engineering Bot name OPS_ENG_BOT_NAME = "Operations Engineering Bot" - # The reason why a full organisation collaborator is missing from a Terraform file - REASON1 = "Full Org member / collaborator missing from Terraform file" - # The reason why a collaborator is missing from a Terraform file - REASON2 = "Collaborator missing from Terraform file" + REASON1 = "Collaborator missing from Terraform file" # The Terraform files to exclude, these are not part of the app EXCLUDE_FILES = ["main.tf", "variables.tf", "versions.tf", "backend.tf"] @@ -45,15 +39,6 @@ module Constants # Pull request type TYPE_REMOVE = "remove" - # Pull request type - TYPE_REMOVE_FULL_ORG_MEMBER = "remove_full_org_member" - - # Pull request type - TYPE_PERMISSION = "permission" - - # Pull request type - TYPE_ADD = "add" - # Pull request type TYPE_ADD_FROM_ISSUE = "add_from_issue" @@ -66,15 +51,9 @@ module Constants # Github issue title COLLABORATOR_EXPIRES_SOON = "Collaborator review date expires soon for user" - # Github issue title - COLLABORATOR_EXPIRY_UPCOMING = "Review after date expiry is upcoming for user" - # Github issue title DEFINE_COLLABORATOR_IN_CODE = "Please define outside collaborators in code" - # Github issue title - USE_TEAM_ACCESS = "User access removed, access is now via a team" - # App internal issue REVIEW_DATE_WITHIN_MONTH = "Review after date is within a month" @@ -90,12 +69,6 @@ module Constants # Pull request title EMPTY_FILES_PR_TITLE = "Delete empty Terraform file/s" - # Pull request title - ADD_FULL_ORG_MEMBER_PR_TITLE = "Add full Org member / collaborator to Terraform file/s for" - - # Pull request title - REMOVE_FULL_ORG_MEMBER_PR_TITLE = "Remove full Org member collaborator from Terraform file/s for" - # Pull request title ADD_COLLAB_FROM_ISSUE = "Add collaborator to Terraform file/s from Issue for" @@ -105,9 +78,6 @@ module Constants # Pull request title REMOVE_EXPIRED_COLLABORATOR_PR_TITLE = "Remove expired collaborator from Terraform file/s for" - # Pull request title - CHANGE_PERMISSION_PR_TITLE = "Modify permission in Terraform file/s for" - # Pull request title ARCHIVED_REPOSITORY_PR_TITLE = "Delete archived repository Terraform file/s" @@ -162,15 +132,6 @@ module Constants # Branch name REMOVE_EXPIRED_COLLABORATORS_BRANCH_NAME = "remove-expired-collaborator-" - # Branch name - MODIFY_COLLABORATORS_BRANCH_NAME = "modify-collaborator-permission-" - - # Branch name - ADD_COLLABORATOR_BRANCH_NAME = "add-collaborator-" - - # Branch name - REMOVE_FULL_ORG_MEMBER_BRANCH_NAME = "remove-full-org-member-" - # Organization name ORG = "moj-analytical-services" @@ -234,9 +195,6 @@ module Constants # Line offset number REVIEW_AFTER = 7 - # Description given to automated generated teams - AUTOMATED_GENERATED_TEAM = "Automated generated team to grant users access to this repository" - # Notify template ID value EXPIRE_EMAIL_TEMPLATE_ID = "7a23a323-5b67-4793-a682-3cb2c6bae9b7" diff --git a/lib/github_collaborators.rb b/lib/github_collaborators.rb index 97db195..a24a20f 100644 --- a/lib/github_collaborators.rb +++ b/lib/github_collaborators.rb @@ -10,28 +10,23 @@ require "uuidtools" require "logger" require "notifications/client" -require_relative "./constants" -require_relative "./logging" -require_relative "./helper_module" -require_relative "./github_collaborators/archived_repositories" -require_relative "./github_collaborators/branch_creator" -require_relative "./github_collaborators/collaborator" -require_relative "./github_collaborators/expired" -require_relative "./github_collaborators/expires_soon" -require_relative "./github_collaborators/full_org_member_expired" -require_relative "./github_collaborators/full_org_member_expires_soon" -require_relative "./github_collaborators/full_org_member" -require_relative "./github_collaborators/github_graph_ql_client" -require_relative "./github_collaborators/http_client" -require_relative "./github_collaborators/notify_client" -require_relative "./github_collaborators/odd_full_org_members" -require_relative "./github_collaborators/organization" -require_relative "./github_collaborators/outside_collaborators" -require_relative "./github_collaborators/removed" -require_relative "./github_collaborators/repository" -require_relative "./github_collaborators/slack_notifier" -require_relative "./github_collaborators/terraform_files" -require_relative "./github_collaborators/unknown_collaborators" -require_relative "./github_collaborators/undelivered_approver_notify_email" -require_relative "./github_collaborators/undelivered_expire_notify_email" -require_relative "./create_pr_from_issue" +require_relative "constants" +require_relative "logging" +require_relative "helper_module" +require_relative "github_collaborators/branch_creator" +require_relative "github_collaborators/collaborator" +require_relative "github_collaborators/expired" +require_relative "github_collaborators/expires_soon" +require_relative "github_collaborators/github_graph_ql_client" +require_relative "github_collaborators/http_client" +require_relative "github_collaborators/notify_client" +require_relative "github_collaborators/organization" +require_relative "github_collaborators/outside_collaborators" +require_relative "github_collaborators/removed" +require_relative "github_collaborators/repository" +require_relative "github_collaborators/slack_notifier" +require_relative "github_collaborators/terraform_files" +require_relative "github_collaborators/unknown_collaborators" +require_relative "github_collaborators/undelivered_approver_notify_email" +require_relative "github_collaborators/undelivered_expire_notify_email" +require_relative "create_pr_from_issue" diff --git a/lib/github_collaborators/archived_repositories.rb b/lib/github_collaborators/archived_repositories.rb deleted file mode 100644 index 07767ed..0000000 --- a/lib/github_collaborators/archived_repositories.rb +++ /dev/null @@ -1,33 +0,0 @@ -# The GithubCollaborators class namespace -class GithubCollaborators - # The ArchivedRepositories class - class ArchivedRepositories - include Logging - - # Creates a line to be used within a Slack message using app data - # - # @param collaborator [Hash{login => String, repository => String}] the collaborator data - # @return [String] the formatted string - def create_line(collaborator) - logger.debug "create_line" - "- #{collaborator[:login].downcase} in #{collaborator[:repository].downcase}" - end - - # Creates the first line to be used within a Slack message when a single - # collaborator is reported by the Slack message - # - # @return [String] the formatted string - def singular_message - "I've found a collaborator who is a full Org member attached to an archived repository. Un-archive the repository and remove this collaborator" - end - - # Creates the first line to be used within a Slack message when a multiple - # collaborators are reported by the Slack message - # - # @param collaborators [Numeric] the number of collaborators in the message - # @return [String] the formatted string - def multiple_message(collaborators) - "I've found #{collaborators} collaborators who are full Org members attached to archived repositories. Un-archive the repositories and remove these collaborators" - end - end -end diff --git a/lib/github_collaborators/full_org_member.rb b/lib/github_collaborators/full_org_member.rb deleted file mode 100644 index db2e184..0000000 --- a/lib/github_collaborators/full_org_member.rb +++ /dev/null @@ -1,367 +0,0 @@ -# The GithubCollaborators class namespace -class GithubCollaborators - # The FullOrgMember class - class FullOrgMember - include Logging - include HelperModule - attr_reader :login, :email, :org, :name, :missing_from_repositories, :removed_from_repositories, :repository_permission_mismatches, :attached_archived_repositories, :github_repositories, :terraform_repositories, :github_archived_repositories, :ignore_repositories, :everyone_team_repositories - - # This class covers collaborators that are full Organization members - # Full Organization members have access to repositories via Organization teams. - # We need to track these collaborators. - # Tracking these collaborators increases the App complexity. - # Because collaborator can be in a team, their permission to the repository can be different to the Terraform file. - - def initialize(login) - logger.debug "initialize" - - # Store the repositories the collaborator is associated within this array - # This is updated by a query directly on the collaborator - # Array - @github_repositories = [] - - # Store the Terraform files related repositories the collaborator is associated within this array - # This is updated by reading each Terraform file - # Array - @terraform_repositories = [] - - # This array will store the repositories where the collaborator is not defined in Terraform files - # Array - @missing_from_repositories = [] - - # This array will store the Github repositories where the collaborator has been removed - # Array - @removed_from_repositories = [] - - # This array stores the everyone team repositories - # Array - @everyone_team_repositories = [] - - # This array stores which repositories have a permission mismatch, meaning the team has different permissions - # Array[Hash{ permission => String, repository_name => String }] - @repository_permission_mismatches = [] - - # This array stores which repositories the full org member has been newly added to a Terraform file, - # because they were missing from that Terraform file. The reason for this array is because the Terraform - # file may not exist until a pull request has been created and merged in. - # Array - @ignore_repositories = [] - - # This array stores the Organization repositories that have been archived. This array of repositories is - # used to check if the collaborator has access to archived repositories. - # Array - @github_archived_repositories = [] - - # This array stores which Organization repositories the collaborator has access to. - # Array - @attached_archived_repositories = [] - - @login = login.downcase - @email = "" - @name = "" - @org = "" - end - - # Add new values to the collaborator - # - # @param email [String] the new email address - # @param name [String] the new collaborator name - # @param org [String] the new organization name - def add_info_from_file(email, name, org) - logger.debug "add_info_from_file" - @email = email.downcase - @name = name.downcase - @org = org.downcase - end - - # Add a repository name to the ignore repositories array - # - # @param repository_name [String] the repository name - def add_ignore_repository(repository_name) - logger.debug "add_ignore_repository" - @ignore_repositories.push(repository_name.downcase) - ignore_repositories.sort! - ignore_repositories.uniq! - end - - # Add repository names to the everyone team repositories array - # - # @param repositories [Array] the repository names - def add_everyone_team_repositories(repositories) - logger.debug "add_everyone_team_repositories" - @everyone_team_repositories = repositories - @everyone_team_repositories.sort! - @everyone_team_repositories.uniq! - end - - # Add repository name to the github repositories array - # - # @param repositories [String] the repository name - def add_github_repository(repository_name) - logger.debug "add_github_repository" - @github_repositories.append(repository_name) - @github_repositories.sort! - @github_repositories.uniq! - end - - # Add repository names to the archived repositories array - # - # @param repositories [Array] the repository names - def add_archived_repositories(repositories) - logger.debug "add_archived_repositories" - @github_archived_repositories = repositories - @github_archived_repositories.sort! - @github_archived_repositories.uniq! - end - - # Add names of Terraform file to the terraform repositories array - # - # @param terraform_repositories [Array] the repository names - def add_terraform_repositories(terraform_repositories) - logger.debug "add_terraform_repositories" - terraform_repositories.each do |terraform_repository_name| - # Ignore excluded repositories ie the everyone team repositories and archived repositories - # This is to focus on active repositories that should be tracked - if !@everyone_team_repositories.include?(terraform_repository_name.downcase) && !@github_archived_repositories.include?(terraform_repository_name.downcase) - @terraform_repositories.push(terraform_repository_name.downcase) - end - end - @terraform_repositories.sort! - @terraform_repositories.uniq! - end - - # A check too see if the collaborator is attached to no repositories - # - # @return [Bool] true if collaborator is not attached to any repositories or defined in a Terraform file - def odd_full_org_member_check - logger.debug "odd_full_org_members" - if (@github_repositories.length == 0 || @terraform_repositories.length == 0) && @everyone_team_repositories.length == 0 - return true - end - false - end - - # Collect which GitHub repository names the collaborator is attached to - # - def get_full_org_member_repositories - logger.debug "get_full_org_member_repositories" - end_cursor = nil - graphql = GithubCollaborators::GithubGraphQlClient.new - repositories = [] - - loop do - response = graphql.run_query(full_org_member_query(end_cursor)) - json_data = JSON.parse(response) - repos = json_data.dig("data", "user", "repositories", "edges") - repositories += repos - end_cursor = json_data.dig("data", "user", "repositories", "pageInfo", "endCursor") - break unless json_data.dig("data", "user", "repositories", "pageInfo", "hasNextPage") - end - - repositories.each do |repo| - # Accept only moj-analytical-services repositories - if repo.dig("node", "owner", "login").downcase == ORG - repository_name = repo.dig("node", "name").downcase - - # Filter out repositories from the everyone team and archived repositories - if !is_repo_already_known(repository_name) - # Store new repository - add_github_repository(repository_name) - end - - # Store which archived repositories the collaborator is attached to - # App will raise Slack alerts for this later on - if @github_archived_repositories.include?(repository_name) - add_attached_archived_repository(repository_name) - end - end - end - end - - # Add the repository name to the attached archived array - # - # @param repository_name [String] the repository name - def add_attached_archived_repository(repository_name) - logger.debug "add_attached_archived_repository" - @attached_archived_repositories.push(repository_name) - @attached_archived_repositories.sort! - @attached_archived_repositories.uniq! - end - - # Check if the collaborator is defined in the same repositories on GitHub and within the Terraform files - # - # @return [Bool] true if collaborator repositories on GitHub and in Terraform files match each other - def missing_from_terraform_files - logger.debug "missing_from_terraform_files" - - # Join the two arrays - repositories = @github_repositories + @terraform_repositories - repositories.uniq! - repositories.sort! - - repositories.each do |repository_name| - repository_name = repository_name.downcase - # expect to find the repository name on GitHub but not in a Terraform file - # Filter out repositories from the everyone team and archived repositories - if @github_repositories.count(repository_name) > 0 && - @terraform_repositories.count(repository_name) == 0 && - !is_repo_already_known(repository_name) - @missing_from_repositories.push(repository_name) - end - end - - # Result is based on any missing repositories - if @missing_from_repositories.length == 0 - return false - end - true - end - - # Check if the full org member has been removed from any GitHub repositories - # - # @return [Bool] true if full org member exists in a Terraform file but is missing from the Github repository - def removed_from_github_repository - logger.debug "removed_from_github_repository" - removed_repositories = [] - - # Join the two arrays - repositories = @github_repositories + @terraform_repositories - repositories.uniq! - repositories.sort! - - repositories.each do |repository_name| - repository_name = repository_name.downcase - # expect to find the repository name in a Terraform file but not on Github - if @terraform_repositories.count(repository_name) > 0 && - @github_repositories.count(repository_name) == 0 - removed_repositories.push(repository_name) - end - end - - if removed_repositories.length > 0 - removed_repositories.each do |repository_name| - repository_name = repository_name.downcase - # filter out the everyone team team repositories - if !@everyone_team_repositories.include?(repository_name) - @removed_from_repositories.push(repository_name) - end - end - - @removed_from_repositories.sort! - @removed_from_repositories.uniq! - end - - if @removed_from_repositories.length == 0 - return false - end - true - end - - # Check collaborator for permissions mismatches between GitHub and the Terraform files - # - # @param terraform_files_obj [Array] the terraform file objects - # @return [Bool] true if a permission mismatch exists - def mismatched_repository_permissions_check(terraform_files_obj) - logger.debug "mismatched_repository_permissions_check" - - permission_mismatch = false - # Search through the collaborators repositories - @github_repositories.each do |github_repository_name| - github_repository_name = github_repository_name.downcase - # Find the matching Terraform file - terraform_files = terraform_files_obj.get_terraform_files - terraform_files.each do |terraform_file| - # Skip this iteration if file name is in the ignore array, the ignore array - # contains repositories / Terraform files that are not on the GitHub yet - if !@ignore_repositories.include?(terraform_file.filename.downcase) && terraform_file.filename.downcase == tf_safe(github_repository_name) - - # Get the github permission for that repository - github_permission = get_repository_permission(github_repository_name) - - # Get the permission for the Terraform file - terraform_permission = terraform_file.get_collaborator_permission(@login) - - if github_permission != terraform_permission - permission_mismatch = true - # Store values as a hash like this { permission: "granted_permission", repository_name: "repo_name" } - @repository_permission_mismatches.push({permission: github_permission.to_s, repository_name: github_repository_name.to_s}) - end - end - end - end - permission_mismatch - end - - # Get the collaborator permission for a specific repository name - # - # @param repository_name [String] the repository name - # @return [String] the collaborator repository permission value - def get_repository_permission(repository_name) - logger.debug "get_repository_permission" - url = "#{GH_API_URL}/#{repository_name.downcase}/collaborators/#{@login}/permission" - json = GithubCollaborators::HttpClient.new.fetch_json(url) - json_data = JSON.parse(json) - if json_data.dig("user", "permissions", "admin") - "admin" - elsif json_data.dig("user", "permissions", "maintain") - "maintain" - elsif json_data.dig("user", "permissions", "push") - "push" - elsif json_data.dig("user", "permissions", "triage") - "triage" - else - "pull" - end - end - - private - - # Check if repository name is in arrays that store repository names for various reasons - # This includes the everyone team and archived array of repository names - # The reason for this is to focus on active repositories that should be tracked and filter - # out those that do not need to be - # - # @param repository_name [String] the repository name - # @return [Bool] true if the repository name is in the archived array or everyone team array of repositories - def is_repo_already_known(repository_name) - if @everyone_team_repositories.include?(repository_name) || @github_archived_repositories.include?(repository_name) - return true - end - false - end - - # Create a GraphQL query that returns the repository names the collaborators has access to - # - # @param end_cursor [String] id of next page in search results - # @return [String] the GraphQL query - def full_org_member_query(end_cursor) - logger.debug "full_org_member_query" - after = end_cursor.nil? ? "null" : "\"#{end_cursor}\"" - %[ - { - user(login: "#{@login}") { - repositories( - affiliations: ORGANIZATION_MEMBER - ownerAffiliations: ORGANIZATION_MEMBER - first: 100 - after: #{after} - ) { - edges { - node { - name - owner { - login - } - } - } - pageInfo { - endCursor - hasNextPage - } - } - } - } - ] - end - end -end diff --git a/lib/github_collaborators/full_org_member_expired.rb b/lib/github_collaborators/full_org_member_expired.rb deleted file mode 100644 index a334c57..0000000 --- a/lib/github_collaborators/full_org_member_expired.rb +++ /dev/null @@ -1,48 +0,0 @@ -# The GithubCollaborators class namespace -class GithubCollaborators - # The FullOrgMemberExpired class - class FullOrgMemberExpired - include Logging - - # Creates a line to be used within a Slack message using app data - # - # @param collaborator [GithubCollaborators::Collaborator] a collaborator object - # @return [String] the formatted string - def create_line(collaborator) - logger.debug "create_line" - - review_date = collaborator.review_after_date - if review_date.nil? || review_date == "" - review_date = Date.today - end - - age = (Date.today - review_date).to_i - - expired_when = if review_date == Date.today - "today" - elsif age == 1 - "yesterday" - else - "#{age} days ago" - end - "- #{collaborator.login.downcase} in <#{collaborator.repo_url.downcase}|#{collaborator.repository.downcase}> see <#{collaborator.href}|terraform file> (#{expired_when})" - end - - # Creates the first line to be used within a Slack message when a single - # collaborator is reported by the Slack message - # - # @return [String] the formatted string - def singular_message - "I've found a full Org member / collaborator whose review date has expired, a pull request has been created to remove the collaborator from the Terraform file/s. Manually remove the collaborator from the repository" - end - - # Creates the first line to be used within a Slack message when a multiple - # collaborators are reported by the Slack message - # - # @param collaborators [Numeric] the number of collaborators in the message - # @return [String] the formatted string - def multiple_message(collaborators) - "I've found #{collaborators} full Org members / collaborators whose review dates have expired, pull requests have been created to remove these collaborators from the Terraform file/s. Manually remove the collaborator from the repository" - end - end -end diff --git a/lib/github_collaborators/full_org_member_expires_soon.rb b/lib/github_collaborators/full_org_member_expires_soon.rb deleted file mode 100644 index 84366ce..0000000 --- a/lib/github_collaborators/full_org_member_expires_soon.rb +++ /dev/null @@ -1,48 +0,0 @@ -# The GithubCollaborators class namespace -class GithubCollaborators - # The FullOrgMemberExpiresSoon class - class FullOrgMemberExpiresSoon - include Logging - - # Creates a line to be used within a Slack message using app data - # - # @param collaborator [GithubCollaborators::Collaborator] a collaborator object - # @return [String] the formatted string - def create_line(collaborator) - logger.debug "create_line" - - review_date = collaborator.review_after_date - if review_date.nil? || review_date == "" - review_date = Date.today - end - - age = (review_date - Date.today).to_i - - expires_when = if review_date == Date.today - "today" - elsif age == 1 - "tomorrow" - else - "in #{age} days" - end - "- #{collaborator.login.downcase} in <#{collaborator.repo_url.downcase}|#{collaborator.repository.downcase}> see <#{collaborator.href}|terraform file> (#{expires_when})" - end - - # Creates the first line to be used within a Slack message when a single - # collaborator is reported by the Slack message - # - # @return [String] the formatted string - def singular_message - "I've found a collaborator who is a full Org member whose review date will expire shortly, a pull request has been created to extend the date for this collaborator" - end - - # Creates the first line to be used within a Slack message when a multiple - # collaborators are reported by the Slack message - # - # @param collaborators [Numeric] the number of collaborators in the message - # @return [String] the formatted string - def multiple_message(collaborators) - "I've found #{collaborators} collaborators who are full Org members whose review date will expire shortly, pull requests have been created to extend the date for these collaborators" - end - end -end diff --git a/lib/github_collaborators/odd_full_org_members.rb b/lib/github_collaborators/odd_full_org_members.rb deleted file mode 100644 index 44f13b3..0000000 --- a/lib/github_collaborators/odd_full_org_members.rb +++ /dev/null @@ -1,33 +0,0 @@ -# The GithubCollaborators class namespace -class GithubCollaborators - # The OddFullOrgMembers class - class OddFullOrgMembers - include Logging - - # Creates a line to be used within a Slack message using app data - # - # @param collaborator [String] the collaborator login name - # @return [String] the formatted string - def create_line(collaborator) - logger.debug "create_line" - "- #{collaborator.downcase}" - end - - # Creates the first line to be used within a Slack message when a single - # collaborator is reported by the Slack message - # - # @return [String] the formatted string - def singular_message - "I've found a collaborator who is a full Org member but isn't attached to any GitHub repositories except the everyone team respositories. Consider removing this collaborator" - end - - # Creates the first line to be used within a Slack message when a multiple - # collaborators are reported by the Slack message - # - # @param collaborators [Numeric] the number of collaborators in the message - # @return [String] the formatted string - def multiple_message(collaborators) - "I've found #{collaborators} collaborators who are full Org members but are not attached to any GitHub repositories except the everyone team respositories. Consider removing these collaborators" - end - end -end diff --git a/lib/github_collaborators/organization.rb b/lib/github_collaborators/organization.rb index 8036fa4..397528d 100644 --- a/lib/github_collaborators/organization.rb +++ b/lib/github_collaborators/organization.rb @@ -4,7 +4,7 @@ class GithubCollaborators class Organization include Logging include HelperModule - attr_reader :repositories, :full_org_members, :archived_repositories + attr_reader :repositories, :archived_repositories def initialize logger.debug "initialize" @@ -13,10 +13,6 @@ def initialize # Array @outside_collaborators = get_org_outside_collaborators - # This is a list of Organization member login names - # Array - @organization_members = get_all_organisation_members - # This is a list of Organization archived repository names # Array @archived_repositories = get_archived_repositories @@ -27,15 +23,6 @@ def initialize # This is the number of Organization outside collaborators @github_collaborators = @outside_collaborators.length - - # This is an list of the FullOrgMember objects who are collaborators - # that have full Org membership - # Array - @full_org_members = [] - - # This is a list of the everyone team repositories - # Array - @everyone_team_repositories = get_everyone_team_repositories end # Get the Organization archived repository name @@ -46,169 +33,6 @@ def get_org_archived_repositories @archived_repositories end - # See if a specific collaborator is an outside collaborator that - # also has full Organization membership - # - # @param collaborator_name [String] the name of the collaborator - # @return [Bool] true if find collaborator who is a full Organization member - def is_collaborator_a_full_org_member(collaborator_name) - logger.debug "is_collaborator_a_full_org_member" - user_exists = false - @full_org_members.each do |full_org_member| - if full_org_member.login.downcase == collaborator_name.downcase - user_exists = true - end - end - user_exists - end - - # See if a specific login name is a Organization member - # - # @param login [String] the login name to check - # @return [Bool] true if find Organization member with same login name - def is_collaborator_an_org_member(login) - logger.debug "is_collaborator_an_org_member" - # Loop through all the org members - login = login.downcase - @organization_members.each do |org_member| - # See if collaborator name is in the org members list - if org_member.downcase == login - add_new_full_org_member(login) - return true - end - end - false - end - - # Create a FullOrgMember object and add it to the full_org_members array - # - # @param login [String] the login name of FullOrgMember - def add_full_org_member(login) - logger.debug "add_full_org_member" - full_org_member = GithubCollaborators::FullOrgMember.new(login.downcase) - @full_org_members.push(full_org_member) - end - - # Create all the Organization FullOrgMember objects and populate those objects. - # The Terraform file collaborators are used as the base to find out which - # collaborators are FullOrgMembers and thus be turned into FullOrgMember objects. - # - # @param terraform_collaborators [Array] the Terraform file collaborators - def create_full_org_members(terraform_collaborators) - logger.debug "create_full_org_members" - - # FullOrgMember objects are created within is_collaborator_an_org_member() when a full org member is detected - terraform_collaborators.each { |collaborator| is_collaborator_an_org_member(collaborator.login.downcase) } - - # Iterate over the list of FullOrgMember objects - @full_org_members.each do |full_org_member| - # Add the everyone team repositories - full_org_member.add_everyone_team_repositories(@everyone_team_repositories) - - # Add the archived repositories - full_org_member.add_archived_repositories(@archived_repositories) - - # Collect the GitHub and Terraform repositories for each full org member - - # Get the GitHub repositories - full_org_member.get_full_org_member_repositories - - # Get the repository names where collaborator is defined in Terraform files - tc_repositories = [] - collaborator_repositories = terraform_collaborators.select { |terraform_collaborator| terraform_collaborator.login.downcase == full_org_member.login.downcase } - collaborator_repositories.each do |collaborator| - tc_repositories.push(collaborator.repository.downcase) - end - - # Add the repositories names to the object - full_org_member.add_terraform_repositories(tc_repositories) - - # When collaborators already defined in Terraform files, parse them - # to get additional information about the full org member - if does_collaborator_already_exist(full_org_member.login.downcase, terraform_collaborators) - name = get_name(full_org_member.login, terraform_collaborators) - email = get_email(full_org_member.login, terraform_collaborators) - org = get_org(full_org_member.login, terraform_collaborators) - full_org_member.add_info_from_file(email, name, org) - end - end - end - - # Find which FullOrgMembers are not defined in a Terraform file - # - # @return [Array] a list of FullOrgMember objects - def get_full_org_members_not_in_terraform_file - logger.debug "get_full_org_members_not_in_terraform_file" - return_list = [] - @full_org_members.each do |full_org_member| - # Compare the GitHub and Terraform repositories - if full_org_member.missing_from_terraform_files - return_list.push(full_org_member) - end - end - return_list - end - - # Find which full org members are defined in a Terraform file but not on GitHub - # - # @return [Array] a list of FullOrgMember objects - def get_full_org_members_not_on_github - logger.debug "get_full_org_members_not_on_github" - return_list = [] - @full_org_members.each do |full_org_member| - # Compares the GitHub and Terraform repositories - if full_org_member.removed_from_github_repository - return_list.push(full_org_member) - end - end - return_list - end - - # Find which FullOrgMembers have a difference in repository access permissions - # - # @return [Array String, mismatches => Array[Hash{ permission => String, repository_name => String }]}>] a list of hash items that have data from the the FullOrgMember objects - def get_full_org_members_with_repository_permission_mismatches(terraform_files_obj) - logger.debug "get_full_org_members_with_repository_permission_mismatches" - return_list = [] - @full_org_members.each do |full_org_member| - # Compare the GitHub and Terraform repositories to find a permission mismatch - if full_org_member.mismatched_repository_permissions_check(terraform_files_obj) - return_list.push({login: full_org_member.login.downcase, mismatches: full_org_member.repository_permission_mismatches}) - end - end - return_list - end - - # Find which FullOrgMembers are attached to no GitHub repositories - # - # @return [Array] the list FullOrgMember login names - def get_odd_full_org_members - logger.debug "get_odd_full_org_members" - return_list = [] - @full_org_members.each do |full_org_member| - if full_org_member.odd_full_org_member_check - return_list.push(full_org_member.login.downcase) - end - end - return_list - end - - # Find which FullOrgMembers are attached to archived repositories - # - # @return [Array String, repository_name => String}>] a list of hash items that contain the FullOrgMember login name and archived repository - def get_full_org_members_attached_to_archived_repositories(terraform_files_obj) - logger.debug "get_full_org_members_attached_to_archived_repositories" - return_list = [] - @full_org_members.each do |full_org_member| - full_org_member.attached_archived_repositories.each do |archived_repository| - if terraform_files_obj.does_file_exist(archived_repository.downcase) - return_list.push({login: full_org_member.login.downcase, repository: archived_repository.downcase}) - end - end - end - return_list - end - # Call the function to get the issues for a repository from # GitHub and add them to the repository object # @param repositories [Array] the repository names @@ -236,33 +60,5 @@ def read_repository_issues(repository_name) end [] end - - # Check if a full Organization member is attached to a repository - # @param repository_name [String] the repository name - # @return [Bool] true if attached to the repository - def is_full_org_member_attached_to_repository(repository_name) - logger.debug "is_full_org_member_attached_to_repository" - @full_org_members.each do |full_org_member| - if full_org_member.github_repositories.include?(repository_name) - return true - end - end - false - end - - private - - # Adds a new full Organization member if it doesn't already exist - # - # @param collaborator_login [String] the login name of the collaborator - def add_new_full_org_member(collaborator_login) - logger.debug "add_new_full_org_member" - - collaborator_login = collaborator_login.downcase - - if is_collaborator_a_full_org_member(collaborator_login) == false - add_full_org_member(collaborator_login) - end - end end end diff --git a/lib/github_collaborators/outside_collaborators.rb b/lib/github_collaborators/outside_collaborators.rb index 7df6069..034f6dd 100644 --- a/lib/github_collaborators/outside_collaborators.rb +++ b/lib/github_collaborators/outside_collaborators.rb @@ -31,9 +31,8 @@ def initialize @repo_pull_requests = get_pull_requests # Create a Organization object, which contains the Organization repositories, - # full Org members, Org outside collaborators and each repository collaborators + # Org outside collaborators and each repository collaborators @organization = GithubCollaborators::Organization.new - @organization.create_full_org_members(@collaborators) # An array to store collaborators login names that are defined in Terraform but are not on GitHub # [Array String, repository => String}>] @@ -47,8 +46,6 @@ def start deleted_repository_check compare_terraform_and_github collaborator_checks - full_org_members_check - print_full_org_member_collaborators end # Find the collaborator differences between GitHub and Terraform files then @@ -66,16 +63,6 @@ def compare_terraform_and_github # Get the Terraform defined outside collaborators for the repository collaborators_in_file = @terraform_files.get_collaborators_in_file(repository_name) - # Some Terraform collaborators have been upgraded to full organization members, - # get them and add them to the collaborator GitHub array - if collaborators_in_file.length > 0 - collaborators_in_file.each do |collaborator_login| - if @organization.is_collaborator_an_org_member(collaborator_login) - collaborators_on_github.push(collaborator_login) - end - end - end - if collaborators_on_github.length == 0 && collaborators_in_file.length == 0 # When no collaborators skip to next iteration next @@ -121,7 +108,7 @@ def create_unknown_collaborators(unknown_collaborators, repository_name) end end - # Do the checks on the collaborators who are not also full Organization members + # Do the checks on the collaborators def collaborator_checks logger.debug "collaborator_checks" @@ -147,59 +134,6 @@ def collaborator_checks has_review_date_expired(collaborators_with_issues) end - # Do the checks on collaborators who are also full Organization members - def full_org_members_check - logger.debug "full_org_members_check" - - @organization.get_full_org_members_not_on_github.each do |full_org_member| - remove_full_org_member_from_terraform_files(full_org_member) - end - - @organization.get_full_org_members_not_in_terraform_file.each do |full_org_member| - add_collaborator(full_org_member) - end - - @organization.get_full_org_members_with_repository_permission_mismatches(@terraform_files).each do |full_org_member| - # This code removes the repositories from the mismatches array in each full_org_member - # when the user was not added to the Terraform file by our automation. In this scenario - # we know what permission to the repository the collaborator should have. Therefore - # either create a new team with the required permissions to the repository and add - # the collaborator to it or add the collaborator to an existing team. - full_org_member[:mismatches].delete_if do |mismatch| - collaborator_name = full_org_member[:login].downcase - repository_name = mismatch[:repository_name].downcase - required_permission = mismatch[:permission] - automation_added_user_to_file = @terraform_files.did_automation_add_collaborator_to_file(repository_name, collaborator_name) - if automation_added_user_to_file == false - if add_collaborator_to_automation_generated_team(repository_name, collaborator_name, required_permission) == false - add_collaborator_to_repository_team(repository_name, collaborator_name, required_permission) - end - true - end - end - - # If our automation added the collaborator to the Terraform file, and the collaborators - # permission has changed on GitHub (because the collaborator team permission has changed) - # then match the permission set on GitHub. We dont know what permission the collaborator - # should have had originally. - if full_org_member[:mismatches].length > 0 - change_collaborator_permission(full_org_member[:login].downcase, full_org_member[:mismatches]) - end - end - - # Raise Slack message for collaborators that are attached to no Github repositories - odd_full_org_members = @organization.get_odd_full_org_members - if odd_full_org_members.length > 0 - GithubCollaborators::SlackNotifier.new(GithubCollaborators::OddFullOrgMembers.new, odd_full_org_members).post_slack_message - end - - # Raise Slack message for collaborators that are attached to archived repositories - attached_full_org_members = @organization.get_full_org_members_attached_to_archived_repositories(@terraform_files) - if attached_full_org_members.length > 0 - GithubCollaborators::SlackNotifier.new(GithubCollaborators::ArchivedRepositories.new, attached_full_org_members).post_slack_message - end - end - # Call the function to raise a GitHub issue for collaborator whose review date have # an expiry within one month # @param collaborators [Array] a list of Collaborator objects @@ -209,13 +143,11 @@ def is_renewal_within_one_month(collaborators) repository_name = collaborator.repository.downcase collaborator_login = collaborator.login.downcase - if @organization.is_collaborator_a_full_org_member(collaborator_login) == false - issues = @organization.read_repository_issues(repository_name) - issue_exist = does_issue_already_exist(issues, COLLABORATOR_EXPIRES_SOON, repository_name, collaborator_login) + issues = @organization.read_repository_issues(repository_name) + issue_exist = does_issue_already_exist(issues, COLLABORATOR_EXPIRES_SOON, repository_name, collaborator_login) - if collaborator.issues.include?(REVIEW_DATE_WITHIN_MONTH) && issue_exist == false - create_review_date_expires_soon_issue(collaborator_login, repository_name) - end + if collaborator.issues.include?(REVIEW_DATE_WITHIN_MONTH) && issue_exist == false + create_review_date_expires_soon_issue(collaborator_login, repository_name) end end end @@ -227,11 +159,8 @@ def is_renewal_within_one_month(collaborators) def remove_expired_collaborators(collaborators) logger.debug "remove_expired_collaborators" - # Filter out full org collaborators - expired_collaborators = collaborators.select { |collaborator| !@organization.is_collaborator_an_org_member(collaborator.login.downcase) } - - if expired_collaborators.length > 0 - removed_collaborators = remove_collaborator(expired_collaborators) + if collaborators.length > 0 + removed_collaborators = remove_collaborator(collaborators) if removed_collaborators.length > 0 GithubCollaborators::SlackNotifier.new(GithubCollaborators::Expired.new, removed_collaborators).post_slack_message @@ -239,42 +168,6 @@ def remove_expired_collaborators(collaborators) end end - # Call the functions to remove collaborators from Terraform file/s who are full Organization - # members whose review date has expired then call the function to raise a Slack message - # with the collaborators that were modified - # @param collaborators [Array] a list of Collaborator objects - def remove_expired_full_org_members(collaborators) - logger.debug "remove_expired_full_org_members" - - # Find the collaborators that have full org membership - full_org_collaborators = collaborators.select { |collaborator| @organization.is_collaborator_an_org_member(collaborator.login.downcase) } - - if full_org_collaborators.length > 0 - removed_collaborators = remove_collaborator(full_org_collaborators) - if removed_collaborators.length > 0 - GithubCollaborators::SlackNotifier.new(GithubCollaborators::FullOrgMemberExpired.new, removed_collaborators).post_slack_message - end - end - end - - # Call the functions to extend the review date for collaborators who are also full - # Organization members in the Terraform file/s then call the function to raise a - # Slack message with the collaborators that were modified - # @param collaborators [Array] a list of Collaborator objects - def extend_full_org_member_review_date(collaborators) - logger.debug "extend_full_org_member_review_date" - - # Find the collaborators that have full Organization membership - full_org_collaborators = collaborators.select { |collaborator| @organization.is_collaborator_an_org_member(collaborator.login.downcase) } - - if full_org_collaborators.length > 0 - extended_collaborators = extend_date(full_org_collaborators) - if extended_collaborators.length > 0 - GithubCollaborators::SlackNotifier.new(GithubCollaborators::FullOrgMemberExpiresSoon.new, extended_collaborators).post_slack_message - end - end - end - # Find the collaborators whose review date has expired then call # the functions to remove the collaborator from the Terraform file/s # @param collaborators [Array] a list of Collaborator objects @@ -282,7 +175,6 @@ def has_review_date_expired(collaborators) logger.debug "has_review_date_expired" all_collaborators = find_collaborators_who_have_expired(collaborators) remove_expired_collaborators(all_collaborators) - remove_expired_full_org_members(all_collaborators) end # Find the collaborators whose review date expires within the week @@ -292,7 +184,6 @@ def is_review_date_within_a_week(collaborators) logger.debug "is_review_date_within_a_week" collaborators_who_expire_soon = find_collaborators_who_expire_soon(collaborators) extend_collaborators_review_date(collaborators_who_expire_soon) - extend_full_org_member_review_date(collaborators_who_expire_soon) end # Call the functions to extend the review date in Terraform file/s for collaborators then call @@ -301,11 +192,8 @@ def is_review_date_within_a_week(collaborators) def extend_collaborators_review_date(collaborators) logger.debug "extend_collaborators_review_date" - # Filter out full org collaborators - outside_collaborators = collaborators.select { |collaborator| !@organization.is_collaborator_an_org_member(collaborator.login.downcase) } - - if outside_collaborators.length > 0 - extended_collaborators = extend_date(outside_collaborators) + if collaborators.length > 0 + extended_collaborators = extend_date(collaborators) if extended_collaborators.length > 0 send_collaborator_expire_notify_email(extended_collaborators) GithubCollaborators::SlackNotifier.new(GithubCollaborators::ExpiresSoon.new, extended_collaborators).post_slack_message @@ -542,42 +430,6 @@ def remove_empty_files end end - # Call the functions to remove full Organization member from Terraform file/s - # then call the functions to create a new pull request on GitHub - # @param collaborator [GithubCollaborators::FullOrgMember] a collaborator object - def remove_full_org_member_from_terraform_files(collaborator) - logger.debug "remove_full_org_member_from_terraform_files" - - collaborator_name = collaborator.login.downcase - repositories = collaborator.removed_from_repositories - pull_request_title = REMOVE_FULL_ORG_MEMBER_PR_TITLE + " " + collaborator_name - - # Remove the repository if an open pull request is already removing the full org member - repositories.delete_if { |repository_name| does_pr_already_exist("#{repository_name.downcase}.tf", pull_request_title) } - - edited_files = [] - repositories.each do |repository_name| - repository_name = repository_name.downcase - # No pull request exists, modify the file/s - if @terraform_files.does_file_exist(repository_name) - @terraform_files.remove_collaborator_from_file(repository_name, collaborator_name) - edited_files.push("#{TERRAFORM_DIR}/#{repository_name}.tf") - else - logger.warn "The #{repository_name}.tf file is missing when removing #{collaborator_name}" - end - end - - if edited_files.length > 0 - branch_name = "#{REMOVE_FULL_ORG_MEMBER_BRANCH_NAME}#{collaborator_name}" - type = TYPE_REMOVE_FULL_ORG_MEMBER - edited_files.each do |file_name| - logger.info "Removing full org member #{collaborator_name} from #{file_name}" - end - create_branch_and_pull_request(branch_name, edited_files, pull_request_title, collaborator_name, type) - add_new_pull_request(pull_request_title, edited_files) - end - end - # Call the functions to remove a collaborator from Terraform file/s # then call the functions to create a new pull request on GitHub # @param expired_collaborators [Array] a list of Collaborator objects @@ -623,81 +475,6 @@ def remove_collaborator(expired_collaborators) collaborators_for_slack_message end - # Call the functions to modify the access permission to a repository within the - # Terraform file/s then call the functions to create a new pull request on GitHub - # @param collaborator_name [String] the login name of the collaborator - # @param repositories [Array String, repository_name => String }>] A list of hash objects containing the repositories and the permission to be used - def change_collaborator_permission(collaborator_name, repositories) - logger.debug "change_collaborator_permission" - - pull_request_title = CHANGE_PERMISSION_PR_TITLE + " " + collaborator_name.downcase - - # Remove the repository if an open pull request is already open with the modified permission - repositories.delete_if { |repository| does_pr_already_exist("#{repository[:repository_name].downcase}.tf", pull_request_title) } - - edited_files = [] - repositories.each do |repository| - # No pull request exists, modify the file/s - repository_name = repository[:repository_name].downcase - @terraform_files.ensure_file_exists_in_memory(repository_name) - @terraform_files.change_collaborator_permission_in_file(repository_name, collaborator_name, repository[:permission]) - edited_files.push("#{TERRAFORM_DIR}/#{repository_name}.tf") - end - - if edited_files.length > 0 - branch_name = "#{MODIFY_COLLABORATORS_BRANCH_NAME}#{collaborator_name}" - type = TYPE_PERMISSION - edited_files.each do |file_name| - logger.info "Changing collaborator #{collaborator_name} permission in #{file_name}" - end - create_branch_and_pull_request(branch_name, edited_files, pull_request_title, collaborator_name, type) - add_new_pull_request(pull_request_title, edited_files) - end - end - - # Call the functions to add a collaborator who is a full Organization member to - # the Terraform file/s then call the functions to create a new pull request on GitHub - # @param collaborator [GithubCollaborators::FullOrgMember] a collaborator object - def add_collaborator(collaborator) - logger.debug "add_collaborator" - - collaborator_name = collaborator.login.downcase - repositories = collaborator.missing_from_repositories - title_message = ADD_FULL_ORG_MEMBER_PR_TITLE + " " + collaborator_name - - # Remove the repository if an open pull request is already adding the full org member - repositories.delete_if { |repository_name| does_pr_already_exist("#{repository_name.downcase}.tf", title_message) } - - # Remove the repository if the full org member is already in the file - repositories.delete_if { |repository_name| @terraform_files.is_user_in_file(repository_name.downcase, collaborator_name) } - - edited_files = [] - repositories.each do |repository_name| - repository_name = repository_name.downcase - # No pull request exists, modify the file/s - @terraform_files.ensure_file_exists_in_memory(repository_name) - # Get the github permission for that repository - repository_permission = collaborator.get_repository_permission(repository_name) - @terraform_files.add_full_org_collaborator_to_file(repository_name, collaborator, repository_permission) - edited_files.push("#{TERRAFORM_DIR}/#{repository_name}.tf") - - # Add repository name to this array because related Terraform file is not on the main - # branch on GitHub, this array will exclude checking for this file name later on - collaborator.add_ignore_repository(repository_name) - end - - if edited_files.length > 0 - branch_name = "#{ADD_COLLABORATOR_BRANCH_NAME}#{collaborator_name}" - type = TYPE_ADD - pull_request_title = ADD_FULL_ORG_MEMBER_PR_TITLE + " " + collaborator_name - edited_files.each do |file_name| - logger.info "Add full Org collaborator #{collaborator_name} to #{file_name}" - end - create_branch_and_pull_request(branch_name, edited_files, pull_request_title, collaborator_name, type) - add_new_pull_request(pull_request_title, edited_files) - end - end - # Call the functions to get the repository invites, print the invite status, # find unknown invited collaborators and delete expired invites # @param collaborators_in_file [Array] a list of collaborator login names @@ -762,13 +539,6 @@ def add_new_pull_request(title, edited_files) @repo_pull_requests.push({title: title.to_s, files: edited_files}) end - # Print the number of and names of the collaborators who have full Organization membership - def print_full_org_member_collaborators - logger.debug "print_full_org_member_collaborators" - logger.info "There are #{@organization.full_org_members.length} full Org member / outside collaborators." - @organization.full_org_members.each { |collaborator| logger.info "#{collaborator.login.downcase} is a full Org member / outside collaborator." } - end - # Call the functions to create an issue on a repository that has an # unknown collaborator then remove that collaborator from the repository # after raise a Slack message with the collaborators that were removed diff --git a/lib/github_collaborators/terraform_files.rb b/lib/github_collaborators/terraform_files.rb index b88b9dc..04193e8 100644 --- a/lib/github_collaborators/terraform_files.rb +++ b/lib/github_collaborators/terraform_files.rb @@ -7,7 +7,7 @@ class TerraformBlock include Constants attr_reader :username, :permission, :reason, :added_by, :review_after, :email, :name, :org - attr_writer :review_after, :permission + attr_writer :review_after def initialize logger.debug "initialize" @@ -22,40 +22,6 @@ def initialize @defined_in_terraform = true end - # Add collaborator details to the TerraformBlock. This - # is called when the collaborator who is also a full - # Organization member is missing from a Terraform file - # - # @param collaborator [GithubCollaborators::Collaborator] a collaborator object - # @param repository_permission [String] the access permission to the repository - def add_org_member_collaborator_data(collaborator, repository_permission) - logger.debug "add_org_member_collaborator_data" - @username = collaborator.login.downcase - @permission = repository_permission - @email = collaborator.email - @name = collaborator.name - @org = collaborator.org - @reason = REASON1 - @added_by = ADDED_BY_EMAIL - review_date = (Date.today + 90).strftime(DATE_FORMAT) - @review_after = review_date.to_s - end - - # Add collaborator name to the TerraformBlock. This is not used, keeping it, - # in case create PR's for unknown GitHub collaborators at the moment they are - # removed automatically and the add_unknown_collaborator_data is used instead. - # - # @param collaborator_name [String] the name of the collaborator - def add_missing_collaborator_data(collaborator_name) - logger.debug "add_missing_collaborator_data" - @username = collaborator_name.to_s.downcase - @reason = REASON2 - @added_by = ADDED_BY_EMAIL - review_date = (Date.today + 90).strftime(DATE_FORMAT) - @review_after = review_date.to_s - @defined_in_terraform = false - end - # Add collaborator name to the TerraformBlock. This is called when a # collaborator is found on GitHub but not defined in a Terraform file. # @@ -132,10 +98,10 @@ def initialize(repository_name, folder) @terraform_modified_blocks = [] # A temporary list of the TerraformBlock objects - # that have been added or removed by the App, these - # objects need to removed or added back in after the + # that have been removed by the App, these + # objects need to be added back in after the # App has finished modifying the Terraform file object - @add_removed_terraform_blocks = [] + @removed_terraform_blocks = [] # The contents of the Terraform file stored as an array @terraform_file_data = [] @@ -162,20 +128,6 @@ def revert_terraform_blocks @terraform_modified_blocks.clear end - # Add a collaborator who is also a full Organization member - # information to a TerraformBlock. This is called when the - # collaborator is missing from a Terraform file - # - # @param collaborator [GithubCollaborators::Collaborator] a collaborator object - # @param permission [String] the access permission to the repository - def add_org_member_collaborator(collaborator, permission) - logger.debug "add_org_member_collaborator" - block = GithubCollaborators::TerraformBlock.new - block.add_org_member_collaborator_data(collaborator, permission) - @terraform_blocks.push(block) - @add_removed_terraform_blocks.push({added: true, removed: false, block: block.clone, index: @terraform_blocks.index(block)}) - end - # Add a collaborator from an GitHub issue to a # TerraformBlock. This is called outside of the # App, called by a script in the bin folder. @@ -210,25 +162,22 @@ def remove_collaborator(collaborator_name) @terraform_blocks.delete_if do |terraform_block| if terraform_block.username.downcase == collaborator_name.downcase index = @terraform_blocks.index(terraform_block) - @add_removed_terraform_blocks.push({added: false, removed: true, block: terraform_block.clone, index: index}) + @removed_terraform_blocks.push({removed: true, block: terraform_block.clone, index: index}) true end end end # Restore TerraformBlock objects within the Terraform file - # back to their original state. Either remove added objects - # or add object back to the Terraform file object + # back to their original state def restore_terraform_blocks logger.debug "restore_terraform_blocks" - @add_removed_terraform_blocks.each do |original_block| + @removed_terraform_blocks.each do |original_block| if original_block[:removed] @terraform_blocks.insert(original_block[:index], original_block[:block]) - elsif original_block[:added] - @terraform_blocks.delete_at(original_block[:index]) end end - @add_removed_terraform_blocks.clear + @removed_terraform_blocks.clear end # Write the TerraformBlock objects to a Terraform file @@ -247,50 +196,6 @@ def read_file end end - # Return the repository access permission from a - # TerraformBlock object for a specific collaborator - # - # @param collaborator_name [String] the collaborator login name - # @return [String] the repository access permission - def get_collaborator_permission(collaborator_name) - logger.debug "get_collaborator_permission" - @terraform_blocks.each do |terraform_block| - if terraform_block.username.downcase == collaborator_name.downcase - return terraform_block.permission - end - end - "" - end - - # Temporarily overwrite the repository access permission within - # a TerraformBlock object for a specific collaborator - # - # @param collaborator_name [String] the collaborator login name - # @param permission [String] the repository access permission - def change_collaborator_permission(collaborator_name, permission) - logger.debug "get_collaborator_permission" - @terraform_blocks.each do |terraform_block| - if terraform_block.username.downcase == collaborator_name.downcase - @terraform_modified_blocks.push(terraform_block.clone) - terraform_block.permission = permission - end - end - end - - # Return the reason value in a TerraformBlock object for a specific collaborator - # - # @param collaborator_name [String] the collaborator login name - # @return [String] the reason value - def get_collaborator_reason(collaborator_name) - logger.debug "get_collaborator_reason" - @terraform_blocks.each do |terraform_block| - if terraform_block.username.downcase == collaborator_name.downcase - return terraform_block.reason - end - end - "" - end - # Return the added_by value in a TerraformBlock object for a specific collaborator # # @param collaborator_name [String] the collaborator login name @@ -551,44 +456,6 @@ def remove_collaborator_from_file(repository_name, collaborator_name) end end - # Call the functions to change the repository access permission for a specific - # collaborator a within a TerraformFile object, then write that Terraform - # file in the Terraform folder and revert the TerraformFile object - # back to its original state. - # - # @param repository_name [String] the name of the repository to modify - # @param collaborator_name [String] the collaborator login name - # @param repository_permission [String] the repository access permission - def change_collaborator_permission_in_file(repository_name, collaborator_name, repository_permission) - logger.debug "change_collaborator_permission_in_file" - @terraform_files.each do |terraform_file| - if terraform_file.filename.downcase == tf_safe(repository_name.downcase) - terraform_file.change_collaborator_permission(collaborator_name.downcase, repository_permission) - terraform_file.write_to_file - terraform_file.revert_terraform_blocks - end - end - end - - # Call the functions to change the add a collaborator who also has - # full Organization membership to a TerraformFile object,then write - # that Terraform file in the Terraform folder and revert the - # TerraformFile object back to its original state. - # - # @param repository_name [String] the name of the repository to modify - # @param collaborator [GithubCollaborators::Collaborator] a collaborator object - # @param repository_permission [String] the repository access permission - def add_full_org_collaborator_to_file(repository_name, collaborator, repository_permission) - logger.debug "add_full_org_collaborator_to_file" - @terraform_files.each do |terraform_file| - if terraform_file.filename.downcase == tf_safe(repository_name.downcase) - terraform_file.add_org_member_collaborator(collaborator, repository_permission) - terraform_file.write_to_file - terraform_file.restore_terraform_blocks - end - end - end - # Find which Terraform files have zero TerraformBlock objects # # @return [Array] the name of the empty Terraform files @@ -630,25 +497,6 @@ def does_file_exist(repository_name) false end - # Check if a collaborator in a Terraform file was added by this code - # - # @param repository_name [String] the name of the repository - # @param collaborator_name [String] the name of the collaborator - # @return [Bool] true if collaborator was added by this code - def did_automation_add_collaborator_to_file(repository_name, collaborator_name) - logger.debug "did_automation_add_collaborator_to_file" - @terraform_files.each do |terraform_file| - if terraform_file.filename.downcase == tf_safe(repository_name.downcase) - reason = terraform_file.get_collaborator_reason(collaborator_name.downcase) - added_by = terraform_file.get_collaborator_added_by(collaborator_name.downcase) - if reason == REASON1 && added_by == ADDED_BY_EMAIL - return true - end - end - end - false - end - # Check if a collaborator name is in a Terraform file for a specific repository # # @param repository_name [String] the name of the repository diff --git a/lib/helper_module.rb b/lib/helper_module.rb index a295f5a..ba49284 100644 --- a/lib/helper_module.rb +++ b/lib/helper_module.rb @@ -90,9 +90,7 @@ def close_expired_issues(repository_name) # Check for the issues created by this application and that the issue is open if ( issue[:title].include?(COLLABORATOR_EXPIRES_SOON) || - issue[:title].include?(COLLABORATOR_EXPIRY_UPCOMING) || - issue[:title].include?(DEFINE_COLLABORATOR_IN_CODE) || - issue[:title].include?(USE_TEAM_ACCESS) + issue[:title].include?(DEFINE_COLLABORATOR_IN_CODE) ) && issue[:state] == "open" # Get issue created date and add 45 day grace period created_date = Date.parse(issue[:created_at]) @@ -257,283 +255,6 @@ def does_issue_already_exist(issues, issue_title, repository_name, user_name) found_issues end - # Get full list of Organization member login names - # - # @return [Array] the Organization member login names - def get_all_organisation_members - module_logger.debug "get_all_organisation_members" - org_members = [] - end_cursor = nil - graphql = GithubCollaborators::GithubGraphQlClient.new - loop do - response = graphql.run_query(organisation_members_query(end_cursor)) - json_data = JSON.parse(response) - if !json_data.dig("data", "organization", "membersWithRole", "edges").nil? - members = json_data.dig("data", "organization", "membersWithRole", "edges") - members.each do |member| - login = member.dig("node", "login") - org_members.push(login.downcase) - end - end - end_cursor = json_data.dig("data", "organization", "membersWithRole", "pageInfo", "endCursor") - break unless json_data.dig("data", "organization", "membersWithRole", "pageInfo", "hasNextPage") - end - org_members.sort! - end - - # Create a GraphQL query that returns the Organization member login names - # - # @param end_cursor [String] id of next page in search results - # @return [String] the GraphQL query - def organisation_members_query(end_cursor) - module_logger.debug "organisation_members_query" - after = end_cursor.nil? ? "null" : "\"#{end_cursor}\"" - %[ - { - organization(login: "#{ORG}") { - membersWithRole( - first: 100 - after: #{after} - ) { - edges { - node { - login - } - } - pageInfo { - hasNextPage - endCursor - } - } - } - } - ] - end - - # Remove a user from a team - # - # @param team_name [String] name of the team - # @param user_name [String] name of the user - def remove_user_from_team(team_name, user_name) - logger.debug("remove_user_from_team") - - url = "#{GH_ORG_API_URL}/teams/#{team_name}/memberships/#{user_name}" - - if ENV.fetch("REALLY_POST_TO_GH", 0) == "1" - GithubCollaborators::HttpClient.new.delete(url) - module_logger.info "Removed user #{user_name} from #{team_name}" - sleep 1 - else - module_logger.debug "Didn't remove user #{user_name} from #{team_name}, this is a dry run" - end - end - - # Assign a GitHub team to a repository - # - # @param repository_name [String] name of the repository - # @param team_name [String] name of the team - # @param required_permission [String] team access permission to the repository - def add_team_to_repository(repository_name, team_name, required_permission) - logger.debug("add_team_to_repository") - - actual_permission = if required_permission == "read" - "pull" - elsif required_permission == "write" - "push" - else - required_permission - end - - url = "#{GH_ORG_API_URL}/teams/#{team_name}/repos/#{ORG}/#{repository_name}" - permission_hash = {permission: actual_permission.to_s} - - if ENV.fetch("REALLY_POST_TO_GH", 0) == "1" - GithubCollaborators::HttpClient.new.put_json(url, permission_hash.to_json) - module_logger.info "Added #{team_name} to #{repository_name}" - sleep 1 - else - module_logger.debug "Didn't #{team_name} to #{repository_name}, this is a dry run" - end - end - - # Create a new GitHub team - # - # @param repository_name [String] name of the repository - # @param team_name [String] name of the team - def create_team(repository_name, team_name) - logger.debug("create_team") - - url = "#{GH_ORG_API_URL}/teams" - team_hash = { - name: team_name.to_s, - description: AUTOMATED_GENERATED_TEAM.to_s, - privacy: "closed", - repo_names: [repository_name.to_s] - } - - if ENV.fetch("REALLY_POST_TO_GH", 0) == "1" - GithubCollaborators::HttpClient.new.post_json(url, team_hash.to_json) - module_logger.info "Create #{team_name}" - sleep 1 - else - module_logger.debug "Didn't create #{team_name}, this is a dry run" - end - end - - # Add a collaborator to a team - # - # @param repository_name [String] name of the repository - # @param collaborator_name [String] name of the collaborator - def add_collaborator_to_team(team_name, collaborator_name) - logger.debug("add_collaborator_to_team") - - if ENV.fetch("REALLY_POST_TO_GH", 0) == "1" - url = "#{GH_ORG_API_URL}/teams/#{team_name}/memberships/#{collaborator_name}" - role_hash = {role: "member"} - GithubCollaborators::HttpClient.new.put_json(url, role_hash.to_json) - module_logger.info "Added collaborator #{collaborator_name} to #{team_name}" - sleep 1 - else - module_logger.debug "Didn't add collaborator #{collaborator_name} to #{team_name}, this is a dry run" - end - end - - # If find a repository team that was created by automation and - # it has the required access permissions, add the collaborator - # to it. - # - # @param repository_name [String] name of the repository - # @param collaborator_name [String] name of the collaborator - # @param required_permission [String] team access permission to the repository - # @return [bool] true if collaborator added to a repository team - def add_collaborator_to_automation_generated_team(repository_name, collaborator_name, required_permission) - logger.debug("add_collaborator_to_automation_generated_team") - teams = get_repository_teams_and_access_permissions(repository_name) - teams.each do |team| - if team[:permission] == required_permission && team[:description] == AUTOMATED_GENERATED_TEAM - add_collaborator_to_team(team[:team_name], collaborator_name) - return true - end - end - false - end - - # Create a team name for a GitHub team - # - # @param repository_name [String] name of the repository - # @param required_permission [String] access permission to repository - def create_team_name(repository_name, required_permission) - module_logger.debug "create_team_name" - - team_name_permission = if required_permission == "pull" - "read" - elsif required_permission == "push" - "write" - else - required_permission - end - tf_safe(repository_name) + "-" + team_name_permission + "-team" - end - - # Create a new repository team with the required access and - # add the collaborator to it. - # - # @param repository_name [String] name of the repository - # @param collaborator_name [String] name of the collaborator - # @param required_permission [String] team access permission to the repository - # @return [bool] true if collaborator added to a repository team - def add_collaborator_to_repository_team(repository_name, collaborator_name, required_permission) - module_logger.debug "add_collaborator_to_repository_team" - - team_name = create_team_name(repository_name, required_permission) - - # Check if the team already exists - url = "#{GH_ORG_API_URL}/teams/#{team_name}" - http_code = GithubCollaborators::HttpClient.new.fetch_code(url) - - # When team doesn't exist then create the team - if http_code == "404" - create_team(repository_name, team_name) - # Remove Ops-Eng user that might have run this automation - remove_user_from_team(team_name, "nickwalt01") - remove_user_from_team(team_name, "ben-al") - remove_user_from_team(team_name, "AntonyBishop") - remove_user_from_team(team_name, "moj-operations-engineering-bot") - end - - # Ensure team exists - http_code = GithubCollaborators::HttpClient.new.fetch_code(url) - if http_code == "200" - add_team_to_repository(repository_name, team_name, required_permission) - add_collaborator_to_team(team_name, collaborator_name) - end - end - - # Query the repository teams and their access to the repository - # - # @param repository_name [String] name of the repository - # @return [Array<[Hash{team_name => String, permission => String, description => String}]>] array of the team names and permissions in a hash item - def get_repository_teams_and_access_permissions(repository_name) - module_logger.debug "get_repository_teams" - url = "#{GH_API_URL}/#{repository_name}/teams" - teams = [] - - response = GithubCollaborators::HttpClient.new.fetch_json(url) - JSON.parse(response) - .find_all { |team| team["slug"].downcase } - .map { |team| - teams.push( - { - team_name: team["slug"].downcase, - permission: team["permission"], - description: team["description"] - } - ) - } - - # Remove any teams missing the permission value - teams.delete_if { |team| team[:permission].nil? } - - teams - end - - # Query the all_org_members team and return its repositories - # - # @return [Array] list of the repository names - def get_everyone_team_repositories - module_logger.debug "get_everyone_team_repositories" - - team_repositories = [] - - [1, 2, 3].each do |page_number| - url = "#{GH_ORG_API_URL}/teams/everyone/repos?per_page=100&page=#{page_number}" - - json = GithubCollaborators::HttpClient.new.fetch_json(url) - JSON.parse(json) - .find_all { |repository| repository["name"].downcase } - .map { |repository| team_repositories.push(repository["name"].downcase) } - end - - team_repositories - end - - # Check a list of collaborator objects for a specific login name - # - # @param login [String] login name of the collaborator to find - # @param collaborators [Array] list of collaborator objects - # @return [Bool] true if the collaborator login name is found - def does_collaborator_already_exist(login, collaborators) - module_logger.debug "does_collaborator_already_exist" - exists = false - collaborators.each do |collaborator| - if collaborator.login.downcase == login.downcase - exists = true - break - end - end - exists - end - # Return the name of a specific collaborator from a list of collaborator objects # # @param login [String] login name of the collaborator to find @@ -672,12 +393,6 @@ def create_branch_and_pull_request(branch_name, edited_files, pull_request_title create_pull_request(extend_date_hash(collaborator_name, branch_name)) elsif type == TYPE_REMOVE create_pull_request(remove_collaborator_hash(collaborator_name, branch_name)) - elsif type == TYPE_REMOVE_FULL_ORG_MEMBER - create_pull_request(remove_full_org_member_hash(collaborator_name, branch_name)) - elsif type == TYPE_PERMISSION - create_pull_request(modify_collaborator_permission_hash(collaborator_name, branch_name)) - elsif type == TYPE_ADD - create_pull_request(add_collaborator_hash(collaborator_name, branch_name)) elsif type == TYPE_DELETE_ARCHIVE create_pull_request(delete_archive_file_hash(branch_name)) elsif type == TYPE_DELETE_FILE @@ -883,35 +598,6 @@ def add_collaborator_from_issue_hash(login, branch_name) } end - # Composes a GitHub branch structured message - # - # @param login [String] the login name of the collaborator - # @param branch_name [String] the name of the branch - # @return [Hash{title => String, head => String, base => String, body => String}] the message to send to GitHub - def add_collaborator_hash(login, branch_name) - module_logger.debug "add_collaborator_hash" - { - title: ADD_FULL_ORG_MEMBER_PR_TITLE + " " + login.downcase, - head: branch_name.downcase, - draft: true, - base: GITHUB_BRANCH, - body: <<~EOF - Hi there - - This is the GitHub-Outside-Collaborator repository bot. - - The collaborator #{login.downcase} was found to be missing from the file/s in this pull request. - - This is because the collaborator is a full organization member and is able to join repositories outside of Terraform. - - This pull request ensures we keep track of those collaborators and which repositories they are accessing. - - Edit the pull request file/s because some of the data about the collaborator is missing. - - EOF - } - end - # Composes a GitHub branch structured message # # @param login [String] name of collaborator @@ -936,65 +622,6 @@ def remove_collaborator_hash(login, branch_name) } end - # Composes a GitHub branch structured message - # - # @param login [String] name of collaborator - # @param branch_name [String] name of new branch - # @return [Hash{title => String, head => String, base => String, body => String}] the message to send to GitHub - def remove_full_org_member_hash(login, branch_name) - module_logger.debug "remove_full_org_member_hash" - { - title: REMOVE_FULL_ORG_MEMBER_PR_TITLE + " " + login.downcase, - head: branch_name.downcase, - draft: true, - base: GITHUB_BRANCH, - body: <<~EOF - Hi there - - **IMPORTANT** Approve and run this PR before any others. A collaborator repository access has been removed. Running tf apply on another PR will invite the collaborator to repository again. - - This is the GitHub-Outside-Collaborator repository bot. - - The full org member / collaborator #{login.downcase} access to one or more repositories has been revoked. - - This is because the collaborator is a full organization member and is able to join repositories outside of Terraform via Teams. - - This pull request ensures we keep track of those collaborators and which repositories they are accessing. - EOF - } - end - - # Composes a GitHub branch structured message - # - # @param login [String] name of collaborator - # @param branch_name [String] name of new branch - # @return [Hash{title => String, head => String, base => String, body => String}] the message to send to GitHub - def modify_collaborator_permission_hash(login, branch_name) - module_logger.debug "modify_collaborator_permission_hash" - { - title: CHANGE_PERMISSION_PR_TITLE + " " + login.downcase, - head: branch_name.downcase, - draft: true, - base: GITHUB_BRANCH, - body: <<~EOF - Hi there - - This is the GitHub-Outside-Collaborator repository bot. - - The collaborator #{login.downcase} permission on Github is different to the permission in the Terraform file for the repository. - - This is because the collaborator is a full organization member, is able to join repositories outside of Terraform and may have different access to the repository now they are in a Team. - - The permission on Github is given the priority. - - This pull request ensures we keep track of those collaborators, which repositories they are accessing and their permission. - - Permission can either be admin, push, maintain, pull or triage. - - EOF - } - end - # Create a list of Repository objects which are not disabled or archived # # @return [Array] list of Repository objects diff --git a/locals.tf b/locals.tf index aeaee3d..660c7d0 100644 --- a/locals.tf +++ b/locals.tf @@ -7,7 +7,7 @@ locals { environment-name = "production" owner = "Operations Engineering: operations-engineering@digital.justice.gov.uk" infrastructure-support = "Operations Engineering: operations-engineering@digital.justice.gov.uk" - runbook = "https://operations-engineering.service.justice.gov.uk/documentation/runbooks.html#runbooks" + runbook = "https://runbooks.operations-engineering.service.justice.gov.uk/" source-code = "https://github.com/moj-analytical-services/github-outside-collaborators" } } diff --git a/spec/archived_repositories_spec.rb b/spec/archived_repositories_spec.rb deleted file mode 100644 index f782097..0000000 --- a/spec/archived_repositories_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -class GithubCollaborators - include TestConstants - - describe ArchivedRepositories do - context "test ArchivedRepositories" do - subject(:archived_repositories) { described_class.new } - - it "call create_line" do - collaborator = {login: TEST_USER, repository: REPOSITORY_NAME} - line = archived_repositories.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in #{REPOSITORY_NAME}") - end - - it "call singular_message" do - line = archived_repositories.singular_message - test_equal(line, "I've found a collaborator who is a full Org member attached to an archived repository. Un-archive the repository and remove this collaborator") - end - - it "call multiple_message" do - line = archived_repositories.multiple_message(4) - test_equal(line, "I've found 4 collaborators who are full Org members attached to archived repositories. Un-archive the repositories and remove these collaborators") - end - end - end -end diff --git a/spec/close_expired_issues_spec.rb b/spec/close_expired_issues_spec.rb index 23ef341..8855934 100644 --- a/spec/close_expired_issues_spec.rb +++ b/spec/close_expired_issues_spec.rb @@ -38,18 +38,6 @@ class GithubCollaborators helper_module.close_expired_issues(REPOSITORY_NAME) end - it "when collaborator expiry upcoming, issue has expired and is open" do - issues = create_issues(COLLABORATOR_EXPIRY_UPCOMING, CREATED_DATE, OPEN, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - - it "when collaborator expiry upcoming, grace period expired and is open" do - issues = create_issues(COLLABORATOR_EXPIRY_UPCOMING, GRACE_PERIOD_EXPIRED, OPEN, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - it "when define collaborator in code, issue has expired and is open" do issues = create_issues(DEFINE_COLLABORATOR_IN_CODE, CREATED_DATE, OPEN, 1) expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) @@ -61,18 +49,6 @@ class GithubCollaborators expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) helper_module.close_expired_issues(REPOSITORY_NAME) end - - it "when use team access, issue has expired and is open" do - issues = create_issues(USE_TEAM_ACCESS, CREATED_DATE, OPEN, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - - it "when use team access, grace period expired and is open" do - issues = create_issues(USE_TEAM_ACCESS, GRACE_PERIOD_EXPIRED, OPEN, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end end context "do not remove issue" do @@ -86,12 +62,6 @@ class GithubCollaborators helper_module.close_expired_issues(REPOSITORY_NAME) end - it "when collaborator expiry upcoming, grace period expired and is closed" do - issues = create_issues(COLLABORATOR_EXPIRY_UPCOMING, GRACE_PERIOD_EXPIRED, CLOSED, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - it "when define collaborator in code, grace period expired and is closed" do issues = create_issues(DEFINE_COLLABORATOR_IN_CODE, GRACE_PERIOD_EXPIRED, CLOSED, 1) expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) @@ -122,18 +92,6 @@ class GithubCollaborators helper_module.close_expired_issues(REPOSITORY_NAME) end - it "when collaborator expiry upcoming, grace period okay and is open" do - issues = create_issues(COLLABORATOR_EXPIRY_UPCOMING, GRACE_PERIOD_OKAY, OPEN, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - - it "when collaborator expiry upcoming, grace period okay and is closed" do - issues = create_issues(COLLABORATOR_EXPIRY_UPCOMING, GRACE_PERIOD_OKAY, CLOSED, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - it "when define collaborator in code, grace period okay and is open" do issues = create_issues(DEFINE_COLLABORATOR_IN_CODE, GRACE_PERIOD_OKAY, OPEN, 1) expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) @@ -145,62 +103,18 @@ class GithubCollaborators expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) helper_module.close_expired_issues(REPOSITORY_NAME) end - - it "when use team access, grace period okay and is open" do - issues = create_issues(USE_TEAM_ACCESS, GRACE_PERIOD_OKAY, OPEN, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - - it "when use team access, grace period okay and is closed" do - issues = create_issues(USE_TEAM_ACCESS, GRACE_PERIOD_OKAY, CLOSED, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - - it "when use team access, grace period expired and is closed" do - issues = create_issues(USE_TEAM_ACCESS, GRACE_PERIOD_EXPIRED, CLOSED, 1) - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - helper_module.close_expired_issues(REPOSITORY_NAME) - end - end - - it "call close_expired_issues when use team access, multiple issues, expired and open" do - issues = [ - { - title: USE_TEAM_ACCESS, - created_at: CREATED_DATE, - state: OPEN, - number: 1 - }, - { - title: USE_TEAM_ACCESS, - created_at: CREATED_DATE, - state: OPEN, - number: 2 - }, - { - title: USE_TEAM_ACCESS, - created_at: CREATED_DATE, - state: OPEN, - number: 3 - } - ] - expect(helper_module).to receive(:get_issues_from_github).with(REPOSITORY_NAME).and_return(issues) - expect(helper_module).to receive(:remove_issue).at_least(3).times - helper_module.close_expired_issues(REPOSITORY_NAME) end it "call close_expired_issues when multiple issues, some expired and open" do issues = [ { - title: COLLABORATOR_EXPIRY_UPCOMING, + title: COLLABORATOR_EXPIRES_SOON, created_at: GRACE_PERIOD_OKAY, state: OPEN, number: 1 }, { - title: USE_TEAM_ACCESS, + title: COLLABORATOR_EXPIRES_SOON, created_at: CREATED_DATE, state: OPEN, number: 2 diff --git a/spec/create_pr_from_issue_spec.rb b/spec/create_pr_from_issue_spec.rb index 9cd1af1..eee7ad0 100644 --- a/spec/create_pr_from_issue_spec.rb +++ b/spec/create_pr_from_issue_spec.rb @@ -24,7 +24,7 @@ class GithubCollaborators context "test good path" do before { - good_json_one_user = {number: 123, body: "### usernames\n\n#{TEST_COLLABORATOR_LOGIN}\n\n### names\n\n#{TEST_COLLABORATOR_NAME}\n\n### emails\n\n#{TEST_COLLABORATOR_EMAIL}\n\n### org\n\n#{TEST_COLLABORATOR_ORG}\n\n### reason\n\n#{REASON1}\n\n### added_by\n\n#{ADDED_BY_EMAIL}\n\n### review_after\n\n#{CORRECT_REVIEW_DATE}\n\n### permission\n\n#{CORRECT_PERMISSION}\n\n### repositories\n\n#{TEST_REPO_NAME}"}.to_json + good_json_one_user = {number: 123, body: "### usernames\n\n#{TEST_COLLABORATOR_LOGIN}\n\n### names\n\n#{TEST_COLLABORATOR_NAME}\n\n### emails\n\n#{TEST_COLLABORATOR_EMAIL}\n\n### org\n\n#{TEST_COLLABORATOR_ORG}\n\n### reason\n\n#{REASON1}\n\n### added_by\n\n#{TEST_COLLABORATOR_ADDED_BY}\n\n### review_after\n\n#{CORRECT_REVIEW_DATE}\n\n### permission\n\n#{CORRECT_PERMISSION}\n\n### repositories\n\n#{TEST_REPO_NAME}"}.to_json @create_pr_from_issue = CreatePrFromIssue.new(good_json_one_user) } @@ -81,7 +81,7 @@ class GithubCollaborators end it "call get_added_by" do - test_equal(@create_pr_from_issue.get_added_by, ADDED_BY_EMAIL) + test_equal(@create_pr_from_issue.get_added_by, TEST_COLLABORATOR_ADDED_BY) end it "call get_review_after" do @@ -164,7 +164,7 @@ class GithubCollaborators context "test start" do before { - good_json_one_user = {number: 123, body: "### usernames\n\n#{TEST_COLLABORATOR_LOGIN}\n\n### names\n\n#{TEST_COLLABORATOR_NAME}\n\n### emails\n\n#{TEST_COLLABORATOR_EMAIL}\n\n### org\n\n#{TEST_COLLABORATOR_ORG}\n\n### reason\n\n#{REASON1}\n\n### added_by\n\n#{ADDED_BY_EMAIL}\n\n### review_after\n\n#{CORRECT_REVIEW_DATE}\n\n### permission\n\n#{CORRECT_PERMISSION}\n\n### repositories\n\n#{TEST_REPO_NAME}"}.to_json + good_json_one_user = {number: 123, body: "### usernames\n\n#{TEST_COLLABORATOR_LOGIN}\n\n### names\n\n#{TEST_COLLABORATOR_NAME}\n\n### emails\n\n#{TEST_COLLABORATOR_EMAIL}\n\n### org\n\n#{TEST_COLLABORATOR_ORG}\n\n### reason\n\n#{REASON1}\n\n### added_by\n\n#{TEST_COLLABORATOR_ADDED_BY}\n\n### review_after\n\n#{CORRECT_REVIEW_DATE}\n\n### permission\n\n#{CORRECT_PERMISSION}\n\n### repositories\n\n#{TEST_REPO_NAME}"}.to_json @create_pr_from_issue = CreatePrFromIssue.new(good_json_one_user) } @@ -231,7 +231,7 @@ class GithubCollaborators context "test good path when have multiple users" do before { - good_json_multiple_users = {number: 123, body: "### usernames\n\n#{TEST_COLLABORATOR_LOGIN}\r\n#{TEST_COLLABORATOR_LOGIN}\n\n### names\n\n#{TEST_COLLABORATOR_NAME}\r\n#{TEST_COLLABORATOR_NAME}\n\n### emails\n\n#{TEST_COLLABORATOR_EMAIL}\r\n#{TEST_COLLABORATOR_EMAIL}\n\n### org\n\n#{TEST_COLLABORATOR_ORG}\n\n### reason\n\n#{REASON1}\n\n### added_by\n\n#{ADDED_BY_EMAIL}\n\n### review_after\n\n#{CORRECT_REVIEW_DATE}\n\n### permission\n\n#{CORRECT_PERMISSION}\n\n### repositories\n\n#{TEST_REPO_NAME}\r\n#{TEST_REPO_NAME}"}.to_json + good_json_multiple_users = {number: 123, body: "### usernames\n\n#{TEST_COLLABORATOR_LOGIN}\r\n#{TEST_COLLABORATOR_LOGIN}\n\n### names\n\n#{TEST_COLLABORATOR_NAME}\r\n#{TEST_COLLABORATOR_NAME}\n\n### emails\n\n#{TEST_COLLABORATOR_EMAIL}\r\n#{TEST_COLLABORATOR_EMAIL}\n\n### org\n\n#{TEST_COLLABORATOR_ORG}\n\n### reason\n\n#{REASON1}\n\n### added_by\n\n#{TEST_COLLABORATOR_ADDED_BY}\n\n### review_after\n\n#{CORRECT_REVIEW_DATE}\n\n### permission\n\n#{CORRECT_PERMISSION}\n\n### repositories\n\n#{TEST_REPO_NAME}\r\n#{TEST_REPO_NAME}"}.to_json @create_pr_from_issue = CreatePrFromIssue.new(good_json_multiple_users) } diff --git a/spec/full_org_member_expired_spec.rb b/spec/full_org_member_expired_spec.rb deleted file mode 100644 index 5ba6d86..0000000 --- a/spec/full_org_member_expired_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -class GithubCollaborators - include TestConstants - include Constants - - describe FullOrgMemberExpired do - context "test FullOrgMemberExpired" do - subject(:expired) { described_class.new } - - context "call create_line" do - it "when collaborator expired today" do - terraform_block = create_terraform_block_review_date_today - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expired.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (today)") - end - - it "when collaborator expired yesterday" do - terraform_block = create_terraform_block_review_date_yesterday - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expired.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (yesterday)") - end - - it "when collaborator expired two days ago" do - terraform_block = create_terraform_block_review_date_two_days_ago - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expired.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (2 days ago)") - end - - it "when collaborator expired no date provided" do - terraform_block = create_terraform_block_review_date_empty - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expired.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (today)") - end - end - - it "singular message" do - line = expired.singular_message - test_equal(line, "I've found a full Org member / collaborator whose review date has expired, a pull request has been created to remove the collaborator from the Terraform file/s. Manually remove the collaborator from the repository") - end - - it "multiple message" do - line = expired.multiple_message(4) - test_equal(line, "I've found 4 full Org members / collaborators whose review dates have expired, pull requests have been created to remove these collaborators from the Terraform file/s. Manually remove the collaborator from the repository") - end - end - end -end diff --git a/spec/full_org_member_expires_soon_spec.rb b/spec/full_org_member_expires_soon_spec.rb deleted file mode 100644 index 9a303cd..0000000 --- a/spec/full_org_member_expires_soon_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -class GithubCollaborators - include TestConstants - include Constants - - describe FullOrgMemberExpiresSoon do - context "test FullOrgMemberExpiresSoon" do - subject(:expires_soon) { described_class.new } - - context "call create_line" do - it "when collaborator expires today" do - terraform_block = create_terraform_block_review_date_today - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expires_soon.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (today)") - end - - it "when collaborator expires tomorrow" do - terraform_block = create_terraform_block_review_date_tomorrow - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expires_soon.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (tomorrow)") - end - - it "when collaborator in two days" do - terraform_block = create_terraform_block_review_date_in_two_days - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expires_soon.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (in 2 days)") - end - - it "when collaborator expired no date provided" do - terraform_block = create_terraform_block_review_date_empty - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - line = expires_soon.create_line(collaborator) - test_equal(line, "- #{TEST_USER} in <#{REPO_URL}> see <#{HREF}> (today)") - end - end - - it "singular message" do - line = expires_soon.singular_message - test_equal(line, "I've found a collaborator who is a full Org member whose review date will expire shortly, a pull request has been created to extend the date for this collaborator") - end - - it "multiple message" do - line = expires_soon.multiple_message(4) - test_equal(line, "I've found 4 collaborators who are full Org members whose review date will expire shortly, pull requests have been created to extend the date for these collaborators") - end - end - end -end diff --git a/spec/full_org_member_spec.rb b/spec/full_org_member_spec.rb deleted file mode 100644 index 1427da2..0000000 --- a/spec/full_org_member_spec.rb +++ /dev/null @@ -1,394 +0,0 @@ -class GithubCollaborators - include TestConstants - include Constants - - describe FullOrgMember do - context "test FullOrgMember" do - before { - allow_any_instance_of(GithubCollaborators::GithubGraphQlClient).to receive(:sleep) - allow_any_instance_of(GithubCollaborators::HttpClient).to receive(:sleep) - @full_org_member = GithubCollaborators::FullOrgMember.new(TEST_USER_1) - } - - before do - ENV["OPS_BOT_TOKEN"] = "" - end - - let(:terraform_files) { double(GithubCollaborators::TerraformFiles) } - let(:graphql_client) { double(GithubCollaborators::GithubGraphQlClient) } - let(:http_client) { double(GithubCollaborators::HttpClient) } - let(:collaborator_repositories_json) { File.read("spec/fixtures/collaborator-repositories.json") } - - url = "#{GH_API_URL}/test-repo1/collaborators/someuser1/permission" - - query = - %[ - { - user(login: "#{TEST_USER_1}") { - repositories( - affiliations: ORGANIZATION_MEMBER - ownerAffiliations: ORGANIZATION_MEMBER - first: 100 - after: null - ) { - edges { - node { - name - owner { - login - } - } - } - pageInfo { - endCursor - hasNextPage - } - } - } - } - ] - - it "call add_github_repository" do - @full_org_member.add_github_repository(TEST_USER_1) - test_equal(@full_org_member.github_repositories.length, 1) - end - - it "call add_info_from_file" do - @full_org_member.add_info_from_file(TEST_COLLABORATOR_EMAIL, TEST_COLLABORATOR_NAME, TEST_COLLABORATOR_ORG) - test_equal(@full_org_member.login, TEST_USER_1) - test_equal(@full_org_member.email, TEST_COLLABORATOR_EMAIL) - test_equal(@full_org_member.name, TEST_COLLABORATOR_NAME) - test_equal(@full_org_member.org, TEST_COLLABORATOR_ORG) - end - - it "call add_archived_repositories" do - @full_org_member.add_archived_repositories([TEST_REPO_NAME1, TEST_REPO_NAME2]) - test_equal(@full_org_member.github_archived_repositories.length, 2) - end - - it "call add_everyone_team_repositories" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME1, TEST_REPO_NAME2]) - test_equal(@full_org_member.everyone_team_repositories.length, 2) - end - - it "call add_attached_archived_repository" do - @full_org_member.add_attached_archived_repository(TEST_REPO_NAME1) - @full_org_member.add_attached_archived_repository(TEST_REPO_NAME2) - test_equal(@full_org_member.attached_archived_repositories.length, 2) - end - - it "call add_ignore_repository" do - @full_org_member.add_ignore_repository(TEST_REPO_NAME1) - @full_org_member.add_ignore_repository(TEST_REPO_NAME2) - test_equal(@full_org_member.ignore_repositories.length, 2) - end - - context "call add_terraform_repositories" do - it "when add to array" do - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 1) - end - - it "when don't add to array because repo is an archived everyone team repo" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.everyone_team_repositories.length, 1) - @full_org_member.add_archived_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.github_archived_repositories.length, 1) - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 0) - end - - it "when don't add to array because repo is an everyone team repo" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.everyone_team_repositories.length, 1) - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 0) - end - - it "when don't add to array because repo is an archived repo" do - @full_org_member.add_archived_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.github_archived_repositories.length, 1) - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 0) - end - end - - context "call get_full_org_member_repositories" do - before do - expect(GithubCollaborators::GithubGraphQlClient).to receive(:new).and_return(graphql_client) - expect(graphql_client).to receive(:run_query).with(query).and_return(collaborator_repositories_json) - end - - it "when terraform repositories is 0" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - test_equal(@full_org_member.odd_full_org_member_check, true) - end - - it "when repos are not known already" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - end - - it "when repo is already archived" do - @full_org_member.add_archived_repositories([TEST_REPO_NAME2]) - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 2) - end - - it "when repo is already org repo" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME2]) - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 2) - end - - it "call get_full_org_member_repositories and add to archive array" do - test_equal(@full_org_member.attached_archived_repositories.length, 0) - @full_org_member.add_archived_repositories([TEST_REPO_NAME2]) - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.attached_archived_repositories.length, 1) - end - end - - context "call odd_full_org_member_check" do - it "when member is odd" do - test_equal(@full_org_member.odd_full_org_member_check, true) - end - - it "when org team array greater than 0" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME]) - test_equal(@full_org_member.everyone_team_repositories.length, 1) - test_equal(@full_org_member.odd_full_org_member_check, false) - end - - it "when github repositories is 0" do - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 1) - test_equal(@full_org_member.odd_full_org_member_check, true) - end - end - - def create_repo_permission_json_reply(admin, maintain, push, triage, pull) - %( - { - "user": { - "permissions": { - "admin": #{admin}, - "maintain": #{maintain}, - "push": #{push}, - "triage": #{triage}, - "pull": #{pull} - } - } - } - ) - end - - context "call get_repository_permission" do - before do - expect(GithubCollaborators::HttpClient).to receive(:new).and_return(http_client) - end - - it "when use admin" do - json = create_repo_permission_json_reply(true, true, true, true, true) - expect(http_client).to receive(:fetch_json).with(url).and_return(json) - permission = @full_org_member.get_repository_permission(TEST_REPO_NAME1) - test_equal(permission, "admin") - end - - it "when use maintain" do - json = create_repo_permission_json_reply(false, true, true, true, true) - expect(http_client).to receive(:fetch_json).with(url).and_return(json) - permission = @full_org_member.get_repository_permission(TEST_REPO_NAME1) - test_equal(permission, "maintain") - end - - it "when use push" do - json = create_repo_permission_json_reply(false, false, true, true, true) - expect(http_client).to receive(:fetch_json).with(url).and_return(json) - permission = @full_org_member.get_repository_permission(TEST_REPO_NAME1) - test_equal(permission, "push") - end - - it "when use triage" do - json = create_repo_permission_json_reply(false, false, false, true, true) - expect(http_client).to receive(:fetch_json).with(url).and_return(json) - permission = @full_org_member.get_repository_permission(TEST_REPO_NAME1) - test_equal(permission, "triage") - end - - it "when use pull" do - json = create_repo_permission_json_reply(false, false, false, false, true) - expect(http_client).to receive(:fetch_json).with(url).and_return(json) - permission = @full_org_member.get_repository_permission(TEST_REPO_NAME1) - test_equal(permission, "pull") - end - - it "when use no permission" do - json = create_repo_permission_json_reply(false, false, false, false, false) - expect(http_client).to receive(:fetch_json).with(url).and_return(json) - permission = @full_org_member.get_repository_permission(TEST_REPO_NAME1) - test_equal(permission, "pull") - end - end - - context "call removed_from_github_repository" do - it "when added no repositories" do - test_equal(@full_org_member.removed_from_github_repository, false) - end - - it "when user is in a Terraform file and GitHub repo" do - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - @full_org_member.add_github_repository(TEST_REPO_NAME1) - test_equal(@full_org_member.terraform_repositories.length, 1) - test_equal(@full_org_member.github_repositories.length, 1) - test_equal(@full_org_member.removed_from_github_repository, false) - end - - it "when user is in a Terraform file but not on the GitHub repo" do - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 1) - test_equal(@full_org_member.github_repositories.length, 0) - test_equal(@full_org_member.removed_from_github_repository, true) - end - - it "when user is in a Terraform file but not on the GitHub repo but repo is an everyone team repo" do - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 1) - test_equal(@full_org_member.github_repositories.length, 0) - test_equal(@full_org_member.removed_from_github_repository, false) - end - end - - context "call missing_from_terraform_files" do - it "when added no repositories" do - test_equal(@full_org_member.missing_from_terraform_files, false) - end - - it "when user is in a Terraform file" do - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.terraform_repositories.length, 1) - test_equal(@full_org_member.missing_from_terraform_files, false) - end - end - - context "" do - before do - expect(GithubCollaborators::GithubGraphQlClient).to receive(:new).and_return(graphql_client) - expect(graphql_client).to receive(:run_query).with(query).and_return(collaborator_repositories_json) - end - - context "call missing_from_terraform_files" do - it "when add only github repositories" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - test_equal(@full_org_member.missing_from_terraform_files, true) - end - - it "when github and terraform repositories do not match but a repo is an everyone team repo" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME1]) - @full_org_member.get_full_org_member_repositories - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.github_repositories.length, 2) - test_equal(@full_org_member.terraform_repositories.length, 0) - test_equal(@full_org_member.missing_from_terraform_files, true) - end - - it "when github and terraform repositories do not match" do - @full_org_member.get_full_org_member_repositories - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1]) - test_equal(@full_org_member.github_repositories.length, 3) - test_equal(@full_org_member.terraform_repositories.length, 1) - test_equal(@full_org_member.missing_from_terraform_files, true) - end - - it "when github and terraform repositories do match" do - @full_org_member.get_full_org_member_repositories - @full_org_member.add_terraform_repositories([TEST_REPO_NAME2, TEST_REPO_NAME1, TEST_REPO_NAME3]) - test_equal(@full_org_member.github_repositories.length, 3) - test_equal(@full_org_member.terraform_repositories.length, 3) - test_equal(@full_org_member.missing_from_terraform_files, false) - end - - it "when github and terraform repositories do match but a repo is an everyone team repo" do - @full_org_member.add_everyone_team_repositories([TEST_REPO_NAME1]) - @full_org_member.get_full_org_member_repositories - @full_org_member.add_terraform_repositories([TEST_REPO_NAME2, TEST_REPO_NAME1, TEST_REPO_NAME3]) - test_equal(@full_org_member.github_repositories.length, 2) - test_equal(@full_org_member.terraform_repositories.length, 2) - test_equal(@full_org_member.missing_from_terraform_files, false) - end - - it "when github and terraform repositories do match but one repo is an archived repo" do - @full_org_member.add_archived_repositories([TEST_REPO_NAME1]) - @full_org_member.get_full_org_member_repositories - @full_org_member.add_terraform_repositories([TEST_REPO_NAME2, TEST_REPO_NAME1, TEST_REPO_NAME3]) - test_equal(@full_org_member.github_repositories.length, 2) - test_equal(@full_org_member.terraform_repositories.length, 2) - test_equal(@full_org_member.missing_from_terraform_files, false) - end - - it "when repos are archived repos" do - @full_org_member.add_archived_repositories([TEST_REPO_NAME1, TEST_REPO_NAME2, TEST_REPO_NAME3]) - @full_org_member.get_full_org_member_repositories - @full_org_member.add_terraform_repositories([TEST_REPO_NAME1, TEST_REPO_NAME2, TEST_REPO_NAME3]) - test_equal(@full_org_member.github_repositories.length, 0) - test_equal(@full_org_member.terraform_repositories.length, 0) - test_equal(@full_org_member.missing_from_terraform_files, false) - end - end - - context "call mismatched_repository_permissions_check" do - it "when github_repositories has repositories" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - expect(terraform_files).to receive(:get_terraform_files).and_return([]).at_least(3).times - test_equal(@full_org_member.mismatched_repository_permissions_check(terraform_files), false) - end - - it "when github_repositories and terraform_files have repositories" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - file = create_empty_terraform_file - expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(3).times - test_equal(@full_org_member.mismatched_repository_permissions_check(terraform_files), false) - end - - it "when github_repositories and terraform_files have repositories and permissions do not match" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - file = create_terraform_file_with_name(TEST_REPO_NAME1) - expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(2).times - expect(@full_org_member).to receive(:get_repository_permission).with(TEST_REPO_NAME1).and_return("push") - expect(file).to receive(:get_collaborator_permission).with(TEST_USER_1).and_return("admin") - test_equal(@full_org_member.mismatched_repository_permissions_check(terraform_files), true) - end - - it "when github_repositories and terraform_files have repositories and permissions do match" do - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - file = create_terraform_file_with_name(TEST_REPO_NAME1) - expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(2).times - expect(@full_org_member).to receive(:get_repository_permission).with(TEST_REPO_NAME1).and_return("push") - expect(file).to receive(:get_collaborator_permission).with(TEST_USER_1).and_return("push") - test_equal(@full_org_member.mismatched_repository_permissions_check(terraform_files), false) - end - - it "when github_repositories and terraform_files have repositories but repository is in the ignore list" do - @full_org_member.add_ignore_repository(TEST_REPO_NAME1) - @full_org_member.get_full_org_member_repositories - test_equal(@full_org_member.github_repositories.length, 3) - file = create_terraform_file_with_name(TEST_REPO_NAME1) - expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(2).times - test_equal(@full_org_member.mismatched_repository_permissions_check(terraform_files), false) - end - end - end - - after do - ENV.delete("OPS_BOT_TOKEN") - end - end - end -end diff --git a/spec/helper_module_spec.rb b/spec/helper_module_spec.rb index 665a495..11bb87f 100644 --- a/spec/helper_module_spec.rb +++ b/spec/helper_module_spec.rb @@ -91,75 +91,13 @@ class GithubCollaborators end end - context "call get_repository_teams_and_access_permissions" do - url = "#{GH_API_URL}/#{REPOSITORY_NAME}/teams" - repository_teams_json = File.read("spec/fixtures/repository-teams.json") - before do - expect(GithubCollaborators::HttpClient).to receive(:new).and_return(http_client) - end - - it "when team has admin permission to repository" do - expected_teams = [ - { - description: "", - permission: "admin", - team_name: "operations-engineering" - }, - { - description: AUTOMATED_GENERATED_TEAM.to_s, - permission: "read", - team_name: "operations-engineering-read-team" - } - ] - expect(http_client).to receive(:fetch_json).with(url).and_return(repository_teams_json) - the_teams = helper_module.get_repository_teams_and_access_permissions(REPOSITORY_NAME) - test_equal(the_teams, expected_teams) - end - end - - context "call get_all_org_members_team_repositories" do - url1 = "#{GH_ORG_API_URL}/teams/everyone/repos?per_page=100&page=1" - url2 = "#{GH_ORG_API_URL}/teams/everyone/repos?per_page=100&page=2" - url3 = "#{GH_ORG_API_URL}/teams/everyone/repos?per_page=100&page=3" - before do - expect(GithubCollaborators::HttpClient).to receive(:new).and_return(http_client).at_least(3).times - end - - it "when team has repositories" do - response = %([{"name": "#{TEST_REPO_NAME1}"},{"name": "#{TEST_REPO_NAME2}"}]) - expect(http_client).to receive(:fetch_json).with(url1).and_return(response) - expect(http_client).to receive(:fetch_json).with(url2).and_return([].to_json) - expect(http_client).to receive(:fetch_json).with(url3).and_return([].to_json) - repositories = [TEST_REPO_NAME1, TEST_REPO_NAME2] - test_equal(helper_module.get_everyone_team_repositories, repositories) - end - - it "when team has no repositories" do - response = [] - expect(http_client).to receive(:fetch_json).with(url1).and_return(response.to_json) - expect(http_client).to receive(:fetch_json).with(url2).and_return(response.to_json) - expect(http_client).to receive(:fetch_json).with(url3).and_return(response.to_json) - test_equal(helper_module.get_everyone_team_repositories, []) - end - end - - context "call does_collaborator_already_exist" do - it COLLABORATOR_EXISTS do - test_equal(helper_module.does_collaborator_already_exist(TEST_USER_1, @collaborators), true) - end - - it COLLABORATOR_DOESNT_EXIST do - test_equal(helper_module.does_collaborator_already_exist(TEST_USER_6, @collaborators), false) - end - end - context "call get_name" do it COLLABORATOR_EXISTS do test_equal(helper_module.get_name(TEST_USER_1, @collaborators), TEST_COLLABORATOR_NAME) end it COLLABORATOR_DOESNT_EXIST do - test_equal(helper_module.get_name(TEST_USER_6, @collaborators), "") + test_equal(helper_module.get_name(TEST_USER_4, @collaborators), "") end end @@ -169,7 +107,7 @@ class GithubCollaborators end it COLLABORATOR_DOESNT_EXIST do - test_equal(helper_module.get_email(TEST_USER_6, @collaborators), "") + test_equal(helper_module.get_email(TEST_USER_4, @collaborators), "") end end @@ -179,196 +117,7 @@ class GithubCollaborators end it COLLABORATOR_DOESNT_EXIST do - test_equal(helper_module.get_org(TEST_USER_6, @collaborators), "") - end - end - - context "call add_collaborator_to_automation_generated_team" do - context "" do - before do - incorrect_team_data = [{ - team_name: TEST_TEAM, - permission: "admin", - description: "some description" - }] - expect(helper_module).to receive(:get_repository_teams_and_access_permissions).and_return(incorrect_team_data) - expect(helper_module).not_to receive(:add_collaborator_to_team) - end - - it "when a repository team exists but the permission doesn't match" do - result = helper_module.add_collaborator_to_automation_generated_team(REPOSITORY_NAME, TEST_USER_1, "pull") - test_equal(result, false) - end - - it "when a repository team exists with the required permission but isn't an automation created team" do - result = helper_module.add_collaborator_to_automation_generated_team(REPOSITORY_NAME, TEST_USER_1, "admin") - test_equal(result, false) - end - end - - it "when a repository team exists with the required permission and is an automation created team" do - correct_team_data = [{team_name: TEST_TEAM, permission: "admin", description: AUTOMATED_GENERATED_TEAM}] - expect(helper_module).to receive(:get_repository_teams_and_access_permissions).and_return(correct_team_data) - expect(helper_module).to receive(:add_collaborator_to_team).with(TEST_TEAM, TEST_USER_1) - result = helper_module.add_collaborator_to_automation_generated_team(REPOSITORY_NAME, TEST_USER_1, "admin") - test_equal(result, true) - end - end - - context "when post to GitHub is disabled" do - before do - ENV.delete("REALLY_POST_TO_GH") - end - - it "so do not call remove_user_from_team" do - expect(http_client).not_to receive(:delete) - helper_module.remove_user_from_team(TEST_TEAM, TEST_USER_1) - end - - context "" do - before do - expect(http_client).not_to receive(:put_json) - end - - it "so do not call add_collaborator_to_team" do - helper_module.add_collaborator_to_team(TEST_TEAM, TEST_USER_1) - end - - it "so do not create_team" do - helper_module.create_team(REPOSITORY_NAME, TEST_TEAM) - end - - it "so do not call add_team_to_repository" do - helper_module.add_team_to_repository(REPOSITORY_NAME, TEST_TEAM, "admin") - end - end - end - - it "call create_team_name with all the permissions" do - permissions = ["admin", "pull", "push", "maintain", "triage"] - permissions.each do |permission| - created_name = helper_module.create_team_name(TEST_TEAM, permission) - expected_name = if permission == "pull" - "#{TEST_TEAM}-read-team" - elsif permission == "push" - "#{TEST_TEAM}-write-team" - else - "#{TEST_TEAM}-#{permission}-team" - end - test_equal(created_name, expected_name) - end - end - - context "when post to GitHub is enabled" do - before do - ENV["REALLY_POST_TO_GH"] = "1" - @team_url = "#{GH_ORG_API_URL}/teams/#{TEST_TEAM}/memberships/#{TEST_USER_1}" - @url = "#{GH_ORG_API_URL}/teams/#{TEST_TEAM}/repos/#{ORG}/#{REPOSITORY_NAME}" - end - - context "" do - before do - expect(GithubCollaborators::HttpClient).to receive(:new).and_return(http_client).at_least(5).time - end - - it "call add_team_to_repository with all the permissions" do - permissions = ["admin", "pull", "push", "maintain", "triage"] - permissions.each do |permission| - expected_json = %({"permission":"#{permission}"}) - expect(http_client).to receive(:put_json).with(@url, expected_json) - helper_module.add_team_to_repository(REPOSITORY_NAME, TEST_TEAM, permission) - end - end - end - - context "" do - before do - expect(GithubCollaborators::HttpClient).to receive(:new).and_return(http_client) - end - - it "call create_team" do - url = "#{GH_ORG_API_URL}/teams" - expected_json = %({"name":"#{TEST_TEAM}","description":"#{AUTOMATED_GENERATED_TEAM}","privacy":"closed","repo_names":["#{REPOSITORY_NAME}"]}) - expect(http_client).to receive(:post_json).with(url, expected_json) - helper_module.create_team(REPOSITORY_NAME, TEST_TEAM) - end - - it "call remove_user_from_team" do - expect(http_client).to receive(:delete).with(@team_url) - helper_module.remove_user_from_team(TEST_TEAM, TEST_USER_1) - end - - it "call add_collaborator_to_team" do - role = {role: "member"}.to_json - expect(http_client).to receive(:put_json).with(@team_url, role) - helper_module.add_collaborator_to_team(TEST_TEAM, TEST_USER_1) - end - - it "call add_team_to_repository with read permissions" do - expected_json = %({"permission":"pull"}) - expect(http_client).to receive(:put_json).with(@url, expected_json) - helper_module.add_team_to_repository(REPOSITORY_NAME, TEST_TEAM, "read") - end - - it "call add_team_to_repository with write permissions" do - expected_json = %({"permission":"push"}) - expect(http_client).to receive(:put_json).with(@url, expected_json) - helper_module.add_team_to_repository(REPOSITORY_NAME, TEST_TEAM, "write") - end - end - - after do - ENV.delete("REALLY_POST_TO_GH") - end - end - - context "call add_collaborator_to_repository_team" do - before do - expect(GithubCollaborators::HttpClient).to receive(:new).at_least(2).times.and_return(http_client) - end - - team_name = "#{REPOSITORY_NAME}-admin-team" - url = "#{GH_ORG_API_URL}/teams/#{team_name}" - - it "when first http_code is 404 and second http code is 404" do - expect(http_client).to receive(:fetch_code).with(url).and_return("404") - expect(http_client).to receive(:fetch_code).with(url).and_return("404") - expect(helper_module).to receive(:create_team).with(REPOSITORY_NAME, team_name) - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "nickwalt01") - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "ben-al") - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "AntonyBishop") - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "moj-operations-engineering-bot") - expect(helper_module).not_to receive(:add_team_to_repository) - helper_module.add_collaborator_to_repository_team(REPOSITORY_NAME, TEST_USER_1, "admin") - end - - it "when first http_code is 200 and second http code is 404" do - expect(http_client).to receive(:fetch_code).with(url).and_return("200") - expect(http_client).to receive(:fetch_code).with(url).and_return("404") - expect(helper_module).not_to receive(:create_team) - expect(helper_module).not_to receive(:add_team_to_repository) - helper_module.add_collaborator_to_repository_team(REPOSITORY_NAME, TEST_USER_1, "admin") - end - - it "when first http_code is 200 and second http code is 200" do - expect(http_client).to receive(:fetch_code).with(url).at_least(2).times.and_return("200") - expect(helper_module).not_to receive(:create_team) - expect(helper_module).to receive(:add_team_to_repository).with(REPOSITORY_NAME, team_name, "admin") - expect(helper_module).to receive(:add_collaborator_to_team).with(team_name, TEST_USER_1) - helper_module.add_collaborator_to_repository_team(REPOSITORY_NAME, TEST_USER_1, "admin") - end - - it "when first http_code is 404 and second http code is 200" do - expect(http_client).to receive(:fetch_code).with(url).and_return("404") - expect(http_client).to receive(:fetch_code).with(url).and_return("200") - expect(helper_module).to receive(:create_team).with(REPOSITORY_NAME, team_name) - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "nickwalt01") - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "ben-al") - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "AntonyBishop") - expect(helper_module).to receive(:remove_user_from_team).with(team_name, "moj-operations-engineering-bot") - expect(helper_module).to receive(:add_team_to_repository).with(REPOSITORY_NAME, team_name, "admin") - expect(helper_module).to receive(:add_collaborator_to_team).with(team_name, TEST_USER_1) - helper_module.add_collaborator_to_repository_team(REPOSITORY_NAME, TEST_USER_1, "admin") + test_equal(helper_module.get_org(TEST_USER_4, @collaborators), "") end end @@ -397,7 +146,7 @@ class GithubCollaborators filenames = ["file1", "file2", "file3"] branch_name = BRANCH_NAME collaborator_name = TEST_USER - types = [TYPE_DELETE_EMPTY_FILE, TYPE_EXTEND, TYPE_REMOVE, TYPE_PERMISSION, TYPE_ADD, TYPE_DELETE_ARCHIVE, TYPE_DELETE_FILE, TYPE_ADD_FROM_ISSUE] + types = [TYPE_DELETE_EMPTY_FILE, TYPE_EXTEND, TYPE_REMOVE, TYPE_DELETE_ARCHIVE, TYPE_DELETE_FILE, TYPE_ADD_FROM_ISSUE] it "when branch name valid and unknown type" do expect(GithubCollaborators::BranchCreator).to receive(:new).and_return(branch_creator) @@ -438,18 +187,9 @@ class GithubCollaborators elsif type == TYPE_EXTEND expect(helper_module).to receive(:create_pull_request) expect(helper_module).to receive(:extend_date_hash).with(collaborator_name, branch_name) - elsif type == TYPE_REMOVE_FULL_ORG_MEMBER - expect(helper_module).to receive(:create_pull_request) - expect(helper_module).to receive(:remove_full_org_member_hash).with(collaborator_name, branch_name) elsif type == TYPE_REMOVE expect(helper_module).to receive(:create_pull_request) expect(helper_module).to receive(:remove_collaborator_hash).with(collaborator_name, branch_name) - elsif type == TYPE_PERMISSION - expect(helper_module).to receive(:create_pull_request) - expect(helper_module).to receive(:modify_collaborator_permission_hash).with(collaborator_name, branch_name) - elsif type == TYPE_ADD - expect(helper_module).to receive(:create_pull_request) - expect(helper_module).to receive(:add_collaborator_hash).with(collaborator_name, branch_name) elsif type == TYPE_DELETE_ARCHIVE expect(helper_module).to receive(:create_pull_request) expect(helper_module).to receive(:delete_archive_file_hash).with(branch_name) @@ -607,35 +347,6 @@ class GithubCollaborators end end - context "" do - login = TEST_USER - branch_name = BRANCH_NAME - hash_body = { - title: ADD_FULL_ORG_MEMBER_PR_TITLE + " " + login.downcase, - head: branch_name.downcase, - draft: true, - base: GITHUB_BRANCH, - body: <<~EOF - Hi there - - This is the GitHub-Outside-Collaborator repository bot. - - The collaborator #{login.downcase} was found to be missing from the file/s in this pull request. - - This is because the collaborator is a full organization member and is able to join repositories outside of Terraform. - - This pull request ensures we keep track of those collaborators and which repositories they are accessing. - - Edit the pull request file/s because some of the data about the collaborator is missing. - - EOF - } - - it "call add_collaborator_hash" do - test_equal(helper_module.add_collaborator_hash(login, branch_name), hash_body) - end - end - context "" do login = TEST_USER branch_name = BRANCH_NAME @@ -685,65 +396,6 @@ class GithubCollaborators end end - context "" do - login = TEST_USER - branch_name = BRANCH_NAME - hash_body = { - title: REMOVE_FULL_ORG_MEMBER_PR_TITLE + " " + login.downcase, - head: branch_name.downcase, - draft: true, - base: GITHUB_BRANCH, - body: <<~EOF - Hi there - - **IMPORTANT** Approve and run this PR before any others. A collaborator repository access has been removed. Running tf apply on another PR will invite the collaborator to repository again. - - This is the GitHub-Outside-Collaborator repository bot. - - The full org member / collaborator #{login.downcase} access to one or more repositories has been revoked. - - This is because the collaborator is a full organization member and is able to join repositories outside of Terraform via Teams. - - This pull request ensures we keep track of those collaborators and which repositories they are accessing. - EOF - } - - it "call remove_full_org_member_hash" do - test_equal(helper_module.remove_full_org_member_hash(login, branch_name), hash_body) - end - end - - context "" do - login = TEST_USER - branch_name = BRANCH_NAME - hash_body = { - title: CHANGE_PERMISSION_PR_TITLE + " " + login.downcase, - head: branch_name.downcase, - draft: true, - base: GITHUB_BRANCH, - body: <<~EOF - Hi there - - This is the GitHub-Outside-Collaborator repository bot. - - The collaborator #{login.downcase} permission on Github is different to the permission in the Terraform file for the repository. - - This is because the collaborator is a full organization member, is able to join repositories outside of Terraform and may have different access to the repository now they are in a Team. - - The permission on Github is given the priority. - - This pull request ensures we keep track of those collaborators, which repositories they are accessing and their permission. - - Permission can either be admin, push, maintain, pull or triage. - - EOF - } - - it "call modify_collaborator_permission_hash" do - test_equal(helper_module.modify_collaborator_permission_hash(login, branch_name), hash_body) - end - end - context "call get_active_repositories" do it "when no repositories exist" do expect(helper_module).to receive(:get_active_repositories_from_github).and_return([]) @@ -975,7 +627,7 @@ class GithubCollaborators end it "when archived repositories exist" do - # FUT has a loop with tree iterations. Each loop produces a list of repo names. + # FUT has a loop with three iterations. Each loop produces a list of repo names. expect(graphql_client).to receive(:run_query).with(json_query_public).and_return(return_data) expect(graphql_client).to receive(:run_query).with(json_query_private).and_return(return_data) expect(graphql_client).to receive(:run_query).with(json_query_internal).and_return(return_data) diff --git a/spec/odd_full_org_members_spec.rb b/spec/odd_full_org_members_spec.rb deleted file mode 100644 index 4f3a27c..0000000 --- a/spec/odd_full_org_members_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -class GithubCollaborators - include TestConstants - include Constants - - describe OddFullOrgMembers do - context "test OddFullOrgMembers" do - subject(:odd_collaborator) { described_class.new } - - it "call create_line" do - line = odd_collaborator.create_line("bob") - test_equal(line, "- bob") - end - - it "singular_message" do - line = odd_collaborator.singular_message - test_equal(line, "I've found a collaborator who is a full Org member but isn't attached to any GitHub repositories except the everyone team respositories. Consider removing this collaborator") - end - - it "multiple_message" do - line = odd_collaborator.multiple_message(4) - test_equal(line, "I've found 4 collaborators who are full Org members but are not attached to any GitHub repositories except the everyone team respositories. Consider removing these collaborators") - end - end - end -end diff --git a/spec/organization_members_spec.rb b/spec/organization_members_spec.rb deleted file mode 100644 index 1402fcd..0000000 --- a/spec/organization_members_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -class GithubCollaborators - include TestConstants - include Constants - - describe HelperModule do - let(:helper_module) { Class.new { extend HelperModule } } - let(:graphql_client) { double(GithubCollaborators::GithubGraphQlClient) } - - json_data = %( - { - organization(login: "#{ORG}") { - membersWithRole( - first: 100 - after: null - ) { - edges { - node { - login - } - } - pageInfo { - hasNextPage - endCursor - } - } - } - } - ) - - before do - expect(GithubCollaborators::GithubGraphQlClient).to receive(:new).and_return(graphql_client) - end - - it "call get_all_organisation_members when create collaborators where no pagination" do - return_data = File.read("spec/fixtures/organisation-members.json") - expect(graphql_client).to receive(:run_query).with(json_data).and_return(return_data) - organization_members = helper_module.get_all_organisation_members - test_equal(organization_members.length, 2) - test_equal(organization_members, [TEST_USER_1, TEST_USER_2]) - end - - json_data_no_collaborators = - %( - { - "data": { - "organization": { - "membersWithRole": { - "pageInfo": { - "hasNextPage": false, - "endCursor": null - }, - "edges": [] - } - } - } - } - ) - - it "call get_all_organisation_members when no collaborators exist" do - expect(graphql_client).to receive(:run_query).with(json_data).and_return(json_data_no_collaborators) - organization_members = helper_module.get_all_organisation_members - test_equal(organization_members.length, 0) - end - end -end diff --git a/spec/organization_spec.rb b/spec/organization_spec.rb index 935b884..15dbc84 100644 --- a/spec/organization_spec.rb +++ b/spec/organization_spec.rb @@ -11,13 +11,10 @@ class GithubCollaborators it "initialize object" do repo2 = GithubCollaborators::Repository.new(TEST_REPO_NAME2, 5) repo3 = GithubCollaborators::Repository.new(TEST_REPO_NAME3, 0) - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([repo2, repo3]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([TEST_REPO_NAME1, TEST_REPO_NAME2]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) organization = GithubCollaborators::Organization.new test_equal(organization.repositories.length, 2) - test_equal(organization.full_org_members.length, 0) test_equal(organization.archived_repositories.length, 2) test_equal(organization.archived_repositories, [TEST_REPO_NAME1, TEST_REPO_NAME2]) end @@ -27,18 +24,7 @@ class GithubCollaborators context "" do before do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) - end - - context "call is_full_org_member_attached_to_repository" do - it "when there is no full org member" do - allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) - organization = GithubCollaborators::Organization.new - result = organization.is_full_org_member_attached_to_repository(TEST_REPO_NAME) - test_equal(result, false) - end end context "call get_repository_issues_from_github" do @@ -74,28 +60,6 @@ class GithubCollaborators end end - context "call get_full_org_members_not_on_github" do - before do - allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) - @organization = GithubCollaborators::Organization.new - end - - it "when no full org members" do - test_equal(@organization.get_full_org_members_not_on_github.length, 0) - end - - it "when full org member hasn't been removed on GitHub" do - @organization.add_full_org_member(TEST_USER_1) - test_equal(@organization.get_full_org_members_not_on_github.length, 0) - end - - it "when full org member has been removed on GitHub" do - @organization.add_full_org_member(TEST_USER_1) - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:removed_from_github_repository).and_return(true) - test_equal(@organization.get_full_org_members_not_on_github.length, 1) - end - end - context "call read_repository_issues" do it "when no repositories exist" do allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) @@ -137,66 +101,10 @@ class GithubCollaborators before do allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) - end - - context "" do - before do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) - @organization = GithubCollaborators::Organization.new - end - - it "call add_full_org_member" do - @organization.add_full_org_member(TEST_USER_1) - test_equal(@organization.full_org_members.length, 1) - end - - it "call is_collaborator_an_org_member when no collaborators" do - test_equal(@organization.is_collaborator_an_org_member(TEST_USER_6), false) - end - end - - context "call is_collaborator_an_org_member" do - before do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([TEST_USER_1, TEST_USER_2]) - @organization = GithubCollaborators::Organization.new - end - - it "when collaborator is not an org member" do - test_equal(@organization.is_collaborator_an_org_member(TEST_USER_6), false) - end - - it "when collaborator is an org member" do - test_equal(@organization.is_collaborator_an_org_member(TEST_USER_2), true) - end - end - - context "call is_collaborator_a_full_org_member" do - before do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) - @organization = GithubCollaborators::Organization.new - end - - it "when array is empty" do - test_equal(@organization.is_collaborator_a_full_org_member(TEST_USER_2), false) - end - - it "when array has collaborators but no match" do - @organization.add_full_org_member(TEST_USER_1) - @organization.add_full_org_member(TEST_USER_2) - test_equal(@organization.is_collaborator_a_full_org_member(TEST_USER_3), false) - end - - it "when array has collaborators and a match" do - @organization.add_full_org_member(TEST_USER_1) - @organization.add_full_org_member(TEST_USER_2) - test_equal(@organization.is_collaborator_a_full_org_member(TEST_USER_2), true) - end end context "" do before do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:get_full_org_member_repositories) terraform_block = create_collaborator_with_login(TEST_USER_1) @collaborator1 = GithubCollaborators::Collaborator.new(terraform_block, TEST_REPO_NAME) terraform_block = create_collaborator_with_login(TEST_USER_2) @@ -207,164 +115,19 @@ class GithubCollaborators context "" do before do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:get_full_org_member_repositories) - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) @organization = GithubCollaborators::Organization.new end - it "call create_full_org_members when collaborators are not org members" do - @organization.create_full_org_members([@collaborator1, @collaborator2, @collaborator3]) - test_equal(@organization.full_org_members.length, 0) - end - it "call get_org_archived_repositories when empty" do test_equal(@organization.get_org_archived_repositories.length, 0) end - - it "call get_full_org_members_not_in_terraform_file when no full org members" do - test_equal(@organization.get_full_org_members_not_in_terraform_file, []) - end - - it "call get_full_org_members_with_repository_permission_mismatches when no full org members" do - test_equal(@organization.get_full_org_members_with_repository_permission_mismatches(nil), []) - end - - it "call get_odd_full_org_members when no full org members" do - test_equal(@organization.get_odd_full_org_members, []) - end - - it "call get_full_org_members_attached_to_archived_repositories when no full org members" do - test_equal(@organization.get_full_org_members_attached_to_archived_repositories(nil), []) - end - end - - context "call create_full_org_members" do - it "when collaborators are org members and names are the same" do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([TEST_USER_1]) - organization = GithubCollaborators::Organization.new - organization.create_full_org_members([@collaborator1, @collaborator1, @collaborator1]) - test_equal(organization.full_org_members.length, 1) - end - - it "when collaborators are org members and names are different" do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([TEST_USER_1, TEST_USER_2, TEST_USER_3]) - organization = GithubCollaborators::Organization.new - organization.create_full_org_members([@collaborator1, @collaborator2, @collaborator3]) - test_equal(organization.full_org_members.length, 3) - end - end - - context "" do - before do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([TEST_USER_1, TEST_USER_2, TEST_USER_3]) - @organization = GithubCollaborators::Organization.new - @organization.create_full_org_members([@collaborator1, @collaborator2, @collaborator3]) - test_equal(@organization.full_org_members.length, 3) - end - - context "call is_full_org_member_attached_to_repository" do - before do - @organization.full_org_members.each do |org_member| - org_member.add_github_repository(TEST_REPO_NAME) - end - end - - it "when there is full org member who is not attached to the repo" do - result = @organization.is_full_org_member_attached_to_repository(TEST_REPO_NAME4) - test_equal(result, false) - end - - it "when there is full org memberwho is attached to the repo" do - result = @organization.is_full_org_member_attached_to_repository(TEST_REPO_NAME) - test_equal(result, true) - end - end - - context "call get_full_org_members_with_repository_permission_mismatches" do - it "when collaborator permissions do not match" do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:mismatched_repository_permissions_check).and_return(false) - test_equal(@organization.get_full_org_members_with_repository_permission_mismatches(nil), []) - end - - it "when collaborator permissions do match" do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:mismatched_repository_permissions_check).and_return(true) - result = @organization.get_full_org_members_with_repository_permission_mismatches(nil) - test_equal(result.length, 3) - expected_collaborators = [{login: TEST_USER_1, mismatches: []}, {login: TEST_USER_2, mismatches: []}, {login: TEST_USER_3, mismatches: []}] - test_equal(result, expected_collaborators) - end - end - - context "call get_full_org_members_not_in_terraform_file" do - it "when collaborators are defined in terraform file" do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:missing_from_terraform_files).and_return(false) - test_equal(@organization.get_full_org_members_not_in_terraform_file, []) - end - - it "when collaborators are not defined in terraform file" do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:missing_from_terraform_files).and_return(true) - test_equal(@organization.get_full_org_members_not_in_terraform_file.length, 3) - end - end - - context "call get_odd_full_org_members" do - it "when collaborators are odd" do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:odd_full_org_member_check).and_return(false) - test_equal(@organization.get_odd_full_org_members, []) - end - - it "when collaborators are not odd" do - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:odd_full_org_member_check).and_return(true) - result = @organization.get_odd_full_org_members - test_equal(result, [TEST_USER_1, TEST_USER_2, TEST_USER_3]) - end - end - - context "call get_full_org_members_attached_to_archived_repositories" do - let(:terraform_files) { double(GithubCollaborators::TerraformFiles) } - - it "when full org member has no archived repositories" do - test_equal(@organization.get_full_org_members_attached_to_archived_repositories(nil), []) - end - - it "when full org member has archived repositories but the file doesn't exist" do - @organization.full_org_members.each do |full_org_member| - full_org_member.add_attached_archived_repository(TEST_REPO_NAME1) - full_org_member.add_attached_archived_repository(TEST_REPO_NAME2) - end - expect(terraform_files).to receive(:does_file_exist).and_return(false).at_least(6).times - result = @organization.get_full_org_members_attached_to_archived_repositories(terraform_files) - test_equal(result, []) - end - - it "when full org member has archived repositories and the file does exist" do - @organization.full_org_members.each do |full_org_member| - full_org_member.add_attached_archived_repository(TEST_REPO_NAME1) - full_org_member.add_attached_archived_repository(TEST_REPO_NAME2) - end - expect(terraform_files).to receive(:does_file_exist).and_return(true).at_least(6).times - result = @organization.get_full_org_members_attached_to_archived_repositories(terraform_files) - expected_result = [ - {login: TEST_USER_1, repository: TEST_REPO_NAME1}, - {login: TEST_USER_1, repository: TEST_REPO_NAME2}, - {login: TEST_USER_2, repository: TEST_REPO_NAME1}, - {login: TEST_USER_2, repository: TEST_REPO_NAME2}, - {login: TEST_USER_3, repository: TEST_REPO_NAME1}, - {login: TEST_USER_3, repository: TEST_REPO_NAME2} - ] - test_equal(result, expected_result) - end - end end end end it "call get_org_archived_repositories when there are archived_repositories" do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([TEST_REPO_NAME1, TEST_REPO_NAME2]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) - allow_any_instance_of(GithubCollaborators::FullOrgMember).to receive(:get_full_org_member_repositories) organization = GithubCollaborators::Organization.new test_equal(organization.get_org_archived_repositories.length, 2) end diff --git a/spec/outside_collaborators_spec.rb b/spec/outside_collaborators_spec.rb index e5e9168..6203e04 100644 --- a/spec/outside_collaborators_spec.rb +++ b/spec/outside_collaborators_spec.rb @@ -4,11 +4,7 @@ class GithubCollaborators describe OutsideCollaborators do let(:terraform_files) { double(GithubCollaborators::TerraformFiles) } - let(:odd_full_org_slack_message) { double(GithubCollaborators::OddFullOrgMembers) } - let(:full_org_archived_repository_slack_message) { double(GithubCollaborators::ArchivedRepositories) } let(:expires_soon_slack_message) { double(GithubCollaborators::ExpiresSoon) } - let(:full_org_expires_soon_slack_message) { double(GithubCollaborators::FullOrgMemberExpiresSoon) } - let(:full_org_expired_slack_message) { double(GithubCollaborators::FullOrgMemberExpired) } let(:expired_slack_message) { double(GithubCollaborators::Expired) } let(:unkown_collaborators_slack_message) { double(GithubCollaborators::UnknownCollaborators) } let(:removed_collaborators_slack_message) { double(GithubCollaborators::Removed) } @@ -26,7 +22,7 @@ class GithubCollaborators allow_any_instance_of(HelperModule).to receive(:get_pull_requests).and_return([]) expect(GithubCollaborators::TerraformFiles).to receive(:new).and_return(terraform_files).at_least(1).times expect(GithubCollaborators::Organization).to receive(:new).and_return(organization).at_least(1).times - expect(organization).to receive(:create_full_org_members) + terraform_block = create_terraform_block_review_date_yesterday @expired_collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) @expired_collaborator.check_for_issues @@ -43,7 +39,10 @@ class GithubCollaborators @collaborator1 = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) @collaborator1.check_for_issues - terraform_block = create_collaborator_with_login(TEST_USER_2) + review_date = Date.today.strftime(DATE_FORMAT) + collaborator_data = create_collaborator_data(review_date) + collaborator_data[:login] = TEST_USER_2 + terraform_block = create_terraform_block(collaborator_data) @collaborator2 = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) end @@ -59,8 +58,6 @@ class GithubCollaborators expect(@outside_collaborators).to receive(:deleted_repository_check) expect(@outside_collaborators).to receive(:compare_terraform_and_github) expect(@outside_collaborators).to receive(:collaborator_checks) - expect(@outside_collaborators).to receive(:full_org_members_check) - expect(@outside_collaborators).to receive(:print_full_org_member_collaborators) @outside_collaborators.start end @@ -96,14 +93,12 @@ class GithubCollaborators it "call has_review_date_expired" do expect(@outside_collaborators).to receive(:find_collaborators_who_have_expired).with([@collaborator1]).and_return([@collaborator1]) expect(@outside_collaborators).to receive(:remove_expired_collaborators).with([@collaborator1]) - expect(@outside_collaborators).to receive(:remove_expired_full_org_members).with([@collaborator1]) @outside_collaborators.has_review_date_expired([@collaborator1]) end it "call is_review_date_within_a_week" do expect(@outside_collaborators).to receive(:find_collaborators_who_expire_soon).with([@collaborator1]).and_return([@collaborator1]) expect(@outside_collaborators).to receive(:extend_collaborators_review_date).with([@collaborator1]) - expect(@outside_collaborators).to receive(:extend_full_org_member_review_date).with([@collaborator1]) @outside_collaborators.is_review_date_within_a_week([@collaborator1]) end @@ -180,131 +175,6 @@ class GithubCollaborators test_equal(removed_collaborators.length, 3) end end - - context "call change_collaborator_permission" do - it "when no repositories passed in" do - @outside_collaborators.change_collaborator_permission(TEST_USER_2, []) - expect(terraform_files).not_to receive(:ensure_file_exists_in_memory) - end - - it WHEN_PULL_REQUEST_DOESNT_EXIST do - repositories = [ - {permission: "push", repository_name: REPOSITORY_NAME}, - {permission: "admin", repository_name: REPOSITORY_NAME}, - {permission: "pull", repository_name: REPOSITORY_NAME} - ] - allow_any_instance_of(OutsideCollaborators).to receive(:does_pr_already_exist).with(TEST_TERRAFORM_FILE, "#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}").and_return(false) - expect(terraform_files).to receive(:ensure_file_exists_in_memory).with(REPOSITORY_NAME).at_least(3).times - expect(terraform_files).to receive(:change_collaborator_permission_in_file).with(REPOSITORY_NAME, TEST_USER_2, "push") - expect(terraform_files).to receive(:change_collaborator_permission_in_file).with(REPOSITORY_NAME, TEST_USER_2, "admin") - expect(terraform_files).to receive(:change_collaborator_permission_in_file).with(REPOSITORY_NAME, TEST_USER_2, "pull") - allow_any_instance_of(HelperModule).to receive(:create_branch_and_pull_request).with("#{MODIFY_COLLABORATORS_BRANCH_NAME}#{TEST_USER_2}", [TEST_TERRAFORM_FILE_FULL_PATH, TEST_TERRAFORM_FILE_FULL_PATH, TEST_TERRAFORM_FILE_FULL_PATH], "#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}", TEST_USER_2, TYPE_PERMISSION) - expect(@outside_collaborators).to receive(:add_new_pull_request).with("#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}", [TEST_TERRAFORM_FILE_FULL_PATH, TEST_TERRAFORM_FILE_FULL_PATH, TEST_TERRAFORM_FILE_FULL_PATH]) - @outside_collaborators.change_collaborator_permission(TEST_USER_2, repositories) - end - - it "when a pull request does exist" do - repositories = [ - {permission: "push", repository_name: REPOSITORY_NAME}, - {permission: "admin", repository_name: TEST_REPO_NAME}, - {permission: "pull", repository_name: REPOSITORY_NAME} - ] - expect(@outside_collaborators).to receive(:does_pr_already_exist).with(TEST_TERRAFORM_FILE, "#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}").and_return(false) - expect(@outside_collaborators).to receive(:does_pr_already_exist).with(TEST_REPO_NAME_TERRAFORM_FILE, "#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}").and_return(true) - expect(@outside_collaborators).to receive(:does_pr_already_exist).with(TEST_TERRAFORM_FILE, "#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}").and_return(false) - expect(terraform_files).to receive(:ensure_file_exists_in_memory).with(REPOSITORY_NAME).at_least(2).times - expect(terraform_files).to receive(:change_collaborator_permission_in_file).with(REPOSITORY_NAME, TEST_USER_2, "push") - expect(terraform_files).to receive(:change_collaborator_permission_in_file).with(REPOSITORY_NAME, TEST_USER_2, "pull") - allow_any_instance_of(HelperModule).to receive(:create_branch_and_pull_request).with("#{MODIFY_COLLABORATORS_BRANCH_NAME}#{TEST_USER_2}", [TEST_TERRAFORM_FILE_FULL_PATH, TEST_TERRAFORM_FILE_FULL_PATH], "#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}", TEST_USER_2, TYPE_PERMISSION) - expect(@outside_collaborators).to receive(:add_new_pull_request).with("#{CHANGE_PERMISSION_PR_TITLE} #{TEST_USER_2}", [TEST_TERRAFORM_FILE_FULL_PATH, TEST_TERRAFORM_FILE_FULL_PATH]) - @outside_collaborators.change_collaborator_permission(TEST_USER_2, repositories) - end - end - - context "call remove_full_org_member_from_terraform_files" do - before do - @full_org_member = GithubCollaborators::FullOrgMember.new(TEST_USER_1) - end - - context "" do - before do - expect(terraform_files).not_to receive(:remove_collaborator_from_file) - expect(@outside_collaborators).not_to receive(:add_new_pull_request) - end - - it "when collaborator hasn't been removed from any repositories" do - @outside_collaborators.remove_full_org_member_from_terraform_files(@full_org_member) - end - - it "when a pull request already exists" do - @full_org_member.removed_from_repositories.push(TEST_REPO_NAME) - expect(@outside_collaborators).to receive(:does_pr_already_exist).and_return(true) - @outside_collaborators.remove_full_org_member_from_terraform_files(@full_org_member) - end - - it "when terraform file doesn't exist" do - @full_org_member.removed_from_repositories.push(TEST_REPO_NAME) - expect(@outside_collaborators).to receive(:does_pr_already_exist).and_return(false) - expect(terraform_files).to receive(:does_file_exist).and_return(false) - @outside_collaborators.remove_full_org_member_from_terraform_files(@full_org_member) - end - end - - it "and create a new PR" do - @full_org_member.removed_from_repositories.push(TEST_REPO_NAME) - expect(@outside_collaborators).to receive(:does_pr_already_exist).and_return(false) - expect(terraform_files).to receive(:does_file_exist).and_return(true) - expect(terraform_files).to receive(:remove_collaborator_from_file) - expect(@outside_collaborators).to receive(:add_new_pull_request).with("#{REMOVE_FULL_ORG_MEMBER_PR_TITLE} #{TEST_USER_1}", [TEST_FILE]) - @outside_collaborators.remove_full_org_member_from_terraform_files(@full_org_member) - end - end - - context "call add_collaborator" do - before do - @full_org_member = GithubCollaborators::FullOrgMember.new(TEST_USER_1) - end - - it "when have no mismatch in collaborator repositories" do - test_equal(@full_org_member.missing_from_terraform_files, false) - expect(terraform_files).not_to receive(:ensure_file_exists_in_memory) - @outside_collaborators.add_collaborator(@full_org_member) - end - - context "" do - before do - @full_org_member.add_github_repository(TEST_REPO_NAME) - test_equal(@full_org_member.terraform_repositories.length, 0) - test_equal(@full_org_member.github_repositories.length, 1) - test_equal(@full_org_member.missing_from_terraform_files, true) - end - - it "when a pull request already exists" do - expect(@outside_collaborators).to receive(:does_pr_already_exist).with(TEST_REPO_NAME_TERRAFORM_FILE, "#{ADD_FULL_ORG_MEMBER_PR_TITLE} #{TEST_USER_1}").and_return(true) - expect(terraform_files).not_to receive(:ensure_file_exists_in_memory) - @outside_collaborators.add_collaborator(@full_org_member) - end - - it "when collaborator is on the GitHub repository and already in the Terraform file and a pull request does not exist" do - expect(@outside_collaborators).to receive(:does_pr_already_exist).with(TEST_REPO_NAME_TERRAFORM_FILE, "#{ADD_FULL_ORG_MEMBER_PR_TITLE} #{TEST_USER_1}").and_return(false) - expect(terraform_files).to receive(:is_user_in_file).with(TEST_REPO_NAME, TEST_USER_1).and_return(true) - expect(terraform_files).not_to receive(:ensure_file_exists_in_memory) - @outside_collaborators.add_collaborator(@full_org_member) - end - - it "when collaborator is on the GitHub repository but not in the Terraform file and collaborator isn't in the Terraform file and a pull request does not exist" do - expect(@outside_collaborators).to receive(:does_pr_already_exist).with(TEST_REPO_NAME_TERRAFORM_FILE, "#{ADD_FULL_ORG_MEMBER_PR_TITLE} #{TEST_USER_1}").and_return(false) - expect(terraform_files).to receive(:is_user_in_file).with(TEST_REPO_NAME, TEST_USER_1).and_return(false) - expect(terraform_files).to receive(:ensure_file_exists_in_memory).with(TEST_REPO_NAME) - expect(@full_org_member).to receive(:get_repository_permission).with(TEST_REPO_NAME).and_return("triage") - expect(terraform_files).to receive(:add_full_org_collaborator_to_file).with(TEST_REPO_NAME, @full_org_member, "triage") - expect(@full_org_member).to receive(:add_ignore_repository).with(TEST_REPO_NAME) - allow_any_instance_of(HelperModule).to receive(:create_branch_and_pull_request).with("#{ADD_COLLABORATOR_BRANCH_NAME}#{TEST_USER_1}", [TEST_FILE], "#{ADD_FULL_ORG_MEMBER_PR_TITLE} #{TEST_USER_1}", TEST_USER_1, TYPE_ADD) - expect(@outside_collaborators).to receive(:add_new_pull_request).with("#{ADD_FULL_ORG_MEMBER_PR_TITLE} #{TEST_USER_1}", [TEST_FILE]) - @outside_collaborators.add_collaborator(@full_org_member) - end - end - end end it "call remove_empty_files when no empty file exists" do @@ -461,126 +331,12 @@ class GithubCollaborators end end - context "call full_org_members_check" do - before do - expect(terraform_files).to receive(:get_terraform_files).and_return([]) - end - - it "when full org member not in terraform file" do - outside_collaborators = GithubCollaborators::OutsideCollaborators.new - expect(organization).to receive(:get_full_org_members_not_on_github).and_return([]) - expect(organization).to receive(:get_full_org_members_not_in_terraform_file).and_return([@collaborator1]) - expect(organization).to receive(:get_full_org_members_with_repository_permission_mismatches).and_return([]) - expect(organization).to receive(:get_odd_full_org_members).and_return([]) - expect(organization).to receive(:get_full_org_members_attached_to_archived_repositories).and_return([]) - - expect(outside_collaborators).to receive(:add_collaborator).with(@collaborator1) - expect(outside_collaborators).not_to receive(:change_collaborator_permission) - expect(GithubCollaborators::SlackNotifier).not_to receive(:new) - outside_collaborators.full_org_members_check - end - - it "when full org member not on GitHub but in terraform file so call remove_full_org_member_from_terraform_files" do - outside_collaborators = GithubCollaborators::OutsideCollaborators.new - full_org_member = GithubCollaborators::FullOrgMember.new(TEST_USER_1) - expect(organization).to receive(:get_full_org_members_not_on_github).and_return([full_org_member]) - expect(outside_collaborators).to receive(:remove_full_org_member_from_terraform_files).with(full_org_member) - expect(organization).to receive(:get_full_org_members_not_in_terraform_file).and_return([]) - expect(organization).to receive(:get_full_org_members_with_repository_permission_mismatches).and_return([]) - expect(organization).to receive(:get_odd_full_org_members).and_return([]) - expect(organization).to receive(:get_full_org_members_attached_to_archived_repositories).and_return([]) - outside_collaborators.full_org_members_check - end - - context "" do - before do - expect(organization).to receive(:get_full_org_members_not_in_terraform_file).and_return([]) - expect(organization).to receive(:get_full_org_members_not_on_github).and_return([]) - @outside_collaborators = GithubCollaborators::OutsideCollaborators.new - end - - it "when org and arrays are empty" do - expect(organization).to receive(:get_full_org_members_with_repository_permission_mismatches).and_return([]) - expect(organization).to receive(:get_odd_full_org_members).and_return([]) - expect(organization).to receive(:get_full_org_members_attached_to_archived_repositories).and_return([]) - expect(terraform_files).not_to receive(:did_automation_add_collaborator_to_file) - expect(@outside_collaborators).not_to receive(:add_collaborator) - expect(@outside_collaborators).not_to receive(:change_collaborator_permission) - expect(GithubCollaborators::SlackNotifier).not_to receive(:new) - @outside_collaborators.full_org_members_check - end - - context "when full org member has repository permissions mismatches" do - before do - mismatch1 = {permission: "admin", repository_name: TEST_REPO_NAME1} - mismatch2 = {permission: "push", repository_name: TEST_REPO_NAME2} - @mismatches = [mismatch1, mismatch2] - member = {login: TEST_USER_1, mismatches: @mismatches} - expect(organization).to receive(:get_full_org_members_with_repository_permission_mismatches).and_return([member]) - expect(organization).to receive(:get_odd_full_org_members).and_return([]) - expect(organization).to receive(:get_full_org_members_attached_to_archived_repositories).and_return([]) - expect(@outside_collaborators).not_to receive(:add_collaborator) - end - - it "and add the collaborator to an automation generated team" do - expect(terraform_files).to receive(:did_automation_add_collaborator_to_file).and_return(false).at_least(2).times - allow_any_instance_of(HelperModule).to receive(:add_collaborator_to_automation_generated_team).and_return(true) - expect(@outside_collaborators).not_to receive(:change_collaborator_permission) - expect(GithubCollaborators::SlackNotifier).not_to receive(:new) - @outside_collaborators.full_org_members_check - end - - it "and add the collaborator to a repository team" do - expect(terraform_files).to receive(:did_automation_add_collaborator_to_file).and_return(false).at_least(2).times - allow_any_instance_of(HelperModule).to receive(:add_collaborator_to_automation_generated_team).and_return(false) - allow_any_instance_of(HelperModule).to receive(:add_collaborator_to_repository_team) - expect(@outside_collaborators).not_to receive(:change_collaborator_permission) - expect(GithubCollaborators::SlackNotifier).not_to receive(:new) - @outside_collaborators.full_org_members_check - end - - it "and change the collaborator repository permission" do - expect(terraform_files).to receive(:did_automation_add_collaborator_to_file).and_return(true).at_least(2).times - expect(@outside_collaborators).to receive(:change_collaborator_permission).with(TEST_USER_1, @mismatches) - expect(GithubCollaborators::SlackNotifier).not_to receive(:new) - @outside_collaborators.full_org_members_check - end - end - - it "when find a odd full org member" do - expect(organization).to receive(:get_full_org_members_with_repository_permission_mismatches).and_return([]) - expect(organization).to receive(:get_odd_full_org_members).and_return([TEST_USER_1]) - expect(organization).to receive(:get_full_org_members_attached_to_archived_repositories).and_return([]) - expect(@outside_collaborators).not_to receive(:add_collaborator) - expect(@outside_collaborators).not_to receive(:change_collaborator_permission) - expect(GithubCollaborators::SlackNotifier).to receive(:new).with(instance_of(GithubCollaborators::OddFullOrgMembers), [TEST_USER_1]).and_return(odd_full_org_slack_message) - expect(odd_full_org_slack_message).to receive(:post_slack_message) - expect(GithubCollaborators::SlackNotifier).not_to receive(:new) - @outside_collaborators.full_org_members_check - end - - it "when full org member attached to archived repository" do - expect(organization).to receive(:get_full_org_members_with_repository_permission_mismatches).and_return([]) - expect(organization).to receive(:get_odd_full_org_members).and_return([]) - member = {login: TEST_USER_1, repository: TEST_REPO_NAME1} - expect(organization).to receive(:get_full_org_members_attached_to_archived_repositories).and_return([member]) - expect(@outside_collaborators).not_to receive(:add_collaborator) - expect(@outside_collaborators).not_to receive(:change_collaborator_permission) - expect(GithubCollaborators::SlackNotifier).to receive(:new).with(instance_of(GithubCollaborators::ArchivedRepositories), [member]).and_return(full_org_archived_repository_slack_message) - expect(full_org_archived_repository_slack_message).to receive(:post_slack_message) - @outside_collaborators.full_org_members_check - end - end - end - context "functions that have a collaborators parameter" do before do expect(terraform_files).to receive(:get_terraform_files).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_org_outside_collaborators).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) @organization = GithubCollaborators::Organization.new @outside_collaborators = GithubCollaborators::OutsideCollaborators.new end @@ -614,14 +370,7 @@ class GithubCollaborators @outside_collaborators.extend_collaborators_review_date([]) end - it WHEN_COLLABORATOR_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(true) - expect(@outside_collaborators).not_to receive(:extend_date) - @outside_collaborators.extend_collaborators_review_date([@collaborator1]) - end - - it WHEN_COLLABORATOR_NOT_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(false) + it WITH_COLLABORATOR do expect(@outside_collaborators).to receive(:extend_date).with([@collaborator1]).and_return([@collaborator1]) expect(GithubCollaborators::SlackNotifier).to receive(:new).with(instance_of(GithubCollaborators::ExpiresSoon), [@collaborator1]).and_return(expires_soon_slack_message) allow_any_instance_of(HelperModule).to receive(:send_collaborator_expire_notify_email).with([@collaborator1]) @@ -630,62 +379,13 @@ class GithubCollaborators end end - context "call extend_full_org_member_review_date" do - it WHEN_NO_COLLABORATORS_PASSED_IN do - expect(@outside_collaborators).not_to receive(:extend_date) - @outside_collaborators.extend_full_org_member_review_date([]) - end - - it WHEN_COLLABORATOR_NOT_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(false) - expect(@outside_collaborators).not_to receive(:extend_date) - @outside_collaborators.extend_full_org_member_review_date([@collaborator1]) - end - - it WHEN_COLLABORATOR_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(true) - expect(@outside_collaborators).to receive(:extend_date).with([@collaborator1]).and_return([@collaborator1]) - expect(GithubCollaborators::SlackNotifier).to receive(:new).with(instance_of(GithubCollaborators::FullOrgMemberExpiresSoon), [@collaborator1]).and_return(full_org_expires_soon_slack_message) - expect(full_org_expires_soon_slack_message).to receive(:post_slack_message) - @outside_collaborators.extend_full_org_member_review_date([@collaborator1]) - end - end - - context "call remove_expired_full_org_members" do - it WHEN_NO_COLLABORATORS_PASSED_IN do - expect(@outside_collaborators).not_to receive(:remove_collaborator) - @outside_collaborators.remove_expired_full_org_members([]) - end - - it WHEN_COLLABORATOR_NOT_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(false) - expect(@outside_collaborators).not_to receive(:remove_collaborator) - @outside_collaborators.remove_expired_full_org_members([@collaborator1]) - end - - it WHEN_COLLABORATOR_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(true) - expect(@outside_collaborators).to receive(:remove_collaborator).with([@collaborator1]).and_return([@collaborator1]) - expect(GithubCollaborators::SlackNotifier).to receive(:new).with(instance_of(GithubCollaborators::FullOrgMemberExpired), [@collaborator1]).and_return(full_org_expired_slack_message) - expect(full_org_expired_slack_message).to receive(:post_slack_message) - @outside_collaborators.remove_expired_full_org_members([@collaborator1]) - end - end - context "call remove_expired_collaborators" do it "when no collaborator passed to function exist" do expect(@outside_collaborators).not_to receive(:remove_collaborator) @outside_collaborators.remove_expired_collaborators([]) end - it WHEN_COLLABORATOR_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(true) - expect(@outside_collaborators).not_to receive(:remove_collaborator) - @outside_collaborators.remove_expired_collaborators([@collaborator1]) - end - - it WHEN_COLLABORATOR_NOT_FULL_ORG_MEMBER do - expect(@organization).to receive(:is_collaborator_an_org_member).with(@collaborator1.login).and_return(false) + it WITH_COLLABORATOR do expect(@outside_collaborators).to receive(:remove_collaborator).with([@collaborator1]).and_return([@collaborator1]) expect(GithubCollaborators::SlackNotifier).to receive(:new).with(instance_of(GithubCollaborators::Expired), [@collaborator1]).and_return(expired_slack_message) expect(expired_slack_message).to receive(:post_slack_message) @@ -694,12 +394,11 @@ class GithubCollaborators end end - context "call is_renewal_within_one_month when user is non full org member" do + context "call is_renewal_within_one_month" do before do expect(terraform_files).to receive(:get_terraform_files).and_return([]) @outside_collaborators = GithubCollaborators::OutsideCollaborators.new expect(organization).to receive(:read_repository_issues).with(REPOSITORY_NAME).and_return([]) - expect(organization).to receive(:is_collaborator_a_full_org_member).with(TEST_USER).and_return(false) end it "when collaborator issue is not renewal within a month" do @@ -722,22 +421,6 @@ class GithubCollaborators @outside_collaborators.is_renewal_within_one_month([@collaborator1]) end end - - context "call is_renewal_within_one_month when user is a full org member" do - before do - expect(terraform_files).to receive(:get_terraform_files).and_return([]) - @outside_collaborators = GithubCollaborators::OutsideCollaborators.new - expect(organization).to receive(:is_collaborator_a_full_org_member).with(TEST_USER).and_return(true) - end - - it "do not create an issue" do - terraform_block = create_terraform_block_review_date_more_than_month - collaborator = GithubCollaborators::Collaborator.new(terraform_block, REPOSITORY_NAME) - collaborator.check_for_issues - expect(@outside_collaborators).not_to receive(:create_review_date_expires_soon_issue) - @outside_collaborators.is_renewal_within_one_month([collaborator]) - end - end end context "test outside_collaborators" do @@ -750,7 +433,6 @@ class GithubCollaborators before do allow_any_instance_of(HelperModule).to receive(:get_org_outside_collaborators).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) end context "call deleted_repository_check" do @@ -759,7 +441,6 @@ class GithubCollaborators context "when no terraform files exist" do before do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) expect(terraform_files).to receive(:get_terraform_files).and_return([]).at_least(2).times expect(terraform_files).not_to receive(:remove_file) allow_any_instance_of(OutsideCollaborators).to receive(:does_pr_already_exist).with(TEST_REPO_NAME_TERRAFORM_FILE, ARCHIVED_REPOSITORY_PR_TITLE.to_s).and_return(false) @@ -783,7 +464,6 @@ class GithubCollaborators expect(GithubCollaborators::HttpClient).to receive(:new).and_return(http_client) file = create_terraform_file expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(2).times - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([repo1, repo2]) @outside_collaborators = GithubCollaborators::OutsideCollaborators.new end @@ -825,27 +505,13 @@ class GithubCollaborators end end - it "call print_full_org_member_collaborators" do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([]) - expect(terraform_files).to receive(:get_terraform_files).and_return([]) - organization = GithubCollaborators::Organization.new - organization.add_full_org_member(TEST_USER_1) - organization.add_full_org_member(TEST_USER_2) - outside_collaborators = GithubCollaborators::OutsideCollaborators.new - outside_collaborators.print_full_org_member_collaborators - end - - repo1 = GithubCollaborators::Repository.new(TEST_REPO_NAME1, 0) - repo2 = GithubCollaborators::Repository.new(TEST_REPO_NAME2, 0) - context "call compare_terraform_and_github with a repo that has no collaborators" do it "when no collaborators exist" do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) + repo1 = GithubCollaborators::Repository.new(TEST_REPO_NAME1, 0) + repo2 = GithubCollaborators::Repository.new(TEST_REPO_NAME2, 0) allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([repo1, repo2]) organization = GithubCollaborators::Organization.new expect(GithubCollaborators::Organization).to receive(:new).and_return(organization).at_least(1).times - expect(organization).to receive(:create_full_org_members) file = create_empty_terraform_file expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(1).times @@ -853,23 +519,6 @@ class GithubCollaborators outside_collaborators = GithubCollaborators::OutsideCollaborators.new outside_collaborators.compare_terraform_and_github end - - it "when collaborator is a full org member" do - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([TEST_USER_2]) - allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([repo1, repo2]) - organization = GithubCollaborators::Organization.new - - file = create_terraform_file - expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(1).times - expect(GithubCollaborators::Organization).to receive(:new).and_return(organization).at_least(1).times - expect(terraform_files).to receive(:get_collaborators_in_file).and_return([TEST_USER_2]).at_least(2).times - expect(organization).to receive(:create_full_org_members) - - outside_collaborators = GithubCollaborators::OutsideCollaborators.new - expect(organization).to receive(:is_collaborator_an_org_member).and_return(TEST_USER_2).at_least(1).times - expect(outside_collaborators).not_to receive(:print_comparison) - outside_collaborators.compare_terraform_and_github - end end end @@ -878,10 +527,8 @@ class GithubCollaborators repo1.store_collaborators_names([TEST_USER_3, TEST_USER_3]) repo2 = GithubCollaborators::Repository.new(TEST_REPO_NAME2, 0) allow_any_instance_of(HelperModule).to receive(:get_org_outside_collaborators).and_return([]) - allow_any_instance_of(HelperModule).to receive(:get_all_organisation_members).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_archived_repositories).and_return([]) allow_any_instance_of(HelperModule).to receive(:get_active_repositories).and_return([repo1, repo2]) - allow_any_instance_of(HelperModule).to receive(:get_everyone_team_repositories).and_return([]) organization = GithubCollaborators::Organization.new file = create_terraform_file @@ -889,7 +536,6 @@ class GithubCollaborators expect(terraform_files).to receive(:get_terraform_files).and_return([file]).at_least(1).times expect(GithubCollaborators::Organization).to receive(:new).and_return(organization).at_least(1).times expect(terraform_files).to receive(:get_collaborators_in_file).and_return([TEST_USER_1]).at_least(1).times - expect(organization).to receive(:create_full_org_members) outside_collaborators = GithubCollaborators::OutsideCollaborators.new diff --git a/spec/slack_notifier_spec.rb b/spec/slack_notifier_spec.rb index a7be432..567217f 100644 --- a/spec/slack_notifier_spec.rb +++ b/spec/slack_notifier_spec.rb @@ -7,7 +7,7 @@ class GithubCollaborators context "test SlackNotifier" do before do @terraform_block = create_terraform_block_review_date_today - @test_object = GithubCollaborators::FullOrgMemberExpired.new + @test_object = GithubCollaborators::Expired.new @collaborators = [] end @@ -54,7 +54,7 @@ class GithubCollaborators ENV["SLACK_WEBHOOK_URL"] = "someurl" } - json_payload = {body: "{\"username\":\"GitHub Collaborator repository bot\",\"icon_emoji\":\":robot_face:\",\"text\":\"I've found a full Org member / collaborator whose review date has expired, a pull request has been created to remove the collaborator from the Terraform file/s. Manually remove the collaborator from the repository:\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n\",\"mrkdwn\":true,\"channel\":\"#operations-engineering-alerts\"}"} + json_payload = {body: "{\"username\":\"GitHub Collaborator repository bot\",\"icon_emoji\":\":robot_face:\",\"text\":\"I've found a collaborator whose review date has expired, a pull request has been created to remove the collaborator:\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n\",\"mrkdwn\":true,\"channel\":\"#operations-engineering-alerts\"}"} it TEST_TITLE do expect(HTTP).to receive(:post).with("someurl", json_payload) @@ -81,7 +81,7 @@ class GithubCollaborators @collaborators.push(collaborator1) @collaborators.push(collaborator2) @collaborators.push(collaborator3) - json_payload_multiple = {body: "{\"username\":\"GitHub Collaborator repository bot\",\"icon_emoji\":\":robot_face:\",\"text\":\"I've found 3 full Org members / collaborators whose review dates have expired, pull requests have been created to remove these collaborators from the Terraform file/s. Manually remove the collaborator from the repository:\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n\",\"mrkdwn\":true,\"channel\":\"#operations-engineering-alerts\"}"} + json_payload_multiple = {body: "{\"username\":\"GitHub Collaborator repository bot\",\"icon_emoji\":\":robot_face:\",\"text\":\"I've found 3 collaborators whose review dates have expired, pull requests have been created to remove these collaborators:\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n- #{TEST_USER} in <#{GH_ORG_URL}/#{REPOSITORY_NAME}|#{REPOSITORY_NAME}> see <#{GH_ORG_URL}/#{REPO_NAME}/blob/main/terraform/#{REPOSITORY_NAME}.tf|terraform file> (today)\\n\",\"mrkdwn\":true,\"channel\":\"#operations-engineering-alerts\"}"} expect(HTTP).to receive(:post).with("someurl", json_payload_multiple) slack_notififer = GithubCollaborators::SlackNotifier.new(@test_object, @collaborators) slack_notififer.post_slack_message diff --git a/spec/terraform_block_spec.rb b/spec/terraform_block_spec.rb index 56deefb..cfb3c4e 100644 --- a/spec/terraform_block_spec.rb +++ b/spec/terraform_block_spec.rb @@ -6,7 +6,7 @@ class GithubCollaborators context "test TerraformBlock" do before do @terraform_block = GithubCollaborators::TerraformBlock.new - @review_date = (Date.today + 90).strftime(DATE_FORMAT) + @review_date = Date.today.strftime(DATE_FORMAT) end def check_terraform_block_empty(terraform_block) @@ -30,8 +30,7 @@ def check_terraform_block_empty(terraform_block) end it "call add_terraform_file_collaborator_data" do - review_date = Date.today.strftime(DATE_FORMAT) - collaborator_data = create_collaborator_data(review_date) + collaborator_data = create_collaborator_data(@review_date) @terraform_block.add_terraform_file_collaborator_data(collaborator_data) test_equal(@terraform_block.username, TEST_COLLABORATOR_LOGIN) test_equal(@terraform_block.permission, TEST_COLLABORATOR_PERMISSION) @@ -40,7 +39,7 @@ def check_terraform_block_empty(terraform_block) test_equal(@terraform_block.org, TEST_COLLABORATOR_ORG) test_equal(@terraform_block.reason, TEST_COLLABORATOR_REASON) test_equal(@terraform_block.added_by, TEST_COLLABORATOR_ADDED_BY) - test_equal(@terraform_block.review_after, review_date) + test_equal(@terraform_block.review_after, @review_date) end it "call add_collaborator_email_address" do @@ -67,47 +66,18 @@ def check_terraform_block_empty(terraform_block) test_equal(@terraform_block.review_after, "") end - it "call add_org_member_collaborator_data" do - collaborator = GithubCollaborators::FullOrgMember.new(TEST_COLLABORATOR_LOGIN) - collaborator.add_info_from_file(TEST_COLLABORATOR_EMAIL, TEST_COLLABORATOR_NAME, TEST_COLLABORATOR_ORG) - @terraform_block.add_org_member_collaborator_data(collaborator, TEST_COLLABORATOR_PERMISSION) - test_equal(@terraform_block.username, TEST_COLLABORATOR_LOGIN) - test_equal(@terraform_block.permission, TEST_COLLABORATOR_PERMISSION) - test_equal(@terraform_block.name, TEST_COLLABORATOR_NAME) - test_equal(@terraform_block.email, TEST_COLLABORATOR_EMAIL) - test_equal(@terraform_block.org, TEST_COLLABORATOR_ORG) - test_equal(@terraform_block.reason, REASON1) - test_equal(@terraform_block.added_by, ADDED_BY_EMAIL) - test_equal(@terraform_block.review_after, @review_date) - end - - it "call add_missing_collaborator_data" do - @terraform_block.add_missing_collaborator_data(TEST_COLLABORATOR_LOGIN) - test_equal(@terraform_block.username, TEST_COLLABORATOR_LOGIN) - test_equal(@terraform_block.permission, "") - test_equal(@terraform_block.name, "") - test_equal(@terraform_block.email, "") - test_equal(@terraform_block.org, "") - test_equal(@terraform_block.reason, REASON2) - test_equal(@terraform_block.added_by, ADDED_BY_EMAIL) - test_equal(@terraform_block.review_after, @review_date) - end - it "call revert_block" do - @terraform_block.add_terraform_file_collaborator_data({}) - check_terraform_block_empty(@terraform_block) - terraform_block2 = GithubCollaborators::TerraformBlock.new - terraform_block2.add_missing_collaborator_data(TEST_COLLABORATOR_LOGIN) - test_equal(terraform_block2.username, TEST_COLLABORATOR_LOGIN) - test_equal(terraform_block2.permission, "") - test_equal(terraform_block2.name, "") - test_equal(terraform_block2.email, "") - test_equal(terraform_block2.org, "") - test_equal(terraform_block2.reason, REASON2) - test_equal(terraform_block2.added_by, ADDED_BY_EMAIL) - test_equal(terraform_block2.review_after, @review_date) - terraform_block2.revert_block(@terraform_block) - check_terraform_block_empty(terraform_block2) + terraform_block = create_test_data(@review_date) + test_equal(terraform_block.username, TEST_COLLABORATOR_LOGIN) + test_equal(terraform_block.permission, TEST_COLLABORATOR_PERMISSION) + test_equal(terraform_block.name, TEST_COLLABORATOR_NAME) + test_equal(terraform_block.email, TEST_COLLABORATOR_EMAIL) + test_equal(terraform_block.org, TEST_COLLABORATOR_ORG) + test_equal(terraform_block.reason, TEST_COLLABORATOR_REASON) + test_equal(terraform_block.added_by, TEST_COLLABORATOR_ADDED_BY) + test_equal(terraform_block.review_after, @review_date) + terraform_block.revert_block(terraform_block) + check_terraform_block_empty(terraform_block) end end end diff --git a/spec/terraform_file_spec.rb b/spec/terraform_file_spec.rb index 6ae02e5..092f770 100644 --- a/spec/terraform_file_spec.rb +++ b/spec/terraform_file_spec.rb @@ -4,27 +4,11 @@ class GithubCollaborators describe TerraformFile do context "test TerraformFile" do - original_file = File.read("spec/fixtures/test-repo.tf") - collaborator1 = GithubCollaborators::FullOrgMember.new(TEST_USER_1) - collaborator2 = GithubCollaborators::FullOrgMember.new(TEST_USER_2) - collaborator1.add_info_from_file(TEST_COLLABORATOR_EMAIL, TEST_COLLABORATOR_NAME, TEST_COLLABORATOR_ORG) - collaborator2.add_info_from_file(TEST_COLLABORATOR_EMAIL, TEST_COLLABORATOR_NAME, TEST_COLLABORATOR_ORG) - review_date = (Date.today + 90).strftime(DATE_FORMAT) - new_review_date = (Date.today + 180 + 90).strftime(DATE_FORMAT) - context "" do before do @terraform_file = GithubCollaborators::TerraformFile.new(TEST_REPO_NAME, TERRAFORM_DIR) end - it "call get_collaborator_permission when no collaborator exists" do - test_equal(@terraform_file.get_collaborator_permission(TEST_USER_1), "") - end - - it "call get_collaborator_reason when no collaborator exists" do - test_equal(@terraform_file.get_collaborator_reason(TEST_USER_1), "") - end - it "call get_collaborator_added_by when no collaborator exists" do test_equal(@terraform_file.get_collaborator_added_by(TEST_USER_1), "") end @@ -41,13 +25,18 @@ class GithubCollaborators context "" do before do - @terraform_file.add_org_member_collaborator(collaborator1, TEST_COLLABORATOR_PERMISSION) + @review_date = Date.today.strftime(DATE_FORMAT) + collaborator_data = create_collaborator_data(@review_date) + collaborator_data[:login] = TEST_USER_1 + collaborator_data[:added_by] = TEST_COLLABORATOR_ADDED_BY + @terraform_file.add_collaborator_from_issue(collaborator_data) end it "call extend_review_date and revert_terraform_blocks" do + new_review_date = (Date.today + 180).strftime(DATE_FORMAT) terraform_blocks = @terraform_file.get_terraform_blocks terraform_blocks.each do |terraform_block| - test_equal(terraform_block.review_after, review_date) + test_equal(terraform_block.review_after, @review_date) end @terraform_file.extend_review_date(TEST_USER_1) terraform_blocks = @terraform_file.get_terraform_blocks @@ -57,45 +46,23 @@ class GithubCollaborators @terraform_file.revert_terraform_blocks terraform_blocks = @terraform_file.get_terraform_blocks terraform_blocks.each do |terraform_block| - test_equal(terraform_block.review_after, review_date) + test_equal(terraform_block.review_after, @review_date) end end - it "call get_collaborator_reason when collaborator exists" do - test_equal(@terraform_file.get_collaborator_reason(TEST_USER_1), REASON1) - end - it "call get_collaborator_added_by when collaborator exists" do - test_equal(@terraform_file.get_collaborator_added_by(TEST_USER_1), ADDED_BY_EMAIL) - end - - it "call get_collaborator_permission when collaborator exists" do - test_equal(@terraform_file.get_collaborator_permission(TEST_USER_1), TEST_COLLABORATOR_PERMISSION) - end - - it "call change_collaborator_permission and revert_terraform_blocks" do - terraform_blocks = @terraform_file.get_terraform_blocks - terraform_blocks.each do |terraform_block| - test_equal(terraform_block.permission, TEST_COLLABORATOR_PERMISSION) - end - @terraform_file.change_collaborator_permission(TEST_USER_1, "push") - terraform_blocks = @terraform_file.get_terraform_blocks - terraform_blocks.each do |terraform_block| - test_equal(terraform_block.permission, "push") - end - @terraform_file.revert_terraform_blocks - terraform_blocks = @terraform_file.get_terraform_blocks - terraform_blocks.each do |terraform_block| - test_equal(terraform_block.permission, TEST_COLLABORATOR_PERMISSION) - end + test_equal(@terraform_file.get_collaborator_added_by(TEST_USER_1), TEST_COLLABORATOR_ADDED_BY) end it "call restore_terraform_blocks" do - terraform_blocks = @terraform_file.get_terraform_blocks - test_equal(terraform_blocks.length, 1) - @terraform_file.restore_terraform_blocks - terraform_blocks = @terraform_file.get_terraform_blocks - test_equal(terraform_blocks.length, 0) + terraform_blocks_original = @terraform_file.get_terraform_blocks + test_equal(terraform_blocks_original.length, 1) + name = terraform_blocks_original[0].username + @terraform_file.remove_collaborator(name) + removed_terraform_blocks = @terraform_file.restore_terraform_blocks + test_equal(removed_terraform_blocks.length, 0) + terraform_blocks_restored = @terraform_file.get_terraform_blocks + test_equal(terraform_blocks_original, terraform_blocks_restored) end it "call write_to_file" do @@ -106,12 +73,10 @@ class GithubCollaborators context "" do before do - @terraform_file.add_org_member_collaborator(collaborator2, TEST_COLLABORATOR_PERMISSION) - end - - it "call add_org_member_collaborator" do - terraform_blocks = @terraform_file.get_terraform_blocks - test_equal(terraform_blocks.length, 2) + review_date = Date.today.strftime(DATE_FORMAT) + collaborator_data = create_collaborator_data(review_date) + collaborator_data[:login] = TEST_USER_2 + @terraform_file.add_collaborator_from_issue(collaborator_data) end it "call remove_collaborator" do @@ -121,28 +86,20 @@ class GithubCollaborators terraform_blocks = @terraform_file.get_terraform_blocks test_equal(terraform_blocks.length, 1) end - - it "call remove_collaborator and restore_terraform_blocks" do - terraform_blocks = @terraform_file.get_terraform_blocks - test_equal(terraform_blocks.length, 2) - @terraform_file.remove_collaborator(TEST_USER_1) - @terraform_file.restore_terraform_blocks - terraform_blocks = @terraform_file.get_terraform_blocks - test_equal(terraform_blocks.length, 1) - end end end it "call create_terraform_collaborator_blocks" do + original_file = File.read("spec/fixtures/test-repo.tf") File.write(TEST_FILE, original_file) @terraform_file.create_terraform_collaborator_blocks - @collaborators_in_file = [] + collaborators_in_file = [] terraform_blocks = @terraform_file.get_terraform_blocks terraform_blocks.each do |terraform_block| - @collaborators_in_file.push(terraform_block.username) + collaborators_in_file.push(terraform_block.username) end expected_collaborators = [TEST_USER_1, TEST_USER_2] - test_equal(@collaborators_in_file, expected_collaborators) + test_equal(collaborators_in_file, expected_collaborators) File.delete(TEST_FILE) end end @@ -155,7 +112,7 @@ class GithubCollaborators end def create_test_file_template - review_date = (Date.today + 90).strftime(DATE_FORMAT) + review_date = Date.today.strftime(DATE_FORMAT) template = <<~EOF module "test-repo" { source = "./modules/repository-collaborators" @@ -167,8 +124,8 @@ module "test-repo" { name = "some user" email = "someuser@some-email.com" org = "some org" - reason = "Full Org member / collaborator missing from Terraform file" - added_by = "opseng-bot@digital.justice.gov.uk" + reason = "some reason" + added_by = "other user" review_after = "<%= review_date %>" }, ] diff --git a/spec/terraform_files_spec.rb b/spec/terraform_files_spec.rb index 51754b3..9296b41 100644 --- a/spec/terraform_files_spec.rb +++ b/spec/terraform_files_spec.rb @@ -134,41 +134,6 @@ class GithubCollaborators end end - context "call did_automation_add_collaborator_to_file" do - it "when added_by is incorrect" do - @the_terraform_files.each do |terraform_file| - if terraform_file.filename == TEST_REPO_NAME - collaborator_data = collaborator_with_incorrect_added_by - terraform_file.add_collaborator_from_issue(collaborator_data) - end - end - reply = @terraform_files.did_automation_add_collaborator_to_file(TEST_REPO_NAME, TEST_COLLABORATOR_LOGIN) - test_equal(reply, false) - end - - it "when reason is incorrect" do - @the_terraform_files.each do |terraform_file| - if terraform_file.filename == TEST_REPO_NAME - collaborator_data = collaborator_with_incorrect_reason - terraform_file.add_collaborator_from_issue(collaborator_data) - end - end - reply = @terraform_files.did_automation_add_collaborator_to_file(TEST_REPO_NAME, TEST_COLLABORATOR_LOGIN) - test_equal(reply, false) - end - - it "when reason and added_by are correct" do - @the_terraform_files.each do |terraform_file| - if terraform_file.filename == TEST_REPO_NAME - collaborator_data = collaborator_with_correct_reason_and_added_by - terraform_file.add_collaborator_from_issue(collaborator_data) - end - end - reply = @terraform_files.did_automation_add_collaborator_to_file(TEST_REPO_NAME, TEST_COLLABORATOR_LOGIN) - test_equal(reply, true) - end - end - it "call remove_file when file exists" do @terraform_files.remove_file(TEST_REPO_NAME) new_file_length = @files - 1 @@ -189,29 +154,6 @@ class GithubCollaborators test_not_equal(modified_file, original_file) end - it "call change_collaborator_permission_in_file" do - @terraform_files.change_collaborator_permission_in_file(TEST_REPO_NAME, TEST_USER_1, "pull") - modified_file = File.read(TEST_FILE) - test_not_equal(modified_file, original_file) - end - - it "call add_full_org_collaborator_to_file" do - terraform_block = create_terraform_block_review_date_today - collaborator = GithubCollaborators::Collaborator.new(terraform_block, TEST_REPO_NAME) - @terraform_files.add_full_org_collaborator_to_file(TEST_REPO_NAME, collaborator, "pull") - terraform_file = GithubCollaborators::TerraformFile.new(TEST_REPO_NAME, TERRAFORM_DIR) - terraform_file.create_terraform_collaborator_blocks - collaborators_in_file = [] - terraform_blocks = terraform_file.get_terraform_blocks - terraform_blocks.each do |terraform_block| - collaborators_in_file.push(terraform_block.username) - end - expected_collaborators = [TEST_USER_1, TEST_USER_2, TEST_USER] - test_equal(collaborators_in_file, expected_collaborators) - modified_file = File.read(TEST_FILE) - test_not_equal(modified_file, original_file) - end - it "call ensure_file_exists_in_memory when file already exists" do @terraform_files.ensure_file_exists_in_memory(TEST_REPO_NAME) the_terraform_files = @terraform_files.get_terraform_files diff --git a/spec/test_constants.rb b/spec/test_constants.rb index 553ea7b..f0a050c 100644 --- a/spec/test_constants.rb +++ b/spec/test_constants.rb @@ -19,12 +19,11 @@ module TestConstants TEST_REPO_NAME = "test-repo" TEST_REPO_NAME_TERRAFORM_FILE = "#{TEST_REPO_NAME}.tf" TEST_FILE = "#{TERRAFORM_DIR}/#{TEST_REPO_NAME}.tf" - TEST_TEAM = "someteam" TEST_USER = "someuser" TEST_USER_1 = "someuser1" TEST_USER_2 = "someuser2" TEST_USER_3 = "someuser3" - TEST_USER_6 = "someuser6" + TEST_USER_4 = "someuser4" TEST_REPO_NAME1 = "test-repo1" TEST_REPO_NAME2 = "test-repo2" TEST_REPO_NAME3 = "test-repo3" @@ -43,8 +42,7 @@ module TestConstants WHEN_COLLABORATORS_EXISTS = "when collaborators exist" WHEN_NO_COLLABORATORS_EXISTS = "when collaborators don't exist" WHEN_NO_COLLABORATORS_PASSED_IN = "when no collaborator is passed in" - WHEN_COLLABORATOR_FULL_ORG_MEMBER = "when collaborator is a full org collaborator" - WHEN_COLLABORATOR_NOT_FULL_ORG_MEMBER = "when collaborator is not a full org collaborator" + WITH_COLLABORATOR = "when collaborator is passed in " WHEN_PULL_REQUEST_DOESNT_EXIST = "when pull request doesn't exist" GRACE_PERIOD_OKAY = (Date.today - 45).strftime(DATE_FORMAT) GRACE_PERIOD_EXPIRED = (Date.today - 46).strftime(DATE_FORMAT) @@ -53,7 +51,6 @@ module TestConstants INCORRECT_REVIEW_DATE_FUTURE = (Date.today + 500).strftime(DATE_FORMAT) CORRECT_REVIEW_DATE_FUTURE = (Date.today + 366).strftime(DATE_FORMAT) CORRECT_PERMISSION = "push" - INCORRECT__PERMISSION = "write" OPEN = "open" CLOSED = "closed" CREATED_DATE = "2019-10-01" diff --git a/spec/test_helper_module.rb b/spec/test_helper_module.rb index a907ff1..2f22335 100644 --- a/spec/test_helper_module.rb +++ b/spec/test_helper_module.rb @@ -106,45 +106,6 @@ def create_collaborator_with_login(login) create_terraform_block(collaborator_data) end - def collaborator_with_correct_reason_and_added_by - { - login: TEST_COLLABORATOR_LOGIN, - permission: TEST_COLLABORATOR_PERMISSION, - name: TEST_COLLABORATOR_NAME, - email: TEST_COLLABORATOR_EMAIL, - org: TEST_COLLABORATOR_ORG, - reason: REASON1, - added_by: ADDED_BY_EMAIL, - review_after: "" - } - end - - def collaborator_with_incorrect_added_by - { - login: TEST_COLLABORATOR_LOGIN, - permission: TEST_COLLABORATOR_PERMISSION, - name: TEST_COLLABORATOR_NAME, - email: TEST_COLLABORATOR_EMAIL, - org: TEST_COLLABORATOR_ORG, - reason: REASON1, - added_by: TEST_COLLABORATOR_ADDED_BY, - review_after: "" - } - end - - def collaborator_with_incorrect_reason - { - login: TEST_COLLABORATOR_LOGIN, - permission: TEST_COLLABORATOR_PERMISSION, - name: TEST_COLLABORATOR_NAME, - email: TEST_COLLABORATOR_EMAIL, - org: TEST_COLLABORATOR_ORG, - reason: TEST_COLLABORATOR_REASON, - added_by: ADDED_BY_EMAIL, - review_after: "" - } - end - def create_test_data(review_date) collaborator_data = create_collaborator_data(review_date) create_terraform_block(collaborator_data)