|
- class Api::V1::Projects::PipelinesController < Api::V1::BaseController
- before_action :require_operate_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 = params[:pipeline_json].to_json
- pipeline_yaml = build_pipeline_yaml(params[:pipeline_name], params[:pipeline_json])
- tip_exception("流水线yaml内空不能为空") if pipeline_yaml.blank?
- @pipeline.yaml = pipeline_yaml
- @pipeline.save!
- sha = get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
- tip_exception("#{@pipeline.file_name}已存在") if sha
- interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
- tip_exception(interactor.error) unless interactor.success?
- render_ok({ id: @pipeline.id })
- end
-
- def save_yaml
- @pipeline = Action::Pipeline.new(pipeline_name: params[:pipeline_name], project_id: @project.id)
- @pipeline.file_name = ".gitea/workflows/#{@pipeline.pipeline_name}.yaml"
- @pipeline.json = params[:pipeline_json].to_json
- pipeline_yaml = build_pipeline_yaml(params[:pipeline_name], params[:pipeline_json])
- tip_exception("流水线yaml内空不能为空") if pipeline_yaml.blank?
- @pipeline.yaml = pipeline_yaml
- sha = get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
- interactor = sha.present? ? Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) : Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
- tip_exception(interactor.error) unless interactor.success?
- render_ok
- end
-
- def build_yaml
- if params[:pipeline_json].present?
- @pipeline_yaml = build_pipeline_yaml(params[:pipeline_name], params[:pipeline_json])
- else
- @pipeline_yaml = build_test_yaml
- end
- render plain: @pipeline_yaml
- 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_test_yaml) if @pipeline.blank?
- end
-
- def build_pipeline_yaml(pipeline_name, pipeline_json)
- if pipeline_json.present?
- @pipeline_name = pipeline_name
- params_nodes = pipeline_json["nodes"].select { |node| !["on-push", "on-schedule"].include?(node["component_name"]) }
- on_nodes = 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[:pipeline_yaml]
- end
- @pipeline_yaml
- end
-
- def build_test_yaml
- @pipeline_name = "I like it"
- 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"])
- next if node.blank?
- node.cust_name = input_node["component_label"] if input_node["component_label"].present?
- run_values = {}
- 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"]}"
- if input_key.to_s.gsub("--", "") == "run"
- run_values = run_values.merge({ "#{input_key.gsub("--", "")}": "#{input_node["in_parameters"][input_key]["value"]}" })
- else
- input_values = input_values.merge({ "#{input_key.gsub("--", "")}": "#{input_node["in_parameters"][input_key]["value"]}" })
- end
- end
- node.run_values = run_values
- node.input_values = input_values
- # Rails.logger.info "@input_values run_values===#{node.run_values.to_json}"
- # Rails.logger.info "@input_values input_values===#{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: @pipeline.yaml,
- 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"])
- next if node.blank?
- node.cust_name = input_node["component_label"] if input_node["component_label"].present?
- run_values = {}
- input_values = {}
- if input_node["in_parameters"].present?
- Rails.logger.info "@in_parameters=====11===#{input_node["component_name"]}======#{input_node["in_parameters"].keys}"
- input_node["in_parameters"].keys.each 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"]}"
- if input_key.to_s.gsub("--", "") == "run"
- run_values = run_values.merge({ "#{input_key.gsub("--", "")}": "#{input_node["in_parameters"][input_key]["value"]}" })
- else
- input_values = input_values.merge({ "#{input_key.gsub("--", "")}": "#{input_node["in_parameters"][input_key]["value"]}" })
- end
- end
- node.run_values = run_values
- # 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": {
- "--cron": {
- "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": "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": "echo env"
- }
- }
- },
- {
- "id": "git-clone-245734ab",
- "category_id": 1,
- "component_name": "scp",
- "component_label": "scp",
- "working_directory": "",
- "command": "",
- "in_parameters": {
- "--host": {
- "type": "str",
- "item_type": "",
- "label": "代码仓库地址",
- "require": 1,
- "choice": [],
- "default": "",
- "placeholder": "私有仓库填写ssh地址,公有仓库填写https git地址",
- "describe": "代码仓库地址",
- "editable": 1,
- "condition": "",
- "value": "192.168.1.114"
- }
- }
- }
-
- ],
- # "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
|