forgeplus/app/controllers/api/v1/projects/pipelines_controller.rb

543 lines
18 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class Api::V1::Projects::PipelinesController < Api::V1::BaseController
before_action :require_manager_above
def index
@pipelines = Action::Pipeline.where(project_id: @project.id).order(updated_at: :desc)
@pipelines = paginate @pipelines
end
def create
size = Action::Pipeline.where(pipeline_name: params[:pipeline_name], project_id: @project.id).size
tip_exception("已经存在#{params[:pipeline_name]}流水线!") if size > 0
@pipeline = Action::Pipeline.new(pipeline_name: params[:pipeline_name], project_id: @project.id)
@pipeline.file_name = ".gitea/workflows/#{@pipeline.pipeline_name}.yaml"
@pipeline.json = demo.to_json
# @pipeline.json = params[:json] if params[:json]
@pipeline.yaml = build_pipeline_yaml(@pipeline)
@pipeline.save!
sha = get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
tip_exception("#{@pipeline.file_name}已存在") if sha
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
tip_exception(interactor.error) unless interactor.success?
render_ok({ id: @pipeline.id })
end
def update
@pipeline = Action::Pipeline.find(params[:id])
@pipeline.update!(pipeline_name: params[:pipeline_name])
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
tip_exception(interactor.error) unless interactor.success?
render_ok
end
def destroy
@pipeline = Action::Pipeline.find(params[:id])
if pipeline
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
tip_exception(interactor.error) unless interactor.success?
@pipeline.destroy!
end
render_ok
end
def show
@pipeline = Action::Pipeline.find_by(id: params[:id])
@pipeline = Action::Pipeline.new(id: 0, pipeline_name: "test-ss", yaml: build_yaml) if @pipeline.blank?
end
def build_pipeline_yaml(pipeline)
if pipeline.json.present?
@name = pipeline.pipeline_name
params_nodes = JSON.parse(pipeline.json)["nodes"].select { |node| !["on-push", "on-schedule"].include?(node["component_name"]) }
on_nodes = JSON.parse(pipeline.json)["nodes"].select { |node| ["on-push", "on-schedule"].include?(node["component_name"]) }
@on_nodes = build_nodes(on_nodes)
@steps_nodes = build_nodes(params_nodes)
yaml = ERB.new(File.read(File.join(Rails.root, "app/views/api/v1/projects/pipelines", "build_pipeline.yaml.erb"))).result(binding)
# 删除空行内容
@pipeline_yaml = yaml.gsub(/^\s*\n/, "")
else
@pipeline_yaml = params[:yaml]
end
@pipeline_yaml
end
def build_yaml
@name = "love me"
params_nodes = JSON.parse(demo.to_json)["nodes"].select { |node| !["on-push", "on-schedule"].include?(node["component_name"]) }
on_nodes = JSON.parse(demo.to_json)["nodes"].select { |node| ["on-push", "on-schedule"].include?(node["component_name"]) }
@on_nodes = build_nodes(on_nodes)
@steps_nodes = []
params_nodes.each do |input_node|
# Rails.logger.info "input_node=====0===#{input_node["component_name"]}======#{input_node["in_parameters"]}"
node = Action::Node.find_by(name: input_node["component_name"])
node.cust_name = input_node["component_label"] if input_node["component_label"].present?
input_values = {}
if input_node["in_parameters"].present?
# Rails.logger.info "@in_parameters=====11===#{input_node["component_name"]}======#{input_node["in_parameters"]}"
input_node["in_parameters"].each_key do |input_key|
# Rails.logger.info "@in_parameters.input_key===#{input_key}"
# Rails.logger.info "@in_parameters.input_value===#{input_node["in_parameters"][input_key]["value"]}"
input_values = input_values.merge({ "#{input_key.gsub("--", "")}": "#{input_node["in_parameters"][input_key]["value"]}" })
end
node.input_values = input_values
# Rails.logger.info "@input_values node===#{node.input_values.to_json}"
end
@steps_nodes.push(node)
end
Rails.logger.info "@@on_nodes===#{@on_nodes.to_json}"
Rails.logger.info "@steps_nodes===#{@steps_nodes.to_json}"
yaml = ERB.new(File.read(File.join(Rails.root, "app/views/api/v1/projects/pipelines", "build_pipeline.yaml.erb"))).result(binding)
@pipeline_yaml = yaml.gsub(/^\s*\n/, "")
Rails.logger.info "========================="
Rails.logger.info @pipeline_yaml
@pipeline_yaml
end
private
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
file['sha']
end
end
def content_params
{
filepath: ".gitea/workflows/#{@pipeline.pipeline_name}.yaml",
branch: @pipeline.branch,
new_branch: @pipeline.branch,
content: build_pipeline_yaml(@pipeline),
message: 'create pipeline',
committer: {
email: current_user.mail,
name: current_user.login
},
identifier: @project.identifier
}
end
def build_nodes(params_nodes)
steps_nodes = []
params_nodes.each do |input_node|
node = Action::Node.find_by(name: input_node["component_name"])
node.cust_name = input_node["component_label"] if input_node["component_label"].present?
input_values = {}
if input_node["in_parameters"].present?
# Rails.logger.info "@in_parameters=====11===#{input_node["component_name"]}======#{input_node["in_parameters"]}"
input_node["in_parameters"].each_key do |input_key|
# Rails.logger.info "@in_parameters.input_key===#{input_key}"
# Rails.logger.info "@in_parameters.input_value===#{input_node["in_parameters"][input_key]["value"]}"
input_values = input_values.merge({ "#{input_key.gsub("--", "")}": "#{input_node["in_parameters"][input_key]["value"]}" })
end
# Rails.logger.info "@input_values node1===#{input_values}"
node.input_values = input_values
# Rails.logger.info "@input_values node===#{node.input_values.to_json}"
end
steps_nodes.push(node)
end
steps_nodes
end
def demo
{
"nodes": [
{
"id": "git-clone-245734ab",
"category_id": 1,
"component_name": "on-schedule",
"component_label": "触发器",
"working_directory": "",
"command": "",
"in_parameters": {
"--cro": {
"type": "str",
"item_type": "",
"label": "push代码",
"require": 1,
"choice": [],
"default": "",
"placeholder": "私有仓库填写ssh地址公有仓库填写https git地址",
"describe": "代码仓库地址",
"editable": 1,
"condition": "",
"value": "15 4,5 * * *"
},
"--paths-ignore": {
"type": "str",
"item_type": "",
"label": "push代码",
"require": 1,
"choice": [],
"default": "",
"placeholder": "私有仓库填写ssh地址公有仓库填写https git地址",
"describe": "代码仓库地址",
"editable": 1,
"condition": "",
"value": "**.md"
}
},
"out_parameters": {
"--code_output": {
"type": "str",
"label": "代码输出路径",
"path": "/code",
"require": 1,
"value": "/code"
}
},
"description": "代码拉取组件",
"icon_path": "component-icon-1",
"create_by": "admin",
"create_time": "2024-03-02T05:41:25.000+00:00",
"update_by": "admin",
"update_time": "2024-03-02T05:41:25.000+00:00",
"state": 1,
"image": "172.20.32.187/pipeline-component/built-in/git:202312071000",
"env_variables": "",
"x": 532,
"y": 202,
"label": "代码拉取",
"img": "/assets/images/component-icon-1.png",
"isCluster": false,
"type": "rect-node",
"size": [110, 36],
"--code_path": "https://openi.pcl.ac.cn/somunslotus/somun202304241505581.git",
"--branch": "train_ci_test",
"--depth": "1",
"--code_output": "/code"
},
{
"id": "git-clone-245734ab",
"category_id": 1,
"component_name": "git-clone",
"component_label": "代码拉取",
"working_directory": "",
"command": "",
"in_parameters": {
},
"out_parameters": {
"--code_output": {
"type": "str",
"label": "代码输出路径",
"path": "/code",
"require": 1,
"value": "/code"
}
},
"description": "代码拉取组件",
"icon_path": "component-icon-1",
"create_by": "admin",
"create_time": "2024-03-02T05:41:25.000+00:00",
"update_by": "admin",
"update_time": "2024-03-02T05:41:25.000+00:00",
"state": 1,
"image": "172.20.32.187/pipeline-component/built-in/git:202312071000",
"env_variables": "",
"x": 532,
"y": 202,
"label": "代码拉取",
"img": "/assets/images/component-icon-1.png",
"isCluster": false,
"type": "rect-node",
"size": [110, 36],
"--code_path": "https://openi.pcl.ac.cn/somunslotus/somun202304241505581.git",
"--branch": "train_ci_test",
"--depth": "1",
"--code_output": "/code"
},
{
"id": "git-clone-245734ab",
"category_id": 1,
"component_name": "setup-java",
"component_label": "安装java环境",
"working_directory": "",
"command": "",
"in_parameters": {
"--distribution": {
"type": "str",
"item_type": "",
"label": "代码仓库地址",
"require": 1,
"choice": [],
"default": "",
"placeholder": "私有仓库填写ssh地址公有仓库填写https git地址",
"describe": "代码仓库地址",
"editable": 1,
"condition": "",
"value": "jdkfile"
},
"--java-version": {
"type": "str",
"item_type": "",
"label": "代码分支/tag",
"require": 1,
"choice": [],
"default": "master",
"placeholder": "",
"describe": "代码分支或者tag",
"editable": 1,
"condition": "",
"value": "11.0.0"
},
"--architecture": {
"type": "str",
"item_type": "",
"label": "克隆深度",
"require": 0,
"choice": [],
"default": "1",
"placeholder": "",
"describe": "代码克隆深度",
"editable": 1,
"condition": "",
"value": "x64"
},
"--mvn-toolchain-vendor": {
"type": "str",
"item_type": "",
"label": "ssh私钥",
"require": 0,
"choice": [],
"default": "1",
"placeholder": "",
"describe": "ssh私钥确保ssh公钥已经托管到代码平台否则可能拉取失败",
"editable": 1,
"value": "Oracle"
}
},
"out_parameters": {
"--code_output": {
"type": "str",
"label": "代码输出路径",
"path": "/code",
"require": 1,
"value": "/code"
}
},
"description": "代码拉取组件",
"icon_path": "component-icon-1",
"create_by": "admin",
"create_time": "2024-03-02T05:41:25.000+00:00",
"update_by": "admin",
"update_time": "2024-03-02T05:41:25.000+00:00",
"state": 1,
"image": "172.20.32.187/pipeline-component/built-in/git:202312071000",
"env_variables": "",
"x": 532,
"y": 202,
"label": "代码拉取",
"img": "/assets/images/component-icon-1.png",
"isCluster": false,
"type": "rect-node",
"size": [110, 36],
"--code_path": "https://openi.pcl.ac.cn/somunslotus/somun202304241505581.git",
"--branch": "train_ci_test",
"--depth": "1",
"--code_output": "/code"
},
{
"id": "git-clone-245734ab",
"category_id": 1,
"component_name": "shell",
"component_label": "执行shell命令",
"working_directory": "",
"command": "",
"in_parameters": {
"--run": {
"type": "str",
"item_type": "",
"label": "代码仓库地址",
"require": 1,
"choice": [],
"default": "",
"placeholder": "私有仓库填写ssh地址公有仓库填写https git地址",
"describe": "代码仓库地址",
"editable": 1,
"condition": "",
"value": "service nginx restart"
}
}
},
{
"id": "git-clone-245734ab",
"category_id": 1,
"component_name": "scp",
"component_label": "scp",
"working_directory": "",
"command": "",
"in_parameters": {
"--run": {
"type": "str",
"item_type": "",
"label": "代码仓库地址",
"require": 1,
"choice": [],
"default": "",
"placeholder": "私有仓库填写ssh地址公有仓库填写https git地址",
"describe": "代码仓库地址",
"editable": 1,
"condition": "",
"value": "service nginx restart"
}
}
}
],
# "edges": [
# {
# "source": "git-clone-245734ab",
# "target": "model-train-09b1491",
# "style": {
# "active": {
# "stroke": "rgb(95, 149, 255)",
# "lineWidth": 1
# },
# "selected": {
# "stroke": "rgb(95, 149, 255)",
# "lineWidth": 2,
# "shadowColor": "rgb(95, 149, 255)",
# "shadowBlur": 10,
# "text-shape": {
# "fontWeight": 500
# }
# },
# "highlight": {
# "stroke": "rgb(95, 149, 255)",
# "lineWidth": 2,
# "text-shape": {
# "fontWeight": 500
# }
# },
# "inactive": {
# "stroke": "rgb(234, 234, 234)",
# "lineWidth": 1
# },
# "disable": {
# "stroke": "rgb(245, 245, 245)",
# "lineWidth": 1
# },
# "endArrow": {
# "path": "M 6,0 L 9,-1.5 L 9,1.5 Z",
# "d": 4.5,
# "fill": "#CDD0DC"
# },
# "cursor": "pointer",
# "lineWidth": 1,
# "opacity": 1,
# "stroke": "#CDD0DC",
# "radius": 1
# },
# "nodeStateStyle": {
# "hover": {
# "opacity": 1,
# "stroke": "#8fe8ff"
# }
# },
# "labelCfg": {
# "autoRotate": true,
# "style": {
# "fontSize": 10,
# "fill": "#FFF"
# }
# },
# "id": "edge-0.11773197923997381714446043619",
# "startPoint": {
# "x": 532,
# "y": 220.25,
# "anchorIndex": 1
# },
# "endPoint": {
# "x": 530,
# "y": 304.75,
# "anchorIndex": 0
# },
# "targetAnchor": 0,
# "type": "cubic-vertical",
# "curveOffset": [0, 0],
# "curvePosition": [0.5, 0.5],
# "minCurveOffset": [0, 0],
# "depth": 0
# },
# {
# "source": "model-train-09b1491",
# "target": "model-evaluate-b401ff0",
# "style": {
# "active": {
# "stroke": "rgb(95, 149, 255)",
# "lineWidth": 1
# },
# "selected": {
# "stroke": "rgb(95, 149, 255)",
# "lineWidth": 2,
# "shadowColor": "rgb(95, 149, 255)",
# "shadowBlur": 10,
# "text-shape": {
# "fontWeight": 500
# }
# },
# "highlight": {
# "stroke": "rgb(95, 149, 255)",
# "lineWidth": 2,
# "text-shape": {
# "fontWeight": 500
# }
# },
# "inactive": {
# "stroke": "rgb(234, 234, 234)",
# "lineWidth": 1
# },
# "disable": {
# "stroke": "rgb(245, 245, 245)",
# "lineWidth": 1
# },
# "endArrow": {
# "path": "M 6,0 L 9,-1.5 L 9,1.5 Z",
# "d": 4.5,
# "fill": "#CDD0DC"
# },
# "cursor": "pointer",
# "lineWidth": 1,
# "opacity": 1,
# "stroke": "#CDD0DC",
# "radius": 1
# },
# "nodeStateStyle": {
# "hover": {
# "opacity": 1,
# "stroke": "#8fe8ff"
# }
# },
# "labelCfg": {
# "autoRotate": true,
# "style": {
# "fontSize": 10,
# "fill": "#FFF"
# }
# },
# "id": "edge-0.28238605806531771714446047075",
# "startPoint": {
# "x": 530,
# "y": 341.25,
# "anchorIndex": 1
# },
# "endPoint": {
# "x": 520,
# "y": 431.75,
# "anchorIndex": 0
# },
# "targetAnchor": 0,
# "type": "cubic-vertical",
# "curveOffset": [0, 0],
# "curvePosition": [0.5, 0.5],
# "minCurveOffset": [0, 0],
# "depth": 0
# }
# ]
}
end
end