创建多条流水线、模板管理

This commit is contained in:
victor 2021-01-26 17:15:53 +08:00
parent 131ccc36c7
commit 6c77b73ec6
22 changed files with 476 additions and 123 deletions

View File

@ -3520,6 +3520,7 @@ http://localhost:3000/api/Jason/forge/builds | jq
|page |否|string |页数,第几页 | |page |否|string |页数,第几页 |
|limit |否|string |每页多少条数据默认20条 | |limit |否|string |每页多少条数据默认20条 |
|search |是|string |构建状态条件过滤; 值说明pending: 准备中failure: 构建失败running: 运行中error构建失败(.trustie-pipeline.yml文件错误)success: 构建成功killed: 撤销构建 | |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 | | id | int | 流水线id |
| pipeline_name | string | 流水线名称 | | pipeline_name | string | 流水线名称 |
| file_name | string | 流水线文件名 | | file_name | string | 流水线文件名 |
| created_at | string | 创建时间 | | branch | string | 触发分支 |
| sync | int | 是否同步到gitea | | 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": [ "pipelines": [
{ {
"id": 1, "id": 65,
"pipeline_name": "2020-01-08 流水线", "pipeline_name": "流水线 2021-01-25",
"file_name": ".trustie.pipeline.yaml", "file_name": ".drone.yml",
"created_at": "2021-01-08 04:16:24", "branch": "develop",
"updated_at": "2021-01-08 04:16:24" "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 ' { --data-raw ' {
"pipeline_name": "流水线 2021-01-12", "pipeline_name": "流水线 2021-01-12",
"file_name": ".trustie.pipeline.yaml", "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 | 流水线名称 | | pipeline_name | 是 | string | 流水线名称 |
| file_name | 是 | string | 文件名称(默认初始值:.trustie.pipeline.yaml | | 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服务器绑定 #### 解除CI服务器绑定
``` ```

View File

@ -16,6 +16,10 @@ class Ci::BaseController < ApplicationController
@repos = Ci::Repo.find_all_with_namespace(namespace) @repos = Ci::Repo.find_all_with_namespace(namespace)
end end
def load_repo_by_repo_slug(slug)
@repo_slug = Ci::Repo.load_repo_by_repo_slug(slug)
end
private private
def authorize_access_project! def authorize_access_project!
unless @project.manager?(current_user) unless @project.manager?(current_user)

View File

@ -38,7 +38,7 @@ class Ci::CloudAccountsController < Ci::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
if @repo if @repo
return render_error('该项目已经激活') if @repo.repo_active? return render_error('该项目已经激活') if @repo.repo_active?
@repo.activate!(@ci_user.user_id) @repo.activate!(@project)
else else
@repo = Ci::Repo.auto_create!(@ci_user, @project) @repo = Ci::Repo.auto_create!(@ci_user, @project)
@user.update_column(:user_syncing, false) @user.update_column(:user_syncing, false)

View File

@ -1,18 +1,37 @@
class Ci::PipelinesController < Ci::BaseController class Ci::PipelinesController < Ci::BaseController
before_action :require_login, only: %i[list create] before_action :require_login, only: %i[list create]
skip_before_action :connect_to_ci_db skip_before_action :connect_to_ci_db, except: %i[list create destroy]
before_action :load_project, only: %i[content create_trustie_pipeline] before_action :load_project, only: %i[create]
before_action :load_repository, only: %i[create_trustie_pipeline] before_action :load_repo, only: %i[create]
# ======流水线相关接口========== # # ======流水线相关接口========== #
def list def list
@pipelines = Ci::Pipeline.where('identifier=?', params[:identifier]) @result = Array.new
list = Ci::Pipeline.where('identifier=?', params[:identifier])
# 查询build状态
list = list.collect do |pipeline|
repo = load_repo_by_repo_slug("#{pipeline.login}/#{pipeline.identifier}")
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
@result.push(pipeline)
end
@total_count = @result.size
@pipelines = paginate @result
end end
def create def create
ActiveRecord::Base.transaction do 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=?', params[:branch], params[:repo]).size
if size > 0
render_error("#{params[:branch]}分支已经存在流水线!")
return
end
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],
login: current_user.login, identifier: params[:repo], branch: params[:branch], event: params[:event])
pipeline.save! pipeline.save!
# 默认创建四个初始阶段 # 默认创建四个初始阶段
@ -26,12 +45,70 @@ class Ci::PipelinesController < Ci::BaseController
).save! ).save!
index += 1 index += 1
end end
create_pipeline_file(pipeline)
create_ci_repo(pipeline)
render_ok({id: pipeline.id}) render_ok({id: pipeline.id})
end end
rescue Exception => ex rescue Exception => ex
render_error(ex.message) render_error(ex.message)
end end
# 在代码库创建文件
def create_pipeline_file(pipeline)
sha = get_pipeline_file_sha(pipeline.file_name, pipeline.branch)
if sha
logger.info "#{pipeline.file_name}已存在"
pipeline.update!(sync: 1, sha: sha)
else
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
if interactor.success?
logger.info "#{pipeline.file_name}创建成功"
pipeline.update!(sync: 1, sha: interactor.result['content']['sha'])
end
end
end
# 在drone数据库repo表新增一条repo记录
def create_ci_repo(pipeline)
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
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
return file['sha']
else
return nil
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 def update
pipeline = Ci::Pipeline.find(params[:id]) pipeline = Ci::Pipeline.find(params[:id])
if pipeline if pipeline
@ -45,6 +122,10 @@ class Ci::PipelinesController < Ci::BaseController
def destroy def destroy
pipeline = Ci::Pipeline.find(params[:id]) pipeline = Ci::Pipeline.find(params[:id])
if pipeline if pipeline
repo = load_repo_by_repo_slug("#{pipeline.login}/#{pipeline.identifier}-" + pipeline.id.to_s)
if repo
repo.destroy!
end
pipeline.destroy! pipeline.destroy!
end end
render_ok render_ok
@ -53,10 +134,9 @@ class Ci::PipelinesController < Ci::BaseController
end end
def content def content
@yaml = "#pipeline \n" @yaml = "\n"
pipeline = Ci::Pipeline.find(params[:id]) pipeline = Ci::Pipeline.find(params[:id])
@sync = pipeline.sync @sha = pipeline.sha
@sha = ''
stages = pipeline.pipeline_stages stages = pipeline.pipeline_stages
if stages && !stages.empty? if stages && !stages.empty?
init_step = stages.first.pipeline_stage_steps.first init_step = stages.first.pipeline_stage_steps.first
@ -72,55 +152,13 @@ class Ci::PipelinesController < Ci::BaseController
end end
end end
end end
if @sync == 1 trigger = ''
@sha = get_pipeline_file_sha(pipeline.file_name) 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
end @yaml += "trigger:\r\n" + trigger unless trigger.blank?
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
}
end end
# =========阶段相关接口========= # # =========阶段相关接口========= #
@ -135,8 +173,8 @@ class Ci::PipelinesController < Ci::BaseController
# 修改stage排序 # 修改stage排序
update_stage_index(params[:id], params[:show_index], 1) update_stage_index(params[:id], params[:show_index], 1)
pipeline_stage = Ci::PipelineStage.new(stage_name: params[:stage_name], pipeline_stage = Ci::PipelineStage.new(stage_name: params[:stage_name],
stage_type: params[:stage_type].blank? ? 'customize' : params[:stage_type], stage_type: params[:stage_type].blank? ? 'customize' : params[:stage_type],
pipeline_id: params[:id], show_index: params[:show_index]) pipeline_id: params[:id], show_index: params[:show_index])
pipeline_stage.save! pipeline_stage.save!
render_ok render_ok
end end
@ -188,7 +226,7 @@ class Ci::PipelinesController < Ci::BaseController
unless steps.empty? unless steps.empty?
steps.each do |step| steps.each do |step|
unless step[:template_id] unless step[:template_id]
render_error("请选择模板!") render_error('请选择模板!')
return return
end end
if !step[:id] if !step[:id]

