From 1feb166fd5656f639479341848883bc7009cf65d Mon Sep 17 00:00:00 2001 From: yystopf Date: Mon, 25 Jul 2022 16:20:42 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=AF=B7=E6=B1=82=E8=AF=84=E5=AE=A1=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/issue.rb | 1 - app/models/journal.rb | 3 ++- app/models/pull_request.rb | 7 ++++++- app/models/pull_requests_reviewer.rb | 21 +++++++++++++++++++ app/models/review.rb | 20 +++++++++--------- ...25020217_create_pull_requests_reviewers.rb | 9 ++++++++ ...ange_reviews_reference_to_pull_requests.rb | 6 ++++++ spec/models/pull_requests_reviewer_spec.rb | 5 +++++ 8 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 app/models/pull_requests_reviewer.rb create mode 100644 db/migrate/20220725020217_create_pull_requests_reviewers.rb create mode 100644 db/migrate/20220725020443_change_reviews_reference_to_pull_requests.rb create mode 100644 spec/models/pull_requests_reviewer_spec.rb diff --git a/app/models/issue.rb b/app/models/issue.rb index fa8c43ea9..2a3b95958 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -68,7 +68,6 @@ class Issue < ApplicationRecord has_many :issue_tags, through: :issue_tags_relates has_many :issue_times, dependent: :destroy has_many :issue_depends, dependent: :destroy - has_many :reviews, dependent: :destroy scope :issue_includes, ->{includes(:user)} scope :issue_many_includes, ->{includes(journals: :user)} scope :issue_issue, ->{where(issue_classify: [nil,"issue"])} diff --git a/app/models/journal.rb b/app/models/journal.rb index 297c7a148..19fdce1c9 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -25,7 +25,8 @@ class Journal < ApplicationRecord belongs_to :user - belongs_to :issue, foreign_key: :journalized_id, :touch => true + belongs_to :issue, foreign_key: :journalized_id, :touch => true, optional: true + belongs_to :journalized, polymorphic: true has_many :journal_details, :dependent => :delete_all has_many :attachments, as: :container, dependent: :destroy diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index e36af832b..b3ab1e03b 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -32,12 +32,17 @@ class PullRequest < ApplicationRecord belongs_to :issue belongs_to :user belongs_to :project, counter_cache: true, touch: true - # belongs_to :fork_project, foreign_key: :fork_project_id + belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id, optional: true has_many :pull_request_assigns, foreign_key: :pull_request_id has_many :pull_request_tags, foreign_key: :pull_request_id has_many :project_trends, as: :trend, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy has_one :gitea_pull, foreign_key: :id, primary_key: :gitea_number, class_name: 'Gitea::Pull' + has_many :journals, :as => :journalized, :dependent => :destroy + has_many :journal_details, through: :journals + has_many :reviews, dependent: :destroy + has_many :pull_requests_reviewers, dependent: :destroy + has_many :reviewers, through: :pull_requests_reviewers scope :merged_and_closed, ->{where.not(status: 0)} scope :opening, -> {where(status: 0)} diff --git a/app/models/pull_requests_reviewer.rb b/app/models/pull_requests_reviewer.rb new file mode 100644 index 000000000..31502b2a9 --- /dev/null +++ b/app/models/pull_requests_reviewer.rb @@ -0,0 +1,21 @@ +# == Schema Information +# +# Table name: pull_requests_reviewers +# +# id :integer not null, primary key +# pull_request_id :integer +# reviewer_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_pull_requests_reviewers_on_pull_request_id (pull_request_id) +# index_pull_requests_reviewers_on_reviewer_id (reviewer_id) +# + +class PullRequestsReviewer < ApplicationRecord + + belongs_to :pull_request + belongs_to :reviewers, class_name: 'User', foreign_key: :reviewer_id +end diff --git a/app/models/review.rb b/app/models/review.rb index f2d3e678d..715e11683 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -2,19 +2,19 @@ # # Table name: reviews # -# id :integer not null, primary key -# issue_id :integer -# reviewer_id :integer -# content :text(65535) -# commit_id :string(255) -# status :integer default("0") -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# reviewer_id :integer +# content :text(65535) +# commit_id :string(255) +# status :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# pull_request_id :integer # # Indexes # -# index_reviews_on_issue_id (issue_id) -# index_reviews_on_reviewer_id (reviewer_id) +# index_reviews_on_pull_request_id (pull_request_id) +# index_reviews_on_reviewer_id (reviewer_id) # class Review < ApplicationRecord diff --git a/db/migrate/20220725020217_create_pull_requests_reviewers.rb b/db/migrate/20220725020217_create_pull_requests_reviewers.rb new file mode 100644 index 000000000..be5c561cf --- /dev/null +++ b/db/migrate/20220725020217_create_pull_requests_reviewers.rb @@ -0,0 +1,9 @@ +class CreatePullRequestsReviewers < ActiveRecord::Migration[5.2] + def change + create_table :pull_requests_reviewers do |t| + t.belongs_to :pull_request, index: true + t.belongs_to :reviewer, class_name: User, index:true + t.timestamps + end + end +end diff --git a/db/migrate/20220725020443_change_reviews_reference_to_pull_requests.rb b/db/migrate/20220725020443_change_reviews_reference_to_pull_requests.rb new file mode 100644 index 000000000..e03943915 --- /dev/null +++ b/db/migrate/20220725020443_change_reviews_reference_to_pull_requests.rb @@ -0,0 +1,6 @@ +class ChangeReviewsReferenceToPullRequests < ActiveRecord::Migration[5.2] + def change + remove_reference :reviews, :issue + add_reference :reviews, :pull_request + end +end diff --git a/spec/models/pull_requests_reviewer_spec.rb b/spec/models/pull_requests_reviewer_spec.rb new file mode 100644 index 000000000..f3dfd9b95 --- /dev/null +++ b/spec/models/pull_requests_reviewer_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe PullRequestsReviewer, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 5db43bf76889020b058106d6fbb45763d6a64f1a Mon Sep 17 00:00:00 2001 From: yystopf Date: Mon, 25 Jul 2022 16:21:03 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E6=96=B0?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E8=AF=B7=E6=B1=82=E5=88=97=E8=A1=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/v1/base_controller.rb | 1 + .../api/v1/projects/pulls/base_controller.rb | 15 ------ .../v1/projects/pulls/comments_controller.rb | 2 + .../v1/projects/pulls/reviews_controller.rb | 7 +++ .../api/v1/projects/pulls_controller.rb | 19 ++++++++ app/controllers/concerns/api/pull_helper.rb | 19 ++++++++ .../api/v1/projects/pulls/list_service.rb | 46 +++++++++++++++++++ .../pulls/_simple_detail.json.jbuilder | 25 ++++++++++ .../api/v1/projects/pulls/index.json.jbuilder | 4 ++ 9 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 app/controllers/api/v1/projects/pulls/comments_controller.rb create mode 100644 app/controllers/api/v1/projects/pulls/reviews_controller.rb create mode 100644 app/controllers/api/v1/projects/pulls_controller.rb create mode 100644 app/controllers/concerns/api/pull_helper.rb create mode 100644 app/services/api/v1/projects/pulls/list_service.rb create mode 100644 app/views/api/v1/projects/pulls/_simple_detail.json.jbuilder create mode 100644 app/views/api/v1/projects/pulls/index.json.jbuilder diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index a66bfc528..4b3b8ab13 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -2,6 +2,7 @@ class Api::V1::BaseController < ApplicationController include Api::ProjectHelper include Api::UserHelper + include Api::PullHelper # before_action :doorkeeper_authorize! # skip_before_action :user_setup diff --git a/app/controllers/api/v1/projects/pulls/base_controller.rb b/app/controllers/api/v1/projects/pulls/base_controller.rb index 0d5ae08b5..acb5e2a03 100644 --- a/app/controllers/api/v1/projects/pulls/base_controller.rb +++ b/app/controllers/api/v1/projects/pulls/base_controller.rb @@ -2,19 +2,4 @@ class Api::V1::Projects::Pulls::BaseController < Api::V1::BaseController before_action :require_public_and_member_above before_action :load_pull_request - def load_pull_request - pull_request_id = params[:pull_id] || params[:id] - @pull_request = @project.pull_requests.where(gitea_number: pull_request_id).where.not(id: pull_request_id).take || PullRequest.find_by_id(pull_request_id) - @issue = @pull_request&.issue - if @pull_request - logger.info "###########pull_request founded" - @pull_request - else - logger.info "###########pull_request not found" - @pull_request = nil - render_not_found and return - end - - @pull_request - end end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls/comments_controller.rb b/app/controllers/api/v1/projects/pulls/comments_controller.rb new file mode 100644 index 000000000..8622c3190 --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/comments_controller.rb @@ -0,0 +1,2 @@ +class Api::V1::Projects::Pulls::CommentsController < Api::V1::Projects::Pulls::BaseController +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls/reviews_controller.rb b/app/controllers/api/v1/projects/pulls/reviews_controller.rb new file mode 100644 index 000000000..e07f02e32 --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/reviews_controller.rb @@ -0,0 +1,7 @@ +class Api::V1::Projects::Pulls::ReviewsController < Api::V1::Projects::Pulls::BaseController + + def index + @reviews = @pull_request.reviews + @reviews = kaminari_paginate(@reviews) + end +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls_controller.rb b/app/controllers/api/v1/projects/pulls_controller.rb new file mode 100644 index 000000000..fe39b2ad9 --- /dev/null +++ b/app/controllers/api/v1/projects/pulls_controller.rb @@ -0,0 +1,19 @@ +class Api::V1::Projects::PullsController < Api::V1::BaseController + before_action :require_public_and_member_above + + def index + @pulls = Api::V1::Projects::Pulls::ListService.call(@project, query_params) + @pulls = kaminari_paginate(@pulls) + end + + before_action :load_pull_request, only: [:show] + + def show + + end + + private + def query_params + params.permit(:status, :keyword, :priority_id, :issue_tag_id, :version_id, :reviewer_id, :sort_by, :sort_direction) + end +end \ No newline at end of file diff --git a/app/controllers/concerns/api/pull_helper.rb b/app/controllers/concerns/api/pull_helper.rb new file mode 100644 index 000000000..e186cd6f2 --- /dev/null +++ b/app/controllers/concerns/api/pull_helper.rb @@ -0,0 +1,19 @@ +module Api::PullHelper + extend ActiveSupport::Concern + + def load_pull_request + pull_request_id = params[:pull_id] || params[:id] + @pull_request = @project.pull_requests.where(gitea_number: pull_request_id).where.not(id: pull_request_id).take || PullRequest.find_by_id(pull_request_id) + @issue = @pull_request&.issue + if @pull_request + logger.info "###########pull_request founded" + @pull_request + else + logger.info "###########pull_request not found" + @pull_request = nil + render_not_found and return + end + + @pull_request + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/pulls/list_service.rb b/app/services/api/v1/projects/pulls/list_service.rb new file mode 100644 index 000000000..6b18da2ce --- /dev/null +++ b/app/services/api/v1/projects/pulls/list_service.rb @@ -0,0 +1,46 @@ +class Api::V1::Projects::Pulls::ListService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :keyword, :status, :priority_id, :issue_tag_id, :version_id, :reviewer_id, :sort_by, :sort_direction + attr_accessor :queried_pull_requests + + validates :status, inclusion: {in: [0, 1, 2], message: "请输入正确的Status"}, allow_nil: true + validates :sort_by, inclusion: {in: PullRequest.column_names, message: '请输入正确的SortBy'} + validates :sort_direction, inclusion: {in: %w(asc desc), message: '请输入正确的SortDirection'} + + def initialize(project, params={}) + @project = project + @keyword = params[:keyword] + @status = params[:status].to_i + @priority_id = params[:priority_id] + @issue_tag_id = params[:issue_tag_id] + @version_id = params[:version_id] + @reviewer_id = params[:reviewer_id] + @sort_by = params[:sort_by] || 'created_at' + @sort_direction = params[:sort_direction] || 'desc' + end + + def call + raise Error, errors.full_messages.join(",") unless valid? + pull_request_query_data + + queried_pull_requests + end + + private + def pull_request_query_data + pull_requests = @project.pull_requests + + pull_requests = pull_requests.where(status: status) if status.present? + pull_requests = pull_requests.where(issues: {priority_id: priority_id}) if priority_id.present? + pull_requests = pull_requests.where(issue_tags: {id: issue_tag_id}) if issue_tag_id.present? + pull_requests = pull_requests.where(issues: {fixed_version_id: version_id}) if version_id.present? + pull_requests = pull_requests.where(users: {id: reviewer_id}) if reviewer_id.present? + + q = pull_requests.ransack(title_or_body_cont: keyword) + scope = q.result.includes(:fork_project, :journals, :reviews, :reviewers, issue: [:journals, :priority, :version, :issue_tags]) + scope = scope.order("pull_requests.#{sort_by} #{sort_direction}") + + @queried_pull_requests = scope + end +end \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/_simple_detail.json.jbuilder b/app/views/api/v1/projects/pulls/_simple_detail.json.jbuilder new file mode 100644 index 000000000..e8c668c59 --- /dev/null +++ b/app/views/api/v1/projects/pulls/_simple_detail.json.jbuilder @@ -0,0 +1,25 @@ +json.(pull, :id, :head, :base, :is_original) +json.index pull.gitea_number +json.status pull.status == 1 ? "merged" : (pull.status == 2 ? "closed" : "open") + +fork_project = pull&.fork_project +if fork_project.present? + json.fork_project do + json.(fork_project, :id, :identifier) + json.login fork_project&.owner&.login + end +end + +issue = pull&.issue +json.issue do + json.id issue&.id + json.author do + json.partial! '/api/v1/users/simple_user', user: issue&.user + end + json.priority issue&.priority.try(:name) + json.version issue&.version.try(:name) + json.comments_count issue.journals.count + json.issue_tags issue.get_issue_tags +end + +json.comments_count pull.journals.count \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/index.json.jbuilder b/app/views/api/v1/projects/pulls/index.json.jbuilder new file mode 100644 index 000000000..412ea13d7 --- /dev/null +++ b/app/views/api/v1/projects/pulls/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @pulls.total_count +json.pulls @pulls.each do |pull| + json.partial! 'api/v1/projects/pulls/simple_detail', pull: pull +end \ No newline at end of file From 5463c22518df6823d9feaa2458c8c420b7fd3bd0 Mon Sep 17 00:00:00 2001 From: yystopf Date: Mon, 25 Jul 2022 17:28:38 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=20=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=88=9B=E5=BB=BA=E5=AE=A1=E6=9F=A5=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/v1/base_controller.rb | 6 +++--- .../api/v1/projects/pulls/reviews_controller.rb | 16 ++++++++++++++++ app/models/review.rb | 2 +- .../v1/projects/pulls/reviews/create_service.rb | 8 ++++---- .../projects/issues/_simple_detail.json.jbuilder | 0 .../projects/pulls/reviews/create.json.jbuilder | 8 ++++++++ config/routes/api.rb | 1 + 7 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 app/views/api/v1/projects/issues/_simple_detail.json.jbuilder create mode 100644 app/views/api/v1/projects/pulls/reviews/create.json.jbuilder diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index 4b3b8ab13..c765906b0 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -31,18 +31,18 @@ class Api::V1::BaseController < ApplicationController # 具有对仓库的管理权限 def require_manager_above @project = load_project - return render_forbidden unless current_user.admin? && @project.manager?(current_user) + return render_forbidden if !current_user.admin? && !@project.manager?(current_user) end # 具有对仓库的操作权限 def require_operate_above @project = load_project - return render_forbidden unless current_user.admin? && @project.operator?(current_user) + return render_forbidden if !current_user.admin? && !@project.operator?(current_user) end # 具有对仓库的访问权限 def require_public_and_member_above @project = load_project - return render_forbidden unless @project.is_public || (current_user.admin? && @project.member?(current_user)) + return render_forbidden if !@project.is_public && !current_user.admin? && !@project.member?(current_user) end end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls/reviews_controller.rb b/app/controllers/api/v1/projects/pulls/reviews_controller.rb index e07f02e32..ccb637838 100644 --- a/app/controllers/api/v1/projects/pulls/reviews_controller.rb +++ b/app/controllers/api/v1/projects/pulls/reviews_controller.rb @@ -4,4 +4,20 @@ class Api::V1::Projects::Pulls::ReviewsController < Api::V1::Projects::Pulls::Ba @reviews = @pull_request.reviews @reviews = kaminari_paginate(@reviews) end + + before_action :require_reviewer, only: [:create] + + def create + @journal, @review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user) + end + + private + def require_reviewer + puts @pull_request.reviewers.exists?(current_user.id) + return render_forbidden('您没有审查权限,请联系项目管理员') if !current_user.admin? && !@pull_request.reviewers.exists?(current_user.id) + end + + def review_params + params.require(:review).permit(:content, :commit_id, :status) + end end \ No newline at end of file diff --git a/app/models/review.rb b/app/models/review.rb index 715e11683..efb508139 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -19,7 +19,7 @@ class Review < ApplicationRecord - belongs_to :issue + belongs_to :pull_request belongs_to :reviewer, class_name: 'User', foreign_key: :reviewer_id has_one :journal, dependent: :destroy diff --git a/app/services/api/v1/projects/pulls/reviews/create_service.rb b/app/services/api/v1/projects/pulls/reviews/create_service.rb index 13ec9f7e7..bef944870 100644 --- a/app/services/api/v1/projects/pulls/reviews/create_service.rb +++ b/app/services/api/v1/projects/pulls/reviews/create_service.rb @@ -24,17 +24,17 @@ class Api::V1::Projects::Pulls::Reviews::CreateService < ApplicationService end return @journal, @review - rescue - raise Error, '服务器错误,请联系系统管理员!' + # rescue + # raise Error, '服务器错误,请联系系统管理员!' end private def create_review - @review = issue.reviews.create!(status: status, content: content, commit_id: commit_id, reviewer_id: @current_user.id) + @review = pull_request.reviews.create!(status: status, content: content, commit_id: commit_id, reviewer_id: @current_user.id) end def create_journal - @journal = issue.journals.create!(notes: content, user_id: @current_user.id, review_id: @review.id) + @journal = pull_request.journals.create!(notes: content, user_id: @current_user.id, review_id: @review.id) end end \ No newline at end of file diff --git a/app/views/api/v1/projects/issues/_simple_detail.json.jbuilder b/app/views/api/v1/projects/issues/_simple_detail.json.jbuilder new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/api/v1/projects/pulls/reviews/create.json.jbuilder b/app/views/api/v1/projects/pulls/reviews/create.json.jbuilder new file mode 100644 index 000000000..2b9f0efe1 --- /dev/null +++ b/app/views/api/v1/projects/pulls/reviews/create.json.jbuilder @@ -0,0 +1,8 @@ +json.reviewer do + json.partial! "api/v1/users/simple_user", user: @review.reviewer +end +json.pull_request do + json.partial! "api/v1/projects/pulls/simple_detail", pull: @review.pull_request +end +json.(@review, :id, :commit_id, :content, :status) +json.created_at format_time(@review.created_at) \ No newline at end of file diff --git a/config/routes/api.rb b/config/routes/api.rb index 8340097ee..0dfe6112f 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -25,6 +25,7 @@ defaults format: :json do get :diff end end + resources :reviews, only: [:index, :create] end resources :versions From 3f5754a3a569dcddbe5495a342ff7a8ca6534a16 Mon Sep 17 00:00:00 2001 From: yystopf Date: Mon, 25 Jul 2022 18:23:06 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=AF=B7=E6=B1=82=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 +- .../v1/projects/pulls/reviews_controller.rb | 1 - .../api/v1/projects/pulls_controller.rb | 3 +- app/controllers/pull_requests_controller.rb | 2 +- .../api/v1/projects/pulls/get_service.rb | 32 +++++++++++++++++++ .../api/v1/projects/pulls/show.json.jbuilder | 29 +++++++++++++++++ 6 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 app/services/api/v1/projects/pulls/get_service.rb create mode 100644 app/views/api/v1/projects/pulls/show.json.jbuilder diff --git a/Gemfile b/Gemfile index dd8885df7..c5f4f2ab6 100644 --- a/Gemfile +++ b/Gemfile @@ -135,4 +135,4 @@ gem 'doorkeeper' gem 'doorkeeper-jwt' -gem 'gitea-client', '~> 0.10.4' \ No newline at end of file +gem 'gitea-client', '~> 0.10.5' \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls/reviews_controller.rb b/app/controllers/api/v1/projects/pulls/reviews_controller.rb index ccb637838..523137a86 100644 --- a/app/controllers/api/v1/projects/pulls/reviews_controller.rb +++ b/app/controllers/api/v1/projects/pulls/reviews_controller.rb @@ -13,7 +13,6 @@ class Api::V1::Projects::Pulls::ReviewsController < Api::V1::Projects::Pulls::Ba private def require_reviewer - puts @pull_request.reviewers.exists?(current_user.id) return render_forbidden('您没有审查权限,请联系项目管理员') if !current_user.admin? && !@pull_request.reviewers.exists?(current_user.id) end diff --git a/app/controllers/api/v1/projects/pulls_controller.rb b/app/controllers/api/v1/projects/pulls_controller.rb index fe39b2ad9..a930df760 100644 --- a/app/controllers/api/v1/projects/pulls_controller.rb +++ b/app/controllers/api/v1/projects/pulls_controller.rb @@ -9,7 +9,8 @@ class Api::V1::Projects::PullsController < Api::V1::BaseController before_action :load_pull_request, only: [:show] def show - + @result_object = Api::V1::Projects::Pulls::GetService.call(@project, @pull_request, current_user&.gitea_token) + @last_review = @pull_request.reviews.take end private diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 52da4ac48..8bbfdc230 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -176,7 +176,7 @@ class PullRequestsController < ApplicationController @issue_assign_to = @issue.get_assign_user @gitea_pull = Gitea::PullRequest::GetService.call(@owner.login, @repository.identifier, @pull_request.gitea_number, current_user&.gitea_token) - @last_review = @pull_request.issue.reviews.take + @last_review = @pull_request.reviews.take end def pr_merge diff --git a/app/services/api/v1/projects/pulls/get_service.rb b/app/services/api/v1/projects/pulls/get_service.rb new file mode 100644 index 000000000..3c1bba99b --- /dev/null +++ b/app/services/api/v1/projects/pulls/get_service.rb @@ -0,0 +1,32 @@ +class Api::V1::Projects::Pulls::GetService < ApplicationService + + attr_reader :project, :pull_request, :owner, :repo, :index, :token + attr_accessor :gitea_data + + def initialize(project, pull_request, token = nil) + @project = project + @pull_request = pull_request + @owner = project&.owner.login + @repo = project&.identifier + @index = pull_request.gitea_number + @token = token + end + + def call + load_gitea_data + + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_pulls_by_owner_repo_index(owner, repo, index, {query: request_params}) + # raise Error, '获取合并请求失败!' unless @gitea_data.is_a?(Hash) + end +end \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/show.json.jbuilder b/app/views/api/v1/projects/pulls/show.json.jbuilder new file mode 100644 index 000000000..fce27e17f --- /dev/null +++ b/app/views/api/v1/projects/pulls/show.json.jbuilder @@ -0,0 +1,29 @@ +json.partial! "api/v1/projects/pulls/simple_detail", pull: @pull_request +json.merge_base @result_object['merge_base'] +json.base_commit_sha @result_object['base']['sha'] +json.head_commit_sha @result_object['head']['sha'] +json.commit_num @result_object['commit_num'] +json.changed_files @result_object['changed_files'] +json.is_locked @result_object['is_locked'] +json.mergeable @result_object['mergeable'] # 是否能合并 +json.merged @result_object['merged'] +json.merged_at @result_object['merged_at'].nil? ? '' : render_unix_time( @result_object['merged_at']) +json.merge_commit_sha @result_object['merge_commit_sha'] +json.merge_by do + if @result_object['merged_by'] + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(@result_object['merged_by']), name: @result_object['merged_by']['login'] } + else + json.nil! + end +end +json.last_review do + if @last_review.present? + json.(@last_review, :id, :commit_id, :content, :status) + json.created_at format_time(@last_review.created_at) + json.reviewer do + json.partial! "api/v1/users/simple_user", user: @last_review.reviewer + end + else + json.nil! + end +end \ No newline at end of file From 1bbde165c23852064277a0a2fdd8f3c1d0d86048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cxxq250=E2=80=9D?= <“xxq250@qq.com”> Date: Tue, 26 Jul 2022 10:44:12 +0800 Subject: [PATCH 5/5] =?UTF-8?q?reposyncer=E5=90=8C=E6=AD=A5=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ob_repository_syncs_controller.rb | 111 ++++++++++++ app/models/ob_repository_sync.rb | 28 +++ app/models/ob_repository_sync_job.rb | 24 +++ app/models/repository.rb | 2 +- .../ob_repository_sync/api_service.rb | 166 ++++++++++++++++++ .../ob_repository_syncs/index.json.jbuilder | 8 + config/routes.rb | 10 ++ ...220721034359_create_ob_repository_syncs.rb | 15 ++ ...21034618_create_ob_repository_sync_jobs.rb | 14 ++ 9 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 app/controllers/ob_repository_syncs_controller.rb create mode 100644 app/models/ob_repository_sync.rb create mode 100644 app/models/ob_repository_sync_job.rb create mode 100644 app/services/ob_repository_sync/api_service.rb create mode 100644 app/views/ob_repository_syncs/index.json.jbuilder create mode 100644 db/migrate/20220721034359_create_ob_repository_syncs.rb create mode 100644 db/migrate/20220721034618_create_ob_repository_sync_jobs.rb diff --git a/app/controllers/ob_repository_syncs_controller.rb b/app/controllers/ob_repository_syncs_controller.rb new file mode 100644 index 000000000..0d14d25e2 --- /dev/null +++ b/app/controllers/ob_repository_syncs_controller.rb @@ -0,0 +1,111 @@ +class ObRepositorySyncsController < ApplicationController + before_action :require_login + before_action :load_project + before_action :load_ob_repository_sync, except: [:create] + before_action :authenticate_user! + + def index + + end + + + def create + tip_exception "参数错误" if params[:github_address].blank? && params[:gitee_address].blank? + project_name ="#{@project.owner.name}:#{@project.identifier}" + service = ObRepositorySync::ApiService.new(project_name) + params.merge({ "gitlink_address": @project.repository.url }) + res = service.create_projects(params) + tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200" + sync_id = res["data"]["id"] + ob_repository_sync = ObRepositorySync.find_or_initialize_by(project_id: @project.id) + ob_repository_sync.project_id = @project.id + ob_repository_sync.user_id = current_user.id + ob_repository_sync.name = project_name + ob_repository_sync.github_address = "#{params[:github_address]}" + ob_repository_sync.gitee_address = "#{params[:gitee_address]}" + ob_repository_sync.github_token = "#{params[:github_token]}" + ob_repository_sync.gitee_token = "#{params[:gitee_token]}" + ob_repository_sync.sync_id = sync_id + ob_repository_sync.save! + render_ok + end + + def delete + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + res = service.delete_project @ob_repository_sync.sync_id + tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200" + if res["code"].to_s == "200" + @ob_repository_sync.destroy! + end + end + + def jobs + tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank? + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + res = service.get_projects_jobs + render_ok(count: res["data"]["total"], data: res["data"]["list"]) + end + + def create_jobs + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + res = service.create_projects_jobs(params) + tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200" + job_id = res["data"]["id"] + job = ObRepositorySyncJob.new + job.ob_repository_sync_id = @ob_repository_sync.id + job.github_branch = "#{params[:github_branch]}" + job.gitee_branch = "#{params[:gitee_branch]}" + job.gitlink_branch = "#{params[:gitlink_branch]}" + job.job_type = "#{params[:type]}" + job.base = "#{params[:base]}" + job.job_id = job_id + job.save + render_ok + end + + + def delete_job + tip_exception "缺少参数job_id" if params[:job_id].blank? + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + res = service.delete_job params[:job_id] + tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200" + @ob_repository_sync.destroy! + render_ok + end + + def start_job + tip_exception "缺少参数job_id" if params[:job_id].blank? + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + res = service.start_job params[:job_id] + tip_exception "启动错误: #{res["msg"]}" if res["code"].to_s != "200" + render_ok + end + + def stop_job + tip_exception "缺少参数job_id" if params[:job_id].blank? + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + res = service.stop_job params[:job_id] + tip_exception "停止错误: #{res["msg"]}" if res["code"].to_s != "200" + render_ok + end + + def job_logs + tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank? + tip_exception "缺少参数job_id" if params[:job_id].blank? + service = ObRepositorySync::ApiService.new(@ob_repository_sync.name) + @data = service.job_logs params[:job_id] + tip_exception "请求错误: #{res["msg"]}" if res["code"].to_s != "200" + render_ok(count: res["data"]["total"], data: res["data"]["list"]) + end + + private + + def load_ob_repository_sync + @ob_repository_sync = ObRepositorySync.find_by(project_id: @project.id) + end + + def authenticate_user! + return if @project.member?(current_user) || current_user.admin? + render_forbidden('你没有权限操作') + end +end diff --git a/app/models/ob_repository_sync.rb b/app/models/ob_repository_sync.rb new file mode 100644 index 000000000..b938658e2 --- /dev/null +++ b/app/models/ob_repository_sync.rb @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: ob_repository_syncs +# +# id :integer not null, primary key +# project_id :integer +# user_id :integer +# name :string(255) +# github_address :string(255) +# gitee_address :string(255) +# github_token :string(255) +# gitee_token :string(255) +# sync_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_ob_repository_syncs_on_project_id (project_id) +# index_ob_repository_syncs_on_user_id (user_id) +# + +class ObRepositorySync < ApplicationRecord + belongs_to :project + belongs_to :user + + has_many :ob_repository_sync_jobs, dependent: :destroy +end diff --git a/app/models/ob_repository_sync_job.rb b/app/models/ob_repository_sync_job.rb new file mode 100644 index 000000000..3961f0a2b --- /dev/null +++ b/app/models/ob_repository_sync_job.rb @@ -0,0 +1,24 @@ +# == Schema Information +# +# Table name: ob_repository_sync_jobs +# +# id :integer not null, primary key +# ob_repository_sync_id :integer +# github_branch :string(255) +# gitee_branch :string(255) +# gitlink_branch :string(255) +# job_type :string(255) +# base :string(255) +# job_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_ob_repository_sync_jobs_on_ob_repository_sync_id (ob_repository_sync_id) +# + +class ObRepositorySyncJob < ApplicationRecord + belongs_to :ob_repository_sync + +end diff --git a/app/models/repository.rb b/app/models/repository.rb index 12cc2fa38..03c4e98e0 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -49,7 +49,7 @@ class Repository < ApplicationRecord end def url - self['url'].blank? ? "#{Rails.application.config_for(:configuration)['platform_url']}/#{self.owner&.login}/#{self.identifier}.git" : self['url'] + self['url'].blank? ? "#{Gitea.gitea_config[:domain]}/#{self.owner&.login}/#{self.identifier}.git" : self['url'] end # with repository is mirror diff --git a/app/services/ob_repository_sync/api_service.rb b/app/services/ob_repository_sync/api_service.rb new file mode 100644 index 000000000..7bed888e6 --- /dev/null +++ b/app/services/ob_repository_sync/api_service.rb @@ -0,0 +1,166 @@ +class ObRepositorySync::ApiService < ApplicationService + attr_reader :project_name + + def initialize(project_name) + @project_name = project_name + end + + def call + true + end + + def create_projects(params = {}) + projects_body = { + "name": "#{@project_name}", + "github_address": "#{params[:github_address]}", + "gitee_address": "#{params[:gitee_address]}", + "github_token": "#{params[:github_token]}", + "gitee_token": "#{params[:gitee_token]}" + } + url = URI("#{domain}/cerobot/projects") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Post.new(url) + request["Content-Type"] = "application/json" + request.body = JSON.dump(projects_body) + + response = http.request(request) + # Rails.logger.info "cerobot/projects response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def delete_project sync_id + url = URI("#{domain}/cerobot/projects?id=#{sync_id}") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Delete.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + # Rails.logger.info "delete project response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def get_projects_jobs + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Get.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "cerobot/projects response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def create_projects_jobs(params = {}) + job_body = { + "github_branch": "#{params[:github_branch]}", + "gitee_branch": "#{params[:gitee_branch]}", + "gitlink_branch": "#{params[:gitlink_branch]}", + "type": "#{params[:type]}", + "base": "#{params[:base]}" + } + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Post.new(url) + request["Content-Type"] = "application/json" + request.body = JSON.dump(job_body) + + response = http.request(request) + Rails.logger.info "cerobot/projects response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def delete_job job_id + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs?id=#{job_id}") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Delete.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "delete job response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def start_job job_id + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs/#{job_id}/start") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Put.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "start job response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def stop_job job_id + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs/#{job_id}/stop") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Put.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "stop job response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def set_commit job_id, commit_id + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs/#{job_id}/set_commit?commit=#{commit_id}") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Put.new(url) + response = http.request(request) + Rails.logger.info "set_commit job response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + res + end + + def job_logs job_id + url = URI("#{domain}/cerobot/projects/#{@project_name}/jobs/#{job_id}/logs") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Get.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "set_commit job response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + if res["code"].to_s == "200" + res["data"] + else + [] + end + end + + def pull_requests + url = URI("#{domain}/cerobot/projects/#{@project_name}/pullrequests") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Get.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "pull_requests response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + if res["code"].to_s == "200" + res["data"] + else + [] + end + end + + def pull_requests_sync + url = URI("#{domain}/cerobot/projects/#{@project_name}/pullrequests/sync") + http = Net::HTTP.new(url.host, url.port) + request = Net::HTTP::Get.new(url) + request["Content-Type"] = "application/json" + response = http.request(request) + Rails.logger.info "pull_requests_sync response.read_body======#{response.read_body}" + res = JSON.parse(response.body) + if res["code"].to_s == "200" + res["data"] + else + [] + end + end + + def domain + EduSetting.get("ob_repository_sync_api_domain") || "http://106.75.110.152:50087" + end + +end diff --git a/app/views/ob_repository_syncs/index.json.jbuilder b/app/views/ob_repository_syncs/index.json.jbuilder new file mode 100644 index 000000000..4b719aa86 --- /dev/null +++ b/app/views/ob_repository_syncs/index.json.jbuilder @@ -0,0 +1,8 @@ +json.status 0 +json.message "success" +json.data do + if @ob_repository_sync + json.extract! @ob_repository_sync, :user_id, :name, :github_address, :gitee_address, :github_token, :gitee_token,:sync_id, :created_at, :updated_at + end + +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 73e06ea53..f32f1050f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -555,6 +555,16 @@ Rails.application.routes.draw do resources :project_trends, :path => :activity, only: [:index, :create] resources :issue_tags, :path => :labels, only: [:create, :edit, :update, :destroy, :index] resources :version_releases, :path => :releases, only: [:index,:new, :show, :create, :edit, :update, :destroy] + resources :ob_repository_syncs, :path => :synchronizes, only: [:index, :create] do + collection do + delete :delete + get :jobs + post :create_jobs + delete :delete_job + post :start_job + post :stop_job + end + end scope module: :ci do scope do diff --git a/db/migrate/20220721034359_create_ob_repository_syncs.rb b/db/migrate/20220721034359_create_ob_repository_syncs.rb new file mode 100644 index 000000000..e4b6b91ac --- /dev/null +++ b/db/migrate/20220721034359_create_ob_repository_syncs.rb @@ -0,0 +1,15 @@ +class CreateObRepositorySyncs < ActiveRecord::Migration[5.2] + def change + create_table :ob_repository_syncs do |t| + t.references :project + t.references :user + t.string :name + t.string :github_address + t.string :gitee_address + t.string :github_token + t.string :gitee_token + t.integer :sync_id + t.timestamps + end + end +end diff --git a/db/migrate/20220721034618_create_ob_repository_sync_jobs.rb b/db/migrate/20220721034618_create_ob_repository_sync_jobs.rb new file mode 100644 index 000000000..bd4aa1bf7 --- /dev/null +++ b/db/migrate/20220721034618_create_ob_repository_sync_jobs.rb @@ -0,0 +1,14 @@ +class CreateObRepositorySyncJobs < ActiveRecord::Migration[5.2] + def change + create_table :ob_repository_sync_jobs do |t| + t.references :ob_repository_sync + t.string :github_branch + t.string :gitee_branch + t.string :gitlink_branch + t.string :job_type + t.string :base + t.integer :job_id + t.timestamps + end + end +end