diff --git a/Gemfile b/Gemfile index 3da6f273d..c5f4f2ab6 100644 --- a/Gemfile +++ b/Gemfile @@ -135,4 +135,4 @@ gem 'doorkeeper' gem 'doorkeeper-jwt' -gem 'gitea-client', '~> 0.10.2' \ 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/base_controller.rb b/app/controllers/api/v1/base_controller.rb index a66bfc528..c765906b0 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 @@ -30,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/contents_controller.rb b/app/controllers/api/v1/projects/contents_controller.rb index a4e65051e..44ab8c549 100644 --- a/app/controllers/api/v1/projects/contents_controller.rb +++ b/app/controllers/api/v1/projects/contents_controller.rb @@ -2,7 +2,11 @@ class Api::V1::Projects::ContentsController < Api::V1::BaseController before_action :require_operate_above, only: [:batch] def batch - @result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, batch_content_params, current_user&.gitea_token) + @batch_content_params = batch_content_params + # 处理下author和committer信息,如果没传则默认为当前用户信息 + @batch_content_params.merge!(author_email: current_user.mail, author_name: current_user.login) if batch_content_params[:author_email].blank? && batch_content_params[:author_name].blank? + @batch_content_params.merge!(committer_email: current_user.mail, committer_name: current_user.login) if batch_content_params[:committer_email].blank? && batch_content_params[:committer_name].blank? + @result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, @batch_content_params, current_user&.gitea_token) puts @result_object end diff --git a/app/controllers/api/v1/projects/pulls/base_controller.rb b/app/controllers/api/v1/projects/pulls/base_controller.rb new file mode 100644 index 000000000..acb5e2a03 --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/base_controller.rb @@ -0,0 +1,5 @@ +class Api::V1::Projects::Pulls::BaseController < Api::V1::BaseController + before_action :require_public_and_member_above + before_action :load_pull_request + +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls/journals_controller.rb b/app/controllers/api/v1/projects/pulls/journals_controller.rb new file mode 100644 index 000000000..d32474973 --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/journals_controller.rb @@ -0,0 +1,40 @@ +class Api::V1::Projects::Pulls::JournalsController < Api::V1::Projects::Pulls::BaseController + + def index + @journals = Api::V1::Projects::Pulls::Journals::ListService.call(@project, @pull_request, params, current_user) + @journals = kaminari_paginate(@journals) + end + + def create + @journal = Api::V1::Projects::Pulls::Journals::CreateService.call(@project, @pull_request, create_params, current_user) + end + + before_action :find_journal, only: [:update, :destroy] + + def update + @journal = Api::V1::Projects::Pulls::Journals::UpdateService.call(@project, @pull_request, @journal, update_params, current_user) + end + + def destroy + if @journal.destroy + render_ok + else + render_error("删除评论失败!") + end + end + + private + def create_params + params.permit(:parent_id, :line_code, :note, :commit_id, :path, :type, :review_id, :diff => {}) + end + + def update_params + params.permit(:note, :commit_id, :state) + end + + def find_journal + @journal = @pull_request.journals.find_by_id(params[:id]) + return render_not_found unless @journal.present? + end + +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/pulls/pulls_controller.rb b/app/controllers/api/v1/projects/pulls/pulls_controller.rb new file mode 100644 index 000000000..1a7c574d9 --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/pulls_controller.rb @@ -0,0 +1,20 @@ +class Api::V1::Projects::Pulls::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 + @result_object = Api::V1::Projects::Pulls::GetService.call(@project, @pull_request, current_user&.gitea_token) + @last_review = @pull_request.reviews.order(created_at: :desc).take + 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/api/v1/projects/pulls/reviews_controller.rb b/app/controllers/api/v1/projects/pulls/reviews_controller.rb new file mode 100644 index 000000000..039a6c4df --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/reviews_controller.rb @@ -0,0 +1,22 @@ +class Api::V1::Projects::Pulls::ReviewsController < Api::V1::Projects::Pulls::BaseController + + def index + @reviews = @pull_request.reviews + @reviews = kaminari_paginate(@reviews) + end + + before_action :require_reviewer, only: [:create] + + def create + @review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user) + end + + private + def require_reviewer + 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/controllers/api/v1/projects/pulls/versions_controller.rb b/app/controllers/api/v1/projects/pulls/versions_controller.rb new file mode 100644 index 000000000..dfd5d9e9d --- /dev/null +++ b/app/controllers/api/v1/projects/pulls/versions_controller.rb @@ -0,0 +1,10 @@ +class Api::V1::Projects::Pulls::VersionsController < Api::V1::Projects::Pulls::BaseController + + def index + @result_object = Api::V1::Projects::Pulls::Versions::ListService.call(@project, @pull_request, {page: page, limit: limit}, current_user&.gitea_token) + end + + def diff + @result_object = Api::V1::Projects::Pulls::Versions::GetDiffService.call(@project, @pull_request, params[:id], {filepath: params[:filepath]}, current_user&.gitea_token) + end +end \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 82aa95879..1c937aa79 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,9 +20,9 @@ class ApplicationController < ActionController::Base # TODO # check sql query time before_action do - if request.subdomain === 'testforgeplus' || request.subdomain === "profiler" - Rack::MiniProfiler.authorize_request - end + # if request.subdomain === 'testforgeplus' || request.subdomain === "profiler" + # Rack::MiniProfiler.authorize_request + # end end DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) 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/controllers/mark_files_controller.rb b/app/controllers/mark_files_controller.rb new file mode 100644 index 000000000..4668471e3 --- /dev/null +++ b/app/controllers/mark_files_controller.rb @@ -0,0 +1,38 @@ +class MarkFilesController < ApplicationController + before_action :require_login + before_action :load_project + before_action :load_pull_request + + def index + @files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token) + @mark_files = MarkFile.where(pull_request_id: @pull_request.id) + end + + def create + unless @pull_request.mark_files.present? + MarkFile.bulk_insert(*%i[pull_request_id, file_path_sha file_path created_at updated_at]) do |worker| + @files_result['Files'].each do |file| + worker.add(pull_request_id: @pull_request.id, file_path_sha: SecureRandom.uuid.gsub("-", ""), file_path: file['Name']) + end + end + end + end + + def mark_file_as_unread + + end + + def mark_file_as_read + + end + + private + def review_params + params.require(:review).permit(:content, :commit_id, :status) + end + + def load_pull_request + @pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id]) + end + +end \ No newline at end of file diff --git a/app/controllers/ob_repository_syncs_controller.rb b/app/controllers/ob_repository_syncs_controller.rb new file mode 100644 index 000000000..107320934 --- /dev/null +++ b/app/controllers/ob_repository_syncs_controller.rb @@ -0,0 +1,112 @@ +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 + render_ok(data: @ob_repository_sync) + 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) + project_params = params.merge({ "gitlink_address": @project.repository.url }) + res = service.create_projects(project_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.gitlink_address = @project.repository.url + 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/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 97fafe17a..d25097a19 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -67,6 +67,8 @@ class PullRequestsController < ApplicationController @pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params) if @gitea_pull_request[:status] == :success @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"]) + reviewers = User.where(id: params[:reviewer_ids]) + @pull_request.reviewers = reviewers SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu? Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}" @@ -112,6 +114,9 @@ class PullRequestsController < ApplicationController end end + reviewers = User.where(id: params[:reviewer_ids]) + @pull_request.reviewers = reviewers + if @issue.update_attributes(@issue_params) if @pull_request.update_attributes(@local_params.compact) gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier, @@ -181,7 +186,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/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index eec57113d..b5fedfae0 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -5,7 +5,7 @@ class ReviewsController < ApplicationController def create return render_forbidden('您不是审查人员,无法进行审查!') if current_user&.id != @pull_request.issue.assigned_to_id - @journal, @review = Api::V1::Projects::PullRequests::Reviews::CreateService.call(@project, @pull_request, review_params, current_user) + @review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user) end private diff --git a/app/controllers/traces/projects_controller.rb b/app/controllers/traces/projects_controller.rb index e39d77a9e..89a4aac8d 100644 --- a/app/controllers/traces/projects_controller.rb +++ b/app/controllers/traces/projects_controller.rb @@ -3,6 +3,7 @@ class Traces::ProjectsController < Traces::BaseController before_action :require_login before_action :load_project + before_action :set_trace_token_to_cookie before_action :authorizate_user_can_edit_project!, except: [:task_results] def tasks @@ -35,7 +36,7 @@ class Traces::ProjectsController < Traces::BaseController return render :json => {left_tasks_count: 5, data: []} if current_user.trace_user.nil? code, data, error = Trace::CheckResultService.call(current_user.trace_token, @project, nil, page, limit) if code == 200 - render :json => {left_tasks_count: 5 - @project.user_trace_tasks.size, data: data} + render :json => {left_tasks_count: 5 - @project.user_trace_tasks.size, data: data, view_base: "#{Trace.trace_config[:view_domain]}/analysis_ccf/analysis-results/" } else render_error("获取检测记录失败 Error:#{error}") end @@ -86,4 +87,12 @@ class Traces::ProjectsController < Traces::BaseController puts exception.message normal_status(-1, exception.message) end + + def set_trace_token_to_cookie + cookies[:vue_admin_template_token] = { + :value => current_user&.trace_token, + :expires => 1.hours.from_now, + :domain => Trace.trace_config[:cookie_domain] + } + end end \ No newline at end of file diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb index 1ddadd277..ff45120fb 100644 --- a/app/controllers/users/is_pinned_projects_controller.rb +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -1,7 +1,10 @@ class Users::IsPinnedProjectsController < Users::BaseController before_action :private_user_resources!, only: [:pin] - def index - @is_pinned_projects = observed_user.pinned_projects.order(position: :desc, created_at: :asc).includes(project: [:project_category, :project_language, :repository]).order(position: :desc) + def index + @is_pinned_projects = observed_user.pinned_projects.left_joins(:project) + .where("projects.is_public = TRUE") + .order(position: :desc, created_at: :asc) + .includes(project: [:project_category, :project_language, :repository]).order(position: :desc) @is_pinned_projects = kaminari_paginate(@is_pinned_projects) end diff --git a/app/docs/slate/source/includes/_pulls.md b/app/docs/slate/source/includes/_pulls.md index b9ad3b0ba..adc6e3cc4 100644 --- a/app/docs/slate/source/includes/_pulls.md +++ b/app/docs/slate/source/includes/_pulls.md @@ -1,84 +1,133 @@ # Pulls -## Get a pull request +## 获取一个合并请求 获取合并请求详情接口 > 示例: ```shell -curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls/88.json +curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/1.json ``` ```javascript -await octokit.request('GET /api/Jasder/gitlink/pulls/88.json') +await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/1.json') ``` ### HTTP 请求 -`GET /api/:owner/:repo/pulls/:id.json` +`GET /api/v1/:owner/:repo/pulls/:index.json` ### 请求参数: 参数 | 必选 | 默认 | 类型 | 字段说明 --------- | ------- | ------- | -------- | ---------- |owner |是| |string |用户登录名 | |repo |是| |string |项目标识identifier | -|id |是| | integer | pull id值 | - +|index |是| | integer | pull 序号 | +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|-|-|-| +|id |int|合并请求ID| +|title |string|合并请求标题| +|body| |string|合并请求内容| +|head |int|合并请求源分支| +|base |int|合并请求目标分支| +|index |int|合并请求序号| +|status |string|合并请求状态,open: 开启的, merged: 合并的, closed: 关闭的| +|issue.id |int|疑修ID| +|issue.author |object|疑修作者| +|issue.priority |string|疑修优先级| +|issue.version |string|疑修里程碑| +|issue.journals_count |int|普通评论数量| +|issue.issue_tags |array|标记| +|journals_count |int|审查评论数量| +|merge_base |string|目标的commit ID| +|base_commit_sha |string|合并之后的第一个commit ID| +|head_commit_sha |string|源commit ID| +|commit_num |int|commit数量| +|changed_files |int|更改文件数量| +|is_locked |bool|| +|mergeable |bool|是否能合并| +|merged |bool|是否合并| +|merged_at |string|合并时间| +|merge_commit_sha |string|合并之后的第一个commit ID| +|merge_by |object|被谁合并了| +|last_review.id |int|最后一个审查的id| +|last_review.commit_id|string|最后一个审查对应的commit ID| +|last_review.content |string|最后一个审查的内容| +|last_review.status |string|最后一个审查的状态,common: 一般审查, approved: 通过, rejected: 拒绝通过| +|last_review.created_at|string|审查创建的时间| +|last_review.reviewer |object|审查创建人| +|reviewers |array|指定审查用户标识数组| +|conflict_files |array|有冲突的文件| > 返回的JSON示例: ```json { - "status": 0, - "message": "响应成功", - "project_name": "Gitlink", - "identifier": "forgeplus", - "project_identifier": "forgeplus", - "pr_time": "52分钟前", - "commits_count": 229, - "files_count": 328, - "comments_count": 0, - "comments_total_count": 0, - "pull_request": { - "id": 1189, - "base": "master", - "head": "develop", - "status": 0, - "fork_project_id": null, - "is_original": false, - "pull_request_staus": "open", - "fork_project_user": null, - "create_user": "jasder", - "mergeable": true, - "state": "open" - }, + "id": 168, + "head": "new_branch", + "base": "master", + "is_original": false, + "index": 5, + "status": "merged", "issue": { - "id": 51888, - "subject": "FIx release v3.2.0", - "description": null, - "is_private": false, - "branch_name": null, - "project_author_name": "Gitlink", - "closed_on": "", - "created_at": "2021-10-12 15:51", - "assign_user_name": "victor", - "assign_user_login": "moshenglv", - "author_name": "段甲生", - "author_login": "jasder", - "author_picture": "images/avatars/User/36480?t=1615520120", - "issue_status": "新增", - "priority": "正常", + "id": 265, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, "version": null, + "journals_count": 1, "issue_tags": null }, + "journals_count": 0, + "merge_base": "4a277037093c1248e46d2946ee30b61cccdb9df9", + "base_commit_sha": "dbb510cd852a6bfd4d71a1f84921aa3170654590", + "head_commit_sha": "0f0e27918eb5deb8d514012d84d13db10eebe19a", + "commit_num": 1, + "changed_files": 1, + "is_locked": false, + "mergeable": true, + "merged": true, + "merged_at": 1658743004, + "merge_commit_sha": "dbb510cd852a6bfd4d71a1f84921aa3170654590", + "merge_by": { + "id": null, + "login": "yystopf", + "name": "yystopf", + "type": null, + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "last_review": { + "id": 5, + "commit_id": null, + "content": "新建一个审查", + "status": "common", + "created_at": "2022-07-25 17:08", + "reviewer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + } + }, + "reviewers": [ + "yystopf" + ], "conflict_files": [] } ``` -## 获取pull request文件列表 -获取pull request文件列表 +## 获取合并请求文件列表 +获取合并请求文件列表 > 示例: @@ -204,8 +253,8 @@ await octokit.request('GET /api/jasder/gitlink/pulls/1/files.json') ``` -## 获取pull request的commits列表 -获取pull request的commits列表 +## 获取合并请求的commits列表 +获取合并请求的commits列表 > 示例: @@ -433,70 +482,1219 @@ await octokit.request('GET /api/Jason/test-txt/compare/master...Jason/test-txt:d ``` -## List pull requests +## 获取合并请求列表 获取合并请求列表 > 示例: ```shell -curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls.json +curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls.json ``` ```javascript -await octokit.request('GET /api/Jasder/gitlink/pulls.json') +await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls.json') ``` ### HTTP 请求 -`GET /api/:owner/:repo/pulls.json` +`GET /api/v1/:owner/:repo/pulls.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|keyword |否| |string |搜索关键词| +|status |否| | int | 合并请求类型 0: 开启的, 1: 合并的 2: 关闭的,不传则为全部的 | +|priority_id |否| | int | 优先级ID | +|issue_tag_id |否| |int|标记ID| +|version_id |否| |int|里程碑ID| +|reviewer_id |否| |int| 审查人员ID| +|assign_user_id |否| |int| 指派人员ID| +|sort_by |否| created_at |string| 排序字段,created_at: 创建时间, updated_at: 更新时间| +|sort_direction |否| desc |string| 排序类型 desc: 倒序 asc: 正序| +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|-|-|-| +|total_count |int|合并请求总数| +|id |int|合并请求ID| +|title |string|合并请求标题| +|body |string|合并请求内容| +|head |int|合并请求源分支| +|base |int|合并请求目标分支| +|index |int|合并请求序号| +|is_original |bool|是否为fork仓库发来的合并请求| +|status |string|合并请求状态,open: 开启的, merged: 合并的, closed: 关闭的| +|fork_project.id |int|fork仓库的id| +|fork_project.identifier|string|fork仓库的标识| +|fork_project.login |string|fork仓库拥有者的标识| +|issue.id |int|疑修ID| +|issue.author |object|疑修作者| +|issue.priority |string|疑修优先级| +|issue.version |string|疑修里程碑| +|issue.journals_count |int|普通评论数量| +|issue.issue_tags |array|标记| +|journals_count |int|审查评论数量| + +> 返回的JSON示例: + +```json +{ + "total_count": 2, + "pulls": [ + { + "id": 167, + "head": "master", + "base": "master", + "is_original": true, + "index": 4, + "status": "open", + "fork_project": { + "id": 491, + "identifier": "ceshi_commit", + "login": "testforge1" + }, + "issue": { + "id": 264, + "author": { + "id": 4, + "type": "User", + "name": "tes tforge1", + "login": "testforge1", + "image_url": "system/lets/letter_avatars/2/T/238_117_19/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "journals_count": 0 + }, + { + "id": 165, + "head": "master_1", + "base": "master", + "is_original": false, + "index": 3, + "status": "open", + "issue": { + "id": 262, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "journals_count": 0 + } + ] +} +``` + +## 创建一个合并请求 +为仓库创建一个合并请求 + +> 示例: + +```shell +curl -X POST \ +http://localhost:3000/api/yystopf/ceshi/pulls.json +``` + +```javascript +await octokit.request('POST /api/yystopf/ceshi/pulls.json') +``` + +### HTTP 请求 +`POST /api/:owner/:repo/pulls.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|title |是| | string |合并请求标题| +|body |否| | string |合并请求内容| +|base |是| | string |目标分支| +|head |是| | string |源分支| +|is_original |是| | bool |是否为fork仓库发来的合并请求| +|fork_project_id |否| | integer|fork仓库ID| +|reviewer_ids |否| | array |审查人员id数组| +|assigned_to_id |否| | integer|指派人员ID| +|fixed_version_id |否| | integer|里程碑ID| +|issue_tag_ids |否| | array |标记ID数组| +|priority_id |否| | integer|优先级ID| +|receivers_login |否| | array |@人员的login| + +> 请求的JSON示例: + +```json +{ + "title": "324", + "assigned_to_id": "2", + "fixed_version_id": "", + "issue_tag_ids": [], + "priority_id": "2", + "body": "312", + "head": "new_branch_1", + "base": "master", + "is_original": false, + "fork_project_id": "", + "files_count": 1, + "commits_count": 1, + "reviewer_ids": [], + "receivers_login": [] +} +``` + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "响应成功", + "pull_request_id": 169, + "pull_request_number": 6, + "pull_request_status": 0, + "pull_request_head": "new_branch_1", + "pull_request_base": "master", + "pull_request_staus": "open", + "is_original": false, + "fork_project_id": null, + "fork_project_identifier": null, + "fork_project_user": null, + "reviewers": [ + "yystopf" + ], + "id": 266, + "name": "324", + "pr_time": "1分钟前", + "assign_user_name": "heh", + "assign_user_login": "yystopf", + "author_name": "heh", + "author_login": "yystopf", + "avatar_url": "system/lets/letter_avatars/2/H/188_239_142/120.png", + "priority": "正常", + "version": null, + "journals_count": 0, + "issue_tags": null +} +``` + + + +## 获取合并请求版本列表 +获取合并请求版本列表 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/versions.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/versions.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/pulls/:index/versions.json` ### 请求参数: 参数 | 必选 | 默认 | 类型 | 字段说明 --------- | ------- | ------- | -------- | ---------- |owner |是| |string |用户登录名 | |repo |是| |string |项目标识identifier | +|index |是|| int |合并请求序号| - +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |合并请求版本总数| +|versions.id |int |版本ID| +|versions.add_line_num |int |该版本新增行数| +|versions.del_line_num |int |该版本删除行数| +|versions.commits_count |int |该版本提交总数| +|versions.files_count |int |该版本提交文件总数| +|versions.base_commit_sha |string |目标commit ID| +|versions.head_commit_sha |string |源commit ID| +|versions.start_commit_sha|string |该版本起始commit ID| +|versions.created_time |int |版本创建时间| +|versions.updated_time |int |版本更新时间| > 返回的JSON示例: ```json { - "status": 0, - "message": "响应成功", - "open_count": 4, - "close_count": 51, - "merged_issues_size": 123, - "search_count": 4, - "limit": null, - "user_admin_or_member": true, - "user_admin_or_developer": true, - "project_name": "Gitlink", - "project_author_name": "Gitlink", - "issues": [ - { - "pull_request_id": 1189, - "pull_request_status": 0, - "pull_request_head": "develop", - "pull_request_base": "master", - "pull_request_staus": "open", - "is_original": false, - "fork_project_id": null, - "fork_project_identifier": null, - "fork_project_user": null, - "id": 51888, - "name": "FIx release v3.2.0", - "pr_time": "59分钟前", - "assign_user_name": "victor", - "assign_user_login": "moshenglv", - "author_name": "段甲生", - "author_login": "jasder", - "avatar_url": "images/avatars/User/36480?t=1615520120", - "priority": "正常", - "version": null, - "journals_count": 0, - "issue_tags": null - } - ] + "total_count": 1, + "versions": [ + { + "id": 33, + "add_line_num": 5, + "del_line_num": 2, + "commits_count": 31, + "files_count": 29, + "base_commit_sha": "4a277037093c1248e46d2946ee30b61cccdb9df9", + "head_commit_sha": "fa3b1cdc8e0727d0fb9c96d28c545867c39815b8", + "start_commit_sha": "e49b1fd335e093a440fcf35a21e050afd48ef932", + "created_time": 1658469499, + "updated_time": 1658469499 + } + ] } -``` \ No newline at end of file +``` + +## 获取合并请求版本Diff +获取合并请求版本Diff(支持获取单文件Diff) + +> 示例: + +```shell +curl -X GET \ +-d "filepath=ceshi_dir_1/new_file_1" \ +http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/versions/33/diff.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/versions/33/diff.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/pulls/:index/versions/:version_id/diff.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|index |是|| int |合并请求序号| +|version_id|是|| int |版本ID| +|filepath|否||string|文件路径| + +### 列表返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|file_nums|int|文件数量| +|total_addition|int|新增行数| +|total_deletion|int|删除行数| +|files.name|string|文件名称| +|files.oldname|string|文件修改前名称| +|files.addition|int|文件新增行数| +|files.deletion|int|文件删除行数| +|files.type|int|文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制| +|files.is_created|bool|是否为新建文件| +|files.is_deleted|bool|是否为删除文件| +|files.is_bin|bool|是否为二进制文件| +|files.is_lfs_file|bool|是否为LFS文件| +|files.is_renamed|bool|是否重命名| +|files.is_ambiguous|bool|| +|files.is_submodule|bool|是否为子模块| +|files.sections.file_name|string|文件名称| +|files.sections.name|string|| +|files.sections.lines.left_index|int|文件变动之前所在行数| +|files.sections.lines.right_index|int|文件变动之后所在行数| +|files.sections.lines.match|int|| +|files.sections.lines.type|int|文件变更类型| +|files.sections.lines.content|string|文件变更内容| +|files.sections.lines.section_path|string|文件路径| +|files.sections.lines.section_last_left_index|int|| +|files.sections.lines.section_last_right_index|int|| +|files.sections.lines.section_left_index|int|文件变更之前所在行数| +|files.sections.lines.section_right_index|int|文件变更之后所在行数(即:页面编辑器开始显示的行数)| +|files.sections.lines.section_left_hunk_size|int|文件变更之前的行数| +|files.sections.lines.section_right_hunk_size|int|文件变更之后的行数(及当前页面编辑器显示的总行数)| +|files.is_incomplete|bool|是否不完整| +|files.is_incomplete_line_too_long|bool|文件是否不完整是因为太长了| +|files.is_protected|bool|文件是否被保护| + +> 列表返回的JSON示例: + +```json +{ + "file_nums": 29, + "total_addition": 5, + "total_deletion": 2, + "files": [ + { + "name": "README.md", + "oldname": "README.md", + "addition": 1, + "deletion": 2, + "type": 2, + "is_created": false, + "is_deleted": false, + "is_bin": false, + "is_lfs_file": false, + "is_renamed": false, + "is_ambiguous": false, + "is_submodule": false, + "sections": [ + { + "file_name": "README.md", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": "@@ -1,2 +1 @@", + "section_path": "README.md", + "section_last_left_index": 0, + "section_last_right_index": 0, + "section_left_index": 1, + "section_right_index": 1, + "section_left_hunk_size": 2, + "section_right_hunk_size": 0 + }, + { + "left_index": 1, + "right_index": 0, + "match": 3, + "type": 3, + "content": "-# ceshi_commit" + }, + { + "left_index": 2, + "right_index": 0, + "match": -1, + "type": 3, + "content": "-" + }, + { + "left_index": 0, + "right_index": 1, + "match": 1, + "type": 2, + "content": "+adsa" + } + ] + }, + {} + ], + "is_incomplete": false, + "is_incomplete_line_too_long": false, + "is_protected": false + } + ] +} +``` + +### 单个文件返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|name|string|文件名称| +|oldname|string|文件修改前名称| +|addition|int|文件新增行数| +|deletion|int|文件删除行数| +|type|int|文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制| +|is_created|bool|是否为新建文件| +|is_deleted|bool|是否为删除文件| +|is_bin|bool|是否为二进制文件| +|is_lfs_file|bool|是否为LFS文件| +|is_renamed|bool|是否重命名| +|is_ambiguous|bool|| +|is_submodule|bool|是否为子模块| +|sections.file_name|string|文件名称| +|sections.name|string|| +|sections.lines.left_index|int|文件变动之前所在行数| +|sections.lines.right_index|int|文件变动之后所在行数| +|sections.lines.match|int|| +|sections.lines.type|int|文件变更类型| +|sections.lines.content|string|文件变更内容| +|sections.lines.section_path|string|文件路径| +|sections.lines.section_last_left_index|int|| +|sections.lines.section_last_right_index|int|| +|sections.lines.section_left_index|int|文件变更之前所在行数| +|sections.lines.section_right_index|int|文件变更之后所在行数(即:页面编辑器开始显示的行数)| +|sections.lines.section_left_hunk_size|int|文件变更之前的行数| +|sections.lines.section_right_hunk_size|int|文件变更之后的行数(及当前页面编辑器显示的总行数)| +|is_incomplete|bool|是否不完整| +|is_incomplete_line_too_long|bool|文件是否不完整是因为太长了| +|is_protected|bool|文件是否被保护| + +> 单个文件返回的JSON示例: + +```json +{ + "name": "README.md", + "oldname": "README.md", + "addition": 1, + "deletion": 2, + "type": 2, + "is_created": false, + "is_deleted": false, + "is_bin": false, + "is_lfs_file": false, + "is_renamed": false, + "is_ambiguous": false, + "is_submodule": false, + "sections": [ + { + "file_name": "README.md", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": "@@ -1,2 +1 @@", + "section_path": "README.md", + "section_last_left_index": 0, + "section_last_right_index": 0, + "section_left_index": 1, + "section_right_index": 1, + "section_left_hunk_size": 2, + "section_right_hunk_size": 0 + }, + { + "left_index": 1, + "right_index": 0, + "match": 3, + "type": 3, + "content": "-# ceshi_commit" + }, + { + "left_index": 2, + "right_index": 0, + "match": -1, + "type": 3, + "content": "-" + }, + { + "left_index": 0, + "right_index": 1, + "match": 1, + "type": 2, + "content": "+adsa" + } + ] + }, + { + "file_name": "README.md", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": " ", + "section_path": "README.md", + "section_last_left_index": 0, + "section_last_right_index": 1, + "section_left_index": 3, + "section_right_index": 2, + "section_left_hunk_size": 0, + "section_right_hunk_size": 0 + } + ] + } + ], + "is_incomplete": false, + "is_incomplete_line_too_long": false, + "is_protected": false +} +``` + +## 获取合并请求审查列表 +获取合并请求版本审查列表 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/reviews.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/reviews.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/pulls/:index/reviews.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|index |是| | int |合并请求序号| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |审查总数| +|reviews.reviewer |object |审查者 | +|reviews.pull_request.id |integer|合并请求ID| +|reviews.pull_request.title |string|合并请求标题| +|reviews.pull_request.body |string|合并请求内容| +|reviews.pull_request.head |string|合并请求源分支| +|reviews.pull_request.base |string|合并请求目标分支| +|reviews.pull_request.is_original |string|合并请求是否从fork仓库所来| +|reviews.pull_request.fork_project.id |int|fork仓库的id| +|reviews.pull_request.fork_project.identifier|string|fork仓库的标识| +|reviews.pull_request.fork_project.login |string|fork仓库拥有者的标识| +|reviews.pull_request.index |string|合并请求的序号| +|reviews.pull_request.status |string|合并请求的状态,open: 打开的, merged: 合并的, closed: 关闭的| +|reviews.pull_request.issue.id |integer|合并请求下疑修的ID| +|reviews.pull_request.issue.author |object|合并请求以及疑修的创建着| +|reviews.pull_request.issue.priority |string|疑修的优先级| +|reviews.pull_request.issue.version |string|疑修的里程碑| +|reviews.pull_request.issue.journals_count|integer|普通评论数量| +|reviews.pull_request.issue.issue_tags |array|所属标记| +|reviews.pull_request.journals_count |integer|审查评论数量| +|reviews.id |integer|审查ID| +|reviews.commit_id |string|审查的commit ID| +|reviews.content |string|审查的内容| +|reviews.status |string|审查类型,common: 普通, approved: 通过,rejected: 拒绝通过| +|reviews.created_at |string|审查创建时间| + +> 返回的JSON示例: + +```json +{ + "total_count": 1, + "reviews": [ + { + "reviewer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "pull_request": { + "id": 163, + "title": "新合并请求1", + "body": null, + "head": "master_1", + "base": "master", + "is_original": false, + "index": 1, + "status": "closed", + "issue": { + "id": 260, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "reviewers": [], + "journals_count": 8 + }, + "id": 5, + "commit_id": null, + "content": "新建一个审查", + "status": "common", + "created_at": "2022-07-25 17:08" + } + ] +} +``` + +## 为合并请求创建一个审查 +合并请求创建一个审查 + +> 示例: + +```shell +curl -X POST \ +http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/reviews.json +``` + +```javascript +await octokit.request('POST /api/v1/yystopf/ceshi/pulls/1/reviews.json') +``` + +### HTTP 请求 +`POST /api/v1/:owner/:repo/pulls/:index/reviews.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|index |是| | integer|合并请求序号| +|content |否| | string |审查内容| +|commit_id |否| | string |当前合并请求的commit_id| +|status |是| | string |审查类型, common: 普通, approved: 通过, rejected: 拒绝| + +> 请求的JSON示例: + +```json +{ + "content": "新建一个审查", + "commit_id": "e506844b2467ce25a35dd46dad8236a1595a02da", + "status": "common" +} +``` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|reviewer |object |审查者 | +|pull_request.id |integer|合并请求ID| +|pull_request.title |string|合并请求标题| +|pull_request.body |string|合并请求内容| +|pull_request.head |string|合并请求源分支| +|pull_request.base |string|合并请求目标分支| +|pull_request.is_original |string|合并请求是否从fork仓库所来| +|pull_request.fork_project.id |int|fork仓库的id| +|pull_request.fork_project.identifier|string|fork仓库的标识| +|pull_request.fork_project.login |string|fork仓库拥有者的标识| +|pull_request.index |string|合并请求的序号| +|pull_request.status |string|合并请求的状态,open: 打开的, merged: 合并的, closed: 关闭的| +|pull_request.issue.id |integer|合并请求下疑修的ID| +|pull_request.issue.author |object|合并请求以及疑修的创建着| +|pull_request.issue.priority |string|疑修的优先级| +|pull_request.issue.version |string|疑修的里程碑| +|pull_request.issue.journals_count|integer|普通评论数量| +|pull_request.issue.issue_tags |array|所属标记| +|pull_request.journals_count |integer|审查评论数量| +|id |integer|审查ID| +|commit_id |string|审查的commit ID| +|content |string|审查的内容| +|status |string|审查类型,common: 普通, approved: 通过,rejected: 拒绝通过| +|created_at |string|审查创建时间| + +> 返回的JSON示例: + +```json +{ + "reviewer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "pull_request": { + "id": 163, + "head": "master_1", + "base": "master", + "is_original": false, + "index": 1, + "status": "closed", + "issue": { + "id": 260, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "journals_count": 6 + }, + "id": 10, + "commit_id": "e506844b2467ce25a35dd46dad8236a1595a02da", + "content": "新建一个审查", + "status": "common", + "created_at": "2022-07-26 11:45" +} +``` + + + +## 获取合并请求评论列表 +获取合并请求版本评论列表 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/journals.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/journals.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/pulls/:index/journals.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|index |是| | int |合并请求序号| +|keyword |否| |string |搜索关键词| +|review_id |否| |integer|审查ID| +|need_respond |否| |bool |是否需要回应| +|state |否| |string |状态, opened: 开启的, resolved: 已解决的, disabled: 无效的| +|parent_id |否| |integer|父评论ID| +|sort_by |否|created_on|string |排序字段 created_on: 创建时间, updated_on: 更新时间| +|sort_direction |否|asc |string |排序类型 desc: 倒序, asc: 正序| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |评论总数| +|journals.id |int |评论ID| +|journals.notes |string |评论内容| +|journals.commit_id |string |CommitID| +|journals.line_code |string |评论行数| +|journals.path |string |评论文件路径| +|journals.diff |object |评论文件diff内容| +|journals.need_respond |bool |评论是否要回应| +|journals.state |string |评论状态,opened: 开启的, resolved: 已解决的, disabled: 无效的 | +|journals.parent_id |int |父评论ID| +|journals.user |object |评论创建者| +|journals.review |object |评论所属评审| +|journals.resolveer |object |评论解决者| +|journals.resolve_at |int |评论解决时间| +|journals.created_at |int |评论创建时间| +|journals.updated_at |int |评论更新时间| + +> 返回的JSON示例: + +```json +{ + "total_count": 1, + "journals": [ + { + "id": 200, + "note": "测试评论修改", + "commit_id": null, + "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29", + "path": "Gemfile.lock", + "diff": {}, + "need_respond": true, + "state": "resolved", + "parent_id": nil, + "user": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "review": { + "reviewer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "pull_request": { + "id": 163, + "title": "新合并请求1", + "body": null, + "head": "master_1", + "base": "master", + "is_original": false, + "index": 1, + "status": "closed", + "issue": { + "id": 260, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "reviewers": [], + "journals_count": 9 + }, + "id": 10, + "commit_id": "1", + "content": "新建一个审查", + "status": "common", + "created_at": "2022-07-26 11:45" + }, + "resolveer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "resolve_at": "2022-07-27 14:50", + "created_at": "2022-07-27 14:31", + "updated_at": "2022-07-27 14:50" + } + ] +} +``` + +## 创建一个合并请求评论 +为仓库创建一个合并请求的评论 + +> 示例: + +```shell +curl -X POST \ +http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/journals.json +``` + +```javascript +await octokit.request('POST /api/v1/yystopf/ceshi/pulls/1/journals.json') +``` + +### HTTP 请求 +`POST /api/v1/:owner/:repo/pulls/:index/journals.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|index |是| | integer|合并请求序号| +|type |是| | string |评论类型 comment: 普通, problem: 需要回应的评论| +|note |否| | string |评论内容| +|review_id |是| | string |审查ID| +|line_code |否| | string |行号| +|commit_id |否| | bool |commitID| +|path |否| | integer|文件路径| +|parent_id |否| | integer|父评论ID| +|diff |否| | array |文件diff内容| + +> 请求的JSON示例: + +```json +{ + "type": "problem", + "note": "测试评论", + "review_id": "10", + "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29", + "commit_id": "70eede447ccc01c1902260fd377af5d90be28e0d", + "path": "Gemfile.lock", + "diff": { + "name": "README.md", + "oldname": "README.md", + "addition": 1, + "deletion": 2, + "type": 2, + "is_created": false, + "is_deleted": false, + "is_bin": false, + "is_lfs_file": false, + "is_renamed": false, + "is_ambiguous": false, + "is_submodule": false, + "sections": [ + { + "file_name": "README.md", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": "@@ -1,2 +1 @@", + "section_path": "README.md", + "section_last_left_index": 0, + "section_last_right_index": 0, + "section_left_index": 1, + "section_right_index": 1, + "section_left_hunk_size": 2, + "section_right_hunk_size": 0 + }, + { + "left_index": 1, + "right_index": 0, + "match": 3, + "type": 3, + "content": "-# ceshi_commit" + }, + { + "left_index": 2, + "right_index": 0, + "match": -1, + "type": 3, + "content": "-" + }, + { + "left_index": 0, + "right_index": 1, + "match": 1, + "type": 2, + "content": "+adsa" + } + ] + }, + { + "file_name": "README.md", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": " ", + "section_path": "README.md", + "section_last_left_index": 0, + "section_last_right_index": 1, + "section_left_index": 3, + "section_right_index": 2, + "section_left_hunk_size": 0, + "section_right_hunk_size": 0 + } + ] + } + ], + "is_incomplete": false, + "is_incomplete_line_too_long": false, + "is_protected": false + } +} +``` + +> 返回的JSON示例: + +```json +{ + "id": 200, + "note": "测试评论修改", + "commit_id": null, + "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29", + "path": "Gemfile.lock", + "diff": {}, + "need_respond": true, + "state": "resolved", + "user": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "review": { + "reviewer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "pull_request": { + "id": 163, + "title": "新合并请求1", + "body": null, + "head": "master_1", + "base": "master", + "is_original": false, + "index": 1, + "status": "closed", + "issue": { + "id": 260, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "reviewers": [], + "journals_count": 9 + }, + "id": 10, + "commit_id": "1", + "content": "新建一个审查", + "status": "common", + "created_at": "2022-07-26 11:45" + }, + "resolveer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "resolve_at": "2022-07-27 14:50", + "created_at": "2022-07-27 14:31", + "updated_at": "2022-07-27 14:50" +} +``` + + +## 修改一个合并请求评论 +修改一个仓库合并请求的评论 + +> 示例: + +```shell +curl -X PATCH \ +http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/journals/200.json +``` + +```javascript +await octokit.request('PATCH /api/v1/yystopf/ceshi/pulls/1/journals/200.json') +``` + +### HTTP 请求 +`PATCH /api/v1/:owner/:repo/pulls/:index/journals/:id.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|index |是| | integer|合并请求序号| +|id |是| | integer|评论ID| +|note |是| | string |评论内容| +|commit_id |是| | string |commitID| +|state |是| | string |评论状态, opened: 开启的, resolved: 已解决的, disabled: 无效的| + +> 请求的JSON示例: + +```json +{ + "note": "测试评论", + "commit_id": "70eede447ccc01c1902260fd377af5d90be28e0d", + "state": "resolved" +} +``` + +> 返回的JSON示例: + +```json +{ + "id": 200, + "note": "测试评论修改", + "commit_id": null, + "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29", + "path": "Gemfile.lock", + "diff": {}, + "need_respond": true, + "state": "resolved", + "user": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "review": { + "reviewer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "pull_request": { + "id": 163, + "title": "新合并请求1", + "body": null, + "head": "master_1", + "base": "master", + "is_original": false, + "index": 1, + "status": "closed", + "issue": { + "id": 260, + "author": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "priority": null, + "version": null, + "journals_count": 0, + "issue_tags": null + }, + "reviewers": [], + "journals_count": 9 + }, + "id": 10, + "commit_id": "1", + "content": "新建一个审查", + "status": "common", + "created_at": "2022-07-26 11:45" + }, + "resolveer": { + "id": 2, + "type": "User", + "name": "heh", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "resolve_at": "2022-07-27 14:50", + "created_at": "2022-07-27 14:31", + "updated_at": "2022-07-27 14:50" +} +``` + + +## 删除合并请求的一个评论 +删除合并请求的一个评论 + +> 示例: + +```shell +curl -X DELETE \ +http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/journals/200.json +``` + +```javascript +await octokit.request('DELETE /api/v1/yystopf/ceshi/pulls/1/journals/200.json') +``` + +### HTTP 请求 +`DELETE /api/v1/:owner/:repo/pulls/:index/journals/:id.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|index |是| | integer|合并请求序号| +|id |是| | integer|评论ID | + +### 返回字段说明: + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` + diff --git a/app/docs/slate/source/includes/_repositories.md b/app/docs/slate/source/includes/_repositories.md index ae74dac7f..a9fa42e2c 100644 --- a/app/docs/slate/source/includes/_repositories.md +++ b/app/docs/slate/source/includes/_repositories.md @@ -1126,21 +1126,21 @@ await octokit.request('POST /api/v1/yystopf/ceshi/contents/batch.json') ### 请求参数: 参数 | 必选 | 默认 | 类型 | 字段说明 --------- | ------- | ------- | -------- | ---------- -|owner |是| |string |用户登录名 | -|repo |是| |string |项目标识identifier | -|files.action_type |是| |string|操作类型 create: 创建 update: 更新 delete: 删除| -|files.content |是| |string|文件内容| -|files.encoding |是| |string|文件编码方式 text 文本 base64 加密| -|files.file_path |是| |string|文件路径| -|author_email |是| |string|作者邮箱| -|author_name |是| |string|作者名称| -|author_timeunix |是| |int|编码时间,精确到秒| -|committer_email |是| |string|提交者邮箱| -|committer_name |是| |string|提交者名称| -|committer_timeunix|是| |int|提交时间戳,精确到秒| -|branch |是| |string|提交分支| -|new_branch |否| |string|如果需要创建新分支,这个需要填| -|message |是| |string|提交信息| +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|files.action_type |是| |string|操作类型 create: 创建 update: 更新 delete: 删除| +|files.content |是| |string|文件内容| +|files.encoding |是| |string|文件编码方式 text 文本 base64 加密| +|files.file_path |是| |string|文件路径| +|author_email |否| 当前用户邮箱 |string|作者邮箱,不填时需要与作者名称同时为空| +|author_name |否| 当前用户标识 |string|作者名称,不填时需要与作者邮箱同时为空| +|author_timeunix |否| 当前时间戳 |int|编码时间,精确到秒| +|committer_email |否| 当前用户邮箱 |string|提交者邮箱,不填时需要与提交者名称同时为空| +|committer_name |否| 当前用户标识 |string|提交者名称,不填时需要与提交者邮箱同时为空| +|committer_timeunix|否| 当前时间戳 |int|提交时间戳,精确到秒| +|branch |是| |string|提交分支| +|new_branch |否| |string|如果需要创建新分支,这个需要填| +|message |是| |string|提交信息| > 请求的JSON示例: @@ -1990,25 +1990,27 @@ await octokit.request('GET /api/v1/yystopf/csfjkkj/compare.json') |diff.files.is_created|bool|是否为新建文件| |diff.files.is_deleted|bool|是否为删除文件| |diff.files.is_bin|bool|是否为二进制文件| -|diff.files.is_lfs_file|bool|| +|diff.files.is_lfs_file|bool|是否为LFS文件| |diff.files.is_renamed|bool|是否重命名| |diff.files.is_ambiguous|bool|| |diff.files.is_submodule|bool|是否为子模块| |diff.files.sections.file_name|string|文件名称| |diff.files.sections.name|string|| -|diff.files.sections.lines.left_index|int|| -|diff.files.sections.lines.right_index|int|| +|diff.files.sections.lines.left_index|int|文件变动之前所在行数| +|diff.files.sections.lines.right_index|int|文件变动之后所在行数| |diff.files.sections.lines.match|int|| -|diff.files.sections.lines.type|int|| -|diff.files.sections.lines.content|string|| -|diff.files.sections.lines.section_path|string|| +|diff.files.sections.lines.type|int|文件变更类型| +|diff.files.sections.lines.content|string|文件变更内容| +|diff.files.sections.lines.section_path|string|文件路径| |diff.files.sections.lines.section_last_left_index|int|| |diff.files.sections.lines.section_last_right_index|int|| -|diff.files.sections.lines.section_left_index|int|| -|diff.files.sections.lines.section_right_index|int|| -|diff.files.sections.lines.section_left_hunk_size|int|| -|diff.files.sections.lines.section_right_hunk_size|int|| - +|diff.files.sections.lines.section_left_index|int|文件变更之前所在行数| +|diff.files.sections.lines.section_right_index|int|文件变更之后所在行数(即:页面编辑器开始显示的行数)| +|diff.files.sections.lines.section_left_hunk_size|int|文件变更之前的行数| +|diff.files.sections.lines.section_right_hunk_size|int|文件变更之后的行数(及当前页面编辑器显示的总行数)| +|diff.files.is_incomplete|bool|是否不完整| +|diff.files.is_incomplete_line_too_long|bool|文件是否不完整是因为太长了| +|diff.files.is_protected|bool|文件是否被保护| > 返回的JSON示例: diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 0dcb6ca12..5bed0950c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -63,6 +63,7 @@ module ProjectsHelper project_category_id: project.project_category_id, project_language_id: project.project_language_id, license_id: project.license_id, + jianmu_devops: jianmu_devops_code(project, user), ignore_id: project.ignore_id }).compact @@ -98,4 +99,40 @@ module ProjectsHelper def render_educoder_avatar_url(project_educoder) [Rails.application.config_for(:configuration)['educoder']['cdn_url'], project_educoder&.image_url].join('/') end + + # 静默登录方式: + # + # 数据格式为JSON: + # { + # "userId": "xxx", // 用户唯一标识 + # "ref": "xxx", // 仓库唯一标识 + # "owner": "xxx", // 用户登录名或组织账号 + # "timestamp": xxx // 当前时间戳,单位:毫秒 + # } + # 加密方式:把数据序列化成JSON字符串,用Client Secret和固定IV(5183666c72eec9e4)对称加密(模式:AES-256-CBC) + # + # API: + # GET:https://ci-v3.test.jianmuhub.com/oauth2/authorize?code=${encode(密文)} + def jianmu_devops_code(project, user) + if user.admin? || project.member?(user.id) + data = { userId: user.id, ref: project.identifier, owner: project.owner.login, timestamp: Time.now.to_i * 1000 } + # uid = EduSetting.get("jianmu_oauth2_uid") || 'oedKx4v-WyAfu2oy_AsFpFQCH_-g91ms0PQKN7YcEuw' + # app = Doorkeeper::Application.find_by(uid: uid) + key = 'bf3c199c2470cb477d907b1e0917c17b' + aes_encrypt(key, data.to_json) + end + end + + def aes_encrypt(key, des_text) + # des_text='{"access_key_id":"STS.NTuC9RVmWfJqj3JkcMzPnDf7X","access_key_secret":"E8NxRZWGNxxMfwgt5nFLnBFgg6AzgXCZkSNCyqygLuHM","end_point":"oss-accelerate.aliyuncs.com","security_token":"CAIS8gF1q6Ft5B2yfSjIr5fACIPmu7J20YiaaBX7j2MYdt9Cq6Ocujz2IHhMenVhA+8Wv/02n2hR7PcYlq9IS55VWEqc/VXLaywQo22beIPkl5Gfz95t0e+IewW6Dxr8w7WhAYHQR8/cffGAck3NkjQJr5LxaTSlWS7OU/TL8+kFCO4aRQ6ldzFLKc5LLw950q8gOGDWKOymP2yB4AOSLjIx6lAt2T8vs/7hmZPFukSFtjCglL9J/baWC4O/csxhMK14V9qIx+FsfsLDqnUIs0YWpf0p3P0doGyf54vMWUM05A6dduPS7txkLAJwerjVl1/ADxc0/hqAASXhPeiktbmDjwvnSn4iKcSGQ+xoQB468eHXNdvf13dUlbbE1+JhRi0pZIB2UCtN9oTsLHcwIHt+EJaoMd3+hGwPVmvHSXzECDFHylZ8l/pzTwlE/aCtZyVmI5cZEvmWu2xBa3GRbULo7lLvyeX1cHTVmVWf4Nk6D09PzTU8qlAj","bucket":"edu-bigfiles1","region":"oss-cn-hangzhou","callback_url":"https://data.educoder.net/api/buckets/callback.json","bucket_host":"data.educoder.net"}' + # des = OpenSSL::Cipher::Cipher.new('aes-256-ctr') + des = OpenSSL::Cipher.new('AES-256-CBC') + des.encrypt + # des.padding = + des.key = key + des.iv = "5183666c72eec9e4" + result = des.update(des_text) + result << des.final + Base64.strict_encode64 result + end end diff --git a/app/libs/custom_regexp.rb b/app/libs/custom_regexp.rb index e778c5499..889da4df8 100644 --- a/app/libs/custom_regexp.rb +++ b/app/libs/custom_regexp.rb @@ -1,6 +1,6 @@ module CustomRegexp PHONE = /1\d{10}/ - EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/ + EMAIL = /\A[a-zA-Z0-9]+([._\-\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/ LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ #只含有数字、字母、下划线不能以下划线开头和结尾 LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/ NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/ diff --git a/app/models/issue.rb b/app/models/issue.rb index 9e167b5ec..a691f9e11 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -69,7 +69,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..e0dbf36d3 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -13,6 +13,15 @@ # comments_count :integer default("0") # reply_id :integer # review_id :integer +# commit_id :string(255) +# diff :text(4294967295) +# line_code :string(255) +# path :string(255) +# state :integer default("0") +# resolve_at :datetime +# resolveer_id :integer +# need_respond :boolean default("0") +# updated_on :datetime # # Indexes # @@ -24,8 +33,13 @@ # class Journal < ApplicationRecord + serialize :diff, JSON + alias_attribute :note, :notes 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 + belongs_to :review, optional: true + belongs_to :resolveer, class_name: 'User', foreign_key: :resolveer_id, optional: true has_many :journal_details, :dependent => :delete_all has_many :attachments, as: :container, dependent: :destroy @@ -33,6 +47,7 @@ class Journal < ApplicationRecord scope :parent_journals, ->{where(parent_id: nil)} scope :children_journals, lambda{|journal_id| where(parent_id: journal_id)} + enum state: {opened: 0, resolved: 1, disabled: 2} def is_journal_detail? self.notes.blank? && self.journal_details.present? diff --git a/app/models/mark_file.rb b/app/models/mark_file.rb new file mode 100644 index 000000000..c6c834623 --- /dev/null +++ b/app/models/mark_file.rb @@ -0,0 +1,5 @@ +class MarkFile < ApplicationRecord + belongs_to :pull_request + + +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/pull_request.rb b/app/models/pull_request.rb index a9f215c8d..270e7dc76 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -32,12 +32,18 @@ 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_id, 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 + has_many :mark_files, dependent: :destroy 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/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/models/review.rb b/app/models/review.rb index f2d3e678d..efb508139 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -2,24 +2,24 @@ # # 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 - 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/contents/batch_create_service.rb b/app/services/api/v1/projects/contents/batch_create_service.rb index d987f9318..92bd30a99 100644 --- a/app/services/api/v1/projects/contents/batch_create_service.rb +++ b/app/services/api/v1/projects/contents/batch_create_service.rb @@ -13,7 +13,6 @@ class Api::V1::Projects::Contents::BatchCreateService < ApplicationService def initialize(project, params, token=nil) - puts params @project = project @owner = project&.owner.login @repo = project&.identifier @@ -21,11 +20,11 @@ class Api::V1::Projects::Contents::BatchCreateService < ApplicationService @files = params[:files] @author_email = params[:author_email] @author_name = params[:author_name] - @author_timeunix = params[:author_timeunix] + @author_timeunix = params[:author_timeunix] || Time.now.to_i @branch = params[:branch] @committer_email = params[:committer_email] @committer_name = params[:committer_name] - @committer_timeunix = params[:committer_timeunix] + @committer_timeunix = params[:committer_timeunix] || Time.now.to_i @message = params[:message] @new_branch = params[:new_branch] end @@ -63,6 +62,7 @@ class Api::V1::Projects::Contents::BatchCreateService < ApplicationService committer: Time.at(committer_timeunix.to_i) }, message: message, + branch: branch, new_branch: new_branch, signoff: false } @@ -77,15 +77,16 @@ class Api::V1::Projects::Contents::BatchCreateService < ApplicationService end def excute_data_to_gitea + puts request_body.to_json @gitea_data = $gitea_client.post_repos_contents_batch_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil - raise Error, '创建文件失败!' unless @gitea_data.is_a?(Hash) + raise Error, '提交文件失败!' unless @gitea_data.is_a?(Hash) end def check_branch_exist result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params} ) rescue nil raise Error, '查询分支名称失败!' unless result.is_a?(Hash) raise Error, '分支不存在!' unless result['branch_name'].include?(branch) - raise Error, '分支已存在!' if result['branch_name'].include?(new_branch) && new_branch.nil? + raise Error, '分支已存在!' if result['branch_name'].include?(new_branch) && !new_branch.nil? end end \ No newline at end of file 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/services/api/v1/projects/pulls/journals/create_service.rb b/app/services/api/v1/projects/pulls/journals/create_service.rb new file mode 100644 index 000000000..45b5ec030 --- /dev/null +++ b/app/services/api/v1/projects/pulls/journals/create_service.rb @@ -0,0 +1,48 @@ +class Api::V1::Projects::Pulls::Journals::CreateService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :pull_request, :issue, :parent_id, :line_code, :note, :commit_id, :path, :type, :diff, :review_id, :user + attr_accessor :journal + + validates :type, inclusion: {in: %w(comment problem), message: '请输入正确的Type'} + + def initialize(project, pull_request, params, user) + @project = project + @pull_request = pull_request + @issue = pull_request&.issue + @parent_id = params[:parent_id] + @line_code = params[:line_code] + @note = params[:note] + @commit_id = params[:commit_id] + @path = params[:path] + @type = params[:type] + @diff = params[:diff] + @review_id = params[:review_id] + @user = user + end + + def call + raise Error, errors.full_messages.join(", ") unless valid? + check_review_is_exists + if type == 'problem' + create_problem_journal + else + create_comment_journal + end + + journal + end + + private + def create_comment_journal + @journal = pull_request.journals.create!(user_id: user&.id, notes: note, parent_id: parent_id, review_id: review_id, commit_id: commit_id, diff: diff, line_code: line_code, path: path) + end + + def check_review_is_exists + raise Error, '合并请求审查不存在!' unless @pull_request.reviews.exists?(review_id) + end + + def create_problem_journal + @journal = pull_request.journals.create!(user_id: user&.id, notes: note, parent_id: parent_id, review_id: review_id, commit_id: commit_id, diff: diff, line_code: line_code, path: path, need_respond: true) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/pulls/journals/list_service.rb b/app/services/api/v1/projects/pulls/journals/list_service.rb new file mode 100644 index 000000000..30b650f07 --- /dev/null +++ b/app/services/api/v1/projects/pulls/journals/list_service.rb @@ -0,0 +1,51 @@ +class Api::V1::Projects::Pulls::Journals::ListService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :pull_request, :keyword, :review_id, :need_respond, :state, :parent_id, :sort_by, :sort_direction, :user + attr_accessor :queried_journals + + validates :sort_by, inclusion: {in: Journal.column_names, message: '请输入正确的SortBy'} + validates :sort_direction, inclusion: {in: %w(asc desc), message: '请输入正确的SortDirection'} + validates :need_respond, inclusion: {in: [true, false], message: '请输入正确的NeedRespond'}, allow_nil: true + validates :state, inclusion: {in: %w(opened resolved disabled)}, allow_nil: true + + def initialize(project, pull_request, params, user) + @project = project + @pull_request = pull_request + @keyword = params[:keyword] + @review_id = params[:review_id] + @need_respond = ActiveModel::Type::Boolean.new.cast(params[:need_respond]) + @state = params[:state] + @parent_id = params[:parent_id] + @sort_by = params[:sort_by] || 'created_on' + @sort_direction = params[:sort_direction] || 'asc' + @user = user + end + + def call + raise Error, errors.full_messages.join(",") unless valid? + journal_query_data + + queried_journals + end + + private + def journal_query_data + journals = @pull_request.journals + if parent_id.present? + journals = journals.where(parent_id: parent_id) + else + journals = journals.parent_journals + end + + journals = journals.where(review_id: review_id) if review_id.present? + journals = journals.where(need_respond: need_respond) if need_respond.present? + journals = journals.where(state: state) if state.present? + + q = journals.ransack(notes_cont: keyword) + scope = q.result.includes(:user, :resolveer, review: [:reviewer, pull_request: :issue]) + scope = scope.order("journals.#{sort_by} #{sort_direction}") + + @queried_journals = scope + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/pulls/journals/update_service.rb b/app/services/api/v1/projects/pulls/journals/update_service.rb new file mode 100644 index 000000000..fec4c7ff8 --- /dev/null +++ b/app/services/api/v1/projects/pulls/journals/update_service.rb @@ -0,0 +1,38 @@ +class Api::V1::Projects::Pulls::Journals::UpdateService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :pull_request, :journal, :note, :commit_id, :state, :user + attr_accessor :updated_journal + + validates :state, inclusion: {in: %w(opened resolved disabled)} + + def initialize(project, pull_request, journal, params, user) + @project = project + @pull_request = pull_request + @journal = journal + @note = params[:note] + @commit_id = params[:commit_id] + @state = params[:state] + @user = user + end + + def call + raise Error, errors.full_messages.join(", ") unless valid? + + update_journal + + updated_journal + end + + private + def update_journal + journal.attributes = {notes: note, commit_id: commit_id, state: state} + if state == 'resolved' + journal.resolve_at = Time.now + journal.resolveer_id = user.id + end + return Error, '保存评论失败!' unless journal.save + + @updated_journal = journal.reload + 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..def8a86ba --- /dev/null +++ b/app/services/api/v1/projects/pulls/list_service.rb @@ -0,0 +1,48 @@ +class Api::V1::Projects::Pulls::ListService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :keyword, :status, :priority_id, :issue_tag_id, :version_id, :reviewer_id, :assign_user_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].present? ? params[:status].to_i : nil + @priority_id = params[:priority_id] + @issue_tag_id = params[:issue_tag_id] + @version_id = params[:version_id] + @reviewer_id = params[:reviewer_id] + @assign_user_id = params[:assign_user_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? + pull_requests = pull_requests.where(issues: {assigned_to_id: assign_user_id}) if assign_user_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/services/api/v1/projects/pull_requests/reviews/create_service.rb b/app/services/api/v1/projects/pulls/reviews/create_service.rb similarity index 61% rename from app/services/api/v1/projects/pull_requests/reviews/create_service.rb rename to app/services/api/v1/projects/pulls/reviews/create_service.rb index c003256dc..1c45d9cf2 100644 --- a/app/services/api/v1/projects/pull_requests/reviews/create_service.rb +++ b/app/services/api/v1/projects/pulls/reviews/create_service.rb @@ -1,4 +1,4 @@ -class Api::V1::Projects::PullRequests::Reviews::CreateService < ApplicationService +class Api::V1::Projects::Pulls::Reviews::CreateService < ApplicationService include ActiveModel::Model attr_reader :project, :pull_request, :issue, :status, :commit_id, :content, :current_user @@ -20,21 +20,18 @@ class Api::V1::Projects::PullRequests::Reviews::CreateService < ApplicationServi raise Error, errors.full_messages.join(", ") unless valid? ActiveRecord::Base.transaction do create_review - create_journal + # create_journal end - return @journal, @review - rescue - raise Error, '服务器错误,请联系系统管理员!' + @review + # 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) - end end \ No newline at end of file diff --git a/app/services/api/v1/projects/pulls/versions/get_diff_service.rb b/app/services/api/v1/projects/pulls/versions/get_diff_service.rb new file mode 100644 index 000000000..1a4f144af --- /dev/null +++ b/app/services/api/v1/projects/pulls/versions/get_diff_service.rb @@ -0,0 +1,35 @@ +class Api::V1::Projects::Pulls::Versions::GetDiffService < ApplicationService + + attr_reader :project, :pull_request, :version_id, :owner, :repo, :index, :filepath, :token + attr_accessor :gitea_data + + def initialize(project, pull_request, version_id, params, token=nil) + @project = project + @pull_request = pull_request + @version_id = version_id + @owner = project&.owner.login + @repo = project&.identifier + @index = pull_request.gitea_number + @filepath = params[:filepath] + @token = token + end + + def call + load_gitea_data + + gitea_data + end + + private + def request_params + params = { + access_token: token + } + params.merge!(filepath: filepath) if filepath.present? + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_pulls_versions_diff_by_owner_repo_index_version_id(owner, repo, index, version_id, {query: request_params}) + raise Error, '获取合并请求版本diff失败!' unless @gitea_data.is_a?(Hash) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/pulls/versions/list_service.rb b/app/services/api/v1/projects/pulls/versions/list_service.rb new file mode 100644 index 000000000..ca88ff1f6 --- /dev/null +++ b/app/services/api/v1/projects/pulls/versions/list_service.rb @@ -0,0 +1,36 @@ +class Api::V1::Projects::Pulls::Versions::ListService < ApplicationService + + attr_reader :project, :pull_request, :token, :owner, :repo, :index, :page, :limit + attr_accessor :gitea_data + + def initialize(project, pull_request, params, token = nil) + @project = project + @pull_request = pull_request + @owner = project&.owner.login + @repo = project&.identifier + @page = params[:page] || 1 + @limit = params[:limit] || 15 + @index = pull_request.gitea_number + @token = token + end + + def call + load_gitea_data + + gitea_data + end + + private + def request_params + { + access_token: token, + page: page, + limit: limit + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_pulls_versions_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/services/api/v1/users/projects/list_service.rb b/app/services/api/v1/users/projects/list_service.rb index 9a095c60b..91e25a933 100644 --- a/app/services/api/v1/users/projects/list_service.rb +++ b/app/services/api/v1/users/projects/list_service.rb @@ -13,7 +13,7 @@ class Api::V1::Users::Projects::ListService < ApplicationService def initialize(observe_user, params, current_user=nil) @observe_user = observe_user @category = params[:category] || 'all' - @is_public = params[:is_public] + @is_public = ActiveModel::Type::Boolean.new.cast(params[:is_public]) @project_type = params[:project_type] @sort_by = params[:sort_by] || 'updated_on' @sort_direction = params[:sort_direction] || 'desc' diff --git a/app/services/gitea/repository/languages/list_service.rb b/app/services/gitea/repository/languages/list_service.rb index 88d5dcbed..9c96d56ed 100644 --- a/app/services/gitea/repository/languages/list_service.rb +++ b/app/services/gitea/repository/languages/list_service.rb @@ -10,7 +10,7 @@ class Gitea::Repository::Languages::ListService < Gitea::ClientService def initialize(owner, repo, token) @owner = owner @repo = repo - @args = token + @token = token end def call diff --git a/app/services/issues/list_query_service.rb b/app/services/issues/list_query_service.rb index 73f0b438e..bed8c4837 100644 --- a/app/services/issues/list_query_service.rb +++ b/app/services/issues/list_query_service.rb @@ -15,6 +15,7 @@ class Issues::ListQueryService < ApplicationService end_time = params[:due_date] issues = all_issues.issue_index_includes + issues = issues.includes(pull_request: :reviewers) if status_type.to_s == "2" #表示关闭中的 issues = issues.where(status_id: 5) elsif status_type.to_s == "1" 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..5e93c70e8 --- /dev/null +++ b/app/services/ob_repository_sync/api_service.rb @@ -0,0 +1,168 @@ +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]}", + "gitlink_address": "#{params[:gitlink_address]}", + "gitlink_token": "#{params[:gitlink_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/services/trace/client_service.rb b/app/services/trace/client_service.rb index 0f1449225..137241a70 100644 --- a/app/services/trace/client_service.rb +++ b/app/services/trace/client_service.rb @@ -8,8 +8,11 @@ class Trace::ClientService < ApplicationService def authed_post(token, url, params={}) puts "[trace][POST] request params: #{params}" puts "[trace][POST] request token: #{token}" - conn.headers['Authorization'] = token - conn.post(full_url(url), params[:data]) + conn.post do |req| + req.url full_url(url, 'post') + req.headers['Authorization'] = token + req.body = params[:data].as_json + end end def http_authed_post(token, url, params={}) @@ -55,8 +58,11 @@ class Trace::ClientService < ApplicationService def authed_delete(token, url, params={}) puts "[trace][DELETE] request params: #{params}" puts "[trace][DELETE] request token: #{token}" - conn.headers['Authorization'] = token - conn.delete(full_url(url), params[:data]) + conn.delete do |req| + req.url full_url(url, 'delete') + req.headers['Authorization'] = token + req.body = params[:data].as_json + end end def patch(url, params={}) @@ -67,8 +73,11 @@ class Trace::ClientService < ApplicationService def authed_patch(token, url, params={}) puts "[trace][PATCH] request params: #{params}" puts "[trace][PATCH] request token: #{token}" - conn.headers['Authorization'] = token - conn.patch(full_url(url), params[:data]) + conn.patch do |req| + req.url full_url(url, 'patch') + req.headers['Authorization'] = token + req.body = params[:data].as_json + end end def put(url, params={}) @@ -79,8 +88,11 @@ class Trace::ClientService < ApplicationService def authed_put(token, url, params={}) puts "[trace][PUT] request params: #{params}" puts "[trace][PUT] request token: #{token}" - conn.headers['Authorization'] = token - conn.put(full_url(url), params[:data]) + conn.put do |req| + req.url full_url(url, 'put') + req.headers['Authorization'] = token + req.body = params[:data].as_json + end end def conn diff --git a/app/views/api/v1/projects/_simple_gitea_diff_file_detail.json.jbuilder b/app/views/api/v1/projects/_simple_gitea_diff_file_detail.json.jbuilder new file mode 100644 index 000000000..13f833338 --- /dev/null +++ b/app/views/api/v1/projects/_simple_gitea_diff_file_detail.json.jbuilder @@ -0,0 +1,35 @@ +json.name file['Name'] + json.oldname file['OldName'] + json.addition file['Addition'] + json.deletion file['Deletion'] + json.type file['Type'] + json.is_created file['IsCreated'] + json.is_deleted file['IsDeleted'] + json.is_bin file['IsBin'] + json.is_lfs_file file['IsLFSFile'] + json.is_renamed file['IsRenamed'] + json.is_ambiguous file['IsAmbiguous'] + json.is_submodule file['IsSubmodule'] + json.sections file['Sections'] do |section| + json.file_name section['FileName'] + json.name section['Name'] + json.lines section['Lines'] do |line| + json.left_index line['LeftIdx'] + json.right_index line['RightIdx'] + json.match line['Match'] + json.type line['Type'] + json.content line['Content'] + unless line['SectionInfo'].blank? + json.section_path line['SectionInfo']['Path'] + json.section_last_left_index line['SectionInfo']['LastLeftIdx'] + json.section_last_right_index line['SectionInfo']['LastRightIdx'] + json.section_left_index line['SectionInfo']['LeftIdx'] + json.section_right_index line['SectionInfo']['RightIdx'] + json.section_left_hunk_size line['SectionInfo']['LeftHunkSize'] + json.section_right_hunk_size line['SectionInfo']['RightHunkSize'] + end + end + end + json.is_incomplete file['IsIncomplete'] + json.is_incomplete_line_too_long file['IsIncompleteLineTooLong'] + json.is_protected file['IsProtected'] \ No newline at end of file diff --git a/app/views/api/v1/projects/contents/batch.json.jbuilder b/app/views/api/v1/projects/contents/batch.json.jbuilder index a9ef08fa6..fa41bfb9a 100644 --- a/app/views/api/v1/projects/contents/batch.json.jbuilder +++ b/app/views/api/v1/projects/contents/batch.json.jbuilder @@ -3,12 +3,16 @@ json.commit do json.authored_time render_unix_time(@result_object['commit']['author']['date']) json.commited_time render_unix_time(@result_object['commit']['committer']['date']) end -json.contents @result_object['contents'].each do |content| - json.name content['name'] - json.path content['path'] - json.sha content['sha'] - json.type content['type'] - json.size content['size'] - json.encoding content['encoding'] - json.content content['content'] +if @result_object['contents'].is_a?(Array) + json.contents @result_object['contents'].each do |content| + json.name content['name'] + json.path content['path'] + json.sha content['sha'] + json.type content['type'] + json.size content['size'] + json.encoding content['encoding'] + json.content content['content'] + end +else + json.contents [] 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/_simple_detail.json.jbuilder b/app/views/api/v1/projects/pulls/_simple_detail.json.jbuilder new file mode 100644 index 000000000..a4c3c03bc --- /dev/null +++ b/app/views/api/v1/projects/pulls/_simple_detail.json.jbuilder @@ -0,0 +1,26 @@ +json.(pull, :id, :title, :body, :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.journals_count issue.journals.count + json.issue_tags issue.get_issue_tags +end + +json.reviewers pull.reviewers.pluck(:login) +json.journals_count pull.journals.count \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/journals/_simple_detail.json.jbuilder b/app/views/api/v1/projects/pulls/journals/_simple_detail.json.jbuilder new file mode 100644 index 000000000..d418ffdcd --- /dev/null +++ b/app/views/api/v1/projects/pulls/journals/_simple_detail.json.jbuilder @@ -0,0 +1,21 @@ +json.(journal, :id, :note, :commit_id, :line_code, :path, :diff, :need_respond, :state, :parent_id) +json.user do + json.partial! 'api/v1/users/simple_user', user: journal.user +end +json.review do + if journal.review.present? + json.partial! 'api/v1/projects/pulls/reviews/simple_detail', review: journal.review + else + json.nil! + end +end +json.resolveer do + if journal.resolveer.present? + json.partial! 'api/v1/users/simple_user', user: journal.resolveer + else + json.nil! + end +end +json.resolve_at format_time(journal.resolve_at) +json.created_at format_time(journal.created_on) +json.updated_at format_time(journal.updated_on) \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/journals/create.json.jbuilder b/app/views/api/v1/projects/pulls/journals/create.json.jbuilder new file mode 100644 index 000000000..32bedbf8a --- /dev/null +++ b/app/views/api/v1/projects/pulls/journals/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/v1/projects/pulls/journals/simple_detail', journal: @journal \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/journals/index.json.jbuilder b/app/views/api/v1/projects/pulls/journals/index.json.jbuilder new file mode 100644 index 000000000..e71eb5f71 --- /dev/null +++ b/app/views/api/v1/projects/pulls/journals/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @journals.total_count +json.journals @journals.each do |journal| + json.partial! 'api/v1/projects/pulls/journals/simple_detail', journal: journal +end \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/journals/update.json.jbuilder b/app/views/api/v1/projects/pulls/journals/update.json.jbuilder new file mode 100644 index 000000000..32bedbf8a --- /dev/null +++ b/app/views/api/v1/projects/pulls/journals/update.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/v1/projects/pulls/journals/simple_detail', journal: @journal \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/pulls/index.json.jbuilder b/app/views/api/v1/projects/pulls/pulls/index.json.jbuilder new file mode 100644 index 000000000..412ea13d7 --- /dev/null +++ b/app/views/api/v1/projects/pulls/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 diff --git a/app/views/api/v1/projects/pulls/pulls/show.json.jbuilder b/app/views/api/v1/projects/pulls/pulls/show.json.jbuilder new file mode 100644 index 000000000..2553629ee --- /dev/null +++ b/app/views/api/v1/projects/pulls/pulls/show.json.jbuilder @@ -0,0 +1,30 @@ +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 +json.conflict_files @pull_request.conflict_files \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/reviews/_simple_detail.json.jbuilder b/app/views/api/v1/projects/pulls/reviews/_simple_detail.json.jbuilder new file mode 100644 index 000000000..1ded19d6a --- /dev/null +++ b/app/views/api/v1/projects/pulls/reviews/_simple_detail.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/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/app/views/api/v1/projects/pulls/reviews/index.json.jbuilder b/app/views/api/v1/projects/pulls/reviews/index.json.jbuilder new file mode 100644 index 000000000..04792d5c6 --- /dev/null +++ b/app/views/api/v1/projects/pulls/reviews/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @reviews.total_count +json.reviews @reviews.each do |review| + json.partial! 'api/v1/projects/pulls/reviews/simple_detail', review: review +end \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/versions/diff.json.jbuilder b/app/views/api/v1/projects/pulls/versions/diff.json.jbuilder new file mode 100644 index 000000000..9e2c3430d --- /dev/null +++ b/app/views/api/v1/projects/pulls/versions/diff.json.jbuilder @@ -0,0 +1,6 @@ + +if @result_object.has_key?("NumFiles") + json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object +else + json.partial! "api/v1/projects/simple_gitea_diff_file_detail", file: @result_object +end \ No newline at end of file diff --git a/app/views/api/v1/projects/pulls/versions/index.json.jbuilder b/app/views/api/v1/projects/pulls/versions/index.json.jbuilder new file mode 100644 index 000000000..4888c4f08 --- /dev/null +++ b/app/views/api/v1/projects/pulls/versions/index.json.jbuilder @@ -0,0 +1,13 @@ +json.total_count @result_object[:total_data].to_i +json.versions @result_object[:data].each do |version| + json.id version['id'] + json.add_line_num version['add_line_num'] + json.del_line_num version['del_line_num'] + json.commits_count version['commits_count'] + json.files_count version['files_count'] + json.base_commit_sha version['base_commit_sha'] + json.head_commit_sha version['head_commit_sha'] + json.start_commit_sha version['start_commit_sha'] + json.created_time render_unix_time(version['created_at']) + json.updated_time render_unix_time(version['updated_at']) +end \ No newline at end of file diff --git a/app/views/mark_files/index.json.jbuilder b/app/views/mark_files/index.json.jbuilder new file mode 100644 index 000000000..709be77b8 --- /dev/null +++ b/app/views/mark_files/index.json.jbuilder @@ -0,0 +1,13 @@ +json.status 0 +json.message 'success' +json.count @files_result['NumFiles'] +json.files do + json.array! @files_result['Files'] do |file| + mark_file = @mark_files.select{|mark| mark.file_path.to_s == file['Name']}.first + json.file_path_sha Base64.strict_encode64(file['Name'].to_s) + json.name file['Name'] + json.mark_as_read mark_file.present? ? mark_file.mark_as_read : false + # json.updated_after_read mark_file.present? ? mark_file.updated_after_read : false + end + +end diff --git a/app/views/oauth2/create.js.erb b/app/views/oauth2/create.js.erb new file mode 100644 index 000000000..8850124d8 --- /dev/null +++ b/app/views/oauth2/create.js.erb @@ -0,0 +1,7 @@ +<%if @error.present?%> +var alertDiv = $('
<%= @error[:msg]%>
') +$("#container").prepend(alertDiv) +setTimeout(function() { + $('.alert').remove(); +}, 3000); +<%end%> \ No newline at end of file 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/app/views/pull_requests/_detail.json.jbuilder b/app/views/pull_requests/_detail.json.jbuilder index 5c9347420..814c078ef 100644 --- a/app/views/pull_requests/_detail.json.jbuilder +++ b/app/views/pull_requests/_detail.json.jbuilder @@ -9,7 +9,7 @@ json.is_original pr.is_original json.fork_project_id pr&.fork_project_id json.fork_project_identifier pr&.fork_project&.identifier json.fork_project_user pr&.fork_project&.owner.try(:login) - +json.reviewers pr&.reviewers.pluck(:login) json.id issue.id json.name issue.subject diff --git a/app/views/pull_requests/edit.json.jbuilder b/app/views/pull_requests/edit.json.jbuilder index c6f41559c..683b1961c 100644 --- a/app/views/pull_requests/edit.json.jbuilder +++ b/app/views/pull_requests/edit.json.jbuilder @@ -12,3 +12,4 @@ json.issue_tag_ids @issue&.issue_tags_value&.split(",") json.commits_count @pull_request.commits_count json.files_count @pull_request.files_count json.comments_count @pull_request.comments_count +json.reviewers @pull_request.reviewers.pluck(:login) \ No newline at end of file diff --git a/app/views/pull_requests/index.json.jbuilder b/app/views/pull_requests/index.json.jbuilder index d37901ef8..ace52945c 100644 --- a/app/views/pull_requests/index.json.jbuilder +++ b/app/views/pull_requests/index.json.jbuilder @@ -24,7 +24,8 @@ json.issues do json.fork_project_identifier pr&.fork_project&.identifier json.fork_project_user pr&.fork_project&.owner.try(:login) json.fork_project_user_name pr&.fork_project&.owner.try(:show_real_name) - + json.reviewers pr.reviewers.pluck(:login) + json.id issue.id json.name issue.subject json.pr_time time_from_now(pr.status == 1 ? pr.updated_at : issue.updated_on) diff --git a/app/views/pull_requests/show.json.jbuilder b/app/views/pull_requests/show.json.jbuilder index 684a60e9c..27c393de5 100644 --- a/app/views/pull_requests/show.json.jbuilder +++ b/app/views/pull_requests/show.json.jbuilder @@ -30,6 +30,7 @@ json.pull_request do json.create_user @pull_request&.user&.login json.mergeable @gitea_pull["mergeable"] json.state @gitea_pull["state"] + json.reviewers @pull_request.reviewers.pluck(:login) end json.issue do diff --git a/config/routes.rb b/config/routes.rb index 7a6fa3c28..f7483666b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -556,7 +556,8 @@ Rails.application.routes.draw do post :refuse_merge get :files get :commits - resources :reviews, only: [:create] + resources :reviews, only: [:create] + resources :mark_files, only: [:index, :create] end collection do post :check_can_merge @@ -583,6 +584,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/config/routes/api.rb b/config/routes/api.rb index 81668804e..d5f82ff7b 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -19,7 +19,16 @@ defaults format: :json do # projects文件夹下的 scope module: :projects do resources :issues - resources :pull_requests + resources :pulls, module: 'pulls' do + resources :versions, only: [:index] do + member do + get :diff + end + end + resources :journals, except: [:show, :edit] + resources :reviews, only: [:index, :create] + end + resources :versions resources :release_versions resources :webhooks 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 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/db/migrate/20220726090342_add_line_code_to_journals.rb b/db/migrate/20220726090342_add_line_code_to_journals.rb new file mode 100644 index 000000000..9eb2e45e5 --- /dev/null +++ b/db/migrate/20220726090342_add_line_code_to_journals.rb @@ -0,0 +1,13 @@ +class AddLineCodeToJournals < ActiveRecord::Migration[5.2] + def change + add_column :journals, :commit_id, :string + add_column :journals, :diff, :text, :limit => 4294967295 + add_column :journals, :line_code, :string + add_column :journals, :path, :string + add_column :journals, :state, :integer, default: 0 + add_column :journals, :resolve_at, :datetime + add_column :journals, :resolveer_id, :integer, index: true + add_column :journals, :need_respond, :bool, default: false + add_column :journals, :updated_on, :datetime, index: true + end +end diff --git a/db/migrate/20220728022339_create_mark_files.rb b/db/migrate/20220728022339_create_mark_files.rb new file mode 100644 index 000000000..45f4b1cb3 --- /dev/null +++ b/db/migrate/20220728022339_create_mark_files.rb @@ -0,0 +1,15 @@ +class CreateMarkFiles < ActiveRecord::Migration[5.2] + def change + create_table :mark_files do |t| + t.references :pull_request + t.integer :user_id + t.string :file_path_sha + t.string :file_path + t.boolean :mark_as_read, default: false + t.boolean :updated_after_read, default: false + t.timestamps + end + + add_index :mark_files, :file_path_sha + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 80b1ebdcb..c8fae73ac 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -615,19 +615,46 @@ Pulls @@ -9157,43 +9184,43 @@ http://localhost:3000/api/v1/yystopf/ceshi/contents/batch.json author_email -是 - +否 +当前用户邮箱 string -作者邮箱 +作者邮箱,不填时需要与作者名称同时为空 author_name -是 - +否 +当前用户标识 string -作者名称 +作者名称,不填时需要与作者邮箱同时为空 author_timeunix -是 - +否 +当前时间戳 int 编码时间,精确到秒 committer_email -是 - +否 +当前用户邮箱 string -提交者邮箱 +提交者邮箱,不填时需要与提交者名称同时为空 committer_name -是 - +否 +当前用户标识 string -提交者名称 +提交者名称,不填时需要与提交者邮箱同时为空 committer_timeunix -是 - +否 +当前时间戳 int 提交时间戳,精确到秒 @@ -10806,7 +10833,7 @@ http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json diff.files.is_lfs_file bool - +是否为LFS文件 diff.files.is_renamed @@ -10836,12 +10863,12 @@ http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json diff.files.sections.lines.left_index int - +文件变动之前所在行数 diff.files.sections.lines.right_index int - +文件变动之后所在行数 diff.files.sections.lines.match @@ -10851,17 +10878,17 @@ http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json diff.files.sections.lines.type int - +文件变更类型 diff.files.sections.lines.content string - +文件变更内容 diff.files.sections.lines.section_path string - +文件路径 diff.files.sections.lines.section_last_left_index @@ -10876,22 +10903,37 @@ http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json diff.files.sections.lines.section_left_index int - +文件变更之前所在行数 diff.files.sections.lines.section_right_index int - +文件变更之后所在行数(即:页面编辑器开始显示的行数) diff.files.sections.lines.section_left_hunk_size int - +文件变更之前的行数 diff.files.sections.lines.section_right_hunk_size int - +文件变更之后的行数(及当前页面编辑器显示的总行数) + + +diff.files.is_incomplete +bool +是否不完整 + + +diff.files.is_incomplete_line_too_long +bool +文件是否不完整是因为太长了 + + +diff.files.is_protected +bool +文件是否被保护 @@ -12297,16 +12339,16 @@ http://localhost:3000/api/traces/yystopf/many_branch/task_pdf.json -

