From da0e45a3c6ecd94db8d4f7280ef5b72b264b8c62 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Wed, 15 Jul 2020 09:43:30 +0800 Subject: [PATCH] ADD devops --- app/controllers/dev_ops/builds_controller.rb | 15 ++++ .../dev_ops/cloud_accounts_controller.rb | 6 +- app/helpers/dev_ops/builds_helper.rb | 2 + app/helpers/projects_helper.rb | 3 +- app/libs/dev_ops/drone/api.rb | 54 +++++++++++++ app/libs/dev_ops/drone/error.rb | 14 ++++ app/libs/dev_ops/drone/request.rb | 77 ++++++++++++++----- app/models/project.rb | 1 + app/views/dev_ops/builds/index.json.jbuilder | 2 + app/views/dev_ops/builds/show.json.jbuilder | 2 + config/routes.rb | 3 +- ...d_drone_token_to_dev_ops_cloud_accounts.rb | 5 ++ 12 files changed, 158 insertions(+), 26 deletions(-) create mode 100644 app/controllers/dev_ops/builds_controller.rb create mode 100644 app/helpers/dev_ops/builds_helper.rb create mode 100644 app/libs/dev_ops/drone/api.rb create mode 100644 app/libs/dev_ops/drone/error.rb create mode 100644 app/views/dev_ops/builds/index.json.jbuilder create mode 100644 app/views/dev_ops/builds/show.json.jbuilder create mode 100644 db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb diff --git a/app/controllers/dev_ops/builds_controller.rb b/app/controllers/dev_ops/builds_controller.rb new file mode 100644 index 000000000..24d8b99d7 --- /dev/null +++ b/app/controllers/dev_ops/builds_controller.rb @@ -0,0 +1,15 @@ +class DevOps::BuildsController < ApplicationController + before_action :require_login + before_action :find_project + + def index + end + + def show + end + + private + def find_project + @repo = Repository.find params[:id] + end +end diff --git a/app/controllers/dev_ops/cloud_accounts_controller.rb b/app/controllers/dev_ops/cloud_accounts_controller.rb index 0eb4270ce..83e374486 100644 --- a/app/controllers/dev_ops/cloud_accounts_controller.rb +++ b/app/controllers/dev_ops/cloud_accounts_controller.rb @@ -12,9 +12,9 @@ class DevOps::CloudAccountsController < ApplicationController logger.info "######### ......ff: #{devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num]).to_i, secret: DevOps::CloudAccount.encrypted_secret(devops_params[:secret]))}" create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num]).to_i, secret: DevOps::CloudAccount.encrypted_secret(devops_params[:secret])) logger.info "######### create_params: #{create_params}" - cloud_account = DevOps::CloudAccount.new(create_params) - cloud_account.user = current_user - cloud_account.save + + return if @project.dev_ops_cloud_account + # 2. 生成oauth2应用程序的client_id和client_secrete gitea_oauth = Gitea::Oauth2::CreateService.call(current_user.gitea_token, {name: "pipeline", redirect_uris: ["#{cloud_account.drone_url}/login"]}) logger.info "######### gitea_oauth: #{gitea_oauth}" diff --git a/app/helpers/dev_ops/builds_helper.rb b/app/helpers/dev_ops/builds_helper.rb new file mode 100644 index 000000000..81d98403b --- /dev/null +++ b/app/helpers/dev_ops/builds_helper.rb @@ -0,0 +1,2 @@ +module DevOps::BuildsHelper +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index b9457bd8a..6d36c2b3c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -44,7 +44,8 @@ module ProjectsHelper identifier: project.identifier, name: project.name, id: project.id, - open_devops: project.open_devops, + repo_id: repo.id, + open_devops: project.open_devops?, type: project.numerical_for_project_type, author: { login: project.owner.login, diff --git a/app/libs/dev_ops/drone/api.rb b/app/libs/dev_ops/drone/api.rb new file mode 100644 index 000000000..08dafcb42 --- /dev/null +++ b/app/libs/dev_ops/drone/api.rb @@ -0,0 +1,54 @@ +class DevOps::Drone::API < DevOps::Drone::Request + attr_reader :drone_token, :drone_url, :owner, :repo, :options + + # drone_token: + # owner: repo's owner name or login + # repo: repo's identifier + def initialize(drone_token, drone_url, owner, repo, options={}) + @drone_token = drone_token + @drone_url = drone_url + @owner = owner + @repo = repo + @options = options + end + + # Build List + # GET api/repos/{owner}/{name}/builds + # eq: + # DevOps::Drone::API + def builds + request(:get, drone_url, "api/repos/#{owner}/#{repo}/builds", drone_token: drone_token) + end + + # Build Info + # GET api/repos/{owner}/{name}/builds/{number} + def build + request(:get, "api/repos/#{owner}/#{repo}/builds/#{number}", drone_token: drone_token) + end + + # Update .trustie-pipeline.yml file + # PATCH api/repos/{owner}/{name} + def config_yml + request(:patch, "/api/repos/#{owner}/#{repo}", drone_token: drone_token, config_path: config_path) + end + + # Activate user's project with Drone CI + # POST api/repos/{owner}/{name} + def activate + request(:post, "/api/repos/#{owner}/#{repo}", drone_token: drone_token) + end + + # Build Restart + # POST api/repos/{owner}/{name}/builds/{number} + # Restart the specified build. Please note this api requires read and write access to the repository and the request parameter {build} is not the build id but the build number. + def restart + request(:post, "/api/repos/#{owner}/#{repo}/builds/#{number}", drone_token: drone_token) + end + + # Build Stop + # DELETE api/repos/{owner}/{name}/builds/{number} + # Stop the specified build. Please note this api requires administrative privileges and the request parameter {build} is not the build id but the build number. + def stop + request(:delete, "/api/repos/#{owner}/#{repo}/builds/#{number}", drone_token: drone_token) + end +end diff --git a/app/libs/dev_ops/drone/error.rb b/app/libs/dev_ops/drone/error.rb new file mode 100644 index 000000000..2803a6c88 --- /dev/null +++ b/app/libs/dev_ops/drone/error.rb @@ -0,0 +1,14 @@ +class DevOps::Drone::Error < StandardError + attr_reader :code + + def initialize(code, message) + super message + @code = code + end + + class << self + def parse(result) + new(result['errcode'], result['errmsg']) + end + end +end diff --git a/app/libs/dev_ops/drone/request.rb b/app/libs/dev_ops/drone/request.rb index ddead22b5..7e059dc41 100644 --- a/app/libs/dev_ops/drone/request.rb +++ b/app/libs/dev_ops/drone/request.rb @@ -1,10 +1,9 @@ # @private class DevOps::Drone::Request - format :json - headers 'Accept' => 'application/json' - parser Proc.new { |body, _| parse(body) } + # format :json + # headers 'Accept' => 'application/json' + # parser Proc.new { |body, _| parse(body) } - attr_accessor :private_token # Converts the response body to an ObjectifiedHash. def self.parse(body) @@ -84,27 +83,63 @@ self.class.default_params.delete(:sudo) if sudo.nil? end + def request(method, domain, url, **params) + Rails.logger.info("[drone] request: #{method} #{url} #{params.except(:secret).inspect}") + + client = Faraday.new(url: domain) + response = client.public_send(method, url, params) + result = JSON.parse(response.body) + + Rails.logger.info("[drone] response:#{response.status} #{result.inspect}") + + if response.status != 200 + raise DevOps::Drone::Error.parse(result) + end + + if result['errcode'].present? && result['errcode'].to_i.nonzero? + raise DevOps::Drone::Error.parse(result) + end + + result + end + private + def conn(auth={}) + token = auth[:token] + puts "[gitea] token: #{token}" - # Sets a PRIVATE-TOKEN header for requests. - # @raise [Error::MissingCredentials] if private_token not set. - def set_private_token_header(options, path=nil) - unless path == '/session' - raise Error::MissingCredentials.new("Please set a private_token for user") unless @private_token - options[:headers] = {'PRIVATE-TOKEN' => @private_token} + @client ||= begin + Faraday.new(url: domain) do |req| + req.request :url_encoded + req.headers['Content-Type'] = 'application/json' + req.response :logger # 显示日志 + req.adapter Faraday.default_adapter + req.authorization :Bearer, token + req.headers['Authorization'] + end + end + @client end - end - # Set HTTParty configuration - # @see https://github.com/jnunemaker/httparty - def set_httparty_config(options) - if self.httparty - options.merge!(self.httparty) + # Sets a PRIVATE-TOKEN header for requests. + # @raise [Error::MissingCredentials] if private_token not set. + def set_private_token_header(options, path=nil) + unless path == '/session' + raise Error::MissingCredentials.new("Please set a private_token for user") unless @private_token + options[:headers] = {'PRIVATE-TOKEN' => @private_token} + end end - end - def error_message(response) - "Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \ - "Request URI: #{response.request.base_uri}#{response.request.path}" - end + # Set HTTParty configuration + # @see https://github.com/jnunemaker/httparty + def set_httparty_config(options) + if self.httparty + options.merge!(self.httparty) + end + end + + def error_message(response) + "Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \ + "Request URI: #{response.request.base_uri}#{response.request.path}" + end end diff --git a/app/models/project.rb b/app/models/project.rb index cebb146e6..f06ae8148 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -20,6 +20,7 @@ class Project < ApplicationRecord has_many :fork_users, dependent: :destroy # has_many :commits, dependent: :destroy + has_one :dev_ops_cloud_account, class_name: 'DevOps::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/dev_ops/builds/index.json.jbuilder b/app/views/dev_ops/builds/index.json.jbuilder new file mode 100644 index 000000000..b6539104b --- /dev/null +++ b/app/views/dev_ops/builds/index.json.jbuilder @@ -0,0 +1,2 @@ +

DevOps::Builds#index

+

Find me in app/views/dev_ops/builds/index.html.erb

diff --git a/app/views/dev_ops/builds/show.json.jbuilder b/app/views/dev_ops/builds/show.json.jbuilder new file mode 100644 index 000000000..f25a17b7b --- /dev/null +++ b/app/views/dev_ops/builds/show.json.jbuilder @@ -0,0 +1,2 @@ +

DevOps::Builds#show

+

Find me in app/views/dev_ops/builds/show.html.erb

diff --git a/config/routes.rb b/config/routes.rb index f3a74e4e5..47bf63261 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,11 +17,12 @@ Rails.application.routes.draw do scope '/api' do namespace :dev_ops do resources :cloud_accounts, only: [:create] - resources :languages, only: [:index, :create, :show] do + resources :languages, only: [:index, :show] do collection do get :common end end + resources :builds end resources :sync_forge, only: [:create] do diff --git a/db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb b/db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb new file mode 100644 index 000000000..f777fde2e --- /dev/null +++ b/db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb @@ -0,0 +1,5 @@ +class AddDroneTokenToDevOpsCloudAccounts < ActiveRecord::Migration[5.2] + def change + add_column :dev_ops_cloud_accounts, :drone_token, :string + end +end