View File

@ -41,11 +41,8 @@ class Ci::ProjectsController < Ci::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
if @repo if @repo
return render_error('该项目已经激活') if @repo.repo_active? return render_error('该项目已经激活') if @repo.repo_active?
if @project.ci_reactivate? @repo.activate!(@project)
@project.ci_reactivate!(@repo) return render_ok
return render_ok
end
@repo.activate!(@ci_user.user_id)
else else
@repo = Ci::Repo.auto_create!(@ci_user, @project) @repo = Ci::Repo.auto_create!(@ci_user, @project)
@ci_user.update_column(:user_syncing, false) @ci_user.update_column(:user_syncing, false)
@ -66,7 +63,7 @@ class Ci::ProjectsController < Ci::BaseController
return render_error('该项目已经取消激活') if !@repo.repo_active? return render_error('该项目已经取消激活') if !@repo.repo_active?
@project.update_column(:open_devops, false) @project.update_column(:open_devops, false)
@repo.deactivate! @repo.deactivate_repos!
render_ok render_ok
end 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 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 end
def templates_by_stage def show
stage_type = params[:stage_type] @template = Ci::Template.find(params[:id])
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
end end
def create def create
template = Ci::Template.new(template_name: params[:template_name], stage_type = params[:stage_type]
stage_type: params[:stage_type], category = params[:category]
category: params[:category], if category.blank?
parent_category: params[:parent_category], category = Ci::Template::STAGE_TYPES[:"#{stage_type}"]
content: params[:content] end
)
template.save! 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 render_ok
rescue Exception => ex rescue Exception => ex
render_error(ex.message) render_error(ex.message)
@ -53,4 +76,20 @@ class Ci::TemplatesController < ApplicationController
render_error(ex.message) render_error(ex.message)
end 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?
# 根据模板类别分组
@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 end