Pulls

Get a pull request

+

Pulls

获取一个合并请求

获取合并请求详情接口

示例:

-
curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls/88.json
-
await octokit.request('GET /api/Jasder/gitlink/pulls/88.json')
+
curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/1.json
+
await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/1.json')
 

HTTP 请求

-

GET /api/:owner/:repo/pulls/:id.json

+

GET /api/v1/:owner/:repo/pulls/:index.json

请求参数:

@@ -12332,11 +12374,190 @@ Success — a happy kitten is an authenticated kitten! - + - + + +
项目标识identifier
idindex integerpull id值pull 序号
+

返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
---
idint合并请求ID
titlestring合并请求标题
bodystring
headint合并请求源分支
baseint合并请求目标分支
indexint合并请求序号
statusstring合并请求状态,open: 开启的, merged: 合并的, closed: 关闭的
issue.idint疑修ID
issue.authorobject疑修作者
issue.prioritystring疑修优先级
issue.versionstring疑修里程碑
issue.journals_countint普通评论数量
issue.issue_tagsarray标记
journals_countint审查评论数量
merge_basestring目标的commit ID
base_commit_shastring合并之后的第一个commit ID
head_commit_shastring源commit ID
commit_numintcommit数量
changed_filesint更改文件数量
is_lockedbool
mergeablebool是否能合并
mergedbool是否合并
merged_atstring合并时间
merge_commit_shastring合并之后的第一个commit ID
merge_byobject被谁合并了
last_review.idint最后一个审查的id
last_review.commit_idstring最后一个审查对应的commit ID
last_review.contentstring最后一个审查的内容
last_review.statusstring最后一个审查的状态,common: 一般审查, approved: 通过, rejected: 拒绝通过
last_review.created_atstring审查创建的时间
last_review.reviewerobject审查创建人
reviewersarray指定审查用户标识数组
conflict_filesarray有冲突的文件
@@ -12344,52 +12565,65 @@ Success — a happy kitten is an authenticated kitten!

