模板管理功能

新增功能:
1. 支持多条流水线
2. 完善CI/CD模板管理功能
This commit is contained in:
jasder 2021-02-02 16:39:31 +08:00
commit bbcb515e24
24 changed files with 499 additions and 127 deletions

View File

@ -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服务器绑定
```

View File

@ -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)

View File

@ -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)

View File

@ -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)
@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 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
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]

View File

@ -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

View File

@ -1,30 +1,53 @@
class Ci::TemplatesController < ApplicationController
class Ci::TemplatesController < Ci::BaseController
before_action :require_login, only: %i[list create]
skip_before_action :connect_to_ci_db
#======模板管理======#
def list
@templates = Ci::Template.all
stage_type = params[:stage_type]
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 templates_by_stage
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 }
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

View File

@ -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?

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -1,3 +1,4 @@
json.content @yaml
json.sync @sync
json.sha @sha
json.sha @sha
json.branch @branch

View File

@ -1,3 +1,4 @@
json.total_count @total_count
json.pipelines @pipelines do |pipeline|
json.partial! "/ci/pipelines/list", pipeline: pipeline
end

View File

@ -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

View File

@ -1,3 +1,4 @@
json.total_count @total_count
json.templates @templates do |template|
json.partial! "/ci/templates/list", template: template
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
class AddLoginToCiTemplates < ActiveRecord::Migration[5.2]
def change
add_column :ci_templates, :login, :string
end
end

View File

@ -0,0 +1,5 @@
class AddOwnerToCiPipelines < ActiveRecord::Migration[5.2]
def change
add_column :ci_pipelines, :owner, :string
end
end