| @@ -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 | |||
| ``` | |||
| *请求参数说明:* | |||
| @@ -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服务器绑定 | |||
| ``` | |||
| @@ -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) | |||
| @@ -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) | |||
| @@ -1,18 +1,40 @@ | |||
| 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] | |||
| 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 | |||
| @pipelines = Ci::Pipeline.where('identifier=?', params[:identifier]) | |||
| @result = Array.new | |||
| list = Ci::Pipeline.where('identifier=? and owner=?', params[:identifier], params[:owner]) | |||
| # 查询build状态 | |||
| list.collect do |pipeline| | |||
| pipeline.last_build_time = nil | |||
| 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 | |||
| pipeline.pipeline_status = build.build_status | |||
| pipeline.last_build_time = Time.at(build.build_created) | |||
| end | |||
| 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=? 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],owner: params[:owner], | |||
| login: current_user.login, identifier: params[:repo], branch: params[:branch], event: params[:event]) | |||
| pipeline.save! | |||
| # 默认创建四个初始阶段 | |||
| @@ -26,16 +48,73 @@ 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}已存在" | |||
| else | |||
| interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) | |||
| if interactor.success? | |||
| logger.info "#{pipeline.file_name}创建成功" | |||
| end | |||
| end | |||
| end | |||
| # 在drone数据库repo表新增一条repo记录 | |||
| def create_ci_repo(pipeline) | |||
| 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) | |||
| 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: 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 | |||
| 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 | |||
| @@ -45,6 +124,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 +136,8 @@ class Ci::PipelinesController < Ci::BaseController | |||
| end | |||
| def content | |||
| @yaml = "#pipeline \n" | |||
| @yaml = "\n" | |||
| pipeline = Ci::Pipeline.find(params[:id]) | |||
| @sync = pipeline.sync | |||
| @sha = '' | |||
| stages = pipeline.pipeline_stages | |||
| if stages && !stages.empty? | |||
| init_step = stages.first.pipeline_stage_steps.first | |||
| @@ -72,55 +153,15 @@ class Ci::PipelinesController < Ci::BaseController | |||
| end | |||
| end | |||
| end | |||
| if @sync == 1 | |||
| @sha = get_pipeline_file_sha(pipeline.file_name) | |||
| 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 | |||
| @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? | |||
| trigger += " event:\r\n" | |||
| pipeline.event.split(',').each { |event| trigger += " - #{event}\r\n"} | |||
| 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? | |||
| @branch = pipeline.branch | |||
| end | |||
| # =========阶段相关接口========= # | |||
| @@ -135,8 +176,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 +229,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] | |||
| @@ -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 | |||
| @@ -1,30 +1,53 @@ | |||
| class Ci::TemplatesController < ApplicationController | |||
| class Ci::TemplatesController < Ci::BaseController | |||
| def list | |||
| @templates = Ci::Template.all | |||
| end | |||
| before_action :require_login, only: %i[list create] | |||
| skip_before_action :connect_to_ci_db | |||
| def templates_by_stage | |||
| #======模板管理======# | |||
| def list | |||
| 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 } | |||
| 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 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,29 @@ 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? | |||
| if stage_type == Ci::PipelineStage::INIT_STAGE_TYPE && !@templates.nil? | |||
| @templates.each do |template| | |||
| content = template.content | |||
| unless content.blank? | |||
| pipeline = Ci::Pipeline.find(params[:id]) | |||
| template.content = content.gsub(/{name}/, pipeline.pipeline_name) unless pipeline.nil? | |||
| end | |||
| end | |||
| end | |||
| # 根据模板类别分组 | |||
| @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 | |||
| @@ -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? | |||
| @@ -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 | |||
| @@ -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, | |||
| @@ -10,6 +10,10 @@ | |||
| # updated_at :datetime not null | |||
| # login :string(255) | |||
| # sync :integer default("0"), not null | |||
| # identifier :string(11) | |||
| # branch :string(255) | |||
| # event :string(255) | |||
| # sha :string(255) | |||
| # identifier :string(255) | |||
| # | |||
| @@ -20,4 +24,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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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") | |||
| @@ -1,3 +1,4 @@ | |||
| json.content @yaml | |||
| json.sync @sync | |||
| json.sha @sha | |||
| json.sha @sha | |||
| json.branch @branch | |||
| @@ -1,3 +1,4 @@ | |||
| json.total_count @total_count | |||
| json.pipelines @pipelines do |pipeline| | |||
| json.partial! "/ci/pipelines/list", pipeline: pipeline | |||
| end | |||
| @@ -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 | |||
| @@ -1,3 +1,4 @@ | |||
| json.total_count @total_count | |||
| json.templates @templates do |template| | |||
| json.partial! "/ci/templates/list", template: template | |||
| end | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -0,0 +1,5 @@ | |||
| class AddLoginToCiTemplates < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :ci_templates, :login, :string | |||
| end | |||
| end | |||
| @@ -0,0 +1,5 @@ | |||
| class AddOwnerToCiPipelines < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :ci_pipelines, :owner, :string | |||
| end | |||
| end | |||