返回的JSON示例:

{
-    "status": 0,
-    "message": "响应成功",
-    "project_name": "Gitlink",
-    "identifier": "forgeplus",
-    "project_identifier": "forgeplus",
-    "pr_time": "52分钟前",
-    "commits_count": 229,
-    "files_count": 328,
-    "comments_count": 0,
-    "comments_total_count": 0,
-    "pull_request": {
-        "id": 1189,
-        "base": "master",
-        "head": "develop",
-        "status": 0,
-        "fork_project_id": null,
-        "is_original": false,
-        "pull_request_staus": "open",
-        "fork_project_user": null,
-        "create_user": "jasder",
-        "mergeable": true,
-        "state": "open"
-    },
+    "id": 168,
+    "head": "new_branch",
+    "base": "master",
+    "is_original": false,
+    "index": 5,
+    "status": "merged",
     "issue": {
-        "id": 51888,
-        "subject": "FIx release v3.2.0",
-        "description": null,
-        "is_private": false,
-        "branch_name": null,
-        "project_author_name": "Gitlink",
-        "closed_on": "",
-        "created_at": "2021-10-12 15:51",
-        "assign_user_name": "victor",
-        "assign_user_login": "moshenglv",
-        "author_name": "段甲生",
-        "author_login": "jasder",
-        "author_picture": "images/avatars/User/36480?t=1615520120",
-        "issue_status": "新增",
-        "priority": "正常",
+        "id": 265,
+        "author": {
+            "id": 2,
+            "type": "User",
+            "name": "heh",
+            "login": "yystopf",
+            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+        },
+        "priority": null,
         "version": null,
+        "journals_count": 1,
         "issue_tags": null
     },
+    "journals_count": 0,
+    "merge_base": "4a277037093c1248e46d2946ee30b61cccdb9df9",
+    "base_commit_sha": "dbb510cd852a6bfd4d71a1f84921aa3170654590",
+    "head_commit_sha": "0f0e27918eb5deb8d514012d84d13db10eebe19a",
+    "commit_num": 1,
+    "changed_files": 1,
+    "is_locked": false,
+    "mergeable": true,
+    "merged": true,
+    "merged_at": 1658743004,
+    "merge_commit_sha": "dbb510cd852a6bfd4d71a1f84921aa3170654590",
+    "merge_by": {
+        "id": null,
+        "login": "yystopf",
+        "name": "yystopf",
+        "type": null,
+        "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
+    },
+    "last_review": {
+        "id": 5,
+        "commit_id": null,
+        "content": "新建一个审查",
+        "status": "common",
+        "created_at": "2022-07-25 17:08",
+        "reviewer": {
+            "id": 2,
+            "type": "User",
+            "name": "heh",
+            "login": "yystopf",
+            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+        }
+    },
+    "reviewers": [
+        "yystopf"
+    ],
     "conflict_files": []
 }
