From 6c4fc339db59d43a6b0a266577c49602ce05e02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=B1=E5=91=B1=E5=91=B1?= Date: Wed, 12 Nov 2025 17:33:01 +0800 Subject: [PATCH] add code_check --- .../api/v1/projects/code_check_controller.rb | 36 ++++++ .../api/v1/projects/codecheck_service.rb | 51 +++++++++ app/services/huawei_cloud/code_check.rb | 105 ++++++++++++++++++ app/services/huawei_cloud/ima_account.rb | 59 ++++++++++ config/routes/api.rb | 11 ++ ..._add_huawei_code_check_task_to_projects.rb | 5 + 6 files changed, 267 insertions(+) create mode 100644 app/controllers/api/v1/projects/code_check_controller.rb create mode 100644 app/services/api/v1/projects/codecheck_service.rb create mode 100644 app/services/huawei_cloud/code_check.rb create mode 100644 app/services/huawei_cloud/ima_account.rb create mode 100644 db/migrate/20251112060641_add_huawei_code_check_task_to_projects.rb diff --git a/app/controllers/api/v1/projects/code_check_controller.rb b/app/controllers/api/v1/projects/code_check_controller.rb new file mode 100644 index 000000000..691e3f367 --- /dev/null +++ b/app/controllers/api/v1/projects/code_check_controller.rb @@ -0,0 +1,36 @@ +class Api::V1::Projects::CodeCheckController < Api::V1::BaseController + before_action :require_public_and_member_above + before_action :load_project + before_action do + @client = Api::V1::Projects::CodecheckService.new(@project) + end + + def create + @result = @client.create_task(params["branch"]) + end + + def run_task + @result = @client.run_task + end + + def query_task + @result = @client.query_task + end + + def defects_summary + @result = @client.defects_summary + end + + def defects_detail + @result = @client.defects_detail + end + + def defects_statistic + @result = @client.defects_statistic + end + + def metrics_summary + @result = @client.metrics_summary + end + +end \ No newline at end of file diff --git a/app/services/api/v1/projects/codecheck_service.rb b/app/services/api/v1/projects/codecheck_service.rb new file mode 100644 index 000000000..1ae9fa15a --- /dev/null +++ b/app/services/api/v1/projects/codecheck_service.rb @@ -0,0 +1,51 @@ +class Api::V1::Projects::CodecheckService < ApplicationService + def initialize(project) + @project = project + @client = HuaweiCloud::CodeCheck.new + end + + def create_task(branch) + language = if @project.project_language.present? + @project.project_language.name.upcase + else + "TYPESCRIPT" + end + + result = @client.create_task( + git_url: @project.repository.url, + git_branch: branch, + languages: [language], + username: @project.owner.login, + access_token: "this is opensource" + ) + @project.update(huawei_code_check_task_id: result["task_id"]) + end + + def run_task + @client.run_task(@project.huawei_code_check_task_id) + + end + + def query_task + @client.query_task(@project.huawei_code_check_task_id) + end + + def defects_summary + @client.defects_summary(@project.huawei_code_check_task_id) + end + + def defects_detail + @client.defects_detail(@project.huawei_code_check_task_id) + end + + def defects_statistic + @client.defects_statistic(@project.huawei_code_check_task_id) + end + + def metrics_summary + @client.metrics_summary(@project.huawei_code_check_task_id) + end + + + +end \ No newline at end of file diff --git a/app/services/huawei_cloud/code_check.rb b/app/services/huawei_cloud/code_check.rb new file mode 100644 index 000000000..59f5be127 --- /dev/null +++ b/app/services/huawei_cloud/code_check.rb @@ -0,0 +1,105 @@ +require 'rest-client' +require 'json' +require 'redis' + +module HuaweiCloud + class CodeCheck + CONFIG = Rails.application.config_for(:configuration)['huawei_code_check'] + PROJECT_ID = CONFIG['product_id'] + REGION = CONFIG['region'] + + def initialize + @region = REGION + @project_id = PROJECT_ID + @token = HuaweiCloud::ImaAccount.new.token + @headers = { + "Content-Type" => "application/json;charset=utf8", + "X-Auth-Token" => @token + } + end + + + # 创建检查任务 + # params: git_url, git_branch, languages (array), optional rule_sets etc + def create_task(git_url:, git_branch:, languages: nil, rule_sets: nil, task_type: "full", endpoint_id: nil, username: nil, access_token: nil, resource_pool_id: nil) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/#{@project_id}/task" + Rails.logger.info "################### create_task url #{url}" + + + body = { + git_url: git_url, + git_branch: git_branch, + task_type:task_type + } + body[:language] = languages if languages + body[:rule_sets] = rule_sets if rule_sets + body[:endpoint_id] = endpoint_id if endpoint_id + body[:username] = username if username + body[:access_token] = access_token if access_token + body[:resource_pool_id] = resource_pool_id if resource_pool_id + Rails.logger.info body.to_json + resp = RestClient.post(url, body.to_json, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + + def run_task(task_id) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/run" + body = { + } + resp = RestClient.post(url, body.to_json, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + + def query_task(task_id) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/progress" + resp = RestClient.get(url, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + + def defects_summary(task_id) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defects-summary" + resp = RestClient.get(url, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + + + def defects_detail(task_id) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defects-detail" + resp = RestClient.get(url, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + + def defects_statistic(task_id) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defects-statistic" + resp = RestClient.get(url, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + + def metrics_summary(task_id) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/#{@project_id}/tasks/#{task_id}/metrics-summary" + resp = RestClient.get(url, @headers) + JSON.parse(resp.body) + rescue RestClient::ExceptionWithResponse => e + # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 + raise "CodeCheck create_task failed: #{e.response}" + end + end +end diff --git a/app/services/huawei_cloud/ima_account.rb b/app/services/huawei_cloud/ima_account.rb new file mode 100644 index 000000000..3a35ef5e6 --- /dev/null +++ b/app/services/huawei_cloud/ima_account.rb @@ -0,0 +1,59 @@ +module HuaweiCloud + class ImaAccount + IAM_TOKEN_KEY = "huaweicloud:iam_token".freeze + CONFIG = Rails.application.config_for(:configuration)['huawei_code_check'] + PROJECT_ID = CONFIG['project_id'] + REGION = CONFIG['region'] + DOMAIN_NAME = CONFIG['domain_name'] + USER_NAME = CONFIG['user_name'] + USER_PASSWORD = CONFIG['user_password'] + + def initialize + @region = REGION + @domain_name = DOMAIN_NAME + @user_name = USER_NAME + @user_password = USER_PASSWORD + @project_id = PROJECT_ID + end + + # 获取或缓存 Token + def token + cached = Rails.cache.fetch(IAM_TOKEN_KEY) + return cached if cached + + new_token = fetch_token + Rails.cache.write(IAM_TOKEN_KEY,new_token,expires_in: 23.hour) + new_token + end + private + + def fetch_token + url = "https://iam.#{@region}.myhuaweicloud.com/v3/auth/tokens" + headers = { "Content-Type" => "application/json;charset=utf8" } + + body = { + auth: { + identity: { + methods: ["password"], + password: { + user: { + domain: { name: @domain_name }, + name: @user_name, + password: @user_password + } + } + }, + scope: { + project: { id: @project_id } + } + } + } + response = RestClient.post(url, body.to_json, headers) + token = response.headers[:x_subject_token] + raise "Failed to obtain IAM token" unless token + token + rescue RestClient::ExceptionWithResponse => e + raise "IAM token fetch failed: #{e.response}" + end + end +end \ No newline at end of file diff --git a/config/routes/api.rb b/config/routes/api.rb index 8e007d6b4..a0c912ab4 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -252,6 +252,17 @@ defaults format: :json do get :scan_issues end end + + resource :code_check, only: [:index,:create] do + collection do + post :run_task + get :query_task + get :defects_summary + get :defects_detail + get :defects_statistic + get :metrics_summary + end + end resources :pipelines do post :build_yaml, on: :collection post :save_yaml, on: :collection diff --git a/db/migrate/20251112060641_add_huawei_code_check_task_to_projects.rb b/db/migrate/20251112060641_add_huawei_code_check_task_to_projects.rb new file mode 100644 index 000000000..a28dbc779 --- /dev/null +++ b/db/migrate/20251112060641_add_huawei_code_check_task_to_projects.rb @@ -0,0 +1,5 @@ +class AddHuaweiCodeCheckTaskToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects , :huawei_code_check_task_id, :string + end +end