From c079a70e016326249678d4a5689cbd524ce8d4e4 Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Wed, 9 Oct 2024 10:57:19 -0300 Subject: [PATCH 1/9] Organization Creating a console to create, edit and link githubuser and organization Signed-off-by: Rodrigo Nardi --- bin/organization_console | 126 ++++++++++++++++++ .../20241008100525_create_organization.rb | 22 +++ ...1009102350_add_github_user_organization.rb | 15 +++ lib/models/github_user.rb | 2 + lib/models/organization.rb | 21 +++ 5 files changed, 186 insertions(+) create mode 100755 bin/organization_console create mode 100644 db/migrate/20241008100525_create_organization.rb create mode 100644 db/migrate/20241009102350_add_github_user_organization.rb create mode 100644 lib/models/organization.rb diff --git a/bin/organization_console b/bin/organization_console new file mode 100755 index 0000000..77dfea3 --- /dev/null +++ b/bin/organization_console @@ -0,0 +1,126 @@ +#!/usr/bin/env ruby +# SPDX-License-Identifier: BSD-2-Clause +# +# organization_console.rb +# Part of NetDEF CI System +# +# Copyright (c) 2023 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +require 'irb' +require_relative '../config/setup' + +# Defina métodos para buscar e criar empresas +def find_organization(name) + organization = Organization.find_by(name: name) + if organization + puts "> #{organization.inspect}" + else + puts 'Organization not found' + end +end + +def create_organization(name, attributes = {}) + organization = Organization.create(name: name, **attributes) + if organization.persisted? + puts "Organization created: #{organization.inspect}" + else + puts "Failed to create organization: #{organization.errors.full_messages.join(', ')}" + end +end + +def edit_organization(name, attributes = {}) + organization = Organization.find_by(name: name) + + if organization.nil? + puts 'Organization not found' + return + end + + organization.update(**attributes) + + if organization.persisted? + puts "Organization updated: #{organization.inspect}" + else + puts "Failed to create organization: #{organization.errors.full_messages.join(', ')}" + end +end + +def find_github_user(login) + user = GithubUser.find_by(github_login: login) + if user + puts "> #{user.inspect}" + else + puts 'Github user not found' + end +end + +def add_user_in_organization(github_login, organization_name) + user = GithubUser.find_by(github_login: github_login) + organization = Organization.find_by(name: organization_name) + + if user.nil? + puts 'Github user not found' + return + end + + if organization.nil? + puts 'Organization not found' + return + end + + user.update(organization: organization) + + if user.persisted? + puts "Github user linked to organization: #{user.inspect}" + else + puts "Failed to link github user to organization: #{user.errors.full_messages.join(', ')}" + end +end + +def remove_user_from_organization(github_login) + user = GithubUser.find_by(github_login: github_login) + + if user.nil? + puts 'Github user not found' + return + end + + user.update(organization: nil) + + if user.persisted? + puts "Github user removed from organization: #{user.inspect}" + else + puts "Failed to remove github user from organization: #{user.errors.full_messages.join(', ')}" + end +end + +def help + puts <<~HELP + Available commands: + - find_organization(name) + - create_organization(name, attributes = {}) + - edit_organization(name, attributes = {}) + - find_github_user(login) + - add_user_in_organization(login, organization_name) + - remove_user_from_organization(login) + + create_organization / edit_organization attributes: + - contact_email: string + - contact_name: string + - url: string + + Example: + - find_organization('NetDEF') + - create_organization('NetDEF', contact_name: 'Rodrigo Nardi') + - edit_organization('NetDEF', contact_name: 'Martin Winter') + - find_github_user('rodrigonardi') + - add_user_in_organization('rodrigonardi', 'NetDEF') + - remove_user_from_organization('rodrigonardi') + HELP +end + +# Inicie o console IRB +IRB.start diff --git a/db/migrate/20241008100525_create_organization.rb b/db/migrate/20241008100525_create_organization.rb new file mode 100644 index 0000000..be3a4f9 --- /dev/null +++ b/db/migrate/20241008100525_create_organization.rb @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# 20240617121935_create_delayed_jobs.rb +# Part of NetDEF CI System +# +# Copyright (c) 2024 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +class CreateOrganization < ActiveRecord::Migration[6.0] + def change + create_table :organizations do |t| + t.string :name, null: false + t.string :contact_email + t.string :contact_name + t.string :url + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20241009102350_add_github_user_organization.rb b/db/migrate/20241009102350_add_github_user_organization.rb new file mode 100644 index 0000000..8d084ae --- /dev/null +++ b/db/migrate/20241009102350_add_github_user_organization.rb @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# 20240617121935_create_delayed_jobs.rb +# Part of NetDEF CI System +# +# Copyright (c) 2024 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +class AddGithubUserOrganization < ActiveRecord::Migration[6.0] + def change + add_reference :github_users, :organization, index: true, foreign_key: true + end +end diff --git a/lib/models/github_user.rb b/lib/models/github_user.rb index e74b5f1..4f2f41d 100644 --- a/lib/models/github_user.rb +++ b/lib/models/github_user.rb @@ -14,4 +14,6 @@ class GithubUser < ActiveRecord::Base has_many :pull_requests, dependent: :nullify has_many :check_suites, dependent: :nullify has_many :audit_retries, dependent: :nullify + + belongs_to :organization end diff --git a/lib/models/organization.rb b/lib/models/organization.rb new file mode 100644 index 0000000..c1fa478 --- /dev/null +++ b/lib/models/organization.rb @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# audit_retry.rb +# Part of NetDEF CI System +# +# Copyright (c) 2024 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +require 'otr-activerecord' + +class Organization < ActiveRecord::Base + has_many :github_users + + def inspect + "Organization id: #{id}, name: #{name}, contact_email: #{contact_email}, " \ + "contact_name: #{contact_name}, url: #{url} " \ + "created_at: #{created_at}, updated_at: #{updated_at}" + end +end From 1a1d53328bc83e870ead5175f969f18fec5a245a Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Wed, 9 Oct 2024 11:26:31 -0300 Subject: [PATCH 2/9] Organization Updating schema Signed-off-by: Rodrigo Nardi --- db/schema.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 38f0d82..791e42b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_09_24_140825) do +ActiveRecord::Schema[7.2].define(version: 2024_10_09_102350) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -107,7 +107,18 @@ t.string "organization_url" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "organization_id" t.index ["github_id"], name: "index_github_users_on_github_id", unique: true + t.index ["organization_id"], name: "index_github_users_on_organization_id" + end + + create_table "organizations", force: :cascade do |t| + t.string "name", null: false + t.string "contact_email" + t.string "contact_name" + t.string "url" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "plans", force: :cascade do |t| @@ -185,6 +196,7 @@ add_foreign_key "check_suites", "stages", column: "stopped_in_stage_id" add_foreign_key "ci_jobs", "check_suites" add_foreign_key "ci_jobs", "stages" + add_foreign_key "github_users", "organizations" add_foreign_key "plans", "check_suites" add_foreign_key "pull_request_subscriptions", "pull_requests" add_foreign_key "pull_requests", "github_users" From 2e21fca9a0034eedc4feeacb1fad7134efd6914b Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Wed, 9 Oct 2024 11:30:59 -0300 Subject: [PATCH 3/9] Organization Adding no coverage in inspect method Signed-off-by: Rodrigo Nardi --- lib/models/organization.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/models/organization.rb b/lib/models/organization.rb index c1fa478..1187b49 100644 --- a/lib/models/organization.rb +++ b/lib/models/organization.rb @@ -13,9 +13,11 @@ class Organization < ActiveRecord::Base has_many :github_users + # :nocov: def inspect "Organization id: #{id}, name: #{name}, contact_email: #{contact_email}, " \ "contact_name: #{contact_name}, url: #{url} " \ "created_at: #{created_at}, updated_at: #{updated_at}" end + # :nocov: end From 18bd57e920a9ab2554c9edd8b9a25b2dcf1e0507 Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Tue, 15 Oct 2024 14:43:50 -0300 Subject: [PATCH 4/9] Console - GitHub / Slack Adding details about slack account Signed-off-by: Rodrigo Nardi --- bin/{organization_console => console} | 31 +++++++++++++++--- bin/console.rb | 21 ------------ ...20241014134659_add_github_user_slack_id.rb | 16 ++++++++++ db/schema.rb | 4 ++- lib/github_ci_app.rb | 1 + lib/helpers/request.rb | 4 +-- lib/slack_bot/slack_bot.rb | 5 +++ workers/slack_username2_id.rb | 32 +++++++++++++++++++ 8 files changed, 86 insertions(+), 28 deletions(-) rename bin/{organization_console => console} (81%) delete mode 100755 bin/console.rb create mode 100644 db/migrate/20241014134659_add_github_user_slack_id.rb create mode 100644 workers/slack_username2_id.rb diff --git a/bin/organization_console b/bin/console similarity index 81% rename from bin/organization_console rename to bin/console index 77dfea3..8fedda6 100755 --- a/bin/organization_console +++ b/bin/console @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # SPDX-License-Identifier: BSD-2-Clause # -# organization_console.rb +# console # Part of NetDEF CI System # # Copyright (c) 2023 by @@ -10,9 +10,14 @@ # frozen_string_literal: true require 'irb' + +ENV['RAILS_ENV'] = ARGV.shift || 'production' + +puts "Starting console: #{ENV.fetch('RAILS_ENV', nil)}" + require_relative '../config/setup' +require_relative '../config/delayed_job' -# Defina métodos para buscar e criar empresas def find_organization(name) organization = Organization.find_by(name: name) if organization @@ -97,7 +102,25 @@ def remove_user_from_organization(github_login) end end -def help +def add_github_user_slack_user(github_login, slack_user) + user = GithubUser.find_by(github_login: github_login) + + if user.nil? + puts 'Github user not found' + return + end + + user.update(slack_username: slack_user) + SlackUsername2Id.fetch_id(github_login, slack_user) + + if user.persisted? + puts "Slack user linked to github user: #{user.inspect}" + else + puts "Failed to link slack user to github user: #{user.errors.full_messages.join(', ')}" + end +end + +def help? puts <<~HELP Available commands: - find_organization(name) @@ -106,6 +129,7 @@ def help - find_github_user(login) - add_user_in_organization(login, organization_name) - remove_user_from_organization(login) + - add_github_user_slack_user(github_login, slack_user) create_organization / edit_organization attributes: - contact_email: string @@ -122,5 +146,4 @@ def help HELP end -# Inicie o console IRB IRB.start diff --git a/bin/console.rb b/bin/console.rb deleted file mode 100755 index 4633219..0000000 --- a/bin/console.rb +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env ruby -# SPDX-License-Identifier: BSD-2-Clause -# -# console.rb -# Part of NetDEF CI System -# -# Copyright (c) 2023 by -# Network Device Education Foundation, Inc. ("NetDEF") -# -# frozen_string_literal: true - -require 'irb' - -ENV['RAILS_ENV'] = ARGV.shift || 'production' - -puts "Starting console: #{ENV.fetch('RAILS_ENV', nil)}" - -require_relative '../config/setup' -require_relative '../config/delayed_job' - -IRB.start diff --git a/db/migrate/20241014134659_add_github_user_slack_id.rb b/db/migrate/20241014134659_add_github_user_slack_id.rb new file mode 100644 index 0000000..e552992 --- /dev/null +++ b/db/migrate/20241014134659_add_github_user_slack_id.rb @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# 20240617121935_create_delayed_jobs.rb +# Part of NetDEF CI System +# +# Copyright (c) 2024 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +class AddGithubUserSlackId < ActiveRecord::Migration[6.0] + def change + add_column :github_users, :slack_username, :string + add_column :github_users, :slack_id, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 791e42b..46f4b2e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_09_102350) do +ActiveRecord::Schema[7.2].define(version: 2024_10_14_134659) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -108,6 +108,8 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.bigint "organization_id" + t.string "slack_username" + t.string "slack_id" t.index ["github_id"], name: "index_github_users_on_github_id", unique: true t.index ["organization_id"], name: "index_github_users_on_organization_id" end diff --git a/lib/github_ci_app.rb b/lib/github_ci_app.rb index 6926379..e6479d2 100644 --- a/lib/github_ci_app.rb +++ b/lib/github_ci_app.rb @@ -42,6 +42,7 @@ require_relative '../workers/ci_job_status' require_relative '../workers/timeout_execution' require_relative '../workers/ci_job_fetch_topotest_failures' +require_relative '../workers/slack_username2_id' # Slack libs require_relative 'slack/slack' diff --git a/lib/helpers/request.rb b/lib/helpers/request.rb index e45862d..55bb1e1 100644 --- a/lib/helpers/request.rb +++ b/lib/helpers/request.rb @@ -28,7 +28,7 @@ def download(uri, machine: 'ci1.netdef.org') http.request(req).body end - def get_request(uri, machine: 'ci1.netdef.org') + def get_request(uri, machine: 'ci1.netdef.org', json: true) user, passwd = fetch_user_pass(machine) http = create_http(uri) @@ -40,7 +40,7 @@ def get_request(uri, machine: 'ci1.netdef.org') # Add JSON request header req.add_field 'Accept', 'application/json' - JSON.parse(http.request(req).body) + json ? JSON.parse(http.request(req).body) : http.request(req).body rescue StandardError => e logger(Logger::ERROR, "HTTP GET Request failed (#{e.message}) for #{uri.host}") end diff --git a/lib/slack_bot/slack_bot.rb b/lib/slack_bot/slack_bot.rb index e2b328c..48ad5fc 100644 --- a/lib/slack_bot/slack_bot.rb +++ b/lib/slack_bot/slack_bot.rb @@ -19,6 +19,11 @@ def initialize @logger_manager << GithubLogger.instance.create('github_retry.log', Logger::INFO) end + def find_user_id_by_name(username) + url = "#{GitHubApp::Configuration.instance.config['slack_bot_url']}/github/translate/#{username}" + get_request(URI(url), json: false) + end + def invalid_rerun_group(job) return unless current_execution?(job.check_suite) diff --git a/workers/slack_username2_id.rb b/workers/slack_username2_id.rb new file mode 100644 index 0000000..57ac0ee --- /dev/null +++ b/workers/slack_username2_id.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +# SPDX-License-Identifier: BSD-2-Clause +# +# slack_username2_id.rb +# Part of NetDEF CI System +# +# Copyright (c) 2024 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +class SlackUsername2Id + class << self + def fetch_id(username, slack_name) + @logger = GithubLogger.instance.create('slack_username_to_id.log', Logger::INFO) + + user = GithubUser.find_by(github_login: username) + + return false unless user + + id = SlackBot.instance.find_user_id_by_name(slack_name) + + @logger.info("Username: '#{username}' -> '#{id}'") + + user.slack_id = id + user.save + + true + end + end +end From 03a5a1b23b0d1d9d4742b0ba810163f118f58fce Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Tue, 15 Oct 2024 15:10:22 -0300 Subject: [PATCH 5/9] Console - GitHub / Slack Adding details about slack account Signed-off-by: Rodrigo Nardi --- workers/slack_username2_id.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/workers/slack_username2_id.rb b/workers/slack_username2_id.rb index 57ac0ee..d409106 100644 --- a/workers/slack_username2_id.rb +++ b/workers/slack_username2_id.rb @@ -1,5 +1,4 @@ -# frozen_string_literal: true - +# # SPDX-License-Identifier: BSD-2-Clause # # slack_username2_id.rb @@ -8,7 +7,7 @@ # Copyright (c) 2024 by # Network Device Education Foundation, Inc. ("NetDEF") # -# frozen_string_literal: true +# frozen_string_literal: true class SlackUsername2Id class << self From f82a83ed4b5d8d6fcea6c572a021e9f737c9c70e Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Thu, 17 Oct 2024 10:05:19 -0300 Subject: [PATCH 6/9] Rubocop Updating rubocop to ignore the console Signed-off-by: Rodrigo Nardi --- .rubocop.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.rubocop.yml b/.rubocop.yml index c21e92e..7a7588f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,6 +10,7 @@ AllCops: Exclude: - 'githubapi/**/*' - 'db/schema.rb' + - 'bin/console' Metrics/MethodLength: Max: 20 From 7e676d9091457ef1b4a865256defd238bad10ecc Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Thu, 17 Oct 2024 10:05:38 -0300 Subject: [PATCH 7/9] Update Status Making slack bot less verbose Signed-off-by: Rodrigo Nardi --- lib/github/update_status.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/github/update_status.rb b/lib/github/update_status.rb index 3fe7d43..72e76ae 100644 --- a/lib/github/update_status.rb +++ b/lib/github/update_status.rb @@ -64,11 +64,9 @@ def update_status when 'success' @job.success(@github_check) @job.update_execution_time - slack_notify_success else failure @job.update_execution_time - slack_notify_failure end return [200, 'Success'] unless @job.check_suite.pull_request.current_execution? @job.check_suite From 689ea15644a5909dc5fa902edd9f10c263482aaa Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Fri, 18 Oct 2024 16:51:50 -0300 Subject: [PATCH 8/9] Update Status Removing unless code Signed-off-by: Rodrigo Nardi --- .simplecov | 1 + lib/github/update_status.rb | 16 ++-------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/.simplecov b/.simplecov index b376707..b382a47 100644 --- a/.simplecov +++ b/.simplecov @@ -13,6 +13,7 @@ SimpleCov.start do primary_coverage :branch add_filter %r{^/(spec|config)/} add_filter 'database_loader.rb' + add_filter 'workers/slack_username2_id.rb' add_group 'Models', 'lib/models' add_group 'GitHub Functions', 'lib/github' add_group 'Bamboo CI Functions', 'lib/bamboo_ci' diff --git a/lib/github/update_status.rb b/lib/github/update_status.rb index 72e76ae..e06ae05 100644 --- a/lib/github/update_status.rb +++ b/lib/github/update_status.rb @@ -81,7 +81,7 @@ def update_status end def create_timeout_worker - Delayed::Job.where('handler LIKE ?', "%TimeoutExecution%args%-%#{@check_suite.id}%")&.delete_all + Delayed::Job.where('handler LIKE ?', "%TimeoutExecution%args%-%#{@check_suite.id}%").delete_all logger(Logger::INFO, "CiJobStatus::Update: TimeoutExecution for '#{@check_suite.id}'") @@ -97,7 +97,7 @@ def insert_new_delayed_job end def delete_and_create_delayed_job(queue) - fetch_delayed_job&.destroy_all + fetch_delayed_job.destroy_all CiJobStatus .delay(run_at: DELAYED_JOB_TIMER.seconds.from_now.utc, queue: queue) @@ -130,18 +130,6 @@ def failure .update(@job.id, 1) end - def slack_notify_success - return unless current_execution? - - SlackBot.instance.notify_success(@job) - end - - def slack_notify_failure - return unless current_execution? - - SlackBot.instance.notify_errors(@job) - end - def logger(severity, message) @loggers.each do |logger_object| logger_object.add(severity, message) From 04f1a96a1752d5fc61e5b781e2caef3fdfc55e9a Mon Sep 17 00:00:00 2001 From: Rodrigo Nardi Date: Fri, 18 Oct 2024 17:40:28 -0300 Subject: [PATCH 9/9] GithubApp::Request Adding unit tests Signed-off-by: Rodrigo Nardi --- spec/lib/helpers/git_hub_app_request_spec.rb | 40 ++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 spec/lib/helpers/git_hub_app_request_spec.rb diff --git a/spec/lib/helpers/git_hub_app_request_spec.rb b/spec/lib/helpers/git_hub_app_request_spec.rb new file mode 100644 index 0000000..4ae0e50 --- /dev/null +++ b/spec/lib/helpers/git_hub_app_request_spec.rb @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# git_hub_app_request_spec.rb +# Part of NetDEF CI System +# +# Copyright (c) 2023 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# frozen_string_literal: true + +describe GitHubApp::Request do + let(:dummy_class) { Class.new { include GitHubApp::Request } } + let(:instance) { dummy_class.new } + + describe '#get_request' do + context 'when request json object' do + it 'must return a hash' do + allow(instance).to receive(:fetch_user_pass).and_return(%w[user passwd]) + allow(instance).to receive(:create_http).and_return(double('http', + request: double('response', + body: '{"name": "NetDEF"}'))) + + result = instance.get_request(URI('http://localhost/test'), json: true) + expect(result).to eq({ 'name' => 'NetDEF' }) + end + end + + context 'when request string object' do + it 'must return a string' do + allow(instance).to receive(:fetch_user_pass).and_return(%w[user passwd]) + allow(instance).to receive(:create_http).and_return(double('http', + request: double('response', + body: '{"name": "NetDEF"}'))) + + result = instance.get_request(URI('http://localhost/test'), json: false) + expect(result).not_to eq({ 'name' => 'NetDEF' }) + end + end + end +end