-

获取pull request文件列表

-

获取pull request文件列表

+

获取合并请求文件列表

+

获取合并请求文件列表

示例:

@@ -12427,7 +12661,7 @@ http://localhost:3000/api/Jason/gitlink/pulls/1/files.json pull request's id -

返回字段说明:

+

返回字段说明:

@@ -12654,8 +12888,8 @@ http://localhost:3000/api/Jason/gitlink/pulls/1/files.json } ] } -

获取pull request的commits列表

-

获取pull request的commits列表

+

获取合并请求的commits列表

+

获取合并请求的commits列表

示例:

@@ -12692,7 +12926,7 @@ http://localhost:3000/api/Jason/gitlink/pulls/1/files.json
参数 pull request's id
-

返回字段说明:

+

返回字段说明:

@@ -12846,7 +13080,7 @@ http://localhost:3000/api/Jason/test-txt/compare/master...Jason/test-txt:develop
参数pull request's id
-

返回字段说明:

+

返回字段说明:

@@ -13162,16 +13396,16 @@ http://localhost:3000/api/Jason/test-txt/compare/master...Jason/test-txt:develop } ] } -

List pull requests

+

获取合并请求列表

获取合并请求列表

示例:

-
curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls.json
-
await octokit.request('GET /api/Jasder/gitlink/pulls.json')
+
curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls.json
+
await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls.json')
 

