From 8c8d9f64c4e4806812a7ec4028dfe6084cdbcf55 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 8 Jan 2021 18:07:48 +0800 Subject: [PATCH 01/35] ADD sync repo updated at time (cherry picked from commit 8c6df359a5f27e0d02c28c04a000d17b0245ad9d) --- app/jobs/sync_repo_update_time_job.rb | 25 +++++++++++++++++++ app/models/project.rb | 5 ++++ .../gitea/repository/get_by_id_service.rb | 25 ++++++++++--------- config/initializers/sidekiq.rb | 5 ++++ config/routes.rb | 1 + config/schedule.yml | 5 ++++ 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 app/jobs/sync_repo_update_time_job.rb create mode 100644 config/schedule.yml diff --git a/app/jobs/sync_repo_update_time_job.rb b/app/jobs/sync_repo_update_time_job.rb new file mode 100644 index 000000000..c2337ab94 --- /dev/null +++ b/app/jobs/sync_repo_update_time_job.rb @@ -0,0 +1,25 @@ +class SyncRepoUpdateTimeJob < ApplicationJob + queue_as :default + + def perform(*args) + # Do something later + Project.forge.find_each do |project| + update_repo_time!(project) + end + end + + private + def gitea_repo_updated_at(project) + admin = User.where(admin: true).select(:id, :gitea_token, :gitea_uid).last + + return nil if project.gpid.blank? + + result = Gitea::Repository::GetByIdService.call(project.gpid, admin.gitea_token) + + result[:status] === :success ? result[:body]['updated_at'] : nil + end + + def update_repo_time!(project) + project.set_updated_on gitea_repo_updated_at(project) + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 887a6952c..190f37760 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -279,4 +279,9 @@ class Project < ApplicationRecord ps.increment!(:mirror_projects_count) unless ps.blank? end + def set_updated_on(time) + return if time.blank? + update_column(:updated_on, time) + end + end diff --git a/app/services/gitea/repository/get_by_id_service.rb b/app/services/gitea/repository/get_by_id_service.rb index c633c6b71..74f45708c 100644 --- a/app/services/gitea/repository/get_by_id_service.rb +++ b/app/services/gitea/repository/get_by_id_service.rb @@ -1,31 +1,32 @@ class Gitea::Repository::GetByIdService < Gitea::ClientService - attr_reader :owner, :repo_id + attr_reader :token, :id - def initialize(owner, repo_id) - @owner = owner - @repo_id = repo_id + def initialize(id, token=nil) + @token = token + @id = id end def call response = get(url, params) - render_result(response) + + status, message, body = render_response(response) + json_format(status, message, body) end private def params - Hash.new.merge(token: owner.gitea_token) + Hash.new.merge(token: token) end def url - "/repositories/#{repo_id}".freeze + "/repositories/#{id}".freeze end - def render_result(response) - case response.status - when 200 - JSON.parse(response.body) + def json_format(status, message, body) + case status + when 200 then success(body) else - nil + error(message, status) end end end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index b3f2d0576..79a0e296f 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -3,6 +3,11 @@ sidekiq_url = redis_config["url"] Sidekiq.configure_server do |config| config.redis = { url: sidekiq_url } + + schedule_file = "config/schedule.yml" + if File.exists?(schedule_file) + Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) + end end Sidekiq.configure_client do |config| diff --git a/config/routes.rb b/config/routes.rb index 058dfec02..c8d88d6dc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ Rails.application.routes.draw do require 'sidekiq/web' + require 'sidekiq/cron/web' require 'admin_constraint' # mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new diff --git a/config/schedule.yml b/config/schedule.yml new file mode 100644 index 000000000..2b4269ac4 --- /dev/null +++ b/config/schedule.yml @@ -0,0 +1,5 @@ +sync_gitea_repo_updated_at: + # second minute hour day month date + cron: "0 0 24 * *" + class: "SyncRepoUpdateTimeJob" + queue: default From 20b06473bef3a6e981124664aa53b7deee51a1de Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 8 Jan 2021 18:03:51 +0800 Subject: [PATCH 02/35] ADD gem 'sidekiq-cron' (cherry picked from commit 8f24f6582088aab66640efe204b965ad1212c968) --- Gemfile | 1 + Gemfile.lock | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/Gemfile b/Gemfile index cd6c4b917..281dd705a 100644 --- a/Gemfile +++ b/Gemfile @@ -100,6 +100,7 @@ gem 'rails-i18n', '~> 5.1' # job gem 'sidekiq' gem 'sinatra' +gem "sidekiq-cron", "~> 1.1" # batch insert gem 'bulk_insert' diff --git a/Gemfile.lock b/Gemfile.lock index a6beea407..cbd598f59 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -118,12 +118,17 @@ GEM enumerize (2.3.1) activesupport (>= 3.2) erubi (1.9.0) + et-orbi (1.2.4) + tzinfo execjs (2.7.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) ffi (1.12.2) font-awesome-sass (4.7.0) sass (>= 3.2) + fugit (1.4.1) + et-orbi (~> 1.1, >= 1.1.8) + raabro (~> 1.4) globalid (0.4.2) activesupport (>= 4.2.0) grape-entity (0.7.1) @@ -211,6 +216,7 @@ GEM prettier (0.18.2) public_suffix (4.0.3) puma (3.12.2) + raabro (1.4.0) rack (2.0.9) rack-cors (1.1.1) rack (>= 2.0.0) @@ -353,6 +359,9 @@ GEM rack (< 2.1.0) rack-protection (>= 1.5.0) redis (>= 3.3.5, < 5) + sidekiq-cron (1.2.0) + fugit (~> 1.1) + sidekiq (>= 4.2.1) simple_form (5.0.2) actionpack (>= 5.0) activemodel (>= 5.0) @@ -477,6 +486,7 @@ DEPENDENCIES searchkick selenium-webdriver sidekiq + sidekiq-cron (~> 1.1) simple_form simple_xlsx_reader sinatra From d2e2793d29fe8c5f2b2731589727ea83f32da9ca Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 12 Jan 2021 15:45:18 +0800 Subject: [PATCH 03/35] FIX pull request bug (cherry picked from commit 2b140d6f7cc7a2153a32954f8270bef443474dae) --- app/controllers/pull_requests_controller.rb | 24 +++++----- app/models/issue_status.rb | 7 +++ app/models/project_trend.rb | 3 ++ app/models/pull_request.rb | 14 +++++- .../gitea/pull_request/close_service.rb | 22 ++++++++++ .../gitea/pull_request/merge_service.rb | 7 +-- .../gitea/pull_request/open_service.rb | 22 ++++++++++ .../gitea/pull_request/update_service.rb | 44 +++++++++++++++---- app/services/pull_requests/close_service.rb | 33 ++++++++++++++ app/services/pull_requests/merge_service.rb | 36 +++++++++++++++ app/services/pull_requests/open_service.rb | 33 ++++++++++++++ 11 files changed, 219 insertions(+), 26 deletions(-) create mode 100644 app/services/gitea/pull_request/close_service.rb create mode 100644 app/services/gitea/pull_request/open_service.rb create mode 100644 app/services/pull_requests/close_service.rb create mode 100644 app/services/pull_requests/merge_service.rb create mode 100644 app/services/pull_requests/open_service.rb diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 1699cf608..50e904565 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -87,8 +87,10 @@ class PullRequestsController < ApplicationController if @issue.update_attributes(@issue_params) if @pull_request.update_attributes(@local_params.compact) - gitea_request = Gitea::PullRequest::UpdateService.new(@project.owner, @repository.try(:identifier), @requests_params, @pull_request.try(:gpid)).call - if gitea_request + gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier, + @pull_request.gpid, @requests_params, current_user.gitea_token) + + if gitea_pull[:status] === :success if params[:issue_tag_ids].present? params[:issue_tag_ids].each do |tag| IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag) @@ -117,9 +119,8 @@ class PullRequestsController < ApplicationController def refuse_merge ActiveRecord::Base.transaction do begin - @pull_request.update(status: 2) - @pull_request.issue.update(status_id: 5) - normal_status(1, "已拒绝") + colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user) + colsed === true ? normal_status(1, "已拒绝") : normal_status(-1, '合并失败') rescue => e normal_status(-1, e.message) raise ActiveRecord::Rollback @@ -145,15 +146,10 @@ class PullRequestsController < ApplicationController else ActiveRecord::Base.transaction do begin - requests_params = { - Do: params[:do], - MergeMessageField: params[:body], - MergeTitleField: params[:title] - } - merge_pr = Gitea::PullRequest::MergeService.call(current_user.gitea_token, @project.owner.login, - @repository.try(:identifier), @pull_request.try(:gpid), requests_params) - if @pull_request.update_attribute(:status, 1) && merge_pr[:status].to_i == 200 - @pull_request&.project_trends&.update_all(action_type: "close") + result = PullRequests::MergeService.call(@owner, @repository, @pull_request, current_user, params) + + if result && @pull_request.merge! + @pull_request.project_trend_status! @issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id) normal_status(1, "合并成功") else diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb index a7ec34f8a..a58346ea7 100644 --- a/app/models/issue_status.rb +++ b/app/models/issue_status.rb @@ -17,6 +17,13 @@ # class IssueStatus < ApplicationRecord + ADD = 1 + SOLVING = 2 + SOLVED = 3 + FEEDBACK = 4 + CLOSED = 5 + REJECTED = 6 + has_many :issues belongs_to :project, optional: true end diff --git a/app/models/project_trend.rb b/app/models/project_trend.rb index 5858768b9..8c55c4f94 100644 --- a/app/models/project_trend.rb +++ b/app/models/project_trend.rb @@ -18,6 +18,9 @@ # class ProjectTrend < ApplicationRecord + CLOSE = 'close' + CREATE = 'create' + belongs_to :project belongs_to :trend, polymorphic: true, optional: true belongs_to :user diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index 046e9a0a4..cf057c3f2 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -24,7 +24,11 @@ # class PullRequest < ApplicationRecord - #status 0 默认未合并, 1表示合并, 2表示请求拒绝 + #status 0 默认未合并, 1表示合并, 2表示请求拒绝(或已关闭) + OPEN = 0 + MERGED = 1 + CLOSED = 2 + belongs_to :issue belongs_to :user belongs_to :project, :counter_cache => true @@ -42,6 +46,14 @@ class PullRequest < ApplicationRecord update_column(:gpid, gitea_pull_number) end + def merge! + update_column(:status, PullRequest::MERGED) + end + + def project_trend_status! + self&.project_trends&.update_all(action_type: ProjectTrend::CLOSE) + end + # TODO: sync educoder platform repo's for update some statistics count def self.update_some_count PullRequest.includes(:user, :project).select(:id, :user_id, :gpid, :project_id, :fork_project_id).each do |pr| diff --git a/app/services/gitea/pull_request/close_service.rb b/app/services/gitea/pull_request/close_service.rb new file mode 100644 index 000000000..aed5251b7 --- /dev/null +++ b/app/services/gitea/pull_request/close_service.rb @@ -0,0 +1,22 @@ +class Gitea::PullRequest::CloseService < Gitea::PullRequest::UpdateService + attr_reader :owner, :repo, :base, :number, :token + + # params: + # owner: owner of the repo + # repo: name of the repo + # base: branch name of base + # number: number of pull request + # token: token of gitea user + # eq: + # Gitea::PullRequest::CloseService.call(owner.login, repo.identifier, pull.gpid, pull.base, current_user.gitea_token) + def initialize(owner, repo, number, base,token=nil) + colse_pull_params = Hash.new.merge(base: base, state: 'closed').compact + + super(owner, repo, number, colse_pull_params, token) + end + + def call + super + end + +end diff --git a/app/services/gitea/pull_request/merge_service.rb b/app/services/gitea/pull_request/merge_service.rb index 2129bbeaf..c33c8781d 100644 --- a/app/services/gitea/pull_request/merge_service.rb +++ b/app/services/gitea/pull_request/merge_service.rb @@ -18,7 +18,9 @@ class Gitea::PullRequest::MergeService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + + render_200_no_body(response) end private @@ -27,7 +29,6 @@ class Gitea::PullRequest::MergeService < Gitea::ClientService end def request_params - Hash.new.merge(token: token, data: params) + Hash.new.merge(token: token, data: params.compact) end - end diff --git a/app/services/gitea/pull_request/open_service.rb b/app/services/gitea/pull_request/open_service.rb new file mode 100644 index 000000000..affdfe112 --- /dev/null +++ b/app/services/gitea/pull_request/open_service.rb @@ -0,0 +1,22 @@ +class Gitea::PullRequest::OpenService < Gitea::PullRequest::UpdateService + attr_reader :owner, :repo, :base, :number, :token + + # params: + # owner: owner of the repo + # repo: name of the repo + # base: branch name of base + # number: number of pull request + # token: token of gitea user + # eq: + # Gitea::PullRequest::OpenService.new(owner.login, repo.identifier, pr.gpid, pr.base, current_user.gitea_token) + def initialize(owner, repo, number, base, token=nil) + open_pull_params = Hash.new.merge(base: base, state: 'open').compact + + super(owner, repo, number, open_pull_params, token) + end + + def call + super + end + +end diff --git a/app/services/gitea/pull_request/update_service.rb b/app/services/gitea/pull_request/update_service.rb index a83afe40b..a68981f29 100644 --- a/app/services/gitea/pull_request/update_service.rb +++ b/app/services/gitea/pull_request/update_service.rb @@ -1,26 +1,54 @@ class Gitea::PullRequest::UpdateService < Gitea::ClientService - attr_reader :user, :repo, :params,:pull_request_id + attr_reader :owner, :repo, :params, :number, :token - - def initialize(user, repo, params,pull_request_id) - @user = user + # params: + # { + # "assignee": "string", + # "assignees": [ + # "string" + # ], + # "base": "string", + # "body": "string", + # "due_date": "2021-01-11T10:11:52.074Z", + # "labels": [ + # 0 + # ], + # "milestone": 0, + # "state": "string", + # "title": "string", + # "unset_due_date": true + # } + def initialize(owner, repo, number, params, token=nil) + @owner = owner @repo = repo @params = params - @pull_request_id = pull_request_id + @number = number + @token = token end def call - put(url, request_params) + response = patch(url, request_params) + + status, message, body = render_response(response) + json_format(status, message, body) end private def request_params - Hash.new.merge(token: @user.gitea_token, data: @params) + Hash.new.merge(token: token, data: @params) end def url - "/repos/#{@user.try(:login)}/#{@repo}/pulls/#{@pull_request_id}".freeze + "/repos/#{owner}/#{repo}/pulls/#{number}".freeze + end + + def json_format(status, message, body) + case status + when 201 then success(body) + else + error(message, status) + end end end diff --git a/app/services/pull_requests/close_service.rb b/app/services/pull_requests/close_service.rb new file mode 100644 index 000000000..e0ac19b4e --- /dev/null +++ b/app/services/pull_requests/close_service.rb @@ -0,0 +1,33 @@ +class PullRequests::CloseService < ApplicationService + attr_reader :owner, :repo, :pull, :current_user + + # eq: + # PullRequests::CloseService.call(owner, repo, pull, current_user) + def initialize(owner, repo, pull, current_user) + @owner = owner + @repo = repo + @pull = pull + @current_user = current_user + end + + def call + ActiveRecord::Base.transaction do + return false if close_gitea_pull[:status] != :success + + update_pull_status! + return true + end + end + + private + + def close_gitea_pull + Gitea::PullRequest::CloseService.call(@owner.login, @repo.identifier, + @pull.gpid, @pull.base, current_user.gitea_token) + end + + def update_pull_status! + @pull.update(status: PullRequest::CLOSED) + @pull.issue.update(status_id: IssueStatus::CLOSED) + end +end diff --git a/app/services/pull_requests/merge_service.rb b/app/services/pull_requests/merge_service.rb new file mode 100644 index 000000000..a20ee3aa9 --- /dev/null +++ b/app/services/pull_requests/merge_service.rb @@ -0,0 +1,36 @@ +class PullRequests::MergeService < ApplicationService + attr_reader :owner, :repo, :pull, :current_user, :params + + # eq: + # PullRequests::MergeService.call(owner, repo, pull, current_user, params) + def initialize(owner, repo, pull, current_user, params) + @owner = owner + @repo = repo + @pull = pull + @current_user = current_user + @params = params + end + + def call + ActiveRecord::Base.transaction do + gitea_pull_merge! + end + end + + private + + def gitea_pull_merge! + result = Gitea::PullRequest::MergeService.call(@current_user.gitea_token, @owner.login, + @repo.identifier, @pull.gpid, gitea_merge_pull_params) + + result[:status] === 200 ? true : false + end + + def gitea_merge_pull_params + { + Do: params[:do], + MergeMessageField: params[:body], + MergeTitleField: params[:title] + } + end +end diff --git a/app/services/pull_requests/open_service.rb b/app/services/pull_requests/open_service.rb new file mode 100644 index 000000000..3081e52b5 --- /dev/null +++ b/app/services/pull_requests/open_service.rb @@ -0,0 +1,33 @@ +class PullRequests::OpenService < ApplicationService + attr_reader :owner, :repo, :pull, :current_user + + # eq: + # PullRequests::OpenService.call(owner, repo, pull, current_user) + def initialize(owner, repo, pull, current_user) + @owner = owner + @repo = repo + @pull = pull + @current_user = current_user + end + + def call + ActiveRecord::Base.transaction do + return false if open_gitea_pull[:status] != :success + + update_pull_status! + return true + end + end + + private + + def open_gitea_pull + Gitea::PullRequest::OpenService.call(@owner.login, @repo.identifier, + @pull.gpid, @pull.base, @current_user.gitea_token) + end + + def update_pull_status! + @pull.update(status: PullRequest::OPEN) + @pull.issue.update(status_id: IssueStatus::SOLVING) + end +end From f212c5213da12b8797b97a24bf0089424e7bfe8c Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 12 Jan 2021 15:47:04 +0800 Subject: [PATCH 04/35] FIX base and head params problem for compare api (cherry picked from commit 4c2c3d17e263e402d12f9aa41761ae104b3230cc) --- app/controllers/compare_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb index e5e61598e..0918b9d3b 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -6,9 +6,9 @@ class CompareController < ApplicationController end def show - base_ref = Addressable::URI.unescape(params[:base]) - @ref = head_ref = Addressable::URI.unescape(params[:head]&.split('.json')[0]) - @compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base_ref, head_ref) + base = Addressable::URI.unescape(params[:base]) + head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head] + @compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, head, base) # render json: @compare_result end From b6aa0fd76cfdad9931151ac22e2640eba99f0290 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 12 Jan 2021 15:55:11 +0800 Subject: [PATCH 05/35] FIX render json builder partil performance for pull some api (cherry picked from commit f084b72e3a0e2880a5531c4705efe30b6ea96d10) --- app/views/compare/show.json.jbuilder | 76 ++++++++++++++++++++- app/views/pull_requests/files.json.jbuilder | 50 +++++++++++++- 2 files changed, 123 insertions(+), 3 deletions(-) diff --git a/app/views/compare/show.json.jbuilder b/app/views/compare/show.json.jbuilder index 8f95bbcb5..8257cc7fa 100644 --- a/app/views/compare/show.json.jbuilder +++ b/app/views/compare/show.json.jbuilder @@ -1,5 +1,29 @@ json.commits_count @compare_result['Commits']&.size -json.commits @compare_result['Commits'], partial: 'pull_requests/commit', as: :commit +# json.commits @compare_result['Commits'], partial: 'pull_requests/commit', as: :commit +json.commits do + json.array! @compare_result['Commits'] do |commit| + json.author do + # TODO: 获取头像地址待优化 + forge_user = User.includes(:user_extension).select(:id, :login).find_by(login: commit['Author']['Name']) + json.login commit['Author']['Name'] + json.name commit['Author']['Name'] + json.image_url forge_user.nil? ? '' : url_to_avatar(forge_user) + end + + json.committer do + # TODO: 获取头像地址待优化 + forge_user = User.includes(:user_extension).select(:id, :login).find_by(login: commit['Committer']['Name']) + json.login commit['Committer']['Name'] + json.name commit['Committer']['Name'] + json.image_url forge_user.nil? ? '' : url_to_avatar(forge_user) + end + json.timestamp render_unix_time(commit['Committer']['When']) + json.time_from_now time_from_now(commit['Committer']['When']) + json.created_at render_format_time_with_date(commit['Committer']['When']) + json.message commit['CommitMessage'] + json.sha commit['Sha'] + end +end json.diff do if @compare_result['Diff'].blank? @@ -8,6 +32,54 @@ json.diff do json.files_count @compare_result['Diff']['NumFiles'] json.total_addition @compare_result['Diff']['TotalAddition'] json.total_deletion @compare_result['Diff']['TotalDeletion'] - json.files @compare_result['Diff']['Files'], partial: 'pull_requests/diff_file', as: :file, locals: {sha: @compare_result['LatestSha']} + + # TODO: 解决render partil耗时间问题 + # json.files @compare_result['Diff']['Files'], partial: 'pull_requests/diff_file', as: :file, locals: {sha: @compare_result['LatestSha']} + json.files do + json.array! @compare_result['Diff']['Files'] do |file| + json.sha @compare_result['LatestSha'] + json.name file['Name'] + json.old_name file['OldName'] + json.index file['Index'] + json.addition file['Addition'] + json.deletion file['Deletion'] + json.type file['Type'] + json.isCreated file['IsCreated'] + json.isDeleted file['IsDeleted'] + json.isBin file['IsBin'] + json.isLFSFile file['IsLFSFile'] + json.isRenamed file['IsRenamed'] + json.isSubmodule file['IsSubmodule'] + json.isLFSFile file['IsLFSFile'] + json.sections do + json.array! file['Sections'] do |section| + json.fileName section['FileName'] + json.name section['Name'] + json.lines do + json.array! section['Lines'] do |line| + json.leftIdx line['LeftIdx'] + json.rightIdx line['RightIdx'] + json.type line['Type'] + json.content line['Content'] + json.sectionInfo do + if line['SectionInfo'].blank? + json.nil! + else + json.path line['SectionInfo']['Path'] + json.lastLeftIdx line['SectionInfo']['LastLeftIdx'] + json.lastRightIdx line['SectionInfo']['LastRightIdx'] + json.leftIdx line['SectionInfo']['LeftIdx'] + json.rightIdx line['SectionInfo']['RightIdx'] + json.leftHunkSize line['SectionInfo']['LeftHunkSize'] + json.rightHunkSize line['SectionInfo']['RightHunkSize'] + end + end + end + end + end + end + end + end + end end diff --git a/app/views/pull_requests/files.json.jbuilder b/app/views/pull_requests/files.json.jbuilder index b40fe6068..9708ba843 100644 --- a/app/views/pull_requests/files.json.jbuilder +++ b/app/views/pull_requests/files.json.jbuilder @@ -1,4 +1,52 @@ json.files_count @files_result['NumFiles'] json.total_addition @files_result['TotalAddition'] json.total_deletion @files_result['TotalDeletion'] -json.files @files_result['Files'], partial: 'diff_file', as: :file, locals: {sha: @files_result['LatestSha']} + +# TODO: 解决 render partil file性能问题 +# json.files @files_result['Files'], partial: 'diff_file', as: :file, locals: {sha: @files_result['LatestSha']} +json.files do + json.array! @files_result['Files'] do |file| + json.sha @files_result['LatestSha'] + json.name file['Name'] + json.old_name file['OldName'] + json.index file['Index'] + json.addition file['Addition'] + json.deletion file['Deletion'] + json.type file['Type'] + json.isCreated file['IsCreated'] + json.isDeleted file['IsDeleted'] + json.isBin file['IsBin'] + json.isLFSFile file['IsLFSFile'] + json.isRenamed file['IsRenamed'] + json.isSubmodule file['IsSubmodule'] + json.isLFSFile file['IsLFSFile'] + json.sections do + json.array! file['Sections'] do |section| + json.fileName section['FileName'] + json.name section['Name'] + json.lines do + json.array! section['Lines'] do |line| + json.leftIdx line['LeftIdx'] + json.rightIdx line['RightIdx'] + json.type line['Type'] + json.content line['Content'] + json.sectionInfo do + if line['SectionInfo'].blank? + json.nil! + else + json.path line['SectionInfo']['Path'] + json.lastLeftIdx line['SectionInfo']['LastLeftIdx'] + json.lastRightIdx line['SectionInfo']['LastRightIdx'] + json.leftIdx line['SectionInfo']['LeftIdx'] + json.rightIdx line['SectionInfo']['RightIdx'] + json.leftHunkSize line['SectionInfo']['LeftHunkSize'] + json.rightHunkSize line['SectionInfo']['RightHunkSize'] + end + end + end + end + end + end + end + +end From 5667c0854c3bd25174125c956a6366af04d49d38 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 12 Jan 2021 17:34:07 +0800 Subject: [PATCH 06/35] FIX [api] get pull bug (cherry picked from commit fa01194d3c013112b6548abc20bf71c7d14b2609) --- app/controllers/compare_controller.rb | 20 ++++++++++++++++++-- app/views/pull_requests/show.json.jbuilder | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb index 0918b9d3b..63ca58aa6 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -6,10 +6,26 @@ class CompareController < ApplicationController end def show + compare + end + + private + def compare + base, head = compare_params + + # TODO: 处理fork的项目向源项目发送PR的base、head参数问题 + @compare_result ||= + head.include?(":") ? gitea_compare(base, head) : gitea_compare(head, base) + end + + def compare_params base = Addressable::URI.unescape(params[:base]) head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head] - @compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, head, base) - # render json: @compare_result + [base, head] + end + + def gitea_compare(base, head) + Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head) end end diff --git a/app/views/pull_requests/show.json.jbuilder b/app/views/pull_requests/show.json.jbuilder index 61bbc9159..14dfefefc 100644 --- a/app/views/pull_requests/show.json.jbuilder +++ b/app/views/pull_requests/show.json.jbuilder @@ -1,5 +1,6 @@ json.partial! "commons/success" json.project_name @project.name +json.identifier @project.identifier json.pr_time time_from_now(@pull_request.updated_at) json.commits_count @pull_request.commits_count json.files_count @pull_request.files_count From 10883bf05a8a35b5cbf1ec92280c0faafd73cee1 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Thu, 14 Jan 2021 17:04:58 +0800 Subject: [PATCH 07/35] FIX update cron (cherry picked from commit f959b38a89b3859aaa8cf52e00dfcfe9791dac72) --- config/schedule.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/schedule.yml b/config/schedule.yml index 2b4269ac4..c2def736a 100644 --- a/config/schedule.yml +++ b/config/schedule.yml @@ -1,5 +1,4 @@ sync_gitea_repo_updated_at: - # second minute hour day month date - cron: "0 0 24 * *" + cron: "0 0 * * * " class: "SyncRepoUpdateTimeJob" queue: default From e796776f1e7f962c03df677005f920b445f82528 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Thu, 14 Jan 2021 18:22:01 +0800 Subject: [PATCH 08/35] FIX updage sidekiq cron (cherry picked from commit 1e9bd451e59ab2589cce12f18fc99c40b0929ead) --- config/initializers/sidekiq.rb | 4 ++-- config/schedule.yml | 4 ---- config/sidekiq_cron.yml | 5 +++++ 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 config/schedule.yml create mode 100644 config/sidekiq_cron.yml diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 79a0e296f..d66225711 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1,10 +1,10 @@ redis_config = Rails.application.config_for(:redis) -sidekiq_url = redis_config["url"] +sidekiq_url = redis_config["url"] || 'redis://localhost:6379/0' Sidekiq.configure_server do |config| config.redis = { url: sidekiq_url } - schedule_file = "config/schedule.yml" + schedule_file = "config/sidekiq_cron.yml" if File.exists?(schedule_file) Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) end diff --git a/config/schedule.yml b/config/schedule.yml deleted file mode 100644 index c2def736a..000000000 --- a/config/schedule.yml +++ /dev/null @@ -1,4 +0,0 @@ -sync_gitea_repo_updated_at: - cron: "0 0 * * * " - class: "SyncRepoUpdateTimeJob" - queue: default diff --git a/config/sidekiq_cron.yml b/config/sidekiq_cron.yml new file mode 100644 index 000000000..5a7f530f9 --- /dev/null +++ b/config/sidekiq_cron.yml @@ -0,0 +1,5 @@ +sync_gitea_repo_update_time: + cron: "0 0 * * * " + class: "SyncRepoUpdateTimeJob" + queue: default + description: 'sync gitea repo update time From 536e78ffd6f2210cf0ad4c95ebb91e6f8d15b48e Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Thu, 14 Jan 2021 18:25:49 +0800 Subject: [PATCH 09/35] FIX code bug (cherry picked from commit 0e8d475de799bcf25533a4a6a1df9de89731b2b8) --- config/sidekiq_cron.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/sidekiq_cron.yml b/config/sidekiq_cron.yml index 5a7f530f9..35463673e 100644 --- a/config/sidekiq_cron.yml +++ b/config/sidekiq_cron.yml @@ -1,5 +1,5 @@ sync_gitea_repo_update_time: - cron: "0 0 * * * " + cron: "0 0 * * *" class: "SyncRepoUpdateTimeJob" queue: default description: 'sync gitea repo update time From 4b34822fe2df05aee50ecf874ac7c04d274fa6cd Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Thu, 14 Jan 2021 18:39:12 +0800 Subject: [PATCH 10/35] FIX sidekiq cron config yml bug (cherry picked from commit 2253dce4d734d0b1ac8b486e0006b4cfad8ff76d) --- config/sidekiq_cron.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/config/sidekiq_cron.yml b/config/sidekiq_cron.yml index 35463673e..3e807fa10 100644 --- a/config/sidekiq_cron.yml +++ b/config/sidekiq_cron.yml @@ -2,4 +2,3 @@ sync_gitea_repo_update_time: cron: "0 0 * * *" class: "SyncRepoUpdateTimeJob" queue: default - description: 'sync gitea repo update time From 6fa4ee6c14833ca5869a77827fc6c819f841e9fa Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 15 Jan 2021 15:38:49 +0800 Subject: [PATCH 11/35] ADD get readme api (cherry picked from commit 232f26ea3bf12aaca4b20e664ef72161392d87c5) --- api_document.md | 43 +++++++++++++++++++ app/controllers/repositories_controller.rb | 7 +++ .../gitea/repository/readme/get_service.rb | 39 +++++++++++++++++ config/routes.rb | 1 + 4 files changed, 90 insertions(+) create mode 100644 app/services/gitea/repository/readme/get_service.rb diff --git a/api_document.md b/api_document.md index 35618f799..da19c47ef 100644 --- a/api_document.md +++ b/api_document.md @@ -3062,6 +3062,49 @@ http://localhost:3000/api/trustie/truesite/protected_branches/master.json | jq ``` --- +#### 获取仓库README文件 +``` +GET api/:owner/:repo/readme +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/trusite/trusite/readme | jq +``` + +*请求参数说明:* + +|参数名|类型|说明| +|-|-|-| +|owner |是|string |项目拥有者登录名 | +|repo |否|boolean |仓库名称 | +|ref |否|string |分支、tag或commit。默认: 仓库的默认分支(通常是master)| + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|文件名称| +|path |string|文件相对路径| +|type |string|文件类型, file:文件| +|size |int|文件大小 单位KB| +|content |string|文件内容,base64加密| + +返回值 +```json +{ + "type": "file", + "encoding": "base64", + "size": 13544, + "name": "README.md", + "path": "README.md", + "content": "Q2hpbmVzZSAmbmJzcDsgfCAmbmJzcDsgW0VuZ7i9yZWFkbWUvaW5kZXgucG5" +} +``` +--- + + + ### DevOps相关api --- diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index c189bf24c..82f9e6c71 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -144,6 +144,13 @@ class RepositoriesController < ApplicationController render_ok end + def readme + result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token) + + @readme = result[:status] === :success ? result[:body] : nil + render json: @readme + end + private def find_project diff --git a/app/services/gitea/repository/readme/get_service.rb b/app/services/gitea/repository/readme/get_service.rb new file mode 100644 index 000000000..48e2d4475 --- /dev/null +++ b/app/services/gitea/repository/readme/get_service.rb @@ -0,0 +1,39 @@ +# Gets the preferred README for a repository. +class Gitea::Repository::Readme::GetService < Gitea::ClientService + attr_reader :owner, :repo, :ref, :token + + # owner: owner of the repo + # repo: name of the repo + # name: The name of the commit/branch/tag. Default: the repository’s default branch (usually master) + # eg: + # Gitea::Repository::Readme::GetService.call(user.login, repo.identifier, ref, user.gitea_token) + def initialize(owner, repo, ref, token=nil) + @owner = owner + @repo = repo + @ref = ref || 'master' + @token = token + end + + def call + response = get(url, params) + status, message, body = render_response(response) + json_format(status, message, body) + end + + private + def params + Hash.new.merge(token: token, ref: ref) + end + + def url + "/repos/#{owner}/#{repo}/readme".freeze + end + + def json_format(status, message, body) + case status + when 200 then success(body) + when 404 then error(message, 404) + else error(message, status) + end + end +end diff --git a/config/routes.rb b/config/routes.rb index c8d88d6dc..76a37dab0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -353,6 +353,7 @@ Rails.application.routes.draw do post :sync_mirror get :top_counts get 'commits/:sha', to: 'repositories#commit', as: 'commit' + get 'readme' end end From 06a7cb75580b43b328448ce96211bbd45b54b797 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 15 Jan 2021 18:36:19 +0800 Subject: [PATCH 12/35] FIX get readme file bug (cherry picked from commit 30138cc1fac6f70fb9dd2e4a84d933bb420ba2ab) --- app/helpers/repositories_helper.rb | 17 ++++++++++++++--- .../repositories/_simple_entry.json.jbuilder | 5 +++-- app/views/repositories/entries.json.jbuilder | 13 ++----------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 10ad1377e..07646c07a 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -11,7 +11,7 @@ module RepositoriesHelper end def download_type(str) - default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx) + default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot) default_type.include?(str&.downcase) end @@ -20,8 +20,8 @@ module RepositoriesHelper default_type.include?(str&.downcase) end - def is_readme_type?(str) - return false if str.blank? + def is_readme?(type, str) + return false if type != 'file' || str.blank? readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"] readme_types.include?(str.to_s.downcase) end @@ -72,4 +72,15 @@ module RepositoriesHelper def render_format_time_with_date(date) date.to_time.strftime("%Y-%m-%d %H:%M") end + + def decode64_content(entry, owner, repo, ref, path=nil) + if is_readme?(entry['type'], entry['name']) + content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] + readme_render_decode64_content(content, path) + else + file_type = entry['name'].to_s.split(".").last + return entry['content'] if download_type(file_type) + render_decode64_content(entry['content']) + end + end end diff --git a/app/views/repositories/_simple_entry.json.jbuilder b/app/views/repositories/_simple_entry.json.jbuilder index ab9910dd1..1e8e001af 100644 --- a/app/views/repositories/_simple_entry.json.jbuilder +++ b/app/views/repositories/_simple_entry.json.jbuilder @@ -8,12 +8,13 @@ if @project.forge? json.path entry['path'] json.type entry['type'] json.size entry['size'] - json.content entry['content'].present? && !direct_download ? render_decode64_content(entry['content']) : "" + + json.content decode64_content(entry, @owner, @repository, @ref) json.target entry['target'] json.download_url entry['download_url'] json.direct_download direct_download json.image_type image_type - json.is_readme_file is_readme_type?(file_name) + json.is_readme_file is_readme?(entry['type'], entry['name']) if entry['latest_commit'] if entry['type'] != 'file' json.partial! 'last_commit', entry: entry diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index 20fecec32..ca041fd53 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -51,17 +51,8 @@ if @project.forge? json.sha entry['sha'] json.type entry['type'] json.size entry['size'] - content = - if is_readme_type?(entry['name']) - is_readme_file = true - content = Gitea::Repository::Entries::GetService.call(@owner, @project.identifier, entry['name'], ref: @ref)['content'] - readme_render_decode64_content(content, @path) - else - is_readme_file = false - entry['content'] - end - json.is_readme_file is_readme_file - json.content content + json.is_readme_file is_readme?(entry['type'], entry['name']) + json.content decode64_content(entry, @owner, @repository, @ref, @path) json.target entry['target'] if entry['latest_commit'] json.partial! 'last_commit', entry: entry From ffeb0760862e9cca67f41d8256446febef4af971 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 15 Jan 2021 18:38:53 +0800 Subject: [PATCH 13/35] FIX pull api bug (cherry picked from commit 36a3e36edb21fe6cb0d0af143a965649f18e8fa1) --- app/controllers/pull_requests_controller.rb | 4 ++-- app/services/gitea/pull_request/commits_service.rb | 2 +- app/views/pull_requests/show.json.jbuilder | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 50e904565..145194759 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -187,12 +187,12 @@ class PullRequestsController < ApplicationController def files - @files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid) + @files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid, current_user&.gitea_token) # render json: @files_result end def commits - @commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid) + @commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid, current_user&.gitea_token) # render json: @commits_result end diff --git a/app/services/gitea/pull_request/commits_service.rb b/app/services/gitea/pull_request/commits_service.rb index aca2067cc..dc2877eba 100644 --- a/app/services/gitea/pull_request/commits_service.rb +++ b/app/services/gitea/pull_request/commits_service.rb @@ -22,7 +22,7 @@ class Gitea::PullRequest::CommitsService < Gitea::ClientService private def params - Hash.new.merge(token: owner) + Hash.new.merge(token: token) end def url diff --git a/app/views/pull_requests/show.json.jbuilder b/app/views/pull_requests/show.json.jbuilder index 14dfefefc..c3f781f73 100644 --- a/app/views/pull_requests/show.json.jbuilder +++ b/app/views/pull_requests/show.json.jbuilder @@ -1,6 +1,7 @@ json.partial! "commons/success" json.project_name @project.name json.identifier @project.identifier +json.project_identifier @project.identifier json.pr_time time_from_now(@pull_request.updated_at) json.commits_count @pull_request.commits_count json.files_count @pull_request.files_count @@ -10,6 +11,7 @@ json.pull_request do json.extract! @pull_request, :id,:base, :head, :status,:fork_project_id, :is_original json.pull_request_staus @pull_request.status == 1 ? "merged" : (@pull_request.status == 2 ? "closed" : "open") json.fork_project_user @pull_request&.fork_project&.owner.try(:login) + json.create_user @pull_request&.user&.login end json.issue do From 18c989bb6f6a0c419dd05fa105f85a0d9911dab2 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Mon, 18 Jan 2021 09:51:07 +0800 Subject: [PATCH 14/35] Update api document (cherry picked from commit 0f338ede7d94e0b1d73e7831628c3888987ce507) --- api_document.md | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/api_document.md b/api_document.md index da19c47ef..9c927760c 100644 --- a/api_document.md +++ b/api_document.md @@ -450,7 +450,7 @@ curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror | jq #### 项目详情 ``` -GET /api/:namespace_id/:id +GET /api/:owner/:repo ``` *示例* ```bash @@ -460,8 +460,8 @@ curl -X GET http://localhost:3000/api/jasder/jasder_test | jq |参数名|必选|类型|说明| |-|-|-|-| -|namespace_id |是|string |用户登录名 | -|id |是|string |项目标识identifier | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | *返回参数说明:* @@ -492,7 +492,7 @@ curl -X GET http://localhost:3000/api/jasder/jasder_test | jq #### 项目详情(简版) ``` -GET /api/:namespace_id/:id/simple +GET /api/:owner/:repo/simple ``` *示例* ```bash @@ -502,7 +502,8 @@ curl -X GET http://localhost:3000/api/jasder/jasder_test/simple | jq |参数名|必选|类型|说明| |-|-|-|-| -|id |是|int |项目id | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | *返回参数说明:* @@ -862,7 +863,7 @@ curl -X POST http://localhost:3000/api/projects/3297/forks | jq #### 获取代码目录列表 ``` -POST /api/:namespace_id/:project_id/repository/entries +POST /api/:owner/:repo/repository/entries ``` *示例* ```bash @@ -874,7 +875,8 @@ http://localhost:3000//api/jasder/jasder_test/repository/entries | jq |参数名|必选|类型|说明| |-|-|-|-| -|id |是|int |项目id | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | |ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | @@ -1344,7 +1346,7 @@ http://localhost:3000/api/projects/recommend | jq #### 项目主页 ``` -GET api/:namespace_id/:id/about +GET api/:owner/:repo/about ``` *示例* @@ -1357,8 +1359,8 @@ http://localhost:3000/api/:jason/forgeplus/about | jq |参数名|必选|类型|说明| |-|-|-|-| -|namespace_id |是|string |用户登录名 | -|id |是|string |项目标识identifier | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | *返回参数说明:* @@ -1385,7 +1387,7 @@ http://localhost:3000/api/:jason/forgeplus/about | jq #### 修改项目主页内容 ``` -POST api/:namespace_id/:id/about +POST api/:owner/:repo/about ``` *示例* @@ -1393,15 +1395,15 @@ POST api/:namespace_id/:id/about curl -X POST \ -d "content=内容" \ -d "attachment_ids=[1, 2, 2]" \ -http://localhost:3000/api/:jasder/forgeplus/about | jq +http://localhost:3000/api/jasder/forgeplus/about | jq ``` *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| -|namespace_id |是|string |用户登录名 | -|id |是|string |项目标识identifier | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | |content |是|string |内容信息 | |attachment_ids |是|array |附件id | @@ -1429,7 +1431,7 @@ http://localhost:3000/api/:jasder/forgeplus/about | jq ### 获取分支列表 ``` -GET /api/:namespace_id/:id/branches +GET /api/:owner/:repo/branches ``` *示例* ```bash @@ -1439,7 +1441,8 @@ curl -X GET http://localhost:3000/api/jasder/jasder_test/branches | jq |参数名|必选|类型|说明| |-|-|-|-| -|id |是|id |项目id | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | *返回参数说明:* @@ -1596,7 +1599,7 @@ http://localhost:3000/api/repositories/5836/tags.json | jq ## 仓库详情 ``` -GET /api/:namespace_id/:project_id/repository +GET /api/:owner/:repo/repository ``` *示例* ```bash @@ -1607,8 +1610,8 @@ http://192.168.2.230:3000/api/jasder/forgeplus/repository | jq |参数名|必选|类型|说明| |-|-|-|-| -|namespace_id |是|string |用户登录名 | -|project_id |是|string |项目标识identifier | +|owner |是|string |用户登录名 | +|repo |是|string |项目标识identifier | *返回参数说明:* From 814a1d9e6a6b816b5054af901674f18752aff57b Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Mon, 18 Jan 2021 11:22:31 +0800 Subject: [PATCH 15/35] FIX deal with gitea api response body bug (cherry picked from commit e7662b66ce6b8bf2886da541c54d9264167d7efa) --- app/services/gitea/client_service.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb index 728a98098..1e9de823c 100644 --- a/app/services/gitea/client_service.rb +++ b/app/services/gitea/client_service.rb @@ -178,8 +178,10 @@ class Gitea::ClientService < ApplicationService def get_body_by_status(status, body) body, message = case status + when 401 then [nil, "401"] when 404 then [nil, "404"] when 403 then [nil, "403"] + when 500 then [nil, "500"] else if body.present? body = JSON.parse(body) @@ -198,7 +200,7 @@ class Gitea::ClientService < ApplicationService end def fix_body(body) - return [body, nil] if body.is_a? Array + return [body, nil] if body.is_a?(Array) || body.is_a?(Hash) body['message'].blank? ? [body, nil] : [nil, body['message']] end From 1c59832abfa42ae403feac2683d3fa94955069ee Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Mon, 18 Jan 2021 15:28:20 +0800 Subject: [PATCH 16/35] FIX get assignees bug in issues (cherry picked from commit e9223c53dec8180ab96ae6cc5d641808c649c59a) --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 190f37760..4b9e72e19 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -123,7 +123,7 @@ class Project < ApplicationRecord end def members_user_infos - members.joins(:roles).where("roles.name in ('Manager', 'Developer')").joins("left join users on members.user_id = users.id ").includes(:user).where("users.type = ?", "User") + members.joins(:roles).where("roles.name in ('Manager', 'Developer', 'Reporter')").joins("left join users on members.user_id = users.id ").includes(:user).where("users.type = ?", "User") # members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname") # .pluck("users.id", "users.login","users.lastname", "users.firstname") end From 0adcbaa19fb6a69f94f6745e55a791bd8acefe31 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 19 Jan 2021 16:21:31 +0800 Subject: [PATCH 17/35] ADD repository languages percentage api (cherry picked from commit efa99e0f0633dd24871ae5fa6868d3d3e53c9d0a) --- api_document.md | 29 ++++++++++++++ .../repository/languages_percentagable.rb | 19 +++++++++ app/controllers/repositories_controller.rb | 5 +++ .../repository/languages/list_service.rb | 39 +++++++++++++++++++ config/routes.rb | 1 + 5 files changed, 93 insertions(+) create mode 100644 app/controllers/concerns/repository/languages_percentagable.rb create mode 100644 app/services/gitea/repository/languages/list_service.rb diff --git a/api_document.md b/api_document.md index 9c927760c..27c71b901 100644 --- a/api_document.md +++ b/api_document.md @@ -3106,6 +3106,35 @@ curl -X GET http://localhost:3000/api/trusite/trusite/readme | jq ``` --- +#### 获取仓库仓库的语言百分占比 +``` +GET api/:owner/:repo/languages +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/jasder/trusite/languages | jq +``` + +*请求参数说明:* + +|参数名|类型|说明| +|-|-|-| +|owner |是|string |项目拥有者登录名 | +|repo |否|boolean |仓库名称 | + + +返回值 +```json +{ + "JavaScript": "90.2%", + "CSS": "6.1%", + "Java": "2.9%", + "HTML": "0.8%" +} +``` +--- + + ### DevOps相关api diff --git a/app/controllers/concerns/repository/languages_percentagable.rb b/app/controllers/concerns/repository/languages_percentagable.rb new file mode 100644 index 000000000..620d93bf9 --- /dev/null +++ b/app/controllers/concerns/repository/languages_percentagable.rb @@ -0,0 +1,19 @@ +module Repository::LanguagesPercentagable + extend ActiveSupport::Concern + + def languages_precentagable + result = Gitea::Repository::Languages::ListService.call(@owner.login, + @repository.identifier, current_user&.gitea_token) + + result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil + end + + # hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781} + def hash_transform_precentagable(hash) + total_byte_size = hash.values.sum + hash.transform_values { |v| + ActionController::Base.helpers + .number_to_percentage((v * 100.0 / total_byte_size), precision: 1) + } + end +end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 82f9e6c71..7e708f5e1 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -1,6 +1,7 @@ class RepositoriesController < ApplicationController include ApplicationHelper include OperateProjectAbilityAble + include Repository::LanguagesPercentagable before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] before_action :load_repository @@ -151,6 +152,10 @@ class RepositoriesController < ApplicationController render json: @readme end + def languages + render json: languages_precentagable + end + private def find_project diff --git a/app/services/gitea/repository/languages/list_service.rb b/app/services/gitea/repository/languages/list_service.rb new file mode 100644 index 000000000..88d5dcbed --- /dev/null +++ b/app/services/gitea/repository/languages/list_service.rb @@ -0,0 +1,39 @@ +# Get languages and number of bytes of code written +class Gitea::Repository::Languages::ListService < Gitea::ClientService + attr_reader :owner, :repo, :token + + # owner: owner of the repo + # repo: the name of repository + # token: token of gitea user + # eq: Gitea::Repository::Languages::ListService.call(@owner.identifier, + # @project.identifier, current_user&.gitea_token) + def initialize(owner, repo, token) + @owner = owner + @repo = repo + @args = token + end + + def call + response = get(url, params) + + status, message, body = render_response(response) + json_format(status, message, body) + end + + private + def params + {}.merge(token: token) + end + + def url + "/repos/#{owner}/#{repo}/languages".freeze + end + + def json_format(status, message, body) + case status + when 200 then success(body) + else + error(message, status) + end + end +end diff --git a/config/routes.rb b/config/routes.rb index 76a37dab0..8af453cf8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -354,6 +354,7 @@ Rails.application.routes.draw do get :top_counts get 'commits/:sha', to: 'repositories#commit', as: 'commit' get 'readme' + get 'languages' end end From 67a7df085c971ecf85c5d399f9e954623c8e05bf Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Wed, 20 Jan 2021 09:38:11 +0800 Subject: [PATCH 18/35] ADD sync repo time print log (cherry picked from commit f3d4f437cbd2c60d5159fe705fd55a07e2fa2d91) --- api_document.md | 2 +- app/jobs/sync_repo_update_time_job.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api_document.md b/api_document.md index 27c71b901..b39eb25ad 100644 --- a/api_document.md +++ b/api_document.md @@ -3106,7 +3106,7 @@ curl -X GET http://localhost:3000/api/trusite/trusite/readme | jq ``` --- -#### 获取仓库仓库的语言百分占比 +#### 获库仓库的语言百分占比 ``` GET api/:owner/:repo/languages ``` diff --git a/app/jobs/sync_repo_update_time_job.rb b/app/jobs/sync_repo_update_time_job.rb index c2337ab94..4391f2c13 100644 --- a/app/jobs/sync_repo_update_time_job.rb +++ b/app/jobs/sync_repo_update_time_job.rb @@ -11,9 +11,9 @@ class SyncRepoUpdateTimeJob < ApplicationJob private def gitea_repo_updated_at(project) admin = User.where(admin: true).select(:id, :gitea_token, :gitea_uid).last + puts "########## project id: #{project.id}" return nil if project.gpid.blank? - result = Gitea::Repository::GetByIdService.call(project.gpid, admin.gitea_token) result[:status] === :success ? result[:body]['updated_at'] : nil From 6d51657ecf974ea603c5eda80fe6a13d1ade5bc2 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Wed, 20 Jan 2021 14:25:07 +0800 Subject: [PATCH 19/35] FIX get latest commit bug (cherry picked from commit b7e23a62d0f7fd340d3a2c0582e29a4c6871fc87) --- .../repositories/_last_commit.json.jbuilder | 14 ++++++++------ .../repositories/_simple_entry.json.jbuilder | 17 ++++++++--------- app/views/repositories/entries.json.jbuilder | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/app/views/repositories/_last_commit.json.jbuilder b/app/views/repositories/_last_commit.json.jbuilder index 3c2184637..0c3127384 100644 --- a/app/views/repositories/_last_commit.json.jbuilder +++ b/app/views/repositories/_last_commit.json.jbuilder @@ -1,7 +1,9 @@ -json.commit do - json.message entry['latest_commit']['message'] - json.sha entry['latest_commit']['sha'] - json.created_at render_format_time_with_unix(entry['latest_commit']['created_at'].to_i) - json.time_from_now time_from_now(render_format_time_with_unix(entry['latest_commit']['created_at'].to_i)) - json.created_at_unix entry['latest_commit']['created_at'] +if latest_commit.blank? + json.nil! +else + json.message latest_commit['message'] + json.sha latest_commit['sha'] + json.created_at render_format_time_with_unix(latest_commit['created_at'].to_i) + json.time_from_now time_from_now(render_format_time_with_unix(latest_commit['created_at'].to_i)) + json.created_at_unix latest_commit['created_at'] end diff --git a/app/views/repositories/_simple_entry.json.jbuilder b/app/views/repositories/_simple_entry.json.jbuilder index 1e8e001af..ec2a045bb 100644 --- a/app/views/repositories/_simple_entry.json.jbuilder +++ b/app/views/repositories/_simple_entry.json.jbuilder @@ -15,12 +15,8 @@ if @project.forge? json.direct_download direct_download json.image_type image_type json.is_readme_file is_readme?(entry['type'], entry['name']) - if entry['latest_commit'] - if entry['type'] != 'file' - json.partial! 'last_commit', entry: entry - else - json.commit nil - end + json.commit do + json.partial! 'last_commit', latest_commit: entry['latest_commit'] end end @@ -38,8 +34,11 @@ if @project.educoder? json.direct_download false json.image_type false json.is_readme_file false - if entry['latest_commit'] - # json.partial! 'last_commit', entry: entry - json.partial! 'repositories/simple_entry', locals: { entry: entry } + json.commit do + json.message entry['title'] + json.time_from_now entry['time'] + json.sha nil + json.created_at_unix nil + json.created_at nil end end diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index ca041fd53..9efa0c113 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -54,8 +54,8 @@ if @project.forge? json.is_readme_file is_readme?(entry['type'], entry['name']) json.content decode64_content(entry, @owner, @repository, @ref, @path) json.target entry['target'] - if entry['latest_commit'] - json.partial! 'last_commit', entry: entry + json.commit do + json.partial! 'last_commit', latest_commit: entry['latest_commit'] end end end From 6c77b73ec65c3019035c8783d6eb6fcd84fcd8a3 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Tue, 26 Jan 2021 17:15:53 +0800 Subject: [PATCH 20/35] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E3=80=81=E6=A8=A1=E6=9D=BF=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api_document.md | 227 ++++++++++++++++-- app/controllers/ci/base_controller.rb | 4 + .../ci/cloud_accounts_controller.rb | 2 +- app/controllers/ci/pipelines_controller.rb | 156 +++++++----- app/controllers/ci/projects_controller.rb | 9 +- app/controllers/ci/templates_controller.rb | 79 ++++-- .../concerns/ci/cloud_account_manageable.rb | 3 - app/models/ci/build.rb | 2 + app/models/ci/perm.rb | 6 +- app/models/ci/pipeline.rb | 7 +- app/models/ci/repo.rb | 63 ++++- app/models/ci/template.rb | 4 + app/queries/ci/builds/list_query.rb | 3 + app/views/ci/builds/_author.json.jbuilder | 2 +- app/views/ci/pipelines/_list.json.jbuilder | 6 +- app/views/ci/pipelines/list.json.jbuilder | 1 + app/views/ci/templates/_list.json.jbuilder | 1 + app/views/ci/templates/list.json.jbuilder | 1 + app/views/ci/templates/show.json.jbuilder | 9 + config/routes.rb | 2 +- ...ranch_and_event_and_sha_to_ci_pipelines.rb | 7 + ...0210126071814_add_login_to_ci_templates.rb | 5 + 22 files changed, 476 insertions(+), 123 deletions(-) create mode 100644 app/views/ci/templates/show.json.jbuilder create mode 100644 db/migrate/20210122052755_add_branch_and_event_and_sha_to_ci_pipelines.rb create mode 100644 db/migrate/20210126071814_add_login_to_ci_templates.rb diff --git a/api_document.md b/api_document.md index b39eb25ad..fa536b9ec 100644 --- a/api_document.md +++ b/api_document.md @@ -3520,6 +3520,7 @@ http://localhost:3000/api/Jason/forge/builds | jq |page |否|string |页数,第几页 | |limit |否|string |每页多少条数据,默认20条 | |search |是|string |构建状态条件过滤; 值说明:pending: 准备中,failure: 构建失败,running: 运行中,error:构建失败(.trustie-pipeline.yml文件错误),success: 构建成功,killed: 撤销构建 | +|branch |是|string |分支 | *返回参数说明:* @@ -4042,13 +4043,15 @@ http://localhost:3000/api/ci/pipelines/list.json?identifier="xxx" | jq *返回参数说明:* -| 参数名 | 类型 | 说明 | -| ------------- | ------ | --------------- | -| id | int | 流水线id | -| pipeline_name | string | 流水线名称 | -| file_name | string | 流水线文件名 | -| created_at | string | 创建时间 | -| sync | int | 是否同步到gitea | +| 参数名 | 类型 | 说明 | +| ----------------- | ------ | ------------ | +| id | int | 流水线id | +| pipeline_name | string | 流水线名称 | +| file_name | string | 流水线文件名 | +| branch | string | 触发分支 | +| event | string | 触发事件 | +| last_build_time | string | 上次构建时间 | +| last_build_status | string | 上次构建状态 | 返回值 @@ -4056,11 +4059,15 @@ http://localhost:3000/api/ci/pipelines/list.json?identifier="xxx" | jq { "pipelines": [ { - "id": 1, - "pipeline_name": "2020-01-08 流水线", - "file_name": ".trustie.pipeline.yaml", - "created_at": "2021-01-08 04:16:24", - "updated_at": "2021-01-08 04:16:24" + "id": 65, + "pipeline_name": "流水线 2021-01-25", + "file_name": ".drone.yml", + "branch": "develop", + "event": "push", + "sha": "19fb5eb28603a4a1ec799ad44c1a3ef69d5c2cd0", + "identifier": "trustieTest", + "last_build_status": "success", + "last_build_time": "2021-01-25 15:54:22" } ] } @@ -4082,7 +4089,10 @@ curl --location --request POST 'http://localhost:3000/api/ci/pipelines' \ --data-raw ' { "pipeline_name": "流水线 2021-01-12", "file_name": ".trustie.pipeline.yaml", - "identifier": "xxx" + "repo": "xxx", + "owner": "xxx", + "branch": "master", + "event": "push" }' ``` @@ -4092,7 +4102,10 @@ curl --location --request POST 'http://localhost:3000/api/ci/pipelines' \ | ------------- | ---- | ------ | ---------------------------------------------- | | pipeline_name | 是 | string | 流水线名称 | | file_name | 是 | string | 文件名称(默认初始值:.trustie.pipeline.yaml) | -| identifier | 是 | string | 项目identifier | +| repo | 是 | string | 项目identifier | +| owner | 是 | string | 项目的owner | +| branch | 否 | string | 分支名称, branch必须存在一个 | +| event | 是 | string | 触发事件,可多选,多个逗号隔开 | *返回参数说明:* @@ -4633,6 +4646,192 @@ http://localhost:3000/api/ci/templates/templates_by_stage.json?stage_type=build ------ +#### 模板列表查询 + +``` +GET /api/ci/templates/list.json?limit=10&page=1&name=&stage_type=customize +``` + +*示例* + +```bash +curl --location --request GET 'http://localhost:3000/api/ci/templates/list.json?limit=10&page=1&name=&stage_type=customize' +``` + +*请求参数说明:* + +| 参数名 | 必选 | 类型 | 说明 | +| ---------- | ---- | ------ | ----------------------------------------- | +| stage_type | 是 | string | 阶段类型:init/build/deploy/customize/all | +| limit | 是 | int | 每页条数 | +| page | 是 | int | 页码 | +| name | 否 | string | 模糊查询参数 | + +*返回参数说明:* + +| 参数名 | 类型 | 说明 | +| ------------- | ------ | ---------------- | +| category | string | 分类名称 | +| templates | arr | 分类下的模板列表 | +| id | int | 模板id | +| template_name | string | 模板名称 | +| content | String | 模板内容 | + +返回值 + +```json +{ + "total_count": 1, + "templates": [ + { + "id": 19, + "template_name": "工具1", + "stage_type": "customize", + "category": "其他", + "content": "xxxxxxxxxxxxxxxxxxxxxx", + "login": "victor", + "created_at": "2021-01-26T15:51:30.000+08:00", + "updated_at": "2021-01-26T15:51:30.000+08:00" + } + ] +} +``` + + + +------ + +#### 模板详情查询 + +``` +GET /api/ci/templates/id +``` + +*示例* + +```bash +curl --location --request GET 'http://localhost:3000/api/ci/templates/17.json' +``` + +*请求参数说明:* + +| 参数名 | 必选 | 类型 | 说明 | +| ------ | ---- | ---- | ------ | +| id | 是 | int | 模板id | + +*返回参数说明:* + +| 参数名 | 类型 | 说明 | +| ------------- | ------ | -------- | +| category | string | 分类名称 | +| id | int | 模板id | +| template_name | string | 模板名称 | +| content | String | 模板内容 | + +返回值 + +```json +{ + "id": 17, + "template_name": "win/x86_64", + "stage_type": "init", + "category": "初始化", + "content": "kind: pipeline\r\ntype: docker\r\nname: default\r\nplatform:\r\n os: linux\r\n arch: amd64", + "login": "victor", + "created_at": "2021-01-26T15:29:27.000+08:00", + "updated_at": "2021-01-26T15:29:27.000+08:00" +} +``` + + + +------ + +#### 模板新增/更新 + +``` +POST /api/ci/templates +``` + +*示例* + +```bash +curl --location --request POST 'http://localhost:3000/api/ci/templates' \ +--data-raw ' { + "template_name": "java++", + "stage_type": "build", + "category": "java", + "content": "xxxxxxxxxxxxxxxxxxxxxx", + "id": 21 +}' +``` + +*请求参数说明:* + +| 参数名 | 必选 | 类型 | 说明 | +| ------------- | ---- | ------ | ---------------- | +| template_name | 是 | string | 模板名称 | +| stage_type | 是 | string | 阶段类型 | +| category | 是 | string | 分类 | +| content | 是 | string | 模板内容 | +| id | 否 | int | 模板id,更新时传 | + +*返回参数说明:* + +| 参数名 | 类型 | 说明 | +| ------- | ------ | ------------ | +| status | int | 状态码 0成功 | +| message | string | 消息 | + +返回值 + +```json +{ + "status": 0, + "message": "success" +} +``` + +------ + +#### 模板删除 + +``` +DELETE /api/ci/templates/{id} +``` + +*示例* + +```bash +curl --location --request DELETE 'http://localhost:3000/api/ci/templates/10' +``` + +*请求参数说明:* + +| 参数名 | 必选 | 类型 | 说明 | +| ------ | ---- | ---- | -------- | +| id | 是 | int | 流水线id | + +*返回参数说明:* + +| 参数名 | 类型 | 说明 | +| ------- | ------ | ------------ | +| status | int | 状态码 0成功 | +| message | string | 返回消息 | + +返回值 + +```json +{ + "status": 0, + "message": "success" +} +``` + +------ + +------ + #### 解除CI服务器绑定 ``` diff --git a/app/controllers/ci/base_controller.rb b/app/controllers/ci/base_controller.rb index 5aedbddbf..1649721cd 100644 --- a/app/controllers/ci/base_controller.rb +++ b/app/controllers/ci/base_controller.rb @@ -16,6 +16,10 @@ class Ci::BaseController < ApplicationController @repos = Ci::Repo.find_all_with_namespace(namespace) end + def load_repo_by_repo_slug(slug) + @repo_slug = Ci::Repo.load_repo_by_repo_slug(slug) + end + private def authorize_access_project! unless @project.manager?(current_user) diff --git a/app/controllers/ci/cloud_accounts_controller.rb b/app/controllers/ci/cloud_accounts_controller.rb index 043d24fe0..7d829dbd7 100644 --- a/app/controllers/ci/cloud_accounts_controller.rb +++ b/app/controllers/ci/cloud_accounts_controller.rb @@ -38,7 +38,7 @@ class Ci::CloudAccountsController < Ci::BaseController ActiveRecord::Base.transaction do if @repo return render_error('该项目已经激活') if @repo.repo_active? - @repo.activate!(@ci_user.user_id) + @repo.activate!(@project) else @repo = Ci::Repo.auto_create!(@ci_user, @project) @user.update_column(:user_syncing, false) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index 19460fde9..50417ce80 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -1,18 +1,37 @@ class Ci::PipelinesController < Ci::BaseController before_action :require_login, only: %i[list create] - skip_before_action :connect_to_ci_db - before_action :load_project, only: %i[content create_trustie_pipeline] - before_action :load_repository, only: %i[create_trustie_pipeline] + skip_before_action :connect_to_ci_db, except: %i[list create destroy] + before_action :load_project, only: %i[create] + before_action :load_repo, only: %i[create] # ======流水线相关接口========== # def list - @pipelines = Ci::Pipeline.where('identifier=?', params[:identifier]) + @result = Array.new + list = Ci::Pipeline.where('identifier=?', params[:identifier]) + # 查询build状态 + list = list.collect do |pipeline| + repo = load_repo_by_repo_slug("#{pipeline.login}/#{pipeline.identifier}") + build = repo.builds.order("build_created desc").find_by(build_target: pipeline.branch) + if build + pipeline.pipeline_status = build.build_status + pipeline.last_build_time = Time.at(build.build_created) + end + @result.push(pipeline) + end + @total_count = @result.size + @pipelines = paginate @result end def create ActiveRecord::Base.transaction do - pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name], login: current_user.login, identifier: params[:identifier]) + size = Ci::Pipeline.where('branch=? and identifier=?', params[:branch], params[:repo]).size + if size > 0 + render_error("#{params[:branch]}分支已经存在流水线!") + return + end + pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name], + login: current_user.login, identifier: params[:repo], branch: params[:branch], event: params[:event]) pipeline.save! # 默认创建四个初始阶段 @@ -26,12 +45,70 @@ class Ci::PipelinesController < Ci::BaseController ).save! index += 1 end + create_pipeline_file(pipeline) + create_ci_repo(pipeline) render_ok({id: pipeline.id}) end rescue Exception => ex render_error(ex.message) end + # 在代码库创建文件 + def create_pipeline_file(pipeline) + sha = get_pipeline_file_sha(pipeline.file_name, pipeline.branch) + if sha + logger.info "#{pipeline.file_name}已存在" + pipeline.update!(sync: 1, sha: sha) + else + interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) + if interactor.success? + logger.info "#{pipeline.file_name}创建成功" + pipeline.update!(sync: 1, sha: interactor.result['content']['sha']) + end + end + end + + # 在drone数据库repo表新增一条repo记录 + def create_ci_repo(pipeline) + create_params = { + repo_user_id: @ci_user.user_id, + repo_namespace: @project.owner.login, + repo_name: @project.identifier, + repo_slug: "#{@project.owner.login}/#{@project.identifier}-" + pipeline.id.to_s, + repo_clone_url: @project.repository.url, + repo_branch: pipeline.branch, + repo_config: pipeline.file_name + } + repo = Ci::Repo.create_repo(create_params) + repo + end + + def get_pipeline_file_sha(file_name, branch) + file_path_uri = URI.parse(file_name) + interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: branch || 'master') + if interactor.success? + file = interactor.result + return file['sha'] + else + return nil + end + end + + def content_params + { + filepath: params[:file_name], + branch: params[:branch], + new_branch: params[:new_branch], + content: "#pipeline \n", + message: 'create pipeline', + committer: { + email: current_user.mail, + name: current_user.login + }, + identifier: params[:repo] + } + end + def update pipeline = Ci::Pipeline.find(params[:id]) if pipeline @@ -45,6 +122,10 @@ class Ci::PipelinesController < Ci::BaseController def destroy pipeline = Ci::Pipeline.find(params[:id]) if pipeline + repo = load_repo_by_repo_slug("#{pipeline.login}/#{pipeline.identifier}-" + pipeline.id.to_s) + if repo + repo.destroy! + end pipeline.destroy! end render_ok @@ -53,10 +134,9 @@ class Ci::PipelinesController < Ci::BaseController end def content - @yaml = "#pipeline \n" + @yaml = "\n" pipeline = Ci::Pipeline.find(params[:id]) - @sync = pipeline.sync - @sha = '' + @sha = pipeline.sha stages = pipeline.pipeline_stages if stages && !stages.empty? init_step = stages.first.pipeline_stage_steps.first @@ -72,55 +152,13 @@ class Ci::PipelinesController < Ci::BaseController end end end - if @sync == 1 - @sha = get_pipeline_file_sha(pipeline.file_name) + trigger = '' + trigger += " branch:\r\n - #{pipeline.branch}\r\n" unless pipeline.branch.blank? + unless pipeline.event.blank? + trigger += " event:\r\n" + pipeline.event.split(',').each { |event| trigger += " - #{event}\r\n"} end - end - - def get_pipeline_file_sha(file_name) - file_path_uri = URI.parse(file_name) - interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master") - if interactor.success? - file = interactor.result - return file['sha'] - end - end - - def create_trustie_pipeline - pipeline = Ci::Pipeline.find(params[:id]) - sha = get_pipeline_file_sha(pipeline.file_name) - if sha - pipeline.update!(sync: 1) - interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, params[:owner], params.merge(identifier: @project.identifier,sha: sha)) - if interactor.success? - render_ok - else - render_error(interactor.error) - end - else - interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) - if interactor.success? - pipeline.update!(sync: 1) - render_ok - else - render_error(interactor.error) - end - end - end - - def content_params - { - filepath: params[:filepath], - branch: params[:branch], - new_branch: params[:new_branch], - content: params[:content], - message: params[:message], - committer: { - email: current_user.mail, - name: current_user.login - }, - identifier: @project.identifier - } + @yaml += "trigger:\r\n" + trigger unless trigger.blank? end # =========阶段相关接口========= # @@ -135,8 +173,8 @@ class Ci::PipelinesController < Ci::BaseController # 修改stage排序 update_stage_index(params[:id], params[:show_index], 1) pipeline_stage = Ci::PipelineStage.new(stage_name: params[:stage_name], - stage_type: params[:stage_type].blank? ? 'customize' : params[:stage_type], - pipeline_id: params[:id], show_index: params[:show_index]) + stage_type: params[:stage_type].blank? ? 'customize' : params[:stage_type], + pipeline_id: params[:id], show_index: params[:show_index]) pipeline_stage.save! render_ok end @@ -188,7 +226,7 @@ class Ci::PipelinesController < Ci::BaseController unless steps.empty? steps.each do |step| unless step[:template_id] - render_error("请选择模板!") + render_error('请选择模板!') return end if !step[:id] diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb index c7b7338f1..69644e7a5 100644 --- a/app/controllers/ci/projects_controller.rb +++ b/app/controllers/ci/projects_controller.rb @@ -41,11 +41,8 @@ class Ci::ProjectsController < Ci::BaseController ActiveRecord::Base.transaction do if @repo return render_error('该项目已经激活') if @repo.repo_active? - if @project.ci_reactivate? - @project.ci_reactivate!(@repo) - return render_ok - end - @repo.activate!(@ci_user.user_id) + @repo.activate!(@project) + return render_ok else @repo = Ci::Repo.auto_create!(@ci_user, @project) @ci_user.update_column(:user_syncing, false) @@ -66,7 +63,7 @@ class Ci::ProjectsController < Ci::BaseController return render_error('该项目已经取消激活') if !@repo.repo_active? @project.update_column(:open_devops, false) - @repo.deactivate! + @repo.deactivate_repos! render_ok end diff --git a/app/controllers/ci/templates_controller.rb b/app/controllers/ci/templates_controller.rb index c77a91445..11c6f2779 100644 --- a/app/controllers/ci/templates_controller.rb +++ b/app/controllers/ci/templates_controller.rb @@ -1,30 +1,53 @@ -class Ci::TemplatesController < ApplicationController +class Ci::TemplatesController < Ci::BaseController + before_action :require_login, only: %i[list create] + skip_before_action :connect_to_ci_db + + #======模板管理======# def list - @templates = Ci::Template.all + stage_type = params[:stage_type] + template_name = params[:name] + templates = template_name.blank? ? Ci::Template.all : Ci::Template.where("template_name like ?", "%#{template_name}%") + templates = templates.select{ |template| template.login == current_user.login} unless current_user.admin? + if !stage_type.blank? && stage_type != 'all' + templates = templates.select{ |template| template.stage_type == stage_type} + end + @total_count = templates.map(&:id).count + @templates = paginate templates end - def templates_by_stage - stage_type = params[:stage_type] - if stage_type != Ci::PipelineStage::CUSTOMIZE_STAGE_TYPE - @templates = Ci::Template.where("stage_type = ?", stage_type) - # 根据模板类别分组 - @category_templates = @templates.group_by{ |template| template.category } - else - # 自定义阶段,按阶段分类分类返回模板列表 - @templates = Ci::Template.where("stage_type != ?", Ci::PipelineStage::INIT_STAGE_TYPE) - @category_templates = @templates.group_by{ |template| template.parent_category } - end + def show + @template = Ci::Template.find(params[:id]) end def create - template = Ci::Template.new(template_name: params[:template_name], - stage_type: params[:stage_type], - category: params[:category], - parent_category: params[:parent_category], - content: params[:content] - ) - template.save! + stage_type = params[:stage_type] + category = params[:category] + if category.blank? + category = Ci::Template::STAGE_TYPES[:"#{stage_type}"] + end + + if params[:id] + template = Ci::Template.find(params[:id]) + if template + template.update!(template_name: params[:template_name], + stage_type: stage_type, + category: category, + parent_category: Ci::Template::STAGE_TYPES[:"#{stage_type}"], + content: params[:content], + login: current_user.admin? ? 'admin' : current_user.login + ) + end + else + template = Ci::Template.new(template_name: params[:template_name], + stage_type: stage_type, + category: category, + parent_category: Ci::Template::STAGE_TYPES[:"#{stage_type}"], + content: params[:content], + login: current_user.admin? ? 'admin' : current_user.login + ) + template.save! + end render_ok rescue Exception => ex render_error(ex.message) @@ -53,4 +76,20 @@ class Ci::TemplatesController < ApplicationController render_error(ex.message) end + #======流水线模板查询=====# + def templates_by_stage + stage_type = params[:stage_type] + if stage_type != Ci::PipelineStage::CUSTOMIZE_STAGE_TYPE + @templates = Ci::Template.where("stage_type = ?", stage_type) + @templates = @templates.select{ |template| template.login == current_user.login || template.login == 'admin'} unless current_user.admin? + # 根据模板类别分组 + @category_templates = @templates.group_by{ |template| template.category } + else + # 自定义阶段,按阶段分类分类返回模板列表 + @templates = Ci::Template.where("stage_type != ?", Ci::PipelineStage::INIT_STAGE_TYPE) + @templates = @templates.select{ |template| template.login == current_user.login || template.login == 'admin'} unless current_user.admin? + @category_templates = @templates.group_by{ |template| template.parent_category } + end + end + end diff --git a/app/controllers/concerns/ci/cloud_account_manageable.rb b/app/controllers/concerns/ci/cloud_account_manageable.rb index 00c42305d..13edb09c6 100644 --- a/app/controllers/concerns/ci/cloud_account_manageable.rb +++ b/app/controllers/concerns/ci/cloud_account_manageable.rb @@ -101,9 +101,6 @@ module Ci::CloudAccountManageable if cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_SELF @connection.execute("DROP DATABASE IF EXISTS #{current_user.login}_drone") # TOTO drop drone database - else - #删除drone用户 - @trustie_db_connection.execute("DELETE FROM users WHERE user_login = '#{cloud_account.account}'") end cloud_account.destroy! unless cloud_account.blank? diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 6873f2ede..a21e84459 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -11,4 +11,6 @@ class Ci::Build < Ci::RemoteBase scope :pending, -> { by_status('pending') } scope :killed, -> { by_status('killed') } scope :by_status, ->(status) { where(build_status: status) } + + scope :by_branch, ->(branch) { where(build_target: branch) } end diff --git a/app/models/ci/perm.rb b/app/models/ci/perm.rb index e6bc2ebbb..41ea2c164 100644 --- a/app/models/ci/perm.rb +++ b/app/models/ci/perm.rb @@ -4,10 +4,10 @@ class Ci::Perm < Ci::RemoteBase belongs_to :user, class_name: 'Ci::User', foreign_key: :perm_user_id belongs_to :repo, class_name: 'Ci::Repo', foreign_key: :perm_repo_uid - def self.auto_create!(user, repo) + def self.auto_create!(user_id, repo_id) perm = new( - perm_user_id: user.user_id, - perm_repo_uid: repo.repo_id, + perm_user_id: user_id, + perm_repo_uid: repo_id, perm_read: true, perm_write: true, perm_admin: true, diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 9448512b7..99a4a9950 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -10,7 +10,10 @@ # pipeline_status :string(50) default("unknown"), not null # login :string(255) # sync :integer default("0"), not null -# project_id :integer +# identifier :string(11) +# branch :string(255) +# event :string(255) +# sha :string(255) # class Ci::Pipeline < Ci::LocalBase @@ -20,4 +23,6 @@ class Ci::Pipeline < Ci::LocalBase has_many :pipeline_stages, -> { reorder(show_index: :asc) }, foreign_key: "pipeline_id", :class_name => 'Ci::PipelineStage', dependent: :destroy + attr_accessor :last_build_time + end diff --git a/app/models/ci/repo.rb b/app/models/ci/repo.rb index 6fb42e046..6c2a6d744 100644 --- a/app/models/ci/repo.rb +++ b/app/models/ci/repo.rb @@ -20,37 +20,53 @@ class Ci::Repo < Ci::RemoteBase return repos end - def activate!(ci_user_id) - update(repo_active: 1, - repo_signer: generate_code, - repo_secret: generate_code, - repo_user_id: ci_user_id, - repo_timeout: 60, - repo_config: '.trustie-pipeline.yml', - repo_updated: Time.now.to_i) + def self.load_repo_by_repo_slug(repo_slug) + logger.info "########repo_slug: #{repo_slug}" + repo = Ci::Repo.where(repo_slug: repo_slug).first + return repo + end + + def find_by_repo_name(repo_name) + logger.info "########repo_name: #{repo_name}" + repos = Ci::Repo.where(repo_name: repo_name) + return repos end def self.auto_create!(user, project) - repo = new( + create_params = { repo_user_id: user.user_id, repo_namespace: project.owner.login, repo_name: project.identifier, repo_slug: "#{project.owner.login}/#{project.identifier}", + repo_clone_url: project.repository.url, + repo_branch: 'master', + repo_config: '.trustie-pipeline.yml' + } + repo = create_repo(create_params) + repo + end + + def self.create_repo(create_params) + repo = new( + repo_user_id: create_params[:repo_user_id], + repo_namespace: create_params[:repo_namespace], + repo_name: create_params[:repo_name], + repo_slug: create_params[:repo_slug], repo_scm: "git", repo_ssh_url: "", repo_html_url: "", - repo_clone_url: project.repository.url, + repo_clone_url: create_params[:repo_clone_url], repo_active: 1, repo_private: true, repo_visibility: 'private', - repo_branch: 'master', + repo_branch: create_params[:repo_branch], repo_counter: 0, repo_trusted: false, repo_protected: false, repo_synced: 0, repo_version: 1, repo_timeout: 60, - repo_config: '.trustie-pipeline.yml', + repo_config: create_params[:repo_config], repo_created: Time.now.to_i, repo_updated: Time.now.to_i ) @@ -58,13 +74,34 @@ class Ci::Repo < Ci::RemoteBase repo.repo_signer = repo.generate_code repo.repo_secret = repo.generate_code if repo.save! - Ci::Perm.auto_create!(user, repo) + Ci::Perm.auto_create!(create_params[:repo_user_id], repo.id) repo.update_column(:repo_uid, repo.id) repo end end + # 取消激活同一个项目(多个repo) + def deactivate_repos! + repos = find_by_repo_name(self.repo_name) + repos.each do |repo| + repo.update_column(:repo_active, 0) + end + end + + def activate!(project) + repos = find_by_repo_name(self.repo_name) + project.update_column(:open_devops, true) + project.increment!(:open_devops_count) + repos.each do |repo| + repo.update_column(:repo_active, 1) + end + end + def deactivate! update_column(:repo_active, 0) end + + def destroy! + self.destroy + end end diff --git a/app/models/ci/template.rb b/app/models/ci/template.rb index e7be34a3b..74f06cf07 100644 --- a/app/models/ci/template.rb +++ b/app/models/ci/template.rb @@ -10,6 +10,7 @@ # created_at :datetime not null # updated_at :datetime not null # parent_category :string(255) +# login :string(255) # # Indexes # @@ -20,4 +21,7 @@ class Ci::Template < Ci::LocalBase validates :template_name, presence: {message: "模板名称不能为空"} validates :stage_type, presence: {message: "阶段类型不能为空"} validates :category, presence: {message: "模板类型不能为空"} + + STAGE_TYPES = {init:'初始化',build:'编译构建',deploy:'部署',customize:'其他'} + end diff --git a/app/queries/ci/builds/list_query.rb b/app/queries/ci/builds/list_query.rb index bfb0b0a59..7091723a4 100644 --- a/app/queries/ci/builds/list_query.rb +++ b/app/queries/ci/builds/list_query.rb @@ -24,6 +24,9 @@ class Ci::Builds::ListQuery < ApplicationQuery else scope end + + builds = scope.by_branch(params[:branch]) if params[:branch] + custom_sort(builds, params[:sort_by], params[:sort_direction]) end end diff --git a/app/views/ci/builds/_author.json.jbuilder b/app/views/ci/builds/_author.json.jbuilder index 280f7ef98..163bcad9c 100644 --- a/app/views/ci/builds/_author.json.jbuilder +++ b/app/views/ci/builds/_author.json.jbuilder @@ -1,4 +1,4 @@ json.id user.id -json.name user.real_name +json.name user.real_name == '游客' ? '-' : user.real_name json.login user.login json.image_url url_to_avatar(user) diff --git a/app/views/ci/pipelines/_list.json.jbuilder b/app/views/ci/pipelines/_list.json.jbuilder index 0113da58d..97720ce9f 100644 --- a/app/views/ci/pipelines/_list.json.jbuilder +++ b/app/views/ci/pipelines/_list.json.jbuilder @@ -1,8 +1,12 @@ json.id pipeline.id json.pipeline_name pipeline.pipeline_name -json.pipeline_status pipeline.pipeline_status +json.pipeline_status pipeline.pipeline_status == 'unknown' ? '' : pipeline.pipeline_status json.file_name pipeline.file_name json.sync pipeline.sync +json.branch pipeline.branch +json.event pipeline.event +json.sha pipeline.sha json.identifier pipeline.identifier +json.last_build_time pipeline.last_build_time.nil? ? '' : pipeline.last_build_time.strftime("%Y-%m-%d %H:%M:%S") json.created_at pipeline.created_at.strftime("%Y-%m-%d %H:%M:%S") json.updated_at pipeline.updated_at.strftime("%Y-%m-%d %H:%M:%S") diff --git a/app/views/ci/pipelines/list.json.jbuilder b/app/views/ci/pipelines/list.json.jbuilder index 7cfbeb1a6..86c241421 100644 --- a/app/views/ci/pipelines/list.json.jbuilder +++ b/app/views/ci/pipelines/list.json.jbuilder @@ -1,3 +1,4 @@ +json.total_count @total_count json.pipelines @pipelines do |pipeline| json.partial! "/ci/pipelines/list", pipeline: pipeline end \ No newline at end of file diff --git a/app/views/ci/templates/_list.json.jbuilder b/app/views/ci/templates/_list.json.jbuilder index 1aff25a43..a3f3868a0 100644 --- a/app/views/ci/templates/_list.json.jbuilder +++ b/app/views/ci/templates/_list.json.jbuilder @@ -3,6 +3,7 @@ json.template_name template.template_name json.stage_type template.stage_type json.category template.category json.content template.content +json.login template.login json.created_at template.created_at json.updated_at template.updated_at diff --git a/app/views/ci/templates/list.json.jbuilder b/app/views/ci/templates/list.json.jbuilder index 3b463057b..823bdfb2a 100644 --- a/app/views/ci/templates/list.json.jbuilder +++ b/app/views/ci/templates/list.json.jbuilder @@ -1,3 +1,4 @@ +json.total_count @total_count json.templates @templates do |template| json.partial! "/ci/templates/list", template: template end \ No newline at end of file diff --git a/app/views/ci/templates/show.json.jbuilder b/app/views/ci/templates/show.json.jbuilder new file mode 100644 index 000000000..cbed032dd --- /dev/null +++ b/app/views/ci/templates/show.json.jbuilder @@ -0,0 +1,9 @@ +json.id @template.id +json.template_name @template.template_name +json.stage_type @template.stage_type +json.category @template.category +json.content @template.content +json.login @template.login +json.created_at @template.created_at +json.updated_at @template.updated_at + diff --git a/config/routes.rb b/config/routes.rb index 8af453cf8..067adcce0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,7 +32,7 @@ Rails.application.routes.draw do end end - resources :templates, only: [:list,:templates_by_stage,:create,:update,:destroy] do + resources :templates, only: [:list,:templates_by_stage,:create,:update,:destroy,:show] do collection do get :list get :templates_by_stage diff --git a/db/migrate/20210122052755_add_branch_and_event_and_sha_to_ci_pipelines.rb b/db/migrate/20210122052755_add_branch_and_event_and_sha_to_ci_pipelines.rb new file mode 100644 index 000000000..4d89e3be5 --- /dev/null +++ b/db/migrate/20210122052755_add_branch_and_event_and_sha_to_ci_pipelines.rb @@ -0,0 +1,7 @@ +class AddBranchAndEventAndShaToCiPipelines < ActiveRecord::Migration[5.2] + def change + add_column :ci_pipelines, :branch, :string + add_column :ci_pipelines, :event, :string + add_column :ci_pipelines, :sha, :string + end +end diff --git a/db/migrate/20210126071814_add_login_to_ci_templates.rb b/db/migrate/20210126071814_add_login_to_ci_templates.rb new file mode 100644 index 000000000..eb5da0222 --- /dev/null +++ b/db/migrate/20210126071814_add_login_to_ci_templates.rb @@ -0,0 +1,5 @@ +class AddLoginToCiTemplates < ActiveRecord::Migration[5.2] + def change + add_column :ci_templates, :login, :string + end +end From 24d5f1630255357cd8a8b71476bbcfd5335fc5df Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Wed, 27 Jan 2021 09:35:41 +0800 Subject: [PATCH 21/35] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api_document.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api_document.md b/api_document.md index fa536b9ec..a4294513a 100644 --- a/api_document.md +++ b/api_document.md @@ -3502,13 +3502,13 @@ curl -X GET http://localhost:3000/api/ci/languages/114.json | jq #### 获取构建列表 ``` -GET /api/:owner/:repo/builds +GET /api/:owner/:repo/builds??branch={branch} ``` *示例* ```bash curl -X GET \ -http://localhost:3000/api/Jason/forge/builds | jq +http://localhost:3000/api/Jason/forge/builds?branch=develop | jq ``` *请求参数说明:* From e1ddad504033d6cbcbdea9c05d3f87ef084b1493 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Wed, 27 Jan 2021 10:22:53 +0800 Subject: [PATCH 22/35] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=B5=81=E6=B0=B4?= =?UTF-8?q?=E7=BA=BF=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api_document.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_document.md b/api_document.md index a4294513a..cad8be7ad 100644 --- a/api_document.md +++ b/api_document.md @@ -4104,7 +4104,7 @@ curl --location --request POST 'http://localhost:3000/api/ci/pipelines' \ | file_name | 是 | string | 文件名称(默认初始值:.trustie.pipeline.yaml) | | repo | 是 | string | 项目identifier | | owner | 是 | string | 项目的owner | -| branch | 否 | string | 分支名称, branch必须存在一个 | +| branch | 是 | string | 分支名称, branch必须存在一个 | | event | 是 | string | 触发事件,可多选,多个逗号隔开 | *返回参数说明:* From 2c648b7941d6d17aa60d15cfe6aaebeaf48eff8f Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Wed, 27 Jan 2021 16:27:56 +0800 Subject: [PATCH 23/35] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index 50417ce80..4dda451f3 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -70,17 +70,20 @@ class Ci::PipelinesController < Ci::BaseController # 在drone数据库repo表新增一条repo记录 def create_ci_repo(pipeline) - create_params = { - repo_user_id: @ci_user.user_id, - repo_namespace: @project.owner.login, - repo_name: @project.identifier, - repo_slug: "#{@project.owner.login}/#{@project.identifier}-" + pipeline.id.to_s, - repo_clone_url: @project.repository.url, - repo_branch: pipeline.branch, - repo_config: pipeline.file_name - } - repo = Ci::Repo.create_repo(create_params) - repo + if pipeline.branch != 'master' + create_params = { + repo_user_id: @ci_user.user_id, + repo_namespace: @project.owner.login, + repo_name: @project.identifier, + repo_slug: "#{@project.owner.login}/#{@project.identifier}-" + pipeline.id.to_s, + repo_clone_url: @project.repository.url, + repo_branch: pipeline.branch, + repo_config: pipeline.file_name + } + repo = Ci::Repo.create_repo(create_params) + repo + end + nil end def get_pipeline_file_sha(file_name, branch) @@ -88,9 +91,7 @@ class Ci::PipelinesController < Ci::BaseController interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: branch || 'master') if interactor.success? file = interactor.result - return file['sha'] - else - return nil + file['sha'] end end From c3136fc1a8333ad33d3cd92c0c50eaa34cda9bb0 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Thu, 28 Jan 2021 14:14:22 +0800 Subject: [PATCH 24/35] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index 4dda451f3..50bb65d05 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -10,12 +10,15 @@ class Ci::PipelinesController < Ci::BaseController @result = Array.new list = Ci::Pipeline.where('identifier=?', params[:identifier]) # 查询build状态 - list = list.collect do |pipeline| + list.collect do |pipeline| + pipeline.last_build_time = nil repo = load_repo_by_repo_slug("#{pipeline.login}/#{pipeline.identifier}") - build = repo.builds.order("build_created desc").find_by(build_target: pipeline.branch) - if build - pipeline.pipeline_status = build.build_status - pipeline.last_build_time = Time.at(build.build_created) + if repo + build = repo.builds.order("build_created desc").find_by(build_target: pipeline.branch) + if build + pipeline.pipeline_status = build.build_status + pipeline.last_build_time = Time.at(build.build_created) + end end @result.push(pipeline) end From c3f69a48d616f1009ae2fe0ad53aba59182345c8 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Thu, 28 Jan 2021 15:04:51 +0800 Subject: [PATCH 25/35] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BFsha=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index 50bb65d05..bc2a33108 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -1,9 +1,9 @@ class Ci::PipelinesController < Ci::BaseController - before_action :require_login, only: %i[list create] - skip_before_action :connect_to_ci_db, except: %i[list create destroy] - before_action :load_project, only: %i[create] - before_action :load_repo, only: %i[create] + before_action :require_login, only: %i[list create content] + skip_before_action :connect_to_ci_db, except: %i[list create destroy content] + before_action :load_project, only: %i[create content] + before_action :load_repo, only: %i[create content] # ======流水线相关接口========== # def list @@ -116,7 +116,7 @@ class Ci::PipelinesController < Ci::BaseController def update pipeline = Ci::Pipeline.find(params[:id]) if pipeline - pipeline.update!(pipeline_name: params[:pipeline_name]) + pipeline.update!(pipeline_name: params[:pipeline_name],branch: params[:branch], event: params[:event]) end render_ok rescue Exception => ex @@ -140,7 +140,6 @@ class Ci::PipelinesController < Ci::BaseController def content @yaml = "\n" pipeline = Ci::Pipeline.find(params[:id]) - @sha = pipeline.sha stages = pipeline.pipeline_stages if stages && !stages.empty? init_step = stages.first.pipeline_stage_steps.first @@ -156,6 +155,10 @@ class Ci::PipelinesController < Ci::BaseController end end end + @sha = pipeline.sha + unless @sha + @sha = get_pipeline_file_sha(pipeline.file_name, pipeline.branch) + end trigger = '' trigger += " branch:\r\n - #{pipeline.branch}\r\n" unless pipeline.branch.blank? unless pipeline.event.blank? From 22d7478349876b2329b7d6c6faa2b1cd072a0562 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Mon, 1 Feb 2021 10:36:30 +0800 Subject: [PATCH 26/35] =?UTF-8?q?content=E6=8E=A5=E5=8F=A3=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 1 + app/views/ci/pipelines/content.json.jbuilder | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index bc2a33108..b75a8478b 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -166,6 +166,7 @@ class Ci::PipelinesController < Ci::BaseController pipeline.event.split(',').each { |event| trigger += " - #{event}\r\n"} end @yaml += "trigger:\r\n" + trigger unless trigger.blank? + @branch = pipeline.branch end # =========阶段相关接口========= # diff --git a/app/views/ci/pipelines/content.json.jbuilder b/app/views/ci/pipelines/content.json.jbuilder index 60d211b94..622c97a3f 100644 --- a/app/views/ci/pipelines/content.json.jbuilder +++ b/app/views/ci/pipelines/content.json.jbuilder @@ -1,3 +1,4 @@ json.content @yaml json.sync @sync -json.sha @sha \ No newline at end of file +json.sha @sha +json.branch @branch \ No newline at end of file From d214b1ddae104bf91252e335e47cce45ebf9d265 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Mon, 1 Feb 2021 13:40:15 +0800 Subject: [PATCH 27/35] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E6=A8=A1=E6=9D=BF=E5=90=8D=E7=A7=B0=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/templates_controller.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/controllers/ci/templates_controller.rb b/app/controllers/ci/templates_controller.rb index 11c6f2779..22998333e 100644 --- a/app/controllers/ci/templates_controller.rb +++ b/app/controllers/ci/templates_controller.rb @@ -79,9 +79,19 @@ class Ci::TemplatesController < Ci::BaseController #======流水线模板查询=====# def templates_by_stage stage_type = params[:stage_type] + pipeline_id = params[:id] if stage_type != Ci::PipelineStage::CUSTOMIZE_STAGE_TYPE @templates = Ci::Template.where("stage_type = ?", stage_type) @templates = @templates.select{ |template| template.login == current_user.login || template.login == 'admin'} unless current_user.admin? + if stage_type == Ci::PipelineStage::INIT_STAGE_TYPE && !@templates.nil? + @templates.each do |template| + content = template.content + unless content.blank? + pipeline = Ci::Pipeline.find(pipeline_id) + template.content = content.gsub(/{name}/, pipeline.pipeline_name) unless pipeline.nil? + end + end + end # 根据模板类别分组 @category_templates = @templates.group_by{ |template| template.category } else From ce31875c190d1b6a57a250d20411759e26f80d23 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Mon, 1 Feb 2021 15:17:03 +0800 Subject: [PATCH 28/35] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E9=98=B6=E6=AE=B5?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=A8=A1=E6=9D=BF=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/templates_controller.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/ci/templates_controller.rb b/app/controllers/ci/templates_controller.rb index 22998333e..cb49590dc 100644 --- a/app/controllers/ci/templates_controller.rb +++ b/app/controllers/ci/templates_controller.rb @@ -79,7 +79,6 @@ class Ci::TemplatesController < Ci::BaseController #======流水线模板查询=====# def templates_by_stage stage_type = params[:stage_type] - pipeline_id = params[:id] if stage_type != Ci::PipelineStage::CUSTOMIZE_STAGE_TYPE @templates = Ci::Template.where("stage_type = ?", stage_type) @templates = @templates.select{ |template| template.login == current_user.login || template.login == 'admin'} unless current_user.admin? @@ -87,7 +86,7 @@ class Ci::TemplatesController < Ci::BaseController @templates.each do |template| content = template.content unless content.blank? - pipeline = Ci::Pipeline.find(pipeline_id) + pipeline = Ci::Pipeline.find(params[:id]) template.content = content.gsub(/{name}/, pipeline.pipeline_name) unless pipeline.nil? end end From 155fc35cfaf5052cc9ff7fef28a1bad267e894ad Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Mon, 1 Feb 2021 16:19:42 +0800 Subject: [PATCH 29/35] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=BA=93=E6=96=87=E4=BB=B6sha?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index b75a8478b..4ff6837b2 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -61,12 +61,10 @@ class Ci::PipelinesController < Ci::BaseController sha = get_pipeline_file_sha(pipeline.file_name, pipeline.branch) if sha logger.info "#{pipeline.file_name}已存在" - pipeline.update!(sync: 1, sha: sha) else interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) if interactor.success? logger.info "#{pipeline.file_name}创建成功" - pipeline.update!(sync: 1, sha: interactor.result['content']['sha']) end end end @@ -155,10 +153,7 @@ class Ci::PipelinesController < Ci::BaseController end end end - @sha = pipeline.sha - unless @sha - @sha = get_pipeline_file_sha(pipeline.file_name, pipeline.branch) - end + @sha = get_pipeline_file_sha(pipeline.file_name, pipeline.branch) trigger = '' trigger += " branch:\r\n - #{pipeline.branch}\r\n" unless pipeline.branch.blank? unless pipeline.event.blank? From d2209619f0d867f5b5a304309f88c054bd6d1c06 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Tue, 2 Feb 2021 11:48:09 +0800 Subject: [PATCH 30/35] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0owner=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 6 +++--- db/migrate/20210202034128_add_owner_to_ci_pipelines.rb | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20210202034128_add_owner_to_ci_pipelines.rb diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index 4ff6837b2..5b12aa3cc 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -8,7 +8,7 @@ class Ci::PipelinesController < Ci::BaseController # ======流水线相关接口========== # def list @result = Array.new - list = Ci::Pipeline.where('identifier=?', params[:identifier]) + list = Ci::Pipeline.where('identifier=? and owner=?', params[:identifier], params[:owner]) # 查询build状态 list.collect do |pipeline| pipeline.last_build_time = nil @@ -28,12 +28,12 @@ class Ci::PipelinesController < Ci::BaseController def create ActiveRecord::Base.transaction do - size = Ci::Pipeline.where('branch=? and identifier=?', params[:branch], params[:repo]).size + size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size if size > 0 render_error("#{params[:branch]}分支已经存在流水线!") return end - pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name], + pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner], login: current_user.login, identifier: params[:repo], branch: params[:branch], event: params[:event]) pipeline.save! diff --git a/db/migrate/20210202034128_add_owner_to_ci_pipelines.rb b/db/migrate/20210202034128_add_owner_to_ci_pipelines.rb new file mode 100644 index 000000000..f5a8d3667 --- /dev/null +++ b/db/migrate/20210202034128_add_owner_to_ci_pipelines.rb @@ -0,0 +1,5 @@ +class AddOwnerToCiPipelines < ActiveRecord::Migration[5.2] + def change + add_column :ci_pipelines, :owner, :string + end +end From 4816ee04d392d79331dffc18106f0946f9485dee Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Tue, 2 Feb 2021 13:10:53 +0800 Subject: [PATCH 31/35] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/ci/pipelines_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/ci/pipelines_controller.rb b/app/controllers/ci/pipelines_controller.rb index 5b12aa3cc..ea8b25f77 100644 --- a/app/controllers/ci/pipelines_controller.rb +++ b/app/controllers/ci/pipelines_controller.rb @@ -12,7 +12,7 @@ class Ci::PipelinesController < Ci::BaseController # 查询build状态 list.collect do |pipeline| pipeline.last_build_time = nil - repo = load_repo_by_repo_slug("#{pipeline.login}/#{pipeline.identifier}") + repo = load_repo_by_repo_slug("#{pipeline.owner}/#{pipeline.identifier}") if repo build = repo.builds.order("build_created desc").find_by(build_target: pipeline.branch) if build From 8d3838614f14939c1f6d3ac09b033076e36f5c91 Mon Sep 17 00:00:00 2001 From: victor <121183489011@qq.com> Date: Tue, 2 Feb 2021 14:32:02 +0800 Subject: [PATCH 32/35] FIX pipeline model schma # Conflicts: # app/models/ci/pipeline.rb --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 99a4a9950..b1b7b353d 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -4,10 +4,10 @@ # # id :integer not null, primary key # pipeline_name :string(255) not null +# pipeline_status :string(255) default("unknown"), not null # file_name :string(255) not null # created_at :datetime not null # updated_at :datetime not null -# pipeline_status :string(50) default("unknown"), not null # login :string(255) # sync :integer default("0"), not null # identifier :string(11) From 9121033a10b1cb36fb5da39cbbb78b68de2ee3f8 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 26 Jan 2021 14:49:02 +0800 Subject: [PATCH 33/35] ADD upload avatar api with support multiple image formats --- app/libs/base64_image_converter.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/libs/base64_image_converter.rb b/app/libs/base64_image_converter.rb index 2dc9aa41e..b2563e434 100644 --- a/app/libs/base64_image_converter.rb +++ b/app/libs/base64_image_converter.rb @@ -1,5 +1,7 @@ class Base64ImageConverter - BASE64_HEAD = 'data:image/jpeg;base64,'.freeze + # BASE64_HEAD = 'data:image/jpeg;base64,'.freeze + BASE64_HEAD_ARRAY = ['data:image/jpeg;base64,', 'data:image/jpg;base64,', + 'data:image/png;base64,', 'data:image/gif;base64,'] Error = Class.new(StandardError) OutLimit = Class.new(Error) @@ -27,11 +29,20 @@ class Base64ImageConverter private def valid_base64?(data) - data&.start_with?(BASE64_HEAD) + # data&.start_with?(BASE64_HEAD) + BASE64_HEAD_ARRAY.include? base64_head_data(data) + end + + def base64_head_data(data) + data&.split(',')[0] + ',' + end + + def base64_head(data) + valid_base64?(data) ? base64_head_data(data) : '' end def image_data(data) - data[BASE64_HEAD.size..-1] + data[base64_head(data).size..-1] end def size_limit @@ -74,4 +85,4 @@ class Base64ImageConverter data[0,2] == 0x89.chr + 80.chr end end -end \ No newline at end of file +end From 9f7c9d6ec7e126ec40410fd048694a04ea969c2b Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Wed, 27 Jan 2021 17:22:16 +0800 Subject: [PATCH 34/35] FIX CORS problem for develop --- config/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/application.rb b/config/application.rb index a09b08def..62d95dbf2 100644 --- a/config/application.rb +++ b/config/application.rb @@ -42,7 +42,7 @@ module Educoderplus allow do origins '*' # location of your api - resource '/*', :headers => :any, :methods => [:get, :post, :delete, :options, :put] + resource '/*', :headers => :any, :methods => [:get, :post, :delete, :options, :put, :patch] end end end From 6053907828d671262466ae96c3ea2f85302932a9 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Thu, 28 Jan 2021 15:11:47 +0800 Subject: [PATCH 35/35] fix change stoage file derictory --- app/controllers/attachments_controller.rb | 12 ++++++------ app/controllers/users_controller.rb | 3 ++- app/helpers/application_helper.rb | 10 +++++++++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index 16842fb55..14e53b3e2 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -28,8 +28,8 @@ class AttachmentsController < ApplicationController update_downloads(@file) end - - def get_file + + def get_file normal_status(-1, "参数缺失") if params[:download_url].blank? url = URI.encode(params[:download_url].to_s.gsub("http:", "https:")) response = Faraday.get(url) @@ -45,7 +45,7 @@ class AttachmentsController < ApplicationController uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}") raise "未上传文件" unless upload_file - folder = edu_setting('attachment_folder') + folder = file_storage_directory raise "存储目录未定义" unless folder.present? month_folder = current_month_folder @@ -108,7 +108,7 @@ class AttachmentsController < ApplicationController end # 附件为视频时,点击播放 - def preview_attachment + def preview_attachment attachment = Attachment.find_by(id: params[:id]) dir_path = "#{Rails.root}/public/preview" Dir.mkdir(dir_path) unless Dir.exist?(dir_path) @@ -118,10 +118,10 @@ class AttachmentsController < ApplicationController else normal_status(-1, "出现错误,请稍后重试") end - else + else if system("rm -rf #{dir_path}/#{attachment.disk_filename}") normal_status(1, "操作成功") - else + else normal_status(-1, "出现错误,请稍后重试") end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4a67fd413..d5ca638a6 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,5 @@ class UsersController < ApplicationController + include ApplicationHelper include Ci::DbConnectable before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users] @@ -79,7 +80,7 @@ class UsersController < ApplicationController def attachment_show file_name = params[:file_name] - path = params[:path] || edu_setting('attachment_folder') + path = params[:path] || file_storage_directory send_file "#{path}/#{file_name}", :filename => "#{file_name}", :type => 'game', :disposition => 'attachment' #inline can open in browser diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1ac9a85b7..75532188e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -322,7 +322,15 @@ module ApplicationHelper end def absolute_path(file_path) - File.join(edu_setting('attachment_folder'), file_path) + file_root_directory + File.join(edu_setting('attachment_folder'), file_path) + end + + def file_root_directory + Rails.root.to_s + end + + def file_storage_directory + file_root_directory + edu_setting('attachment_folder') end def local_path(file)