Linux环境下Python用F-string调用SonarQube API返回404问题排查
问题:Jenkins容器中动态拼接SonarQube API参数返回404,静态值及本地环境正常
- 在Linux Jenkins容器中,使用Python的F-string/format/字符串拼接生成
pullRequest参数调用SonarQube API时,服务器返回404错误 - 直接使用静态固定值调用该API则正常
- Mac本地环境用同样的动态拼接方式调用API完全正常
代码示例
GERRIT_CN = os.environ.get('GERRIT_CHANGE_NUMBER') GERRIT_PS = os.environ.get('GERRIT_PATCHSET_NUMBER') sq_url = 'https://sonar.company.com/' projectKey="team-pba" gerrit_cn_ps = f"{GERRIT_CN}-{GERRIT_PS}" print(gerrit_cn_ps) def sonar_api(): debug_requests_on() sonar = SonarQubeClient(sonarqube_url=sq_url, username=myUsr, password=myPass) # 静态值调用正常 # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey="team-pba", pullRequest="124434-120") # 动态拼接调用失败 # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=f"{projectKey}", pullRequest=f"{GERRIT_CN}-{GERRIT_PS}") # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=f"{projectKey}", pullRequest=GERRIT_CN+"-"+GERRIT_PS) # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=projectKey, pullRequest=gerrit_cn_ps)
日志信息
失败日志(Linux Jenkins)
+ python3.8 /home/jenkins/agent/workspace/sonar-api.py DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sonar.company.com:443 DEBUG:urllib3.connectionpool:https://sonar.company.com:443 "GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-139 HTTP/1.1" 404 103 Traceback (most recent call last): File "/home/jenkins/agent/workspace///sonar-api.py", line 61, in <module> print(sonar_api()) File "/home/jenkins/agent/workspace///sonar-api.py", line 51, in sonar_api project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=projectKey, pullRequest=gerrit_cn_ps) File "/usr/local/lib/python3.8/dist-packages/sonarqube/utils/common.py", line 132, in inner_func response = self._get(url_pattern, params=params) File "/usr/local/lib/python3.8/dist-packages/sonarqube/utils/rest_client.py", line 141, in _get return self.request("GET", path=path, params=params, data=data, headers=headers) File "/usr/local/lib/python3.8/dist-packages/sonarqube/utils/rest_client.py", line 99, in request raise NotFoundError(msg) sonarqube.utils.exceptions.NotFoundError: Error in request. Possibly Not Found error [404]: Pull request '124434-139' in project 'team-pba' not found 124434-139 send: b'GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-139 HTTP/1.1\r\nHost: sonar.company.com\r\nUser-Agent: python-requests/2.22.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nAuthorization: Basic xxxxx\r\n\r\n’ reply: 'HTTP/1.1 404 \r\n' header: Server: nginx/1.12.2 header: Date: Tue, 28 Mar 2023 21:16:09 GMT header: Content-Type: application/json header: Content-Length: 103 header: Connection: keep-alive
成功日志(静态值/Linux Jenkins)
+ python3 /home/jenkins/agent/workspace/sonar-api.py DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sonar.company.com:443 DEBUG:urllib3.connectionpool:https://sonar.company.com:443 "GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-139 HTTP/1.1" 200 881 [Pipeline] echo 124434-139 send: b'GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-139 HTTP/1.1\r\nHost [Pipeline] }
成功日志(F-string/Mac本地)
Command> python3 sonar-api.py all values 124434 142 124434-142 DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sonar.company.com:443 send: b'GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-142 HTTP/1.1\r\nHost: sonar.company.com\r\nUser-Agent: python-requests/2.27.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nAuthorization: Basic xxxx\r\n\r\n’ reply: 'HTTP/1.1 200 \r\n' header: Server: nginx/1.12.2 header: Date: Tue, 28 Mar 2023 21:53:55 GMT header: Content-Type: application/json header: Content-Length: 739 header: Connection: keep-alive header: X-Frame-Options: SAMEORIGIN header: X-XSS-Protection: 1; mode=block header: X-Content-Type-Options: nosniff header: Cache-Control: no-cache, no-store, must-revalidate DEBUG:urllib3.connectionpool:https://sonar.company.com:443 "GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-142 HTTP/1.1" 200 739 52.53:0.0
排查方向与解决方案
核心疑点:环境变量的隐形字符
从日志看,动态拼接和静态值的请求URL表面完全一致,但结果不同,最大可能是环境变量GERRIT_CN或GERRIT_PS带有隐形空白字符(比如换行符\n、空格、制表符),导致拼接后的pullRequest参数看起来正常,实际带有不可见字符,SonarQube无法匹配到对应的PR。Jenkins环境中,环境变量可能因构建脚本输出、变量传递方式等引入隐形字符,而Mac本地环境的变量来源更干净。
验证方法
在代码中添加隐形字符检测,确认变量是否含有不可见字符:
# 打印变量原始内容和长度,检测隐形字符 print(f"GERRIT_CN raw: {repr(GERRIT_CN)}, length: {len(GERRIT_CN)}") print(f"GERRIT_PS raw: {repr(GERRIT_PS)}, length: {len(GERRIT_PS)}") print(f"gerrit_cn_ps raw: {repr(gerrit_cn_ps)}")
如果输出中出现'124434\n'或带空格的内容,即可确认存在隐形字符。
解决方案
对环境变量做空白字符清理,使用strip()方法去除首尾所有空白字符:
GERRIT_CN = os.environ.get('GERRIT_CHANGE_NUMBER', '').strip() GERRIT_PS = os.environ.get('GERRIT_PATCHSET_NUMBER', '').strip() gerrit_cn_ps = f"{GERRIT_CN}-{GERRIT_PS}"
其他排查点
- Python版本与库版本差异:检查Jenkins和本地的Python版本、
sonarqube客户端版本是否一致,若版本差异较大,尝试升级Jenkins环境的库版本。 - 字符编码问题:极端情况下可能存在环境编码差异,但从日志看请求参数显示正常,优先级低于隐形字符排查。
内容的提问来源于stack exchange,提问作者AhmFM
相关产品推荐
相关产品推荐