HTTP 请求

-

GET /api/:owner/:repo/pulls.json

+

GET /api/v1/:owner/:repo/pulls.json

请求参数:

参数
@@ -13196,50 +13430,2293 @@ http://localhost:3000/api/Jason/test-txt/compare/master...Jason/test-txt:develop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
string 项目标识identifier
keywordstring搜索关键词
statusint合并请求类型 0: 开启的, 1: 合并的 2: 关闭的,不传则为全部的
priority_idint优先级ID
issue_tag_idint标记ID
version_idint里程碑ID
reviewer_idint审查人员ID
assign_user_idint指派人员ID
sort_bycreated_atstring排序字段,created_at: 创建时间, updated_at: 更新时间
sort_directiondescstring排序类型 desc: 倒序 asc: 正序
+

返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
---
total_countint合并请求总数
idint合并请求ID
titlestring合并请求标题
bodystring合并请求内容
headint合并请求源分支
baseint合并请求目标分支
indexint合并请求序号
is_originalbool是否为fork仓库发来的合并请求
statusstring合并请求状态,open: 开启的, merged: 合并的, closed: 关闭的
fork_project.idintfork仓库的id
fork_project.identifierstringfork仓库的标识
fork_project.loginstringfork仓库拥有者的标识
issue.idint疑修ID
issue.authorobject疑修作者
issue.prioritystring疑修优先级
issue.versionstring疑修里程碑
issue.journals_countint普通评论数量
issue.issue_tagsarray标记
journals_countint审查评论数量