View File

@ -101,9 +101,6 @@ module Ci::CloudAccountManageable
if cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_SELF if cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_SELF
@connection.execute("DROP DATABASE IF EXISTS #{current_user.login}_drone") # TOTO drop drone database @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 end
cloud_account.destroy! unless cloud_account.blank? cloud_account.destroy! unless cloud_account.blank?

View File

@ -11,4 +11,6 @@ class Ci::Build < Ci::RemoteBase
scope :pending, -> { by_status('pending') } scope :pending, -> { by_status('pending') }
scope :killed, -> { by_status('killed') } scope :killed, -> { by_status('killed') }
scope :by_status, ->(status) { where(build_status: status) } scope :by_status, ->(status) { where(build_status: status) }
scope :by_branch, ->(branch) { where(build_target: branch) }
end 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 :user, class_name: 'Ci::User', foreign_key: :perm_user_id
belongs_to :repo, class_name: 'Ci::Repo', foreign_key: :perm_repo_uid 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 = new(
perm_user_id: user.user_id, perm_user_id: user_id,
perm_repo_uid: repo.repo_id, perm_repo_uid: repo_id,
perm_read: true, perm_read: true,
perm_write: true, perm_write: true,
perm_admin: true, perm_admin: true,

View File

@ -10,7 +10,10 @@
# pipeline_status :string(50) default("unknown"), not null # pipeline_status :string(50) default("unknown"), not null
# login :string(255) # login :string(255)
# sync :integer default("0"), not null # sync :integer default("0"), not null
# project_id :integer # identifier :string(11)
# branch :string(255)
# event :string(255)
# sha :string(255)
# #
class Ci::Pipeline < Ci::LocalBase class Ci::Pipeline < Ci::LocalBase
@ -20,4 +23,6 @@ class Ci::Pipeline < Ci::LocalBase
has_many :pipeline_stages, -> { reorder(show_index: :asc) }, foreign_key: "pipeline_id", :class_name => 'Ci::PipelineStage', dependent: :destroy has_many :pipeline_stages, -> { reorder(show_index: :asc) }, foreign_key: "pipeline_id", :class_name => 'Ci::PipelineStage', dependent: :destroy
attr_accessor :last_build_time
end end

View File

@ -20,37 +20,53 @@ class Ci::Repo < Ci::RemoteBase
return repos return repos
end end
def activate!(ci_user_id) def self.load_repo_by_repo_slug(repo_slug)
update(repo_active: 1, logger.info "########repo_slug: #{repo_slug}"
repo_signer: generate_code, repo = Ci::Repo.where(repo_slug: repo_slug).first
repo_secret: generate_code, return repo
repo_user_id: ci_user_id, end
repo_timeout: 60,
repo_config: '.trustie-pipeline.yml', def find_by_repo_name(repo_name)
repo_updated: Time.now.to_i) logger.info "########repo_name: #{repo_name}"
repos = Ci::Repo.where(repo_name: repo_name)
return repos
end end
def self.auto_create!(user, project) def self.auto_create!(user, project)
repo = new( create_params = {
repo_user_id: user.user_id, repo_user_id: user.user_id,
repo_namespace: project.owner.login, repo_namespace: project.owner.login,
repo_name: project.identifier, repo_name: project.identifier,
repo_slug: "#{project.owner.login}/#{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_scm: "git",
repo_ssh_url: "", repo_ssh_url: "",
repo_html_url: "", repo_html_url: "",
repo_clone_url: project.repository.url, repo_clone_url: create_params[:repo_clone_url],
repo_active: 1, repo_active: 1,
repo_private: true, repo_private: true,
repo_visibility: 'private', repo_visibility: 'private',
repo_branch: 'master', repo_branch: create_params[:repo_branch],
repo_counter: 0, repo_counter: 0,
repo_trusted: false, repo_trusted: false,
repo_protected: false, repo_protected: false,
repo_synced: 0, repo_synced: 0,
repo_version: 1, repo_version: 1,
repo_timeout: 60, repo_timeout: 60,
repo_config: '.trustie-pipeline.yml', repo_config: create_params[:repo_config],
repo_created: Time.now.to_i, repo_created: Time.now.to_i,
repo_updated: 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_signer = repo.generate_code
repo.repo_secret = repo.generate_code repo.repo_secret = repo.generate_code
if repo.save! 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.update_column(:repo_uid, repo.id)
repo repo
end end
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! def deactivate!
update_column(:repo_active, 0) update_column(:repo_active, 0)
end end
def destroy!
self.destroy
end
end end

View File

@ -10,6 +10,7 @@
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# parent_category :string(255) # parent_category :string(255)
# login :string(255)
# #
# Indexes # Indexes
# #
@ -20,4 +21,7 @@ class Ci::Template < Ci::LocalBase
validates :template_name, presence: {message: "模板名称不能为空"} validates :template_name, presence: {message: "模板名称不能为空"}
validates :stage_type, presence: {message: "阶段类型不能为空"} validates :stage_type, presence: {message: "阶段类型不能为空"}
validates :category, presence: {message: "模板类型不能为空"} validates :category, presence: {message: "模板类型不能为空"}
STAGE_TYPES = {init:'初始化',build:'编译构建',deploy:'部署',customize:'其他'}
end end

View File

@ -24,6 +24,9 @@ class Ci::Builds::ListQuery < ApplicationQuery
else else
scope scope
end end
builds = scope.by_branch(params[:branch]) if params[:branch]
custom_sort(builds, params[:sort_by], params[:sort_direction]) custom_sort(builds, params[:sort_by], params[:sort_direction])
end end
end end

View File

@ -1,4 +1,4 @@
json.id user.id json.id user.id
json.name user.real_name json.name user.real_name == '游客' ? '-' : user.real_name
json.login user.login json.login user.login
json.image_url url_to_avatar(user) json.image_url url_to_avatar(user)

View File

@ -1,8 +1,12 @@
json.id pipeline.id json.id pipeline.id
json.pipeline_name pipeline.pipeline_name 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.file_name pipeline.file_name
json.sync pipeline.sync json.sync pipeline.sync
json.branch pipeline.branch
json.event pipeline.event
json.sha pipeline.sha
json.identifier pipeline.identifier 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.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") json.updated_at pipeline.updated_at.strftime("%Y-%m-%d %H:%M:%S")

View File

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

View File

@ -3,6 +3,7 @@ json.template_name template.template_name
json.stage_type template.stage_type json.stage_type template.stage_type
json.category template.category json.category template.category
json.content template.content json.content template.content
json.login template.login
json.created_at template.created_at json.created_at template.created_at
json.updated_at template.updated_at json.updated_at template.updated_at

View File

@ -1,3 +1,4 @@
json.total_count @total_count
json.templates @templates do |template| json.templates @templates do |template|
json.partial! "/ci/templates/list", template: template json.partial! "/ci/templates/list", template: template
end 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
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 collection do
get :list get :list
get :templates_by_stage 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