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 1/2] 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 From edb4f8fede889463f31117c255ea799cee19822e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=B1=E5=91=B1=E5=91=B1?= Date: Thu, 13 Nov 2025 11:01:57 +0800 Subject: [PATCH 2/2] update code_check --- app/controllers/api/v1/base_controller.rb | 5 ++ .../api/v1/projects/code_check_controller.rb | 56 +++++++++++++++---- .../api/v1/projects/codecheck_service.rb | 32 +++++++++-- app/services/huawei_cloud/code_check.rb | 55 ++++++++++++++++-- .../projects/code_check/index.json.jbuilder | 1 + app/views/projects/show.json.jbuilder | 1 + config/routes/api.rb | 6 ++ 7 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 app/views/api/v1/projects/code_check/index.json.jbuilder diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index 38e10d5f5..d0efa16cf 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -70,4 +70,9 @@ class Api::V1::BaseController < ApplicationController @project = load_project return render_forbidden if !@project.is_public && !current_user.admin? && !@project.member?(current_user) end + + def verification_with_setting(key) + @project = load_project + return render_forbidden unless EduSetting.get(key).split(",").include?(current_user.id.to_s) + end end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/code_check_controller.rb b/app/controllers/api/v1/projects/code_check_controller.rb index 691e3f367..288617012 100644 --- a/app/controllers/api/v1/projects/code_check_controller.rb +++ b/app/controllers/api/v1/projects/code_check_controller.rb @@ -1,36 +1,72 @@ class Api::V1::Projects::CodeCheckController < Api::V1::BaseController before_action :require_public_and_member_above before_action :load_project + before_action :verification_with_setting('open_huawei_check_users') + before_action do @client = Api::V1::Projects::CodecheckService.new(@project) end + def index + end def create @result = @client.create_task(params["branch"]) + render :index end def run_task @result = @client.run_task + render :index end def query_task @result = @client.query_task + render :index end - + #----- 缺陷管理 ------ def defects_summary - @result = @client.defects_summary - end - - def defects_detail - @result = @client.defects_detail - end - - def defects_statistic - @result = @client.defects_statistic + @result = @client.defects_summary(request.query_string) + render :index end def metrics_summary @result = @client.metrics_summary + render :index + end + + def defects_detail + @result = @client.defects_detail(request.query_string) + render :index + end + + def defects_statistic + @result = @client.defects_statistic + render :index + end + + def defect_status #put + @result = @client.defect_status(request.request_parameters.deep_dup) + render :index + end + #------ 代码问题 ---- + def issue_status #post + @result = @client.issue_status(request.request_parameters) + render :index + end + + def issue_list_by_filter #post + @result = @client.issue_list_by_filter(request.request_parameters) + render :index + end + + def issue_filter #post + @result = @client.issue_filter(request.request_parameters) + render :index + end + + def defect_metric_trend #get + @result = @client.defect_metric_trend(request.query_string) + render :index 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 index 1ae9fa15a..4a60ea99a 100644 --- a/app/services/api/v1/projects/codecheck_service.rb +++ b/app/services/api/v1/projects/codecheck_service.rb @@ -23,19 +23,18 @@ class Api::V1::Projects::CodecheckService < ApplicationService 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) + def defects_summary(query) + @client.defects_summary(@project.huawei_code_check_task_id,query) end - def defects_detail - @client.defects_detail(@project.huawei_code_check_task_id) + def defects_detail(query) + @client.defects_detail(@project.huawei_code_check_task_id,query) end def defects_statistic @@ -46,6 +45,29 @@ class Api::V1::Projects::CodecheckService < ApplicationService @client.metrics_summary(@project.huawei_code_check_task_id) end + def defect_status(query) + @client.defect_status(@project.huawei_code_check_task_id,query) + end + + def issue_status(body) #更新代码问题状态 post + @client.issue_status(@project.huawei_code_check_task_id,body) + end + + def issue_list_by_filter(body) #获取代码问题状态 + @client.issue_list_by_filter(@project.huawei_code_check_task_id,body) + end + + def issue_filter(body) #获取代码问题状态 + @client.issue_filter(@project.huawei_code_check_task_id,body) + end + + def defect_metric_trend(query) + @client.defect_metric_trend(@project.huawei_code_check_task_id,query) + end + def next_status + @client.next_status(@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 index 59f5be127..21133c047 100644 --- a/app/services/huawei_cloud/code_check.rb +++ b/app/services/huawei_cloud/code_check.rb @@ -65,8 +65,8 @@ module HuaweiCloud 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" + def defects_summary(task_id,query) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defects-summary?#{query}" resp = RestClient.get(url, @headers) JSON.parse(resp.body) rescue RestClient::ExceptionWithResponse => e @@ -75,8 +75,8 @@ module HuaweiCloud end - def defects_detail(task_id) - url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defects-detail" + def defects_detail(task_id,query) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defects-detail?#{query}" resp = RestClient.get(url, @headers) JSON.parse(resp.body) rescue RestClient::ExceptionWithResponse => e @@ -101,5 +101,52 @@ module HuaweiCloud # 你可以根据 e.response.code 处理 401 (Token失效) 或其它错误 raise "CodeCheck create_task failed: #{e.response}" end + + def defect_status(task_id,body) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v2/tasks/#{task_id}/defect-status" + resp = RestClient.put(url, body.to_json, @headers) + JSON.parse(resp.body) + end + + def issue_status(task_id,body) + url = "ttps://codecheck-ext.#{@region}.myhuaweicloud.com/v1/defect/issue-status" + body["taskId"] = task_id + 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 issue_list_by_filter(task_id,body) + url = "ttps://codecheck-ext.#{@region}.myhuaweicloud.com/v1/defect/issue-list-by-filter" + body["taskId"] = task_id + 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 issue_filter(task_id,body) + url = "ttps://codecheck-ext.#{@region}.myhuaweicloud.com/v1/defect/issue-filter" + body["taskId"] = task_id + 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 defect_metric_trend(task_id,query) + url = "https://codecheck-ext.#{@region}.myhuaweicloud.com/v1/history/defect-metric-trend?task_id=#{task_id}&&#{query}" + 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/views/api/v1/projects/code_check/index.json.jbuilder b/app/views/api/v1/projects/code_check/index.json.jbuilder new file mode 100644 index 000000000..86a3f08fd --- /dev/null +++ b/app/views/api/v1/projects/code_check/index.json.jbuilder @@ -0,0 +1 @@ +json.data @result \ No newline at end of file diff --git a/app/views/projects/show.json.jbuilder b/app/views/projects/show.json.jbuilder index aa66808b4..ab0742c85 100644 --- a/app/views/projects/show.json.jbuilder +++ b/app/views/projects/show.json.jbuilder @@ -7,6 +7,7 @@ json.repo_id @project.repository.id json.repo_identifier @project.repository.identifier json.is_need_apply @project.is_need_apply json.sca_project_id @project.sca_project_id +json.huawei_code_check_task_id @project.huawei_code_check_task_id user_apply_signatures = @project.apply_signatures.with_user_id(current_user.id) json.user_apply_signatures user_apply_signatures do |signature| json.id signature.id diff --git a/config/routes/api.rb b/config/routes/api.rb index a0c912ab4..1fd09fe53 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -261,6 +261,12 @@ defaults format: :json do get :defects_detail get :defects_statistic get :metrics_summary + put :defect_status + post :issue_status + post :issue_list_by_filter + post :issue_filter + get :defect_metric_trend + end end resources :pipelines do