返回的JSON示例:

{
-  "status": 0,
-  "message": "响应成功",
-  "open_count": 4,
-  "close_count": 51,
-  "merged_issues_size": 123,
-  "search_count": 4,
-  "limit": null,
-  "user_admin_or_member": true,
-  "user_admin_or_developer": true,
-  "project_name": "Gitlink",
-  "project_author_name": "Gitlink",
-  "issues": [
-    {
-      "pull_request_id": 1189,
-      "pull_request_status": 0,
-      "pull_request_head": "develop",
-      "pull_request_base": "master",
-      "pull_request_staus": "open",
-      "is_original": false,
-      "fork_project_id": null,
-      "fork_project_identifier": null,
-      "fork_project_user": null,
-      "id": 51888,
-      "name": "FIx release v3.2.0",
-      "pr_time": "59分钟前",
-      "assign_user_name": "victor",
-      "assign_user_login": "moshenglv",
-      "author_name": "段甲生",
-      "author_login": "jasder",
-      "avatar_url": "images/avatars/User/36480?t=1615520120",
-      "priority": "正常",
-      "version": null,
-      "journals_count": 0,
-      "issue_tags": null
-    }
-  ]
+    "total_count": 2,
+    "pulls": [
+        {
+            "id": 167,
+            "head": "master",
+            "base": "master",
+            "is_original": true,
+            "index": 4,
+            "status": "open",
+            "fork_project": {
+                "id": 491,
+                "identifier": "ceshi_commit",
+                "login": "testforge1"
+            },
+            "issue": {
+                "id": 264,
+                "author": {
+                    "id": 4,
+                    "type": "User",
+                    "name": "tes tforge1",
+                    "login": "testforge1",
+                    "image_url": "system/lets/letter_avatars/2/T/238_117_19/120.png"
+                },
+                "priority": null,
+                "version": null,
+                "journals_count": 0,
+                "issue_tags": null
+            },
+            "journals_count": 0
+        },
+        {
+            "id": 165,
+            "head": "master_1",
+            "base": "master",
+            "is_original": false,
+            "index": 3,
+            "status": "open",
+            "issue": {
+                "id": 262,
+                "author": {
+                    "id": 2,
+                    "type": "User",
+                    "name": "heh",
+                    "login": "yystopf",
+                    "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+                },
+                "priority": null,
+                "version": null,
+                "journals_count": 0,
+                "issue_tags": null
+            },
+            "journals_count": 0
+        }
+    ]
 }
-

Issues

Organizations

Teams

Errors

+

创建一个合并请求

+

为仓库创建一个合并请求

+ +
+

示例:

+
+
curl -X POST \
+http://localhost:3000/api/yystopf/ceshi/pulls.json
+
await octokit.request('POST /api/yystopf/ceshi/pulls.json')
+

HTTP 请求

+

POST /api/:owner/:repo/pulls.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
titlestring合并请求标题
bodystring合并请求内容
basestring目标分支
headstring源分支
is_originalbool是否为fork仓库发来的合并请求
fork_project_idintegerfork仓库ID
reviewer_idsarray审查人员id数组
assigned_to_idinteger指派人员ID
fixed_version_idinteger里程碑ID
issue_tag_idsarray标记ID数组
priority_idinteger优先级ID
receivers_loginarray@人员的login
+ +
+

请求的JSON示例:

+
+
{
+    "title": "324",
+    "assigned_to_id": "2",
+    "fixed_version_id": "",
+    "issue_tag_ids": [],
+    "priority_id": "2",
+    "body": "312",
+    "head": "new_branch_1",
+    "base": "master",
+    "is_original": false,
+    "fork_project_id": "",
+    "files_count": 1,
+    "commits_count": 1,
+    "reviewer_ids": [],
+    "receivers_login": []
+}
+
+
+

返回的JSON示例:

+
+
{
+    "status": 0,
+    "message": "响应成功",
+    "pull_request_id": 169,
+    "pull_request_number": 6,
+    "pull_request_status": 0,
+    "pull_request_head": "new_branch_1",
+    "pull_request_base": "master",
+    "pull_request_staus": "open",
+    "is_original": false,
+    "fork_project_id": null,
+    "fork_project_identifier": null,
+    "fork_project_user": null,
+    "reviewers": [
+        "yystopf"
+    ],
+    "id": 266,
+    "name": "324",
+    "pr_time": "1分钟前",
+    "assign_user_name": "heh",
+    "assign_user_login": "yystopf",
+    "author_name": "heh",
+    "author_login": "yystopf",
+    "avatar_url": "system/lets/letter_avatars/2/H/188_239_142/120.png",
+    "priority": "正常",
+    "version": null,
+    "journals_count": 0,
+    "issue_tags": null
+}
+
+ +

获取合并请求版本列表

+

获取合并请求版本列表

+ +
+

示例:

+
+
curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/versions.json
+
await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/versions.json')
+

HTTP 请求

+

GET /api/v1/:owner/:repo/pulls/:index/versions.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexint合并请求序号
+

返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
total_countint合并请求版本总数
versions.idint版本ID
versions.add_line_numint该版本新增行数
versions.del_line_numint该版本删除行数
versions.commits_countint该版本提交总数
versions.files_countint该版本提交文件总数
versions.base_commit_shastring目标commit ID
versions.head_commit_shastring源commit ID
versions.start_commit_shastring该版本起始commit ID
versions.created_timeint版本创建时间
versions.updated_timeint版本更新时间
+ +
+

返回的JSON示例:

+
+
{
+    "total_count": 1,
+    "versions": [
+        {
+            "id": 33,
+            "add_line_num": 5,
+            "del_line_num": 2,
+            "commits_count": 31,
+            "files_count": 29,
+            "base_commit_sha": "4a277037093c1248e46d2946ee30b61cccdb9df9",
+            "head_commit_sha": "fa3b1cdc8e0727d0fb9c96d28c545867c39815b8",
+            "start_commit_sha": "e49b1fd335e093a440fcf35a21e050afd48ef932",
+            "created_time": 1658469499,
+            "updated_time": 1658469499
+        }
+    ]
+}
+

获取合并请求版本Diff

+

获取合并请求版本Diff(支持获取单文件Diff)

+ +
+

示例:

+
+
curl -X GET \
+-d "filepath=ceshi_dir_1/new_file_1" \
+http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/versions/33/diff.json
+
await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/versions/33/diff.json')
+

HTTP 请求

+

GET /api/v1/:owner/:repo/pulls/:index/versions/:version_id/diff.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexint合并请求序号
version_idint版本ID
filepathstring文件路径
+

列表返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
file_numsint文件数量
total_additionint新增行数
total_deletionint删除行数
files.namestring文件名称
files.oldnamestring文件修改前名称
files.additionint文件新增行数
files.deletionint文件删除行数
files.typeint文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制
files.is_createdbool是否为新建文件
files.is_deletedbool是否为删除文件
files.is_binbool是否为二进制文件
files.is_lfs_filebool是否为LFS文件
files.is_renamedbool是否重命名
files.is_ambiguousbool
files.is_submodulebool是否为子模块
files.sections.file_namestring文件名称
files.sections.namestring
files.sections.lines.left_indexint文件变动之前所在行数
files.sections.lines.right_indexint文件变动之后所在行数
files.sections.lines.matchint
files.sections.lines.typeint文件变更类型
files.sections.lines.contentstring文件变更内容
files.sections.lines.section_pathstring文件路径
files.sections.lines.section_last_left_indexint
files.sections.lines.section_last_right_indexint
files.sections.lines.section_left_indexint文件变更之前所在行数
files.sections.lines.section_right_indexint文件变更之后所在行数(即:页面编辑器开始显示的行数)
files.sections.lines.section_left_hunk_sizeint文件变更之前的行数
files.sections.lines.section_right_hunk_sizeint文件变更之后的行数(及当前页面编辑器显示的总行数)
files.is_incompletebool是否不完整
files.is_incomplete_line_too_longbool文件是否不完整是因为太长了
files.is_protectedbool文件是否被保护
+ +
+

列表返回的JSON示例:

+
+
{
+    "file_nums": 29,
+    "total_addition": 5,
+    "total_deletion": 2,
+    "files": [
+        {
+            "name": "README.md",
+            "oldname": "README.md",
+            "addition": 1,
+            "deletion": 2,
+            "type": 2,
+            "is_created": false,
+            "is_deleted": false,
+            "is_bin": false,
+            "is_lfs_file": false,
+            "is_renamed": false,
+            "is_ambiguous": false,
+            "is_submodule": false,
+            "sections": [
+                {
+                    "file_name": "README.md",
+                    "name": "",
+                    "lines": [
+                        {
+                            "left_index": 0,
+                            "right_index": 0,
+                            "match": 0,
+                            "type": 4,
+                            "content": "@@ -1,2 +1 @@",
+                            "section_path": "README.md",
+                            "section_last_left_index": 0,
+                            "section_last_right_index": 0,
+                            "section_left_index": 1,
+                            "section_right_index": 1,
+                            "section_left_hunk_size": 2,
+                            "section_right_hunk_size": 0
+                        },
+                        {
+                            "left_index": 1,
+                            "right_index": 0,
+                            "match": 3,
+                            "type": 3,
+                            "content": "-# ceshi_commit"
+                        },
+                        {
+                            "left_index": 2,
+                            "right_index": 0,
+                            "match": -1,
+                            "type": 3,
+                            "content": "-"
+                        },
+                        {
+                            "left_index": 0,
+                            "right_index": 1,
+                            "match": 1,
+                            "type": 2,
+                            "content": "+adsa"
+                        }
+                    ]
+                },
+                {}
+            ],
+            "is_incomplete": false,
+            "is_incomplete_line_too_long": false,
+            "is_protected": false
+        }
+    ]
+}
+

单个文件返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
namestring文件名称
oldnamestring文件修改前名称
additionint文件新增行数
deletionint文件删除行数
typeint文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制
is_createdbool是否为新建文件
is_deletedbool是否为删除文件
is_binbool是否为二进制文件
is_lfs_filebool是否为LFS文件
is_renamedbool是否重命名
is_ambiguousbool
is_submodulebool是否为子模块
sections.file_namestring文件名称
sections.namestring
sections.lines.left_indexint文件变动之前所在行数
sections.lines.right_indexint文件变动之后所在行数
sections.lines.matchint
sections.lines.typeint文件变更类型
sections.lines.contentstring文件变更内容
sections.lines.section_pathstring文件路径
sections.lines.section_last_left_indexint
sections.lines.section_last_right_indexint
sections.lines.section_left_indexint文件变更之前所在行数
sections.lines.section_right_indexint文件变更之后所在行数(即:页面编辑器开始显示的行数)
sections.lines.section_left_hunk_sizeint文件变更之前的行数
sections.lines.section_right_hunk_sizeint文件变更之后的行数(及当前页面编辑器显示的总行数)
is_incompletebool是否不完整
is_incomplete_line_too_longbool文件是否不完整是因为太长了
is_protectedbool文件是否被保护
+ +
+

单个文件返回的JSON示例:

+
+
{
+    "name": "README.md",
+    "oldname": "README.md",
+    "addition": 1,
+    "deletion": 2,
+    "type": 2,
+    "is_created": false,
+    "is_deleted": false,
+    "is_bin": false,
+    "is_lfs_file": false,
+    "is_renamed": false,
+    "is_ambiguous": false,
+    "is_submodule": false,
+    "sections": [
+        {
+            "file_name": "README.md",
+            "name": "",
+            "lines": [
+                {
+                    "left_index": 0,
+                    "right_index": 0,
+                    "match": 0,
+                    "type": 4,
+                    "content": "@@ -1,2 +1 @@",
+                    "section_path": "README.md",
+                    "section_last_left_index": 0,
+                    "section_last_right_index": 0,
+                    "section_left_index": 1,
+                    "section_right_index": 1,
+                    "section_left_hunk_size": 2,
+                    "section_right_hunk_size": 0
+                },
+                {
+                    "left_index": 1,
+                    "right_index": 0,
+                    "match": 3,
+                    "type": 3,
+                    "content": "-# ceshi_commit"
+                },
+                {
+                    "left_index": 2,
+                    "right_index": 0,
+                    "match": -1,
+                    "type": 3,
+                    "content": "-"
+                },
+                {
+                    "left_index": 0,
+                    "right_index": 1,
+                    "match": 1,
+                    "type": 2,
+                    "content": "+adsa"
+                }
+            ]
+        },
+        {
+            "file_name": "README.md",
+            "name": "",
+            "lines": [
+                {
+                    "left_index": 0,
+                    "right_index": 0,
+                    "match": 0,
+                    "type": 4,
+                    "content": " ",
+                    "section_path": "README.md",
+                    "section_last_left_index": 0,
+                    "section_last_right_index": 1,
+                    "section_left_index": 3,
+                    "section_right_index": 2,
+                    "section_left_hunk_size": 0,
+                    "section_right_hunk_size": 0
+                }
+            ]
+        }
+    ],
+    "is_incomplete": false,
+    "is_incomplete_line_too_long": false,
+    "is_protected": false
+}
+

获取合并请求审查列表

+

获取合并请求版本审查列表

+ +
+

示例:

+
+
curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/reviews.json
+
await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/reviews.json')
+

HTTP 请求

+

GET /api/v1/:owner/:repo/pulls/:index/reviews.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexint合并请求序号
+

返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
total_countint审查总数
reviews.reviewerobject审查者
reviews.pull_request.idinteger合并请求ID
reviews.pull_request.titlestring合并请求标题
reviews.pull_request.bodystring合并请求内容
reviews.pull_request.headstring合并请求源分支
reviews.pull_request.basestring合并请求目标分支
reviews.pull_request.is_originalstring合并请求是否从fork仓库所来
reviews.pull_request.fork_project.idintfork仓库的id
reviews.pull_request.fork_project.identifierstringfork仓库的标识
reviews.pull_request.fork_project.loginstringfork仓库拥有者的标识
reviews.pull_request.indexstring合并请求的序号
reviews.pull_request.statusstring合并请求的状态,open: 打开的, merged: 合并的, closed: 关闭的
reviews.pull_request.issue.idinteger合并请求下疑修的ID
reviews.pull_request.issue.authorobject合并请求以及疑修的创建着
reviews.pull_request.issue.prioritystring疑修的优先级
reviews.pull_request.issue.versionstring疑修的里程碑
reviews.pull_request.issue.journals_countinteger普通评论数量
reviews.pull_request.issue.issue_tagsarray所属标记
reviews.pull_request.journals_countinteger审查评论数量
reviews.idinteger审查ID
reviews.commit_idstring审查的commit ID
reviews.contentstring审查的内容
reviews.statusstring审查类型,common: 普通, approved: 通过,rejected: 拒绝通过
reviews.created_atstring审查创建时间
+ +
+

返回的JSON示例:

+
+
{
+    "total_count": 1,
+    "reviews": [
+        {
+            "reviewer": {
+                "id": 2,
+                "type": "User",
+                "name": "heh",
+                "login": "yystopf",
+                "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+            },
+            "pull_request": {
+                "id": 163,
+                "title": "新合并请求1",
+                "body": null,
+                "head": "master_1",
+                "base": "master",
+                "is_original": false,
+                "index": 1,
+                "status": "closed",
+                "issue": {
+                    "id": 260,
+                    "author": {
+                        "id": 2,
+                        "type": "User",
+                        "name": "heh",
+                        "login": "yystopf",
+                        "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+                    },
+                    "priority": null,
+                    "version": null,
+                    "journals_count": 0,
+                    "issue_tags": null
+                },
+                "reviewers": [],
+                "journals_count": 8
+            },
+            "id": 5,
+            "commit_id": null,
+            "content": "新建一个审查",
+            "status": "common",
+            "created_at": "2022-07-25 17:08"
+        }
+    ]
+}
+

为合并请求创建一个审查

+

合并请求创建一个审查

+ +
+

示例:

+
+
curl -X POST \
+http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/reviews.json
+
await octokit.request('POST /api/v1/yystopf/ceshi/pulls/1/reviews.json')
+

HTTP 请求

+

POST /api/v1/:owner/:repo/pulls/:index/reviews.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexinteger合并请求序号
contentstring审查内容
commit_idstring当前合并请求的commit_id
statusstring审查类型, common: 普通, approved: 通过, rejected: 拒绝
+ +
+

请求的JSON示例:

+
+
{
+    "content": "新建一个审查",
+    "commit_id": "e506844b2467ce25a35dd46dad8236a1595a02da",
+    "status": "common"
+}
+

返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
reviewerobject审查者
pull_request.idinteger合并请求ID
pull_request.titlestring合并请求标题
pull_request.bodystring合并请求内容
pull_request.headstring合并请求源分支
pull_request.basestring合并请求目标分支
pull_request.is_originalstring合并请求是否从fork仓库所来
pull_request.fork_project.idintfork仓库的id
pull_request.fork_project.identifierstringfork仓库的标识
pull_request.fork_project.loginstringfork仓库拥有者的标识
pull_request.indexstring合并请求的序号
pull_request.statusstring合并请求的状态,open: 打开的, merged: 合并的, closed: 关闭的
pull_request.issue.idinteger合并请求下疑修的ID
pull_request.issue.authorobject合并请求以及疑修的创建着
pull_request.issue.prioritystring疑修的优先级
pull_request.issue.versionstring疑修的里程碑
pull_request.issue.journals_countinteger普通评论数量
pull_request.issue.issue_tagsarray所属标记
pull_request.journals_countinteger审查评论数量
idinteger审查ID
commit_idstring审查的commit ID
contentstring审查的内容
statusstring审查类型,common: 普通, approved: 通过,rejected: 拒绝通过
created_atstring审查创建时间
+ +
+

返回的JSON示例:

+
+
{
+    "reviewer": {
+        "id": 2,
+        "type": "User",
+        "name": "heh",
+        "login": "yystopf",
+        "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+    },
+    "pull_request": {
+        "id": 163,
+        "head": "master_1",
+        "base": "master",
+        "is_original": false,
+        "index": 1,
+        "status": "closed",
+        "issue": {
+            "id": 260,
+            "author": {
+                "id": 2,
+                "type": "User",
+                "name": "heh",
+                "login": "yystopf",
+                "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+            },
+            "priority": null,
+            "version": null,
+            "journals_count": 0,
+            "issue_tags": null
+        },
+        "journals_count": 6
+    },
+    "id": 10,
+    "commit_id": "e506844b2467ce25a35dd46dad8236a1595a02da",
+    "content": "新建一个审查",
+    "status": "common",
+    "created_at": "2022-07-26 11:45"
+}
+
+ +

获取合并请求评论列表

+

获取合并请求版本评论列表

+ +
+

示例:

+
+
curl -X GET http://localhost:3000/api/v1/yystopf/ceshi_commit/pulls/3/journals.json
+
await octokit.request('GET /api/v1/yystopf/ceshi_commit/pulls/3/journals.json')
+

HTTP 请求

+

GET /api/v1/:owner/:repo/pulls/:index/journals.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexint合并请求序号
keywordstring搜索关键词
review_idinteger审查ID
need_respondbool是否需要回应
statestring状态, opened: 开启的, resolved: 已解决的, disabled: 无效的
parent_idinteger父评论ID
sort_bycreated_onstring排序字段 created_on: 创建时间, updated_on: 更新时间
sort_directionascstring排序类型 desc: 倒序, asc: 正序
+

返回字段说明:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型字段说明
total_countint评论总数
journals.idint评论ID
journals.notesstring评论内容
journals.commit_idstringCommitID
journals.line_codestring评论行数
journals.pathstring评论文件路径
journals.diffobject评论文件diff内容
journals.need_respondbool评论是否要回应
journals.statestring评论状态,opened: 开启的, resolved: 已解决的, disabled: 无效的
journals.parent_idint父评论ID
journals.userobject评论创建者
journals.reviewobject评论所属评审
journals.resolveerobject评论解决者
journals.resolve_atint评论解决时间
journals.created_atint评论创建时间
journals.updated_atint评论更新时间
+ +
+

返回的JSON示例:

+
+
{
+    "total_count": 1,
+    "journals": [
+        {
+            "id": 200,
+            "note": "测试评论修改",
+            "commit_id": null,
+            "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29",
+            "path": "Gemfile.lock",
+            "diff": {},
+            "need_respond": true,
+            "state": "resolved",
+            "parent_id": nil,
+            "user": {
+                "id": 2,
+                "type": "User",
+                "name": "heh",
+                "login": "yystopf",
+                "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+            },
+            "review": {
+                "reviewer": {
+                    "id": 2,
+                    "type": "User",
+                    "name": "heh",
+                    "login": "yystopf",
+                    "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+                },
+                "pull_request": {
+                    "id": 163,
+                    "title": "新合并请求1",
+                    "body": null,
+                    "head": "master_1",
+                    "base": "master",
+                    "is_original": false,
+                    "index": 1,
+                    "status": "closed",
+                    "issue": {
+                        "id": 260,
+                        "author": {
+                            "id": 2,
+                            "type": "User",
+                            "name": "heh",
+                            "login": "yystopf",
+                            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+                        },
+                        "priority": null,
+                        "version": null,
+                        "journals_count": 0,
+                        "issue_tags": null
+                    },
+                    "reviewers": [],
+                    "journals_count": 9
+                },
+                "id": 10,
+                "commit_id": "1",
+                "content": "新建一个审查",
+                "status": "common",
+                "created_at": "2022-07-26 11:45"
+            },
+            "resolveer": {
+                "id": 2,
+                "type": "User",
+                "name": "heh",
+                "login": "yystopf",
+                "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+            },
+            "resolve_at": "2022-07-27 14:50",
+            "created_at": "2022-07-27 14:31",
+            "updated_at": "2022-07-27 14:50"
+        }
+    ]
+}
+

创建一个合并请求评论

+

为仓库创建一个合并请求的评论

+ +
+

示例:

+
+
curl -X POST \
+http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/journals.json
+
await octokit.request('POST /api/v1/yystopf/ceshi/pulls/1/journals.json')
+

HTTP 请求

+

POST /api/v1/:owner/:repo/pulls/:index/journals.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexinteger合并请求序号
typestring评论类型 comment: 普通, problem: 需要回应的评论
notestring评论内容
review_idstring审查ID
line_codestring行号
commit_idboolcommitID
pathinteger文件路径
parent_idinteger父评论ID
diffarray文件diff内容
+ +
+

请求的JSON示例:

+
+
{
+    "type": "problem",
+    "note": "测试评论",
+    "review_id": "10",
+    "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29",
+    "commit_id": "70eede447ccc01c1902260fd377af5d90be28e0d",
+    "path": "Gemfile.lock",
+    "diff": {
+        "name": "README.md",
+        "oldname": "README.md",
+        "addition": 1,
+        "deletion": 2,
+        "type": 2,
+        "is_created": false,
+        "is_deleted": false,
+        "is_bin": false,
+        "is_lfs_file": false,
+        "is_renamed": false,
+        "is_ambiguous": false,
+        "is_submodule": false,
+        "sections": [
+            {
+                "file_name": "README.md",
+                "name": "",
+                "lines": [
+                    {
+                        "left_index": 0,
+                        "right_index": 0,
+                        "match": 0,
+                        "type": 4,
+                        "content": "@@ -1,2 +1 @@",
+                        "section_path": "README.md",
+                        "section_last_left_index": 0,
+                        "section_last_right_index": 0,
+                        "section_left_index": 1,
+                        "section_right_index": 1,
+                        "section_left_hunk_size": 2,
+                        "section_right_hunk_size": 0
+                    },
+                    {
+                        "left_index": 1,
+                        "right_index": 0,
+                        "match": 3,
+                        "type": 3,
+                        "content": "-# ceshi_commit"
+                    },
+                    {
+                        "left_index": 2,
+                        "right_index": 0,
+                        "match": -1,
+                        "type": 3,
+                        "content": "-"
+                    },
+                    {
+                        "left_index": 0,
+                        "right_index": 1,
+                        "match": 1,
+                        "type": 2,
+                        "content": "+adsa"
+                    }
+                ]
+            },
+            {
+                "file_name": "README.md",
+                "name": "",
+                "lines": [
+                    {
+                        "left_index": 0,
+                        "right_index": 0,
+                        "match": 0,
+                        "type": 4,
+                        "content": " ",
+                        "section_path": "README.md",
+                        "section_last_left_index": 0,
+                        "section_last_right_index": 1,
+                        "section_left_index": 3,
+                        "section_right_index": 2,
+                        "section_left_hunk_size": 0,
+                        "section_right_hunk_size": 0
+                    }
+                ]
+            }
+        ],
+        "is_incomplete": false,
+        "is_incomplete_line_too_long": false,
+        "is_protected": false
+    }
+}
+
+
+

返回的JSON示例:

+
+
{
+    "id": 200,
+    "note": "测试评论修改",
+    "commit_id": null,
+    "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29",
+    "path": "Gemfile.lock",
+    "diff": {},
+    "need_respond": true,
+    "state": "resolved",
+    "user": {
+        "id": 2,
+        "type": "User",
+        "name": "heh",
+        "login": "yystopf",
+        "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+    },
+    "review": {
+        "reviewer": {
+            "id": 2,
+            "type": "User",
+            "name": "heh",
+            "login": "yystopf",
+            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+        },
+        "pull_request": {
+            "id": 163,
+            "title": "新合并请求1",
+            "body": null,
+            "head": "master_1",
+            "base": "master",
+            "is_original": false,
+            "index": 1,
+            "status": "closed",
+            "issue": {
+                "id": 260,
+                "author": {
+                    "id": 2,
+                    "type": "User",
+                    "name": "heh",
+                    "login": "yystopf",
+                    "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+                },
+                "priority": null,
+                "version": null,
+                "journals_count": 0,
+                "issue_tags": null
+            },
+            "reviewers": [],
+            "journals_count": 9
+        },
+        "id": 10,
+        "commit_id": "1",
+        "content": "新建一个审查",
+        "status": "common",
+        "created_at": "2022-07-26 11:45"
+    },
+    "resolveer": {
+        "id": 2,
+        "type": "User",
+        "name": "heh",
+        "login": "yystopf",
+        "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+    },
+    "resolve_at": "2022-07-27 14:50",
+    "created_at": "2022-07-27 14:31",
+    "updated_at": "2022-07-27 14:50"
+}
+
+ +

修改一个合并请求评论

+

修改一个仓库合并请求的评论

+ +
+

示例:

+
+
curl -X PATCH \
+http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/journals/200.json
+
await octokit.request('PATCH /api/v1/yystopf/ceshi/pulls/1/journals/200.json')
+

HTTP 请求

+

PATCH /api/v1/:owner/:repo/pulls/:index/journals/:id.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexinteger合并请求序号
idinteger评论ID
notestring评论内容
commit_idstringcommitID
statestring评论状态, opened: 开启的, resolved: 已解决的, disabled: 无效的
+ +
+

请求的JSON示例:

+
+
{
+    "note": "测试评论",
+    "commit_id": "70eede447ccc01c1902260fd377af5d90be28e0d",
+    "state": "resolved"
+}
+
+
+

返回的JSON示例:

+
+
{
+    "id": 200,
+    "note": "测试评论修改",
+    "commit_id": null,
+    "line_code": "70eede447ccc01c1902260fd377af5d90be28e0d_0_29",
+    "path": "Gemfile.lock",
+    "diff": {},
+    "need_respond": true,
+    "state": "resolved",
+    "user": {
+        "id": 2,
+        "type": "User",
+        "name": "heh",
+        "login": "yystopf",
+        "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+    },
+    "review": {
+        "reviewer": {
+            "id": 2,
+            "type": "User",
+            "name": "heh",
+            "login": "yystopf",
+            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+        },
+        "pull_request": {
+            "id": 163,
+            "title": "新合并请求1",
+            "body": null,
+            "head": "master_1",
+            "base": "master",
+            "is_original": false,
+            "index": 1,
+            "status": "closed",
+            "issue": {
+                "id": 260,
+                "author": {
+                    "id": 2,
+                    "type": "User",
+                    "name": "heh",
+                    "login": "yystopf",
+                    "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+                },
+                "priority": null,
+                "version": null,
+                "journals_count": 0,
+                "issue_tags": null
+            },
+            "reviewers": [],
+            "journals_count": 9
+        },
+        "id": 10,
+        "commit_id": "1",
+        "content": "新建一个审查",
+        "status": "common",
+        "created_at": "2022-07-26 11:45"
+    },
+    "resolveer": {
+        "id": 2,
+        "type": "User",
+        "name": "heh",
+        "login": "yystopf",
+        "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+    },
+    "resolve_at": "2022-07-27 14:50",
+    "created_at": "2022-07-27 14:31",
+    "updated_at": "2022-07-27 14:50"
+}
+
+ +

删除合并请求的一个评论

+

删除合并请求的一个评论

+ +
+

示例:

+
+
curl -X DELETE \
+http://localhost:3000/api/v1/yystopf/ceshi/pulls/1/journals/200.json
+
await octokit.request('DELETE /api/v1/yystopf/ceshi/pulls/1/journals/200.json')
+

HTTP 请求

+

DELETE /api/v1/:owner/:repo/pulls/:index/journals/:id.json

+

请求参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数必选默认类型字段说明
ownerstring用户登录名
repostring项目标识identifier
indexinteger合并请求序号
idinteger评论ID
+

返回字段说明:

+
+

返回的JSON示例:

+
+
{
+    "status": 0,
+    "message": "success"
+}
+
+ +

Issues

Organizations

Teams

Errors

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