
# 使用构建任务制作SonarQube工具镜像
1. 创建一个CodeArts Repo代码仓用于存放构建镜像脚本，可以参考[新建CodeArts Repo代码仓](https://support.huaweicloud.com/bestpractice-codecheck/codeartscheck_14_1020.html#codeartscheck_14_1020__zh-cn_topic_0000002532635257_section249692773316)。
2. 单击![](https://support.huaweicloud.com/bestpractice-codecheck/zh-cn_image_0000002613889415.png "点击放大")按钮在代码仓根目录中新建一个目录".cloudbuild"，并在该目录下新建一个文件"build.yml"。
3. 在代码仓根目录新建三个空文件，名称分别为：Dockerfile、excute_py.sh、generate_excel.py。 
   此时的目录结构如下图。
   ![](https://support.huaweicloud.com/bestpractice-codecheck/zh-cn_image_0000002614009311.png "点击放大")
   
   
4. 更改[前置步骤](https://support.huaweicloud.com/bestpractice-codecheck/codeartscheck_14_1014.html#codeartscheck_14_1014__zh-cn_topic_0000002501460678_section067315519324)所获取的Dockerfile。
   
   1. 删除第二行的"USER build"。
   
   2. 从第二行开始写入如下内容：
      ```
      # Define build arguments and set default values
      # SonarQube Server version
      ARG SONARQUBE_VERSION=25.4.0.105899
      # SonarScanner CLI version
      ARG SONAR_SCANNER_VERSION=7.2.0.5079
      # JDK version required for SonarQube runtime
      ARG SONAR_JDK_VERSION=17.0.1
      # Node.js version required for SonarQube (optional, required only for JavaScript/TypeScript/CSS scanning scenarios)
      ARG SONAR_NODE_VERSION=20.19.6
      # JDK version required for compiling user code (optional, required only for Java compilation scanning scenarios)
      ARG COMPILE_JDK_VERSION=21.0.1
      # Maven version required for compiling user code (optional, required only for Java compilation scanning scenarios)
      ARG COMPILE_MAVEN_VERSION=3.9.12
      # Print versions
      RUN echo "Version of SonarQube Server: $SONARQUBE_VERSION" \
        && echo "Version of SonarScanner CLI: $SONAR_SCANNER_VERSION" \
        && echo "Version of JDK for SonarQube : $SONAR_JDK_VERSION" \
        && echo "Version of Node.js for SonarQube: $SONAR_NODE_VERSION" \
        && echo "Version of JDK for compiling code: $COMPILE_JDK_VERSION" \
        && echo "Version of Maven for compiling code: $COMPILE_MAVEN_VERSION"
      # Download tools & extract & rename
      RUN mkdir -p /usr/local/tools/sonarqubecustom
      RUN cd /usr/local/tools/sonarqubecustom \
        && curl -fSL https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONARQUBE_VERSION}.zip -o sonarqube_webservice.zip \
        && unzip -q sonarqube_webservice.zip \
        && mv sonarqube-${SONARQUBE_VERSION} sonarqube_webservice \
        && rm -f sonarqube_webservice.zip
      RUN cd /usr/local/tools/sonarqubecustom \
        && curl -fSL https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip -o sonarqube.zip \
        && unzip -q sonarqube.zip \
        && mv sonar-scanner-${SONAR_SCANNER_VERSION}-linux-x64 sonarqube \
        && rm -f sonarqube.zip
      RUN cd /usr/local/tools/sonarqubecustom \
        && curl -fSL https://mirrors.huaweicloud.com/openjdk/${SONAR_JDK_VERSION}/openjdk-${SONAR_JDK_VERSION}_linux-x64_bin.tar.gz -o jdk.tar.gz\
        && tar -xzf jdk.tar.gz \
        && mv jdk-${SONAR_JDK_VERSION} jdk \
        && rm -f jdk.tar.gz
      # Node.js (optional, required only for JavaScript/TypeScript/CSS scanning scenarios, used in conjunction with lines 11)
      RUN cd /usr/local/tools/sonarqubecustom \
        && curl -fSL https://nodejs.org/dist/v${SONAR_NODE_VERSION}/node-v${SONAR_NODE_VERSION}-linux-x64.tar.xz -o nodejs.tar.xz \
        && tar -xf nodejs.tar.xz \
        && mv node-v${SONAR_NODE_VERSION}-linux-x64 nodejs \
        && rm -f nodejs.tar.xz
      #  Download compilation dependencies & extract & rename (optional, required only for Java compilation scanning scenarios, used in conjunction with lines 13 and 15)
      RUN cd /usr/local/ \
        && curl -fSL https://mirrors.huaweicloud.com/openjdk/${COMPILE_JDK_VERSION}/openjdk-${COMPILE_JDK_VERSION}_linux-x64_bin.tar.gz -o compile_jdk.tar.gz \
        && tar -xzf compile_jdk.tar.gz \
        && mv jdk-${COMPILE_JDK_VERSION} compile_jdk \
        && rm -f compile_jdk.tar.gz
      RUN cd /usr/local/ \
        && curl -fSL https://dlcdn.apache.org/maven/maven-3/${COMPILE_MAVEN_VERSION}/binaries/apache-maven-${COMPILE_MAVEN_VERSION}-bin.tar.gz -o maven.tar.gz \
        && tar -xzf maven.tar.gz \
        && mv apache-maven-${COMPILE_MAVEN_VERSION} maven \
        && rm -f maven.tar.gz
      # Configure compilation environment (optional, required only for Java compilation scanning scenarios, used in conjunction with lines 13 and 15)
      ENV JAVA_HOME=/usr/local/compile_jdk
      ENV MAVEN_HOME=/usr/local/maven
      ENV PATH=$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH
      ```
      
   
   3. 将上述操作更新完毕的Dockefile文件内容复制写入代码仓根目录的"Dockerfile"文件中。
   
   
   
   
5. 将如下内容复制写入代码仓中的".cloudbuild/build.yml"文件： 
   ```
   ---
   version: 2.0
   steps:
     BUILD:
       - build_image:
           inputs:
             organization: ${ORGANIZATION}
             image_name: ${IMAGE_NAME}
             image_tag: ${IMAGE_TAG}
             dockerfile_path: ./Dockerfile
             build_args:
               - name: SONAR_USER_NAME
                 value: ${SONAR_USER_NAME}
               - name: SONAR_USER_PASSWORD
                 value: ${SONAR_USER_PASSWORD}
               - name: SONARQUBE_VERSION
                 value: ${SONARQUBE_VERSION}
               - name: SONAR_SCANNER_VERSION
                 value: ${SONAR_SCANNER_VERSION}
               - name: SONAR_JDK_VERSION
                 value: ${SONAR_JDK_VERSION}
               - name: SONAR_NODE_VERSION
                 value: ${SONAR_NODE_VERSION}
               - name: COMPILE_JDK_VERSION
                 value: ${COMPILE_JDK_VERSION}
               - name: COMPILE_MAVEN_VERSION
                 value: ${COMPILE_MAVEN_VERSION}
       - swr:
           image: ${SWR_PATH}/${ORGANIZATION}/${IMAGE_NAME}:${IMAGE_TAG}
           inputs:
             command: sh ./excute_py.sh
       - upload_artifact:
           inputs:
             path: ./output/*
   ```
   
   
6. 将如下内容复制写入代码仓根目录的"excute_py.sh"文件：
   
   ```
   #!/bin/bash
   set -ex
   # Generate Excel for sonarqube rules
   # Configure yum repository
   cp -a /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
   cat >/etc/yum.repos.d/CentOS-Base.repo << 'EOF'
   [base]
   name=CentOS-$releasever - Base - mirrors.huaweicloud.com
   baseurl=https://mirrors.huaweicloud.com/centos/$releasever/os/$basearch/
   #mirrorlist=https://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
   gpgcheck=1
   gpgkey=https://mirrors.huaweicloud.com/centos/RPM-GPG-KEY-CentOS-7
    
   #released updates 
   [updates]
   name=CentOS-$releasever - Updates - mirrors.huaweicloud.com
   baseurl=https://mirrors.huaweicloud.com/centos/$releasever/updates/$basearch/
   #mirrorlist=https://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
   gpgcheck=1
   gpgkey=https://mirrors.huaweicloud.com/centos/RPM-GPG-KEY-CentOS-7
    
   #additional packages that may be useful
   [extras]
   name=CentOS-$releasever - Extras - mirrors.huaweicloud.com
   baseurl=https://mirrors.huaweicloud.com/centos/$releasever/extras/$basearch/
   #mirrorlist=https://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
   gpgcheck=1
   gpgkey=https://mirrors.huaweicloud.com/centos/RPM-GPG-KEY-CentOS-7
    
   #additional packages that extend functionality of existing packages
   [centosplus]
   name=CentOS-$releasever - Plus - mirrors.huaweicloud.com
   baseurl=https://mirrors.huaweicloud.com/centos/$releasever/centosplus/$basearch/
   #mirrorlist=https://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
   gpgcheck=1
   enabled=0
   gpgkey=https://mirrors.huaweicloud.com/centos/RPM-GPG-KEY-CentOS-7
   EOF
   yum clean all
   yum makecache
   # Configure Python script execution environment
   yum install -y python3
   python3 -m pip install requests openpyxl
   yum install -y glibc-common
   localedef -c -f UTF-8 -i en_US en_US.UTF-8
   export LANG=en_US.UTF-8
   export LC_ALL=en_US.UTF-8
   # Create non-root user and start SonarQube Server
   useradd sonar && chown -R sonar:sonar /usr/local/tools/sonarqubecustom/sonarqube_webservice
   su sonar -c "/usr/local/tools/sonarqubecustom/sonarqube_webservice/bin/linux-x86-64/sonar.sh start"
   until curl -sf http://localhost:9000/api/system/status | grep -q '"status":"UP"'; do
     echo "wait to up"
     sleep 5
   done
   # Execute Python script to generate Excel
   python3 ./generate_excel.py
   ```
   
   
7. 将如下内容写入代码仓根目录的"generate_excel.py"文件：
   
   ```
   import requests
   import json
   import uuid
   import openpyxl
   import os
   import re
   USER_NAME = os.getenv("SONAR_USER_NAME")  # SonarQube Server username
   USER_PASSWORD = os.getenv("SONAR_USER_PASSWORD")  # SonarQube Server password
   SONARQUBE_URL = "http://localhost:9000"  # SonarQube Server address
   RULE_SEARCH_API = f"{SONARQUBE_URL}/api/rules/search"
   LANGUAGE_LIST_API = f"{SONARQUBE_URL}/api/languages/list"
   GENERATE_TOKEN_API = f"{SONARQUBE_URL}/api/user_tokens/generate"
   REVOKE_TOKEN_API = f"{SONARQUBE_URL}/api/user_tokens/revoke"
   EN_EXCEL_PATH = "output/sonarqube_rules_en.xlsx"  # Excel for English interface import
   CN_EXCEL_PATH = "output/sonarqube_rules_cn.xlsx"  # Excel for Chinese interface import
   SONAR_CODEARTS_LANGUAGE_MAP = {
       "cs": "C#",
       "css": "CSS",
       "go": "GO",
       "web": "HTML",
       "java": "JAVA",
       "ts": "TYPESCRIPT",
       "js": "JAVASCRIPT",
       "python": "PYTHON",
       "php": "PHP",
       "py": "PYTHON",
       "kotlin": "KOTLIN",
       "rust": "RUST",
       "scala": "SCALA",
       "terraform": "TERRAFORM",
       "plsqlopen": "SQL"
   }
   CN_SONAR_CODEARTS_SEVERITY_MAP = {
       "BLOCKER": "致命",
       "CRITICAL": "严重",
       "MAJOR": "一般",
       "MINOR": "一般",
       "INFO": "提示"
   }
   EN_SONAR_CODEARTS_SEVERITY_MAP = {
       "BLOCKER": "critical",
       "CRITICAL": "major",
       "MAJOR": "minor",
       "MINOR": "minor",
       "INFO": "suggestion"
   }
   # CodeArts Check whitelist validation for rule names and Rule Ids
   NAME_REGEX = r'^[\u4e00-\u9fa5a-zA-Z0-9\s.\-_~\'“”‘’"\(\)#\[\]@<>*+,:!=/\\$?{}`|&;%]+$'
   name_pattern = re.compile(NAME_REGEX)
   RULE_KEY_REGEX = r'^[A-Za-z0-9_\.\-\:]+$'
   rule_key_pattern = re.compile(RULE_KEY_REGEX)
   EN_HEADERS = ["name", "nameCn", "language", "isSupportPersonal", "isSupportVersion", "isSupportIDE", "severity",
                 "criterion_type", "toolRule_name", "toolName", "good_example_cn", "good_example_en", "bad_example_cn",
                 "bad_example_en", "recommend_cn", "recommend_en", "comments_cn", "comments_en", "options"]
   CN_HEADERS = ["规则英文名称", "规则中文名称", "语言", "门禁级", "版本级", "IDE级", "告警严重级别", "规则类型",
                 "工具规则名称", "检查工具", "正确示例（中文）", "正确示例（英文）", "错误示例（中文）", "错误示例（英文）",
                 "修改建议（中文）", "修改建议（英文）", "规则描述（中文）", "规则描述（英文）", "选项"]
   # Generate a random temporary token
   def generate_sonar_token(sonar_token_name):
       try:
           # Send a POST request
           response = requests.post(
               GENERATE_TOKEN_API,
               auth=(USER_NAME, USER_PASSWORD),
               data={
                   "name": sonar_token_name
               }
           )
           if response.status_code == 200:
               try:
                   # Try to parse JSON data
                   data = response.json()
                   print("Token generation successful!")
                   return data.get("token")
               except json.JSONDecodeError as e:
                   print(f"Error parsing token generation JSON: {e}")
                   return ""
           else:
               print(f"Token generation request failed, status code: {response.status_code}")
               return ""
       except requests.exceptions.RequestException as e:
           print(f"Token generation request error: {e}")
           return ""
   # Delete the generated temporary token
   def revoke_token(sonar_token_name):
       try:
           # Send a POST request
           response = requests.post(
               REVOKE_TOKEN_API,
               auth=(USER_NAME, USER_PASSWORD),
               data={
                   "name": sonar_token_name
               }
           )
           if response.status_code != 204:
               print("Token deletion failed!")
               print(f"Token deletion request failed, status code: {response.status_code}")
       except requests.exceptions.RequestException as e:
           print(f"Token deletion request error: {e}")
       print("Token deletion successful!")
   # Get all rule information
   def get_rule_json(sonar_token, language):
       # === Initial pagination parameters ===
       page = 1
       page_size = 500  # Maximum 500 per page (SonarQube maximum)
       data = []
       rules = []
       get_whole_rule = False
       while not get_whole_rule:
           params = {
               "languages": language,  # Specify language
               "p": page,  # Current page number
               "ps": page_size  # Number of items per page
           }
           try:
               # Send a GET request
               response = requests.get(RULE_SEARCH_API, params=params, auth=(sonar_token, ""))
               if response.status_code == 200:
                   try:
                       # Try to parse JSON data
                       data = response.json()
                   except json.JSONDecodeError as e:
                       print(f"Error parsing {language} language rules JSON: {e}")
               else:
                   print(f"Getting {language} rules failed, status code: {response.status_code}")
           except requests.exceptions.RequestException as e:
               print(f"Error getting {language} rules: {e}")
           if not data.get("rules"):
               get_whole_rule = True
           rules += data.get("rules")
           page += 1
       print(f"Parsing {language} rules successful!")
       return rules
   def generate_rules_excel(is_international, rules_list, headers, output_path):
       print("Exporting rules to Excel...")
       excel = openpyxl.Workbook()
       sheet_active = excel.active
       sheet_active.title = "Sheet1"
       sheet = excel["Sheet1"]
       sheet.append(headers)
       for rule_info_dict in rules_list:
           description = ""
           recommendation = ""
           rule_key = rule_info_dict.get("key")
           rule_id = rule_key.split(":")[1]
           name = rule_info_dict.get("name")
           severity = rule_info_dict.get("severity")
           is_template = rule_info_dict.get("isTemplate")
           params = rule_info_dict.get("params")
           option = ""
           if is_template:
               rule_key = rule_key.replace(".", "_") + "_userdefine_template"
               option = option + "sonar_template_key:" + rule_id + ";"
           if params:
               for param in params:
                   option = option + param.get("key") + ":" + \
                            (param.get("defaultValue") if param.get("defaultValue") is not None else "") + ";"
           if option:
               option = option[0: len(option) - 1]
           if not rule_key_pattern.match(rule_key):
               print("SonarQube " + rule_info_dict.get("lang") + " language RuleId violation: " + rule_key)
           if not name_pattern.match(name):
               print("SonarQube " + rule_info_dict.get("lang") + " language rule name violation: " + name)
           for content in rule_info_dict.get("descriptionSections"):
               if content.get("key") == "root_cause" or content.get("key") == "default" \
                       or content.get("key") == "assess_the_problem":
                   description = description + content.get("content")
               elif content.get("key") == "introduction":
                   description = content.get("content") + description
               elif content.get("key") == "how_to_fix":
                   recommendation = recommendation + content.get("content")
           language = SONAR_CODEARTS_LANGUAGE_MAP.get(rule_info_dict.get("lang"))
           if is_international:
               information = [name, name, language if language is not None else rule_info_dict.get("lang").upper(),
                              "yes", "yes", "no", EN_SONAR_CODEARTS_SEVERITY_MAP.get(severity), "common", rule_key,
                              "sonarqubecustom", "N/A", "N/A", "N/A", "N/A", recommendation if recommendation else "N/A",
                              recommendation if recommendation else "N/A", description if description else "N/A",
                              description if description else "N/A", option]
           else:
               information = [name, name, language if language is not None else rule_info_dict.get("lang").upper(),
                              "是", "是", "否", CN_SONAR_CODEARTS_SEVERITY_MAP.get(severity), "通用类（非编程规范）", rule_key,
                              "sonarqubecustom", "无", "无", "无", "无", recommendation if recommendation else "无",
                              recommendation if recommendation else "无", description if description else "无",
                              description if description else "无", option]
           sheet.append(information)
       if not os.path.exists("output"):
           os.mkdir("output")
       excel.save(filename=output_path)
       print("Rules Excel generated successfully!")
   # Get all languages from SonarQube Server
   def get_language_list(sonar_token):
       language_list = []
       languages = []
       try:
           # Send a GET request
           response = requests.get(LANGUAGE_LIST_API, auth=(sonar_token, ""))
           if response.status_code == 200:
               try:
                   # Try to parse JSON data
                   languages = response.json().get("languages")
                   print("Language list retrieved successfully")
               except json.JSONDecodeError as e:
                   print(f"Error parsing language list JSON: {e}")
           else:
               print(f"Getting language list failed, status code: {response.status_code}")
       except requests.exceptions.RequestException as e:
           print(f"Error getting language list: {e}")
       for language in languages:
           language_list.append(language.get("key"))
       return language_list
   if __name__ == "__main__":
       token_name = str((uuid.uuid1()))
       token = generate_sonar_token(token_name)
       if not token:
           raise Exception("Token generation failed")
       sonar_languages = get_language_list(token)
       if not sonar_languages:
           raise Exception("Language list retrieval failed")
       rules = []
       for sonar_language in sonar_languages:
           rules_info = get_rule_json(token, sonar_language)
           if not rules_info:
               print(sonar_language + " language rules retrieval failed")
           rules += rules_info
       revoke_token(token_name)
       generate_rules_excel(False, rules, CN_HEADERS, CN_EXCEL_PATH)
       generate_rules_excel(True, rules, EN_HEADERS, EN_EXCEL_PATH)
   ```
   
   
8. 新建并配置代码化构建任务，参考[新建代码化构建任务](https://support.huaweicloud.com/usermanual-codeci/codeci_ug_0058.html)。
   
   **注意：**创建任务时不要修改build.yml文件。
   
   
9. 单击"编辑"，选择"参数设置 \> 自定义参数"。
10. 单击"立即新建"，创建第一个参数。
11. 单击"新建参数"，需要新建如下12个参数并设置默认值（可选的参数可以不新建），详情参见：[表1]
    
     表1自定义参数表 
    | 参数名                   | 参数描述                                                  | 默认值示例                            | 默认值说明                                                                                                                                                                                                                                                                                                                                                                                              |
    |:---|:---|:---|:---|
    | SONAR_USER_NAME       | SonarQube Server的用户名                                  | admin                            | 从官网直接下载的SonarQube Server，登录的用户名默认为admin。                                                                                                                                                                                                                                                                                                                                                           |
    | SONAR_USER_PASSWORD   | SonarQube Server的密码                                   | admin                            | 从官网直接下载的SonarQube Server，登录的密码默认为admin。                                                                                                                                                                                                                                                                                                                                                            |
    | SONARQUBE_VERSION     | SonarQube Server的版本                                   | 25.4.0.105899                    | 将版本号拼接到下载链接中，即"https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-25.4.0.105899.zip"。下载方式详见[Dockerfile]。 **注意：**需要确保该版本存在，在浏览器中打开如下链接即可进行确认，https://binaries.sonarsource.com/?prefix=Distribution/sonarqube/                               |
    | SONAR_SCANNER_VERSION | SonarScanner CLI的版本                                   | 7.2.0.5079                       | 将版本号拼接到下载链接中，即"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.2.0.5079-linux-x64.zip"。下载方式详见[Dockerfile]。 **注意：**需要确保该版本存在，在浏览器中打开如下链接即可进行确认，https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/ |
    | SONAR_JDK_VERSION     | 该版本SonarQube Server运行所需的JDK版本                         | 17.0.1                           | 将版本号拼接到下载链接中，即"https://mirrors.huaweicloud.com/openjdk/17.0.1/openjdk-17.0.1_linux-x64_bin.tar.gz"。下载方式详见[Dockerfile]。 **注意：**需要确保该版本存在，在浏览器中打开如下链接即可进行确认，https://mirrors.huaweicloud.com/openjdk/                                                     |
    | SONAR_NODE_VERSION    | 可选，SonarQube分析JavaScript/TypeScript/CSS语言所用到Node.js版本 | 20.19.6                          | 将版本号拼接到下载链接中，即"https://nodejs.org/dist/v20.19.6/node-v20.19.6-linux-x64.tar.xz"。下载方式详见[Dockerfile]。 **注意：**需要确保该版本存在，在浏览器中打开如下链接即可进行确认，https://nodejs.org/dist/                                                                                           |
    | COMPILE_JDK_VERSION   | 可选，SonarQube分析Java代码时，编译用户代码所需的JDK版本                  | 21.0.1                           | 将版本号拼接到下载链接中，即"https://mirrors.huaweicloud.com/openjdk/21.0.1/openjdk-21.0.1_linux-x64_bin.tar.gz"。下载方式详见[Dockerfile]。 **注意：**需要确保该版本存在，在浏览器中打开如下链接即可进行确认，https://mirrors.huaweicloud.com/openjdk/                                                         |
    | COMPILE_MAVEN_VERSION | 可选，SonarQube分析Java代码时，编译用户代码所需的Maven版本                | 3.9.12                           | 将版本号拼接到下载链接中，即"https://dlcdn.apache.org/maven/maven-3/3.9.12/binaries/apache-maven-3.9.12-bin.tar.gz"。下载方式详见[Dockerfile]。 **注意：**需要确保该版本存在，在浏览器中打开如下链接即可进行确认，https://dlcdn.apache.org/maven/                                                             |
    | SWR_PATH              | 用户所在局点的SWR地址                                          | swr.cn-north-4.myhuaweicloud.com | 可以在[前置步骤](https://support.huaweicloud.com/bestpractice-codecheck/codeartscheck_14_1014.html#codeartscheck_14_1014__zh-cn_topic_0000002501460678_section067315519324)中获取到的Dockerfile第一行看到。                                                                                                                                                                                                          |
    | ORGANIZATION          | 用户的SWR镜像组织                                            | myorganization                   | 在容器镜像服务所[创建的组织](https://support.huaweicloud.com/usermanual-swr/swr_01_0014.html)。组织的约束与限制参考容器镜像服务的[约束与限制](https://support.huaweicloud.com/productdesc-swr/swr_03_0007.html)。                                                                                                                                                                                                                       |
    | IMAGE_NAME            | 制作出的SonarQube镜像名称                                     | sonarqubecustom                  | 用户自定义。                                                                                                                                                                                                                                                                                                                                                                                             |
    | IMAGE_TAG             | 制作出的SonarQube镜像Tag                                    | v1.0                             | 用户自定义。                                                                                                                                                                                                                                                                                                                                                                                             |
       
    全部配置完后如下图：
    ![](https://support.huaweicloud.com/bestpractice-codecheck/zh-cn_image_0000002583649540.png "点击放大")
    
    
12. 单击"保存并执行"。
    
    **注意：**
    - 若对参数开启了"运行时设置"开关，在运行前还可以修改参数值，需再次单击"确定"开始执行。
    
    - 若用户设置的"IMAGE_NAME"值不是已有的镜像名称而是新建的名称，那么第一次执行会失败，原因是第一次上传的镜像默认为私有镜像，导致镜像无法拉取，如下图。
    
    
    ![](https://support.huaweicloud.com/bestpractice-codecheck/zh-cn_image_0000002583489622.png "点击放大")
    此时需要将镜像设置为公开镜像。参考[使用SWR公共镜像](https://support.huaweicloud.com/usermanual-codeci/codeci_ug_00142.html)将镜像设置为"公开"。设置为公开镜像后重新执行一遍构建任务。
    
    
13. 待任务执行完毕，获取"构建包下载"中的"sonarqube_rules_cn.xlsx"和"sonarqube_rules_en.xlsx"两个文件，用于[导入SonarQube规则](https://support.huaweicloud.com/bestpractice-codecheck/codeartscheck_14_1017.html)。此时在SWR中即可看到对应的镜像。
    
    ![](https://support.huaweicloud.com/bestpractice-codecheck/zh-cn_image_0000002613889419.png "点击放大")
    
    
 
