新增:绑定仓库和webhook触发地址

This commit is contained in:
yystopf 2024-04-16 17:15:22 +08:00
parent 04e70b3b34
commit e358e3b6f6
11 changed files with 268 additions and 1 deletions

View File

@ -0,0 +1,24 @@
class Api::V1::Projects::SyncRepositoriesController < Api::V1::BaseController
before_action :require_public_and_member_above
def create
@sync_repositories = Api::V1::Projects::SyncRepositories::CreateService.call(@project, sync_repository_params)
end
def sync
@sync_repositories = SyncRepository.where(project: @project)
@sync_repository_branches = SyncRepositoryBranch.where(sync_repository_id: @sync_repositories)
@sync_repositories.each do |item|
TouchSyncJob.perform_later(item)
end
@sync_repository_branches.each do |item|
TouchSyncJob.perform_later(item)
end
end
private
def sync_repository_params
param.permit(:type, :external_token, :external_repo_address, :sync_granularity, :external_branch_name, :gitlink_branch_name, :first_sync_direction)
end
end

View File

@ -0,0 +1,24 @@
class TouchSyncJob < ApplicationJob
queue_as :default
def perform(touchable)
puts "aaaa"
case touchable.class.to_s
when 'SyncRepositories::Github' || 'SyncRepositories::Gitee'
Reposync::SyncRepoService.call(touchable.repo_name)
when 'SyncRepositoryBranch'
sync_repository = touchable.sync_repository
result = []
if sync_repository.sync_direction == 1
result = Reposync::SyncBranchService.call(sync_repository.repo_name, touchable.gitlink_branch_name, sync_repository.sync_direction)
else
result = Reposync::SyncBranchService.call(sync_repository.repo_name, touchable.external_branch_name, sync_repository.sync_direction)
end
if result.is_a?(Array)
touchable.update_column(:sync_status, 1)
else
touchable.update_column(:sync_status, 2)
end
end
end
end

View File

@ -0,0 +1,22 @@
# == Schema Information
#
# Table name: sync_repositories
#
# id :integer not null, primary key
# project_id :integer
# type :string(255)
# repo_name :string(255)
# external_repo_address :string(255)
# sync_granularity :integer
# sync_direction :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_sync_repositories_on_project_id (project_id)
#
class SyncRepositories::Gitee < SyncRepository
end

View File

@ -0,0 +1,21 @@
# == Schema Information
#
# Table name: sync_repositories
#
# id :integer not null, primary key
# project_id :integer
# type :string(255)
# repo_name :string(255)
# external_repo_address :string(255)
# sync_granularity :integer
# sync_direction :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_sync_repositories_on_project_id (project_id)
#
class SyncRepositories::Github < SyncRepository
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: sync_repositories
#
# id :integer not null, primary key
# project_id :integer
# type :string(255)
# repo_name :string(255)
# external_repo_address :string(255)
# sync_granularity :integer
# sync_direction :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_sync_repositories_on_project_id (project_id)
#
class SyncRepository < ApplicationRecord
belongs_to :project
validates :repo_name, uniqueness: { message: "已存在" }
end

View File

@ -0,0 +1,23 @@
# == Schema Information
#
# Table name: sync_repository_branches
#
# id :integer not null, primary key
# sync_repository_id :integer
# gitlink_branch_name :string(255)
# external_branch_name :string(255)
# sync_time :datetime
# sync_status :integer default("0")
# reposync_branch_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_sync_repository_branches_on_sync_repository_id (sync_repository_id)
#
class SyncRepositoryBranch < ApplicationRecord
belongs_to :sync_repository
end

View File

