forked from Trustie/forgeplus
Merge branch 'standalone_develop' into dev_osredm_server
This commit is contained in:
commit
7c9b5d689e
|
|
@ -1,5 +1,6 @@
|
|||
class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
||||
include RepositoriesHelper
|
||||
include Api::ActionValidatorHelper
|
||||
before_action :require_operate_above, except: [:upload_results, :run_results]
|
||||
|
||||
def index
|
||||
|
|
@ -102,6 +103,11 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
|||
@pipeline.pipeline_name = params[:pipeline_name] if params[:pipeline_name].present?
|
||||
pipeline_yaml = params[:pipeline_yaml].present? ? params[:pipeline_yaml] : build_pipeline_yaml_new(@pipeline.pipeline_name, params[:pipeline_json])
|
||||
tip_exception("流水线yaml内空不能为空") if pipeline_yaml.blank?
|
||||
begin
|
||||
validate_string(pipeline_yaml)
|
||||
rescue
|
||||
tip_exception("yaml格式有误")
|
||||
end
|
||||
@pipeline.yaml = pipeline_yaml
|
||||
#Rails.logger.info "pipeline_yaml base64=========================#{Base64.encode64(@pipeline.yaml).gsub(/\n/, '')}"
|
||||
sha = get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
require 'yaml'
|
||||
require 'json'
|
||||
|
||||
module Api::ActionValidatorHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def validate_string(yaml_string)
|
||||
begin
|
||||
yaml_content = YAML.safe_load(yaml_string)
|
||||
validate_content(yaml_content)
|
||||
rescue Psych::SyntaxError => e
|
||||
{ valid: false, errors: ["YAML语法错误: #{e.message}"] }
|
||||
rescue => e
|
||||
{ valid: false, errors: ["数据读取错误: #{e.message}"] }
|
||||
end
|
||||
end
|
||||
|
||||
def validate_content(data)
|
||||
errors = []
|
||||
warnings = []
|
||||
|
||||
# 基本结构验证
|
||||
errors.concat(validate_basic_structure(data))
|
||||
|
||||
# 触发器验证
|
||||
errors.concat(validate_trigger(data))
|
||||
|
||||
# 任务验证
|
||||
errors.concat(validate_job(data))
|
||||
|
||||
# 步骤验证
|
||||
if data['jobs']
|
||||
data['jobs'].each do |job_name, job_config|
|
||||
errors.concat(validate_job_steps(job_name, job_config))
|
||||
end
|
||||
end
|
||||
|
||||
{
|
||||
valid: errors.empty?,
|
||||
errors: errors,
|
||||
warnings: warnings,
|
||||
job_count: data['jobs']&.size || 0
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_basic_structure(data)
|
||||
errors = []
|
||||
|
||||
unless data.is_a?(Hash)
|
||||
errors << "Action文件必须是YAML对象"
|
||||
return errors
|
||||
end
|
||||
|
||||
unless data.key?('name')
|
||||
errors << "缺少必需字段: name"
|
||||
end
|
||||
|
||||
unless data.key?(true)
|
||||
errors << "缺少触发器配置: on"
|
||||
end
|
||||
|
||||
unless data.key?('jobs')
|
||||
errors << "缺少任务配置: jobs"
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_trigger(data)
|
||||
errors = []
|
||||
|
||||
if data[true]
|
||||
if data[true]['push']
|
||||
unless data[true]['push'].key?('branches')
|
||||
errors << "push触发器缺少branches配置"
|
||||
end
|
||||
|
||||
unless data[true]['push'].key?('paths-ignore')
|
||||
errors << "push触发器缺少paths-ignore配置"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_job(data)
|
||||
errors = []
|
||||
|
||||
if data['jobs']
|
||||
jobs = data['jobs']
|
||||
|
||||
unless jobs.is_a?(Hash)
|
||||
errors << "jobs字段必须是对象"
|
||||
return errors
|
||||
end
|
||||
|
||||
jobs.each do |job_name, job_config|
|
||||
unless job_config.is_a?(Hash)
|
||||
errors << "任务 #{job_name} 配置必须是对象"
|
||||
next
|
||||
end
|
||||
|
||||
unless job_config.key?('name')
|
||||
errors << "任务 #{job_name} 缺少name字段"
|
||||
end
|
||||
|
||||
unless job_config.key?('runs-on')
|
||||
errors << "任务 #{job_name} 缺少runs-on字段"
|
||||
end
|
||||
|
||||
unless job_config.key?('steps')
|
||||
errors << "任务 #{job_name} 缺少steps字段"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_job_steps(job_name, job_config)
|
||||
errors = []
|
||||
steps = job_config['steps'] || []
|
||||
|
||||
unless steps.is_a?(Array)
|
||||
errors << "任务 #{job_name} 的steps必须是数组"
|
||||
return errors
|
||||
end
|
||||
# 验证每个步骤的详细配置
|
||||
steps.each_with_index do |step, index|
|
||||
errors.concat(validate_step(job_name, step, index))
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_step(job_name, step, index)
|
||||
errors = []
|
||||
|
||||
unless step.is_a?(Hash)
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 必须是对象"
|
||||
return errors
|
||||
end
|
||||
|
||||
unless step.key?('name')
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 缺少name字段"
|
||||
end
|
||||
|
||||
# 验证uses或run字段
|
||||
has_uses = step.key?('uses')
|
||||
has_run = step.key?('run')
|
||||
|
||||
unless has_uses || has_run
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 必须包含uses或run字段"
|
||||
end
|
||||
|
||||
if has_uses && has_run
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 不能同时包含uses和run字段"
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
end
|
||||
|
|
@ -41,7 +41,7 @@ class Repositories::CreateService < ApplicationService
|
|||
begin
|
||||
@gitea_repository = $gitea_client.get_repos_by_owner_repo(project.owner.login, params[:identifier])
|
||||
rescue Gitea::Api::ServerError => e
|
||||
if e.http_code.to_i == 404
|
||||
if e.http_code.to_i == 404 || e.http_code.to_i == 307
|
||||
if project.owner.is_a?(User)
|
||||
# @gitea_repository = Gitea::Repository::CreateProjectService.new(user.gitea_token, gitea_repository_params).call
|
||||
@gitea_repository = $gitea_client.post_user_repos({query: {token: user.gitea_token}, body: gitea_repository_params.to_json})
|
||||
|
|
|
|||
Loading…
Reference in New Issue