From ae9d857d7fb63580ae56b725ff89c82f664526db Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 21 Aug 2020 14:53:48 +0800 Subject: [PATCH] FIX ci server --- README.md | 82 ++++++++----------- app/controllers/ci/builds_controller.rb | 27 +++--- .../ci/cloud_accounts_controller.rb | 4 +- app/controllers/ci/projects_controller.rb | 30 +++++++ app/controllers/concerns/devopsable.rb | 4 +- app/controllers/projects_controller.rb | 1 + app/controllers/users_controller.rb | 13 --- app/models/ci/cloud_account.rb | 1 - app/models/ci/local_base.rb | 2 + app/models/project.rb | 1 - app/views/ci/projects/authorize.json.jbuilder | 12 +++ app/views/projects/ci_authorize.json.jbuilder | 12 +++ config/routes.rb | 33 ++++++-- 13 files changed, 135 insertions(+), 87 deletions(-) create mode 100644 app/controllers/ci/projects_controller.rb create mode 100644 app/views/ci/projects/authorize.json.jbuilder create mode 100644 app/views/projects/ci_authorize.json.jbuilder diff --git a/README.md b/README.md index d24d3d83f..6a5b3db37 100644 --- a/README.md +++ b/README.md @@ -2403,29 +2403,28 @@ http://localhost:3000/api//api/repositories/3868/delete_file | jq ### DevOps相关api --- -#### 获取devops流程步骤(判断devops是否初始化) +#### 获取devops流程步骤 ``` -GET /api/users/devops +GET /api/:owner/:repo/ci_authorize ``` *示例* ``` curl -X GET \ --d "project_id=5988" \ -https://localhost:3000/api/users/devops.json | jq +http://localhost:3000/api/jasder/forgeplus/ci_authorize.json | jq ``` - *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| -|project_id |是|string |项目id或者项目的标识identifier| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | *返回参数说明:* |参数名|类型|说明| |-|-|-| -|step |int|初始化devops流程步骤; 0: 标识未开启devops,1: 标识用户已填写了云服务器相关信息,但并未开启认证, 2: 标识用户已开启了CI服务端的认证, 3: 标识用户已经授权并获取了CI服务的token| +|step |int|初始化devops流程步骤; 0: 标识未开启devops,1: 标识用户已填写了云服务器相关信息,但并未开启认证, 2: 标识用户已开启了CI服务端的认证, 3: 标识用户ci服务已初始化| |account |string|你的云服务器帐号| |ip |string|你的云服务器帐号ip| |secret |string|你的云服务器登录密码| @@ -2450,7 +2449,7 @@ https://localhost:3000/api/users/devops.json | jq #### 初始化DevOps流程 ``` -POST /api/ci/cloud_accounts +POST /api/:owner/:repo/cloud_accounts ``` *示例* @@ -2459,18 +2458,18 @@ curl -X POST \ -d "account=xx" \ -d "secret=xxx" \ -d "ip_num=xx.xx.xx.xx" \ --d "project_id=5988" \ -https://localhost:3000/api/ci/cloud_accounts.json | jq +https://localhost:3000/api/jasder/forgeplus/cloud_accounts.json | jq ``` *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | |account |是|string |云服务器ssh连接登录用户名 | |secret |是|string |云服务器ssh连接登录秘密 | |ip_num |否|string |云服务器公网IP | -|project_id |否|string |project's id| *返回参数说明:* @@ -2492,20 +2491,13 @@ https://localhost:3000/api/ci/cloud_accounts.json | jq #### 用户认证CI服务端后,需要调用该接口进行更新devlops流程状态 ``` -PUT /api/users/devops_authenticate +PUT /api/:owner/:repo/ci_authorize ``` *示例* ``` curl -X PUT \ --d "project_id=5988" \ -http://localhost:3000/api/users/devops_authenticate.json | jq +http://localhost:3000/api/jasder/forgeplus/ci_authorize.json | jq ``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|project_id |是|string |项目id或者项目的标识identifier| - *返回参数说明:* @@ -2523,20 +2515,20 @@ http://localhost:3000/api/users/devops_authenticate.json | jq #### 激活项目 ``` -POST /api/ci/cloud_accounts/:id/activate +POST /api/:owner/:repo/cloud_accounts/:id/activate ``` *示例* ``` curl -X POST \ --d "project_id=4844" \ -d "drone_token=xxxxxxxxxx" \ -http://localhost:3000/api/ci/cloud_accounts/1/activate.json | jq +http://localhost:3000/api/jasder/forgeplus/cloud_accounts/1/activate.json | jq ``` *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| -|project_id |是|int |project's id or identifier | +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | |id |是|int |cloud_account's id | |drone_token |否|string |CI端用户的token值,只有当用户第一次激活时,才需要填写该值 | @@ -2557,19 +2549,19 @@ http://localhost:3000/api/ci/cloud_accounts/1/activate.json | jq #### 获取仓库的.trustie-pipeline.yml ``` -GET /api/ci/builds/get_trustie_pipeline +GET /api/:owner/:repo/get_trustie_pipeline ``` *示例* ``` curl -X GET \ --d "project_id=4844" \ -http://localhost:3000/api/ci/builds/get_trustie_pipeline.json | jq +http://localhost:3000/api/jasder/forge/get_trustie_pipeline.json | jq ``` *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| -|project_id |是|int |project's id | +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | |ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | @@ -2593,12 +2585,12 @@ http://localhost:3000/api/ci/builds/get_trustie_pipeline.json | jq #### 获取语言列表 ``` -GET /api/dev_ops/languages +GET /api/ci/languages ``` *示例* ``` -curl -X GET http://localhost:3000/api/dev_ops/languages.json | jq +curl -X GET http://localhost:3000/api/ci/languages.json | jq ``` *返回参数说明:* @@ -2625,12 +2617,12 @@ curl -X GET http://localhost:3000/api/dev_ops/languages.json | jq #### 获取常用的6大语言 ``` -GET /api/dev_ops/languages/common +GET /api/ci/languages/common ``` *示例* ``` -curl -X GET http://localhost:3000/api/dev_ops/languages/common.json | jq +curl -X GET http://localhost:3000/api/ci/languages/common.json | jq ``` *返回参数说明:* @@ -2657,12 +2649,12 @@ curl -X GET http://localhost:3000/api/dev_ops/languages/common.json | jq #### 获取语言详情 ``` -GET /api/dev_ops/languages/:id +GET /api/ci/languages/:id ``` *示例* ``` -curl -X GET http://localhost:3000/api/dev_ops/languages/114.json | jq +curl -X GET http://localhost:3000/api/ci/languages/114.json | jq ``` *请求参数说明:* @@ -2857,22 +2849,20 @@ http://ocalhost:3000/api/jasder/forge/builds/1 | jq #### 重启构建/重新构建 ``` -POST /api/dev_ops/builds/:number +POST /api/:owner/:repo/builds/:build/restart ``` *示例* ``` curl -X POST \ --d 'project_id=4844' \ -http://localhost:3000/api/dev_ops/builds/1 | jq +http://localhost:3000/api/jasder/forgeplus/builds/1 | jq ``` *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| -|project_id |int|project's id| -|number |是|int |build's number | +|build |是|int |build's number | *返回参数说明:* @@ -2917,22 +2907,20 @@ http://localhost:3000/api/dev_ops/builds/1 | jq #### 关闭构建 ``` -DELETE /api/dev_ops/builds/:number +DELETE /api/:owner/:repo/builds/:build/stop ``` *示例* ``` curl -X DELETE \ --d 'project_id=4844' \ -http://localhost:3000/api/dev_ops/builds/2 | jq +http://localhost:3000/api/jaser/forge/builds/2 | jq ``` *请求参数说明:* |参数名|必选|类型|说明| |-|-|-|-| -|project_id |int|project's id| -|number |是|int |build's number | +|build |是|int |build's number | *返回参数说明:* @@ -3025,13 +3013,12 @@ http://localhost:3000/api/dev_ops/builds/2 | jq #### 获取某条构建的log信息 ``` -GET /api/dev_ops/builds/:number/logs/:stage/:step +GET /api/:owner/:repo/builds/:build/logs/:stage/:step ``` *示例* ``` curl -X GET \ --d 'project_id=4844' \ http://localhost:3000/api/dev_ops/builds/2/logs/1/1 | jq ``` @@ -3039,8 +3026,7 @@ http://localhost:3000/api/dev_ops/builds/2/logs/1/1 | jq |参数名|必选|类型|说明| |-|-|-|-| -|project_id |int|project's id| -|number |是|int |build's number | +|build |是|int |build's number | |stage |是|int |build's stage number | |step |是|int |build's step number | diff --git a/app/controllers/ci/builds_controller.rb b/app/controllers/ci/builds_controller.rb index 336734b6a..33041afe6 100644 --- a/app/controllers/ci/builds_controller.rb +++ b/app/controllers/ci/builds_controller.rb @@ -3,12 +3,13 @@ class Ci::BuildsController < Ci::BaseController include Devopsable before_action :load_repo + before_action :find_cloud_account, except: [:index, :show] def index scope = @repo.builds scope = Ci::Builds::ListQuery.call(@repo, params) - + @total_count = scope.map(&:build_id).size @builds = paginate scope end @@ -17,25 +18,19 @@ class Ci::BuildsController < Ci::BaseController @build = @repo.builds.includes(stages: [:steps]).find_by(build_number: params[:build]) end - def detail - result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).build - - render json: result - end - def restart - result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).restart + result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:number]).restart render json: result end - def delete - result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).stop + def stop + result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:number]).stop render json: result end def logs - result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, build: params[:number], stage: params[:stage], step: params[:step]).logs + result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, build: params[:number], stage: params[:stage], step: params[:step]).logs render json: result end @@ -55,6 +50,14 @@ class Ci::BuildsController < Ci::BaseController private def find_cloud_account - @cloud_account = @project.ci_cloud_account + @cloud_account = current_user.cloud_account + end + + def load_ci_user + begin + @ci_user = Ci::User.find_by(user_login: params[:owner]) + rescue + render_not_found + end end end diff --git a/app/controllers/ci/cloud_accounts_controller.rb b/app/controllers/ci/cloud_accounts_controller.rb index d941a9ae2..2fc488b0e 100644 --- a/app/controllers/ci/cloud_accounts_controller.rb +++ b/app/controllers/ci/cloud_accounts_controller.rb @@ -1,7 +1,7 @@ class Ci::CloudAccountsController < Ci::BaseController include Devopsable - before_action :auto_load_project + before_action :load_project before_action :ci_authorize! before_action :find_cloud_account, only: %i[activate] @@ -83,6 +83,6 @@ class Ci::CloudAccountsController < Ci::BaseController private def devops_params - params.permit(:account, :secret, :ip_num, :project_id) + params.permit(:account, :secret, :ip_num) end end diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb new file mode 100644 index 000000000..3cd2d988e --- /dev/null +++ b/app/controllers/ci/projects_controller.rb @@ -0,0 +1,30 @@ +class Ci::ProjectsController < Ci::BaseController + include Devopsable + + before_action :load_project + + def authorize + @user = current_user + limit_project_owner_can_devops!(@user, @project) + + if request.put? + @user.set_drone_step!(User::DEVOPS_VERIFIED) + render_ok + end + @cloud_account = @user.ci_cloud_account + end + + # get .trustie-pipeline.yml file + def get_trustie_pipeline + file_path_uri = URI.parse('.trustie-pipeline.yml') + interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master") + if interactor.success? + file = interactor.result + return render json: {} if file[:status] + + json = {name: file['name'], path: file['path'], sha: file['sha'], content: render_decode64_content(file['content'])} + render json: json + end + end + +end diff --git a/app/controllers/concerns/devopsable.rb b/app/controllers/concerns/devopsable.rb index ea6a48f16..97983c318 100644 --- a/app/controllers/concerns/devopsable.rb +++ b/app/controllers/concerns/devopsable.rb @@ -15,8 +15,8 @@ module Devopsable end # TODO 暂时限制项目拥有者才有权限操作 - def limit_owner_can_devops!(user) - return if @project.owner? user + def limit_project_owner_can_devops!(user, project) + return if project.owner? user render_forbidden end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f46945f80..8b169cc73 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,6 +2,7 @@ class ProjectsController < ApplicationController include ApplicationHelper include OperateProjectAbilityAble include ProjectsHelper + before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users] before_action :load_project, except: %i[index group_type_list migrate create] before_action :authorizate_user_can_edit_project!, only: %i[update] diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 5ea43c47e..167e7be6c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -220,19 +220,6 @@ class UsersController < ApplicationController render_ok end - def devops - @user = current_user - limit_owner_can_devops!(user) - @cloud_account = @user.dev_ops_cloud_account - end - - # devops 认证 - def devops_authenticate - limit_owner_can_devops!(current_user) - current_user.set_drone_step!(User::DEVOPS_VERIFIED) - render_ok - end - private def load_user @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) diff --git a/app/models/ci/cloud_account.rb b/app/models/ci/cloud_account.rb index 409c77947..f54db49d9 100644 --- a/app/models/ci/cloud_account.rb +++ b/app/models/ci/cloud_account.rb @@ -1,5 +1,4 @@ class Ci::CloudAccount < Ci::LocalBase - belongs_to :project belongs_to :user def drone_host diff --git a/app/models/ci/local_base.rb b/app/models/ci/local_base.rb index 258f88a4b..2d6bf70ff 100644 --- a/app/models/ci/local_base.rb +++ b/app/models/ci/local_base.rb @@ -1,4 +1,6 @@ class Ci::LocalBase < ApplicationRecord + self.abstract_class = true + def self.table_name_prefix "ci_" end diff --git a/app/models/project.rb b/app/models/project.rb index 24bbe9afc..bd2008af6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -20,7 +20,6 @@ class Project < ApplicationRecord has_many :fork_users, dependent: :destroy # has_many :commits, dependent: :destroy - has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy has_one :project_score, dependent: :destroy has_one :repository, dependent: :destroy has_many :pull_requests, dependent: :destroy diff --git a/app/views/ci/projects/authorize.json.jbuilder b/app/views/ci/projects/authorize.json.jbuilder new file mode 100644 index 000000000..7ae5fa2c1 --- /dev/null +++ b/app/views/ci/projects/authorize.json.jbuilder @@ -0,0 +1,12 @@ +json.step @user.devops_step +json.cloud_account do + if @cloud_account && !@user.devops_uninit? + json.account @cloud_account.account + json.ip @cloud_account.drone_ip + json.secret @cloud_account.visible_secret + json.authenticate_url "#{@cloud_account.drone_url}/login" if @user.devops_unverified? + json.get_drone_token_url "#{@cloud_account.drone_url}/account" if @user.devops_verified? + else + json.nil! + end +end diff --git a/app/views/projects/ci_authorize.json.jbuilder b/app/views/projects/ci_authorize.json.jbuilder new file mode 100644 index 000000000..7ae5fa2c1 --- /dev/null +++ b/app/views/projects/ci_authorize.json.jbuilder @@ -0,0 +1,12 @@ +json.step @user.devops_step +json.cloud_account do + if @cloud_account && !@user.devops_uninit? + json.account @cloud_account.account + json.ip @cloud_account.drone_ip + json.secret @cloud_account.visible_secret + json.authenticate_url "#{@cloud_account.drone_url}/login" if @user.devops_unverified? + json.get_drone_token_url "#{@cloud_account.drone_url}/account" if @user.devops_verified? + else + json.nil! + end +end diff --git a/config/routes.rb b/config/routes.rb index 68c4edd19..a1afa6b7c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,11 +21,6 @@ Rails.application.routes.draw do resources :edu_settings scope '/api' do namespace :ci do - resources :cloud_accounts, only: [:create] do - member do - post :activate - end - end resources :languages, only: [:index, :show] do collection do get :common @@ -149,8 +144,6 @@ Rails.application.routes.draw do post :sync_salt get :trustie_projects get :trustie_related_projects - get :devops - put :devops_authenticate end scope module: :users do @@ -339,7 +332,31 @@ Rails.application.routes.draw do resources :version_releases, :path => :releases, only: [:index,:new, :create, :edit, :update, :destroy] scope module: :ci do - resources :builds, param: :build + scope do + match( + 'ci_authorize', + to: 'projects#authorize', + as: :ci_authorize, + :via => [:get, :put] + ) + get( + 'get_trustie_pipeline', + to: 'projects#get_trustie_pipeline', + as: :get_trustie_pipeline + ) + end + resources :cloud_accounts, only: [:create] do + member do + post :activate + end + end + resources :builds, param: :build do + member do + post :restart + delete :stop + get '/logs/:stage/:step', to: 'builds#logs', as: 'logs' + end + end end scope module: :projects do