@ -0,0 +1,95 @@
class Api::V1::Projects::SyncRepositories::CreateService < ApplicationService
include ActiveModel::Model
attr_reader :project, :type, :external_token, :external_repo_address, :sync_granularity, :external_branch_name, :gitlink_branch_name, :first_sync_direction
attr_accessor :sync_repository1, :sync_repository2
validates :type, inclusion: {in: %w(SyncRepositories::Gitee SyncRepositories::Github)}
validates :external_repo_address, format: { with: CustomRegexp::URL_REGEX, multiline: true, message: "地址格式不正确" }
validates :sync_granularity, :first_sync_direction, inclusion: {in: [1,2]}
validate :check_gitlink_branch_name
def initialize(project, params)
@project = project
@type = params[:type]
@external_token = params[:external_token]
@external_repo_address = params[:external_repo_address]
@sync_granularity = params[:sync_granularity].to_i
@external_branch_name = params[:external_branch_name]
@gitlink_branch_name = params[:gitlink_branch_name]
@first_sync_direction = params[:first_sync_direction].to_i
end
def call
raise Error, errors.full_messages.join(",") unless valid?
if sync_granularity == 2
# 创建两个不同方向的同步仓库
create_sync_repository
# 创建两个不同方向的同步分支
create_sync_repository_branch
# 第一次同步
touch_first_sync_branch
else
create_sync_repository
touch_first_sync
end
create_webhook
end
def check_gitlink_branch_name
if sync_granularity == 2
result = $gitea_hat_client.get_repos_branch_name_set_by_owner_repo(project&.owner&.login, project&.identifier) rescue nil
raise Error, '分支不存在' if !result.include?(gitlink_branch_name)
end
end
private
def create_sync_repository
repository1 = Reposync::CreateSyncRepoService.call(repo_name(1), gitlink_repo_address, external_repo_address, sync_granularity, 1)
repository2 = Reposync::CreateSyncRepoService.call(repo_name(2), gitlink_repo_address, external_repo_address, sync_granularity, 2)
@sync_repository1 = SyncRepository.create!(project: project, type: type, repo_name: repo_name(1), external_repo_address: external_repo_address, sync_granularity: sync_granularity, sync_direction: 1)
@sync_repository2 = SyncRepository.create!(project: project, type: type, repo_name: repo_name(2), external_repo_address: external_repo_address, sync_granularity: sync_granularity, sync_direction: 2)
end
def create_sync_repository_branch
branch1 = Reposync::CreateSyncBranchService.call(repo_name(1),gitlink_branch_name, external_branch_name)
branch2 = Reposync::CreateSyncBranchService.call(repo_name(2),gitlink_branch_name, external_branch_name)
@sync_repository_branch1 = SyncRepositoryBranch.create!(sync_repository: @sync_repository1, gitlink_branch_name: gitlink_branch_name, external_branch_name: external_branch_name )
@sync_repository_branch2 = SyncRepositoryBranch.create!(sync_repository: @sync_repository2, gitlink_branch_name: gitlink_branch_name, external_branch_name: external_branch_name)
end
def touch_first_sync
first_sync_direction == 1 ? TouchSyncJob.perform_later(@sync_repository1) : TouchSyncJob.perform_later(@sync_repository2)
end
def touch_first_sync_branch
first_sync_direction == 1 ? TouchSyncJob.perform_later(@sync_repository_branch1) : TouchSyncJob.perform_later(@sync_repository_branch2)
end
def create_webhook
webhook_params = {
active: true,
branch_filter: '*',
http_method: 'POST',
url: "#{Rails.application.config_for(:configuration)['platform_url']}/api/v1/#{project&.owner&.login}/#{project&.identifier}/sync_repositories/sync",
content_type: 'json',
type: 'reposync',
events: ["push"]
}
Api::V1::Projects::Webhooks::CreateService.call(project, webhook_params)
end
def repo_name(sync_direction)
if type == "SyncRepositories::Gitee"
return "gitee:#{project.owner&.login}:#{project.identifier}:#{sync_granularity}:#{sync_direction}"
else
return "github:#{project.owner&.login}:#{project.identifier}:#{sync_granularity}:#{sync_direction}"
end
end
def gitlink_repo_address
"#{EduSetting.get("gitlink_repo_domain")}/#{project.owner&.login}/#{project.identifier}.git"
end
end

View File

@ -8,7 +8,7 @@ class Api::V1::Projects::Webhooks::CreateService < ApplicationService
validates :active, inclusion: {in: [true, false]}
validates :http_method, inclusion: { in: %w(POST GET), message: "请输入正确的请求方式"}
validates :content_type, inclusion: { in: %w(json form), message: "请输入正确的Content Type"}
validates :type, inclusion: {in: %w(gitea slack discord dingtalk telegram msteams feishu matrix jianmu softbot), message: "请输入正确的Webhook Type"}
validates :type, inclusion: {in: %w(gitea slack discord dingtalk telegram msteams feishu matrix jianmu softbot reposync), message: "请输入正确的Webhook Type"}
def initialize(project, params, token=nil)
@project = project
@owner = project&.owner.login

View File

@ -78,6 +78,11 @@ defaults format: :json do
# projects文件夹下的
scope module: :projects do
resources :sync_repositories, only: [:create] do
collection do
post :sync
end
end
resource :dataset, only: [:create, :update, :show]
resources :actions, module: 'actions' do
collection do

View File

@ -0,0 +1,14 @@
class CreateSyncRepositories < ActiveRecord::Migration[5.2]
def change
create_table :sync_repositories do |t|
t.references :project
t.string :type
t.string :repo_name
t.string :external_repo_address
t.integer :sync_granularity
t.integer :sync_direction, comment: "1表示从gitlink到外部2表示从外部到gitlink"
t.timestamps
end
end
end

View File

@ -0,0 +1,14 @@
class CreateSyncRepositoryBranches < ActiveRecord::Migration[5.2]
def change
create_table :sync_repository_branches do |t|
t.references :sync_repository
t.string :gitlink_branch_name, comment: 'gitlink分支'
t.string :external_branch_name, comment: '外部仓库分支'
t.datetime :sync_time
t.integer :sync_status, default: 0
t.integer :reposync_branch_id
t.timestamps
end
end
end