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/73] 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 00000000..c2337ab9 --- /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 887a6952..190f3776 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 c633c6b7..74f45708 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 b3f2d057..79a0e296 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 058dfec0..c8d88d6d 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 00000000..2b4269ac --- /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/73] 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 cd6c4b91..281dd705 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 a6beea40..cbd598f5 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/73] 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 1699cf60..50e90456 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 a7ec34f8..a58346ea 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 5858768b..8c55c4f9 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 046e9a0a..cf057c3f 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 00000000..aed5251b --- /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 2129bbea..c33c8781 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 00000000..affdfe11 --- /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 a83afe40..a68981f2 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 00000000..e0ac19b4 --- /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 00000000..a20ee3aa --- /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 00000000..3081e52b --- /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/73] 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 e5e61598..0918b9d3 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/73] 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 8f95bbcb..8257cc7f 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 b40fe606..9708ba84 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/73] 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 0918b9d3..63ca58aa 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 61bbc915..14dfefef 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/73] 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 2b4269ac..c2def736 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/73] 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 79a0e296..d6622571 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 c2def736..00000000 --- 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 00000000..5a7f530f --- /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/73] 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 5a7f530f..35463673 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/73] 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 35463673..3e807fa1 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/73] 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 35618f79..da19c47e 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 c189bf24..82f9e6c7 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 00000000..48e2d447 --- /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 c8d88d6d..76a37dab 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/73] 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 10ad1377..07646c07 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 ab9910dd..1e8e001a 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 20fecec3..ca041fd5 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/73] 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 50e90456..14519475 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 aca2067c..dc2877eb 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 14dfefef..c3f781f7 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/73] 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 da19c47e..9c927760 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/73] 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 728a9809..1e9de823 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/73] 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 190f3776..4b9e72e1 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/73] 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 9c927760..27c71b90 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 00000000..620d93bf --- /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 82f9e6c7..7e708f5e 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 00000000..88d5dcbe --- /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 76a37dab..8af453cf 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/73] 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 27c71b90..b39eb25a 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 c2337ab9..4391f2c1 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/73] 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 3c218463..0c312738 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 1e8e001a..ec2a045b 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 ca041fd5..9efa0c11 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/73] =?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 b39eb25a..fa536b9e 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 5aedbddb..1649721c 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 043d24fe..7d829dbd 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 19460fde..50417ce8 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 c7b7338f..69644e7a 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 c77a9144..11c6f277 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 00c42305..13edb09c 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 6873f2ed..a21e8445 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 e6bc2ebb..41ea2c16 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 9448512b..99a4a995 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 6fb42e04..6c2a6d74 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 e7be34a3..74f06cf0 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 bfb0b0a5..7091723a 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 280f7ef9..163bcad9 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 0113da58..97720ce9 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 7cfbeb1a..86c24142 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 1aff25a4..a3f3868a 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 3b463057..823bdfb2 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 00000000..cbed032d --- /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 8af453cf..067adcce 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 00000000..4d89e3be --- /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 00000000..eb5da022 --- /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/73] =?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 fa536b9e..a4294513 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/73] =?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 a4294513..cad8be7a 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/73] =?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 50417ce8..4dda451f 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/73] =?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 4dda451f..50bb65d0 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/73] =?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 50bb65d0..bc2a3310 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/73] =?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 bc2a3310..b75a8478 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 60d211b9..622c97a3 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/73] =?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 11c6f277..22998333 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/73] =?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 22998333..cb49590d 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/73] =?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 b75a8478..4ff6837b 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/73] =?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 4ff6837b..5b12aa3c 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 00000000..f5a8d366 --- /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/73] =?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 5b12aa3c..ea8b25f7 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 165f8108f70ebae3831c15fd5d1cfe16a2e2da82 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Tue, 2 Feb 2021 14:07:46 +0800 Subject: [PATCH 32/73] ADD api document on line --- app/docs/slate/.dockerignore | 2 + app/docs/slate/.editorconfig | 18 + app/docs/slate/.gitattributes | 1 + app/docs/slate/.github/ISSUE_TEMPLATE/bug.md | 22 + .../slate/.github/ISSUE_TEMPLATE/config.yml | 5 + .../slate/.github/PULL_REQUEST_TEMPLATE.md | 5 + app/docs/slate/.github/workflows/build.yml | 42 + app/docs/slate/.github/workflows/deploy.yml | 41 + .../slate/.github/workflows/dev_deploy.yml | 50 + app/docs/slate/.github/workflows/publish.yml | 22 + app/docs/slate/.gitignore | 27 + app/docs/slate/CHANGELOG.md | 254 + app/docs/slate/CODE_OF_CONDUCT.md | 46 + app/docs/slate/Gemfile | 12 + app/docs/slate/Gemfile.lock | 136 + app/docs/slate/LICENSE | 201 + app/docs/slate/README.md | 81 + app/docs/slate/Vagrantfile | 46 + app/docs/slate/config.rb | 65 + app/docs/slate/deploy.sh | 226 + app/docs/slate/font-selection.json | 148 + app/docs/slate/lib/monokai_sublime_slate.rb | 95 + app/docs/slate/lib/multilang.rb | 16 + app/docs/slate/lib/nesting_unique_head.rb | 22 + app/docs/slate/lib/toc_data.rb | 31 + app/docs/slate/lib/unique_head.rb | 24 + app/docs/slate/slate.sh | 248 + app/docs/slate/source/api.html.md | 36 + app/docs/slate/source/fonts/slate.eot | Bin 0 -> 1876 bytes app/docs/slate/source/fonts/slate.svg | 14 + app/docs/slate/source/fonts/slate.ttf | Bin 0 -> 1720 bytes app/docs/slate/source/fonts/slate.woff | Bin 0 -> 1796 bytes app/docs/slate/source/fonts/slate.woff2 | Bin 0 -> 796 bytes app/docs/slate/source/images/logo.png | Bin 0 -> 3591 bytes app/docs/slate/source/images/logoWilte.png | Bin 0 -> 2677 bytes app/docs/slate/source/images/navbar.png | Bin 0 -> 96 bytes .../slate/source/includes/_authentication.md | 39 + app/docs/slate/source/includes/_errors.md | 22 + app/docs/slate/source/includes/_gitignores.md | 47 + app/docs/slate/source/includes/_issues.md | 1 + app/docs/slate/source/includes/_licenses.md | 57 + .../slate/source/includes/_organizations.md | 1 + app/docs/slate/source/includes/_projects.md | 401 + app/docs/slate/source/includes/_pulls.md | 1 + .../slate/source/includes/_repositories.md | 621 + app/docs/slate/source/includes/_teams.md | 1 + app/docs/slate/source/includes/_users.md | 42 + app/docs/slate/source/javascripts/all.js | 2 + .../slate/source/javascripts/all_nosearch.js | 27 + .../slate/source/javascripts/app/_copy.js | 15 + .../slate/source/javascripts/app/_lang.js | 164 + .../slate/source/javascripts/app/_search.js | 102 + app/docs/slate/source/javascripts/app/_toc.js | 122 + .../slate/source/javascripts/lib/_energize.js | 169 + .../javascripts/lib/_imagesloaded.min.js | 7 + .../javascripts/lib/_jquery.highlight.js | 108 + .../slate/source/javascripts/lib/_jquery.js | 10872 ++++++++++++++++ .../slate/source/javascripts/lib/_lunr.js | 3475 +++++ app/docs/slate/source/layouts/layout.erb | 128 + .../slate/source/stylesheets/_icon-font.scss | 38 + .../slate/source/stylesheets/_normalize.scss | 427 + app/docs/slate/source/stylesheets/_rtl.scss | 140 + .../slate/source/stylesheets/_variables.scss | 103 + .../slate/source/stylesheets/print.css.scss | 153 + .../slate/source/stylesheets/screen.css.scss | 634 + build_api_docs.sh | 5 + public/docs/api.html | 2606 ++++ public/docs/fonts/slate-7b7da4fe.ttf | Bin 0 -> 1720 bytes public/docs/fonts/slate-cfc9d06b.eot | Bin 0 -> 1876 bytes public/docs/fonts/slate-e55b8307.svg | 14 + public/docs/fonts/slate.woff | Bin 0 -> 1796 bytes public/docs/fonts/slate.woff2 | Bin 0 -> 796 bytes public/docs/images/logo-b38b63e6.png | Bin 0 -> 3591 bytes public/docs/images/logoWilte-81907910.png | Bin 0 -> 2677 bytes public/docs/images/navbar-cad8cdcb.png | Bin 0 -> 96 bytes public/docs/javascripts/all-e033bdd3.js | 120 + .../docs/javascripts/all_nosearch-ec00d1ce.js | 31 + public/docs/stylesheets/print-953e3353.css | 1 + public/docs/stylesheets/screen-cf7c3c82.css | 1 + 79 files changed, 22633 insertions(+) create mode 100644 app/docs/slate/.dockerignore create mode 100644 app/docs/slate/.editorconfig create mode 100644 app/docs/slate/.gitattributes create mode 100644 app/docs/slate/.github/ISSUE_TEMPLATE/bug.md create mode 100644 app/docs/slate/.github/ISSUE_TEMPLATE/config.yml create mode 100644 app/docs/slate/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 app/docs/slate/.github/workflows/build.yml create mode 100644 app/docs/slate/.github/workflows/deploy.yml create mode 100644 app/docs/slate/.github/workflows/dev_deploy.yml create mode 100644 app/docs/slate/.github/workflows/publish.yml create mode 100644 app/docs/slate/.gitignore create mode 100644 app/docs/slate/CHANGELOG.md create mode 100644 app/docs/slate/CODE_OF_CONDUCT.md create mode 100644 app/docs/slate/Gemfile create mode 100644 app/docs/slate/Gemfile.lock create mode 100644 app/docs/slate/LICENSE create mode 100644 app/docs/slate/README.md create mode 100644 app/docs/slate/Vagrantfile create mode 100644 app/docs/slate/config.rb create mode 100755 app/docs/slate/deploy.sh create mode 100755 app/docs/slate/font-selection.json create mode 100644 app/docs/slate/lib/monokai_sublime_slate.rb create mode 100644 app/docs/slate/lib/multilang.rb create mode 100644 app/docs/slate/lib/nesting_unique_head.rb create mode 100644 app/docs/slate/lib/toc_data.rb create mode 100644 app/docs/slate/lib/unique_head.rb create mode 100755 app/docs/slate/slate.sh create mode 100644 app/docs/slate/source/api.html.md create mode 100644 app/docs/slate/source/fonts/slate.eot create mode 100644 app/docs/slate/source/fonts/slate.svg create mode 100644 app/docs/slate/source/fonts/slate.ttf create mode 100644 app/docs/slate/source/fonts/slate.woff create mode 100644 app/docs/slate/source/fonts/slate.woff2 create mode 100644 app/docs/slate/source/images/logo.png create mode 100644 app/docs/slate/source/images/logoWilte.png create mode 100644 app/docs/slate/source/images/navbar.png create mode 100644 app/docs/slate/source/includes/_authentication.md create mode 100644 app/docs/slate/source/includes/_errors.md create mode 100644 app/docs/slate/source/includes/_gitignores.md create mode 100644 app/docs/slate/source/includes/_issues.md create mode 100644 app/docs/slate/source/includes/_licenses.md create mode 100644 app/docs/slate/source/includes/_organizations.md create mode 100644 app/docs/slate/source/includes/_projects.md create mode 100644 app/docs/slate/source/includes/_pulls.md create mode 100644 app/docs/slate/source/includes/_repositories.md create mode 100644 app/docs/slate/source/includes/_teams.md create mode 100644 app/docs/slate/source/includes/_users.md create mode 100644 app/docs/slate/source/javascripts/all.js create mode 100644 app/docs/slate/source/javascripts/all_nosearch.js create mode 100644 app/docs/slate/source/javascripts/app/_copy.js create mode 100644 app/docs/slate/source/javascripts/app/_lang.js create mode 100644 app/docs/slate/source/javascripts/app/_search.js create mode 100644 app/docs/slate/source/javascripts/app/_toc.js create mode 100644 app/docs/slate/source/javascripts/lib/_energize.js create mode 100644 app/docs/slate/source/javascripts/lib/_imagesloaded.min.js create mode 100644 app/docs/slate/source/javascripts/lib/_jquery.highlight.js create mode 100644 app/docs/slate/source/javascripts/lib/_jquery.js create mode 100644 app/docs/slate/source/javascripts/lib/_lunr.js create mode 100644 app/docs/slate/source/layouts/layout.erb create mode 100644 app/docs/slate/source/stylesheets/_icon-font.scss create mode 100644 app/docs/slate/source/stylesheets/_normalize.scss create mode 100644 app/docs/slate/source/stylesheets/_rtl.scss create mode 100644 app/docs/slate/source/stylesheets/_variables.scss create mode 100644 app/docs/slate/source/stylesheets/print.css.scss create mode 100644 app/docs/slate/source/stylesheets/screen.css.scss create mode 100755 build_api_docs.sh create mode 100644 public/docs/api.html create mode 100644 public/docs/fonts/slate-7b7da4fe.ttf create mode 100644 public/docs/fonts/slate-cfc9d06b.eot create mode 100644 public/docs/fonts/slate-e55b8307.svg create mode 100644 public/docs/fonts/slate.woff create mode 100644 public/docs/fonts/slate.woff2 create mode 100644 public/docs/images/logo-b38b63e6.png create mode 100644 public/docs/images/logoWilte-81907910.png create mode 100644 public/docs/images/navbar-cad8cdcb.png create mode 100644 public/docs/javascripts/all-e033bdd3.js create mode 100644 public/docs/javascripts/all_nosearch-ec00d1ce.js create mode 100644 public/docs/stylesheets/print-953e3353.css create mode 100644 public/docs/stylesheets/screen-cf7c3c82.css diff --git a/app/docs/slate/.dockerignore b/app/docs/slate/.dockerignore new file mode 100644 index 00000000..1cf06112 --- /dev/null +++ b/app/docs/slate/.dockerignore @@ -0,0 +1,2 @@ +build/ +.github/ diff --git a/app/docs/slate/.editorconfig b/app/docs/slate/.editorconfig new file mode 100644 index 00000000..1692977c --- /dev/null +++ b/app/docs/slate/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# Top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.rb] +charset = utf-8 + +[*.md] +trim_trailing_whitespace = false diff --git a/app/docs/slate/.gitattributes b/app/docs/slate/.gitattributes new file mode 100644 index 00000000..3069c432 --- /dev/null +++ b/app/docs/slate/.gitattributes @@ -0,0 +1 @@ +source/javascripts/lib/* linguist-vendored diff --git a/app/docs/slate/.github/ISSUE_TEMPLATE/bug.md b/app/docs/slate/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 00000000..25fcdb1d --- /dev/null +++ b/app/docs/slate/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,22 @@ +--- +name: Report a Bug +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Bug Description** +A clear and concise description of what the bug is and how to reproduce it. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Browser (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Last upstream Slate commit (run `git log --author="Robert Lord" | head -n 1`):** +Put the commit hash here diff --git a/app/docs/slate/.github/ISSUE_TEMPLATE/config.yml b/app/docs/slate/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..16f4beed --- /dev/null +++ b/app/docs/slate/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Questions, Ideas, Discussions + url: https://github.com/slatedocs/slate/discussions + about: Ask and answer questions, and propose new features. diff --git a/app/docs/slate/.github/PULL_REQUEST_TEMPLATE.md b/app/docs/slate/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..151e45d7 --- /dev/null +++ b/app/docs/slate/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/docs/slate/.github/workflows/build.yml b/app/docs/slate/.github/workflows/build.yml new file mode 100644 index 00000000..c9ec0ecc --- /dev/null +++ b/app/docs/slate/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: Build + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + ruby-version: [2.3, 2.4, 2.5, 2.6, 2.7] + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: gems-${{ runner.os }}-${{ matrix.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + gems-${{ runner.os }}-${{ matrix.ruby-version }}- + gems-${{ runner.os }}- + + # necessary to get ruby 2.3 to work nicely with bundler vendor/bundle cache + # can remove once ruby 2.3 is no longer supported + - run: gem update --system + + - run: bundle config set deployment 'true' + - name: bundle install + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - run: bundle exec middleman build diff --git a/app/docs/slate/.github/workflows/deploy.yml b/app/docs/slate/.github/workflows/deploy.yml new file mode 100644 index 00000000..341cd5f7 --- /dev/null +++ b/app/docs/slate/.github/workflows/deploy.yml @@ -0,0 +1,41 @@ +name: Deploy + +on: + push: + branches: [ 'main' ] + +jobs: + deploy: + runs-on: ubuntu-latest + env: + ruby-version: 2.5 + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.ruby-version }} + + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: gems-${{ runner.os }}-${{ matrix.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + gems-${{ runner.os }}-${{ matrix.ruby-version }}- + gems-${{ runner.os }}- + + - run: bundle config set deployment 'true' + - name: bundle install + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - run: bundle exec middleman build + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./build + keep_files: true diff --git a/app/docs/slate/.github/workflows/dev_deploy.yml b/app/docs/slate/.github/workflows/dev_deploy.yml new file mode 100644 index 00000000..7f1a40ab --- /dev/null +++ b/app/docs/slate/.github/workflows/dev_deploy.yml @@ -0,0 +1,50 @@ +name: Dev Deploy + +on: + push: + branches: [ 'dev' ] + +jobs: + deploy: + runs-on: ubuntu-latest + env: + ruby-version: 2.5 + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.ruby-version }} + + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: gems-${{ runner.os }}-${{ matrix.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + gems-${{ runner.os }}-${{ matrix.ruby-version }}- + gems-${{ runner.os }}- + + - run: bundle config set deployment 'true' + - name: bundle install + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - run: bundle exec middleman build + + - name: Push to Docker Hub + uses: docker/build-push-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_KEY }} + repository: slatedocs/slate + tag_with_ref: true + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3.7.0-8 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + destination_dir: dev + publish_dir: ./build + keep_files: true diff --git a/app/docs/slate/.github/workflows/publish.yml b/app/docs/slate/.github/workflows/publish.yml new file mode 100644 index 00000000..d57930a5 --- /dev/null +++ b/app/docs/slate/.github/workflows/publish.yml @@ -0,0 +1,22 @@ +name: Publish Docker image + +on: + release: + types: [published] + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v2 + + - name: Push to Docker Hub + uses: docker/build-push-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_KEY }} + repository: slatedocs/slate + tag_with_ref: true + tags: latest diff --git a/app/docs/slate/.gitignore b/app/docs/slate/.gitignore new file mode 100644 index 00000000..1d5d08dd --- /dev/null +++ b/app/docs/slate/.gitignore @@ -0,0 +1,27 @@ +*.gem +*.rbc +.bundle +.config +coverage +InstalledFiles +lib/bundler/man +pkg +rdoc +spec/reports +test/tmp +test/version_tmp +tmp +*.DS_STORE +build/ +.cache +.vagrant +.sass-cache + +# YARD artifacts +.yardoc +_yardoc +doc/ +.idea/ + +# Vagrant artifacts +ubuntu-*-console.log diff --git a/app/docs/slate/CHANGELOG.md b/app/docs/slate/CHANGELOG.md new file mode 100644 index 00000000..1ffe3eb8 --- /dev/null +++ b/app/docs/slate/CHANGELOG.md @@ -0,0 +1,254 @@ +# Changelog + +## Version 2.8.0 + +*October 27, 2020* + +* Remove last trailing newline when using the copy code button +* Rework docker image and make available at slatedocs/slate +* Improve Dockerfile layout to improve caching (thanks @micvbang) +* Bump rouge from 3.20 to 3.24 +* Bump nokogiri from 1.10.9 to 1.10.10 +* Bump middleman from 4.3.8 to 4.3.11 +* Bump lunr.js from 2.3.8 to 2.3.9 + +## Version 2.7.1 + +*August 13, 2020* + +* __[security]__ Bumped middleman from 4.3.7 to 4.3.8 + +_Note_: Slate uses redcarpet, not kramdown, for rendering markdown to HTML, and so was unaffected by the security vulnerability in middleman. +If you have changed slate to use kramdown, and with GFM, you may need to install the `kramdown-parser-gfm` gem. + +## Version 2.7.0 + +*June 21, 2020* + +* __[security]__ Bumped rack in Gemfile.lock from 2.2.2 to 2.2.3 +* Bumped bundled jQuery from 3.2.1 to 3.5.1 +* Bumped bundled lunr from 0.5.7 to 2.3.8 +* Bumped imagesloaded from 3.1.8 to 4.1.4 +* Bumped rouge from 3.17.0 to 3.20.0 +* Bumped redcarpet from 3.4.0 to 3.5.0 +* Fix color of highlighted code being unreadable when printing page +* Add clipboard icon for "Copy to Clipboard" functionality to code boxes (see note below) +* Fix handling of ToC selectors that contain punctutation (thanks @gruis) +* Fix language bar truncating languages that overflow screen width +* Strip HTML tags from ToC title before displaying it in title bar in JS (backup to stripping done in Ruby code) (thanks @atic) + +To enable the new clipboard icon, you need to add `code_clipboard: true` to the frontmatter of source/index.html.md. +See [this line](https://github.com/slatedocs/slate/blame/main/source/index.html.md#L19) for an example of usage. + +## Version 2.6.1 + +*May 30, 2020* + +* __[security]__ update child dependency activesupport in Gemfile.lock to 5.4.2.3 +* Update Middleman in Gemfile.lock to 4.3.7 +* Replace Travis-CI with GitHub actions for continuous integration +* Replace Spectrum with GitHub discussions + +## Version 2.6.0 + +*May 18, 2020* + +__Note__: 2.5.0 was "pulled" due to a breaking bug discovered after release. It is recommended to skip it, and move straight to 2.6.0. + +* Fix large whitespace gap in middle column for sections with codeblocks +* Fix highlighted code elements having a different background than rest of code block +* Change JSON keys to have a different font color than their values +* Disable asset hashing for woff and woff2 elements due to middleman bug breaking woff2 asset hashing in general +* Move Dockerfile to Debian from Alpine +* Converted repo to a [GitHub template](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-template-repository) +* Update sassc to 2.3.0 in Gemfile.lock + +## Version 2.5.0 + +*May 8, 2020* + +* __[security]__ update nokogiri to ~> 1.10.8 +* Update links in example docs to https://github.com/slatedocs/slate from https://github.com/lord/slate +* Update LICENSE to include full Apache 2.0 text +* Test slate against Ruby 2.5 and 2.6 on Travis-CI +* Update Vagrantfile to use Ubuntu 18.04 (thanks @bradthurber) +* Parse arguments and flags for deploy.sh on script start, instead of potentially after building source files +* Install nodejs inside Vagrantfile (thanks @fernandoaguilar) +* Add Dockerfile for running slate (thanks @redhatxl) +* update middleman-syntax and rouge to ~>3.2 +* update middleman to 4.3.6 + +## Version 2.4.0 + +*October 19, 2019* + +- Move repository from lord/slate to slatedocs/slate +- Fix documentation to point at new repo link, thanks to [Arun](https://github.com/slash-arun), [Gustavo Gawryszewski](https://github.com/gawry), and [Daniel Korbit](https://github.com/danielkorbit) +- Update `nokogiri` to 1.10.4 +- Update `ffi` in `Gemfile.lock` to fix security warnings, thanks to [Grey Baker](https://github.com/greysteil) and [jakemack](https://github.com/jakemack) +- Update `rack` to 2.0.7 in `Gemfile.lock` to fix security warnings, thanks to [Grey Baker](https://github.com/greysteil) and [jakemack](https://github.com/jakemack) +- Update middleman to `4.3` and relax constraints on middleman related gems, thanks to [jakemack](https://github.com/jakemack) +- Add sass gem, thanks to [jakemack](https://github.com/jakemack) +- Activate `asset_cache` in middleman to improve cacheability of static files, thanks to [Sam Gilman](https://github.com/thenengah) +- Update to using bundler 2 for `Gemfile.lock`, thanks to [jakemack](https://github.com/jakemack) + +## Version 2.3.1 + +*July 5, 2018* + +- Update `sprockets` in `Gemfile.lock` to fix security warnings + +## Version 2.3 + +*July 5, 2018* + +- Allows strikethrough in markdown by default. +- Upgrades jQuery to 3.2.1, thanks to [Tomi Takussaari](https://github.com/TomiTakussaari) +- Fixes invalid HTML in `layout.erb`, thanks to [Eric Scouten](https://github.com/scouten) for pointing out +- Hopefully fixes Vagrant memory issues, thanks to [Petter Blomberg](https://github.com/p-blomberg) for the suggestion +- Cleans HTML in headers before setting `document.title`, thanks to [Dan Levy](https://github.com/justsml) +- Allows trailing whitespace in markdown files, thanks to [Samuel Cousin](https://github.com/kuzyn) +- Fixes pushState/replaceState problems with scrolling not changing the document hash, thanks to [Andrey Fedorov](https://github.com/anfedorov) +- Removes some outdated examples, thanks [@al-tr](https://github.com/al-tr), [Jerome Dahdah](https://github.com/jdahdah), and [Ricardo Castro](https://github.com/mccricardo) +- Fixes `nav-padding` bug, thanks [Jerome Dahdah](https://github.com/jdahdah) +- Code style fixes thanks to [Sebastian Zaremba](https://github.com/vassyz) +- Nokogiri version bump thanks to [Grey Baker](https://github.com/greysteil) +- Fix to default `index.md` text thanks to [Nick Busey](https://github.com/NickBusey) + +Thanks to everyone who contributed to this release! + +## Version 2.2 + +*January 19, 2018* + +- Fixes bugs with some non-roman languages not generating unique headers +- Adds editorconfig, thanks to [Jay Thomas](https://github.com/jaythomas) +- Adds optional `NestingUniqueHeadCounter`, thanks to [Vladimir Morozov](https://github.com/greenhost87) +- Small fixes to typos and language, thx [Emir Ribić](https://github.com/ribice), [Gregor Martynus](https://github.com/gr2m), and [Martius](https://github.com/martiuslim)! +- Adds links to Spectrum chat for questions in README and ISSUE_TEMPLATE + +## Version 2.1 + +*October 30, 2017* + +- Right-to-left text stylesheet option, thanks to [Mohammad Hossein Rabiee](https://github.com/mhrabiee) +- Fix for HTML5 history state bug, thanks to [Zach Toolson](https://github.com/ztoolson) +- Small styling changes, typo fixes, small bug fixes from [Marian Friedmann](https://github.com/rnarian), [Ben Wilhelm](https://github.com/benwilhelm), [Fouad Matin](https://github.com/fouad), [Nicolas Bonduel](https://github.com/NicolasBonduel), [Christian Oliff](https://github.com/coliff) + +Thanks to everyone who submitted PRs for this version! + +## Version 2.0 + +*July 17, 2017* + +- All-new statically generated table of contents + - Should be much faster loading and scrolling for large pages + - Smaller Javascript file sizes + - Avoids the problem with the last link in the ToC not ever highlighting if the section was shorter than the page + - Fixes control-click not opening in a new page + - Automatically updates the HTML title as you scroll +- Updated design + - New default colors! + - New spacings and sizes! + - System-default typefaces, just like GitHub +- Added search input delay on large corpuses to reduce lag +- We even bumped the major version cause hey, why not? +- Various small bug fixes + +Thanks to everyone who helped debug or wrote code for this version! It was a serious community effort, and I couldn't have done it alone. + +## Version 1.5 + +*February 23, 2017* + +- Add [multiple tabs per programming language](https://github.com/lord/slate/wiki/Multiple-language-tabs-per-programming-language) feature +- Upgrade Middleman to add Ruby 1.4.0 compatibility +- Switch default code highlighting color scheme to better highlight JSON +- Various small typo and bug fixes + +## Version 1.4 + +*November 24, 2016* + +- Upgrade Middleman and Rouge gems, should hopefully solve a number of bugs +- Update some links in README +- Fix broken Vagrant startup script +- Fix some problems with deploy.sh help message +- Fix bug with language tabs not hiding properly if no error +- Add `!default` to SASS variables +- Fix bug with logo margin +- Bump tested Ruby versions in .travis.yml + +## Version 1.3.3 + +*June 11, 2016* + +Documentation and example changes. + +## Version 1.3.2 + +*February 3, 2016* + +A small bugfix for slightly incorrect background colors on code samples in some cases. + +## Version 1.3.1 + +*January 31, 2016* + +A small bugfix for incorrect whitespace in code blocks. + +## Version 1.3 + +*January 27, 2016* + +We've upgraded Middleman and a number of other dependencies, which should fix quite a few bugs. + +Instead of `rake build` and `rake deploy`, you should now run `bundle exec middleman build --clean` to build your server, and `./deploy.sh` to deploy it to Github Pages. + +## Version 1.2 + +*June 20, 2015* + +**Fixes:** + +- Remove crash on invalid languages +- Update Tocify to scroll to the highlighted header in the Table of Contents +- Fix variable leak and update search algorithms +- Update Python examples to be valid Python +- Update gems +- More misc. bugfixes of Javascript errors +- Add Dockerfile +- Remove unused gems +- Optimize images, fonts, and generated asset files +- Add chinese font support +- Remove RedCarpet header ID patch +- Update language tabs to not disturb existing query strings + +## Version 1.1 + +*July 27, 2014* + +**Fixes:** + +- Finally, a fix for the redcarpet upgrade bug + +## Version 1.0 + +*July 2, 2014* + +[View Issues](https://github.com/tripit/slate/issues?milestone=1&state=closed) + +**Features:** + +- Responsive designs for phones and tablets +- Started tagging versions + +**Fixes:** + +- Fixed 'unrecognized expression' error +- Fixed #undefined hash bug +- Fixed bug where the current language tab would be unselected +- Fixed bug where tocify wouldn't highlight the current section while searching +- Fixed bug where ids of header tags would have special characters that caused problems +- Updated layout so that pages with disabled search wouldn't load search.js +- Cleaned up Javascript diff --git a/app/docs/slate/CODE_OF_CONDUCT.md b/app/docs/slate/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..cc17fd98 --- /dev/null +++ b/app/docs/slate/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@lord.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/app/docs/slate/Gemfile b/app/docs/slate/Gemfile new file mode 100644 index 00000000..9a318414 --- /dev/null +++ b/app/docs/slate/Gemfile @@ -0,0 +1,12 @@ +ruby '>=2.3.1' +source 'https://gems.ruby-china.com' + +# Middleman +gem 'middleman', '~>4.3' +gem 'middleman-syntax', '~> 3.2' +gem 'middleman-autoprefixer', '~> 2.7' +gem 'middleman-sprockets', '~> 4.1' +gem 'rouge', '~> 3.21' +gem 'redcarpet', '~> 3.5.0' +gem 'nokogiri', '~> 1.10.8' +gem 'sass' diff --git a/app/docs/slate/Gemfile.lock b/app/docs/slate/Gemfile.lock new file mode 100644 index 00000000..44028888 --- /dev/null +++ b/app/docs/slate/Gemfile.lock @@ -0,0 +1,136 @@ +GEM + remote: https://gems.ruby-china.com/ + specs: + activesupport (5.2.4.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + autoprefixer-rails (9.5.1.1) + execjs + backports (3.18.2) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.12.2) + concurrent-ruby (1.1.7) + contracts (0.13.0) + dotenv (2.7.6) + erubis (2.7.0) + execjs (2.7.0) + fast_blank (1.0.0) + fastimage (2.2.0) + ffi (1.13.1) + haml (5.1.2) + temple (>= 0.8.0) + tilt + hamster (3.0.0) + concurrent-ruby (~> 1.0) + hashie (3.6.0) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + kramdown (2.3.0) + rexml + listen (3.0.8) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + memoist (0.16.2) + middleman (4.3.11) + coffee-script (~> 2.2) + haml (>= 4.0.5) + kramdown (>= 2.3.0) + middleman-cli (= 4.3.11) + middleman-core (= 4.3.11) + middleman-autoprefixer (2.10.1) + autoprefixer-rails (~> 9.1) + middleman-core (>= 3.3.3) + middleman-cli (4.3.11) + thor (>= 0.17.0, < 2.0) + middleman-core (4.3.11) + activesupport (>= 4.2, < 6.0) + addressable (~> 2.3) + backports (~> 3.6) + bundler + contracts (~> 0.13.0) + dotenv + erubis + execjs (~> 2.0) + fast_blank + fastimage (~> 2.0) + hamster (~> 3.0) + hashie (~> 3.4) + i18n (~> 0.9.0) + listen (~> 3.0.0) + memoist (~> 0.14) + padrino-helpers (~> 0.13.0) + parallel + rack (>= 1.4.5, < 3) + sassc (~> 2.0) + servolux + tilt (~> 2.0.9) + uglifier (~> 3.0) + middleman-sprockets (4.1.1) + middleman-core (~> 4.0) + sprockets (>= 3.0) + middleman-syntax (3.2.0) + middleman-core (>= 3.2) + rouge (~> 3.2) + mini_portile2 (2.4.0) + minitest (5.14.2) + nokogiri (1.10.10) + mini_portile2 (~> 2.4.0) + padrino-helpers (0.13.3.4) + i18n (~> 0.6, >= 0.6.7) + padrino-support (= 0.13.3.4) + tilt (>= 1.4.1, < 3) + padrino-support (0.13.3.4) + activesupport (>= 3.1) + parallel (1.19.2) + public_suffix (4.0.6) + rack (2.2.3) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) + redcarpet (3.5.0) + rexml (3.2.4) + rouge (3.24.0) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sassc (2.4.0) + ffi (~> 1.9) + servolux (0.13.0) + sprockets (3.7.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + temple (0.8.2) + thor (1.0.1) + thread_safe (0.3.6) + tilt (2.0.10) + tzinfo (1.2.7) + thread_safe (~> 0.1) + uglifier (3.2.0) + execjs (>= 0.3.0, < 3) + +PLATFORMS + ruby + +DEPENDENCIES + middleman (~> 4.3) + middleman-autoprefixer (~> 2.7) + middleman-sprockets (~> 4.1) + middleman-syntax (~> 3.2) + nokogiri (~> 1.10.8) + redcarpet (~> 3.5.0) + rouge (~> 3.21) + sass + +RUBY VERSION + ruby 2.3.3p222 + +BUNDLED WITH + 2.1.4 diff --git a/app/docs/slate/LICENSE b/app/docs/slate/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/app/docs/slate/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/app/docs/slate/README.md b/app/docs/slate/README.md new file mode 100644 index 00000000..7d15f864 --- /dev/null +++ b/app/docs/slate/README.md @@ -0,0 +1,81 @@ +
+ +Slate helps you create beautiful, intelligent, responsive API documentation.
+ +The example above was created with Slate. Check it out at slatedocs.github.io/slate.
+ +Features +------------ + +* **Clean, intuitive design** — With Slate, the description of your API is on the left side of your documentation, and all the code examples are on the right side. Inspired by [Stripe's](https://stripe.com/docs/api) and [PayPal's](https://developer.paypal.com/webapps/developer/docs/api/) API docs. Slate is responsive, so it looks great on tablets, phones, and even in print. + +* **Everything on a single page** — Gone are the days when your users had to search through a million pages to find what they wanted. Slate puts the entire documentation on a single page. We haven't sacrificed linkability, though. As you scroll, your browser's hash will update to the nearest header, so linking to a particular point in the documentation is still natural and easy. + +* **Slate is just Markdown** — When you write docs with Slate, you're just writing Markdown, which makes it simple to edit and understand. Everything is written in Markdown — even the code samples are just Markdown code blocks. + +* **Write code samples in multiple languages** — If your API has bindings in multiple programming languages, you can easily put in tabs to switch between them. In your document, you'll distinguish different languages by specifying the language name at the top of each code block, just like with GitHub Flavored Markdown. + +* **Out-of-the-box syntax highlighting** for [over 100 languages](https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers), no configuration required. + +* **Automatic, smoothly scrolling table of contents** on the far left of the page. As you scroll, it displays your current position in the document. It's fast, too. We're using Slate at TripIt to build documentation for our new API, where our table of contents has over 180 entries. We've made sure that the performance remains excellent, even for larger documents. + +* **Let your users update your documentation for you** — By default, your Slate-generated documentation is hosted in a public GitHub repository. Not only does this mean you get free hosting for your docs with GitHub Pages, but it also makes it simple for other developers to make pull requests to your docs if they find typos or other problems. Of course, if you don't want to use GitHub, you're also welcome to host your docs elsewhere. + +* **RTL Support** Full right-to-left layout for RTL languages such as Arabic, Persian (Farsi), Hebrew etc. + +Getting started with Slate is super easy! Simply press the green "use this template" button above and follow the instructions below. Or, if you'd like to check out what Slate is capable of, take a look at the [sample docs](https://slatedocs.github.io/slate/). + +Getting Started with Slate +------------------------------ + +To get started with Slate, please check out the [Getting Started](https://github.com/slatedocs/slate/wiki#getting-started) +section in our [wiki](https://github.com/slatedocs/slate/wiki). + +We support running Slate in three different ways: +* [Natively](https://github.com/slatedocs/slate/wiki/Using-Slate-Natively) +* [Using Vagrant](https://github.com/slatedocs/slate/wiki/Using-Slate-in-Vagrant) +* [Using Docker](https://github.com/slatedocs/slate/wiki/Using-Slate-in-Docker) + +Companies Using Slate +--------------------------------- + +* [NASA](https://api.nasa.gov) +* [Sony](http://developers.cimediacloud.com) +* [Best Buy](https://bestbuyapis.github.io/api-documentation/) +* [Travis-CI](https://docs.travis-ci.com/api/) +* [Greenhouse](https://developers.greenhouse.io/harvest.html) +* [WooCommerce](http://woocommerce.github.io/woocommerce-rest-api-docs/) +* [Dwolla](https://docs.dwolla.com/) +* [Clearbit](https://clearbit.com/docs) +* [Coinbase](https://developers.coinbase.com/api) +* [Parrot Drones](http://developer.parrot.com/docs/bebop/) +* [Scale](https://docs.scaleapi.com/) + +You can view more in [the list on the wiki](https://github.com/slatedocs/slate/wiki/Slate-in-the-Wild). + +Questions? Need Help? Found a bug? +-------------------- + +If you've got questions about setup, deploying, special feature implementation in your fork, or just want to chat with the developer, please feel free to [start a thread in our Discussions tab](https://github.com/slatedocs/slate/discussions)! + +Found a bug with upstream Slate? Go ahead and [submit an issue](https://github.com/slatedocs/slate/issues). And, of course, feel free to submit pull requests with bug fixes or changes to the `dev` branch. + +Contributors +-------------------- + +Slate was built by [Robert Lord](https://lord.io) while at [TripIt](https://www.tripit.com/). The project is now maintained by [Matthew Peveler](https://github.com/MasterOdin) and [Mike Ralphson](https://github.com/MikeRalphson). + +Thanks to the following people who have submitted major pull requests: + +- [@chrissrogers](https://github.com/chrissrogers) +- [@bootstraponline](https://github.com/bootstraponline) +- [@realityking](https://github.com/realityking) +- [@cvkef](https://github.com/cvkef) + +Also, thanks to [Sauce Labs](http://saucelabs.com) for sponsoring the development of the responsive styles. diff --git a/app/docs/slate/Vagrantfile b/app/docs/slate/Vagrantfile new file mode 100644 index 00000000..4166fb6b --- /dev/null +++ b/app/docs/slate/Vagrantfile @@ -0,0 +1,46 @@ +Vagrant.configure(2) do |config| + config.vm.box = "ubuntu/bionic64" + config.vm.network :forwarded_port, guest: 4567, host: 4567 + config.vm.provider "virtualbox" do |vb| + vb.memory = "2048" + end + + config.vm.provision "bootstrap", + type: "shell", + inline: <<-SHELL + # add nodejs v12 repository + curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - + + sudo apt-get update + sudo apt-get install -yq ruby ruby-dev + sudo apt-get install -yq pkg-config build-essential nodejs git libxml2-dev libxslt-dev + sudo apt-get autoremove -yq + gem install --no-ri --no-rdoc bundler + SHELL + + # add the local user git config to the vm + config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig" + + config.vm.provision "install", + type: "shell", + privileged: false, + inline: <<-SHELL + echo "==============================================" + echo "Installing app dependencies" + cd /vagrant + bundle config build.nokogiri --use-system-libraries + bundle install + SHELL + + config.vm.provision "run", + type: "shell", + privileged: false, + run: "always", + inline: <<-SHELL + echo "==============================================" + echo "Starting up middleman at http://localhost:4567" + echo "If it does not come up, check the ~/middleman.log file for any error messages" + cd /vagrant + bundle exec middleman server --watcher-force-polling --watcher-latency=1 &> ~/middleman.log & + SHELL +end diff --git a/app/docs/slate/config.rb b/app/docs/slate/config.rb new file mode 100644 index 00000000..4c51315d --- /dev/null +++ b/app/docs/slate/config.rb @@ -0,0 +1,65 @@ +set :build_dir, '../../../public/docs/' + +# Unique header generation +require './lib/unique_head.rb' + +# Markdown +set :markdown_engine, :redcarpet +set :markdown, + fenced_code_blocks: true, + smartypants: true, + disable_indented_code_blocks: true, + prettify: true, + strikethrough: true, + tables: true, + with_toc_data: true, + no_intra_emphasis: true, + renderer: UniqueHeadCounter + +# Assets +set :css_dir, 'stylesheets' +set :js_dir, 'javascripts' +set :images_dir, 'images' +set :fonts_dir, 'fonts' + +# Activate the syntax highlighter +activate :syntax +ready do + require './lib/monokai_sublime_slate.rb' + require './lib/multilang.rb' +end + +activate :sprockets + +activate :autoprefixer do |config| + config.browsers = ['last 2 version', 'Firefox ESR'] + config.cascade = false + config.inline = true +end + +# Github pages require relative links +activate :relative_assets +set :relative_links, true + +# Build Configuration +configure :build do + # We do want to hash woff and woff2 as there's a bug where woff2 will use + # woff asset hash which breaks things. Trying to use a combination of ignore and + # rewrite_ignore does not work as it conflicts weirdly with relative_assets. Disabling + # the .woff2 extension only does not work as .woff will still activate it so have to + # have both. See https://github.com/slatedocs/slate/issues/1171 for more details. + activate :asset_hash, :exts => app.config[:asset_extensions] - %w[.woff .woff2] + # If you're having trouble with Middleman hanging, commenting + # out the following two lines has been known to help + activate :minify_css + activate :minify_javascript + # activate :gzip +end + +# Deploy Configuration +# If you want Middleman to listen on a different port, you can set that below +set :port, 4567 + +helpers do + require './lib/toc_data.rb' +end diff --git a/app/docs/slate/deploy.sh b/app/docs/slate/deploy.sh new file mode 100755 index 00000000..9dbd7db9 --- /dev/null +++ b/app/docs/slate/deploy.sh @@ -0,0 +1,226 @@ +#!/usr/bin/env bash +set -o errexit #abort if any command fails +me=$(basename "$0") + +help_message="\ +Usage: $me [-c FILE] [