Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: CI

# PR 门禁。本仓此前没有任何 workflow,CI 只有一个早已停用的 .travis.yml
# (且只测 3.5/3.6/3.7),等于生成代码从来没有闸门——本文件就是补这一层。
#
# 门禁只保两件事(详见 Makefile 的 ci-syntax):
# G1 生成的代码能被解释器编译 —— 语法错误、非法标识符即失败
# G2 生成的代码没有重复声明 —— python 的重复 def/class 不是语法错误,
# 后者静默覆盖前者,compileall 一律放行,必须另起 ast 扫描
# 代码风格不进门禁:风格不影响 SDK 能否使用,且格式化已由生成侧的 make fmt 负责,
# 见 Makefile 里 ci-syntax 上方关于 black 的说明。
#
# 分支保护只需把 `ci-gate` 配成 required check,其余 job 增删都不影响它。
#
# 版本取 3.12 而不是仓库声明的下界:setup.py 写着 python_requires=">=3.5",
# 但那早就不成立(tests 里曾用 3.10 已移除的 collections.Callable,
# Travis 只测到 3.7 所以从未暴露)。老解释器的兼容性不进 PR 门禁——
# 那是「声明还成不成立」的问题,门禁要回答的是"这次改动有没有把代码写坏"。

on:
pull_request:
branches: [master]
push:
branches: [master]

permissions:
contents: read

Check warning on line 27 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Move this read permission from workflow level to job level.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBr&open=AaAZDJfmff6KG3E28aBr&pullRequest=349

jobs:
ci-syntax:
name: ci-syntax
runs-on: ubuntu-latest
# 两条闸全量扫描整棵 ucloud/,但只对**本轮变更的文件**阻断,存量命中只告警。
# 原因:uphost 那处重复方法是躺在 master 上的存量缺陷(已删除 API 的旧快照被
# publish 集合留了下来),整棵树一律阻断就等于发**任何一个**产品的 codegen PR
# 都会被一个与本次发布毫无关系的问题判红,mergeable_state 变 unstable,
# 自动合并永久失效——那正是这套门禁要解决的问题本身。
# 同源决策见 ucloud-sdk-release/scripts/python-fatal-check.sh(2026-07-31,
# 已被 pipeline 2507836 实证:那次发的是 UHost+UAI-Modelverse,根本没重新
# 生成 uphost,那处重复照样被扫了出来)。
# 变更集怎么算、拿不到时怎么退回,见 scripts/ci-syntax.sh 文件头。
env:
# 严格集的基点。PR 事件取目标分支侧的 base.sha(配三点式 diff 正好等于本 PR
# 引入的改动),push 事件取推送前的 before。两者都拿不到或解析不出时,
# 脚本自行退回整棵树严格判定并打印原因,不会静默放行。
CI_BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
steps:
- uses: actions/checkout@v7
with:
# 默认 fetch-depth: 1 只拉一个 commit,base sha 不在本地对象库里,
# git diff 必然解析不出 → 每次都退回整棵树严格判定,分级就白做了。
# 只有本 job 需要历史,lint / test 保持浅克隆。
fetch-depth: 0
- uses: actions/setup-python@v7
with:
python-version: '3.12'
# ci-syntax 本身只用 stdlib(compileall + ast),装 .[ci] 是为了让三个 job
# 的环境一致,省掉「哪个 job 该装什么」的分叉。
- run: pip install -e '.[ci]'

Check warning on line 59 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBt&open=AaAZDJfmff6KG3E28aBt&pullRequest=349

Check warning on line 59 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBs&open=AaAZDJfmff6KG3E28aBs&pullRequest=349
- run: make ci-syntax

lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.12'
- run: pip install -e '.[ci]'

Check warning on line 70 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBu&open=AaAZDJfmff6KG3E28aBu&pullRequest=349

Check warning on line 70 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBv&open=AaAZDJfmff6KG3E28aBv&pullRequest=349
# flake8 显式 --exclude 掉了 ucloud/services,也就是这一层只管手写代码;
# 生成代码的把关全在 ci-syntax,两者不重叠。
- run: make lint

test:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.12'
- run: pip install -e '.[ci]'

Check warning on line 83 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBw&open=AaAZDJfmff6KG3E28aBw&pullRequest=349

Check warning on line 83 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBx&open=AaAZDJfmff6KG3E28aBx&pullRequest=349
- run: make test-cov
# 上传失败不能影响门禁:codecov 是外部服务,它抖动跟代码质量无关。
# 故 continue-on-error,且这个 step 所在的 test job 之外不另设 codecov job。
- name: Upload coverage
continue-on-error: true
uses: codecov/codecov-action@v7

Check failure on line 89 in .github/workflows/ci.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use full commit SHA hash for this dependency.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfmff6KG3E28aBy&open=AaAZDJfmff6KG3E28aBy&pullRequest=349
with:
fail_ci_if_error: false

ci-gate:
name: ci-gate
needs: [ci-syntax, lint, test]
if: always()
runs-on: ubuntu-latest
steps:
- name: Aggregate
run: |
if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" \
|| "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
echo "ci-gate: 有 job 失败或被取消"
exit 1
fi
echo "ci-gate: 全部通过"
21 changes: 0 additions & 21 deletions .travis.yml

This file was deleted.

40 changes: 39 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ help:
test: clean
pytest

# --cov-report 两项显式写全:只要指定了 --cov-report,pytest-cov 就不再自动出 term 报告。
# xml 是给 codecov-action 用的——它只上传现成的报告文件,不会自己去生成
# (Travis 时代那个 codecov bash uploader 会顺手跑 `coverage xml`,action 不会)。
test-cov: clean
pytest --cov=ucloud/core tests
pytest --cov=ucloud/core tests --cov-report=term --cov-report=xml

test-cov-html:
pytest --cov=ucloud/core tests --cov-report html
Expand All @@ -47,6 +50,41 @@ test-acc: clean
test-all: clean
tox

# CI 门禁:生成代码必须能被解释器接受、且无重复声明。门禁只管「代码能不能用」,
# 不管风格——语法错误、非法标识符、重复声明是缺陷,缩进和空行不是。
# G1 `compileall` 覆盖 ucloud/ 下全部生成代码(现有 lint 显式 --exclude 掉了
# ucloud/services,也就是生成代码一直没人查)。真缺陷它抓得住,实测:
# `def uai-modelverse(self):`(连字符产品名回填成非法标识符,真实事故形态)
# → exit 1 SyntaxError;而纯格式问题 `def foo( a,b ):` → exit 0。
# 这正是想要的分界线。
# G2 python 里重复的 class/def/import 不是语法错误——后者静默覆盖前者,
# compileall 一律 exit 0,只能另起 ast 扫描补上。
# 真实案例:uphost 的 get_phost_disk_upgrade_price 被生成了两遍,
# 后者是已删除 API 的旧快照,把唯一在用的那个覆盖掉了。
#
# 两条闸都**全量扫描、只对本轮变更的文件阻断**,实现收进 scripts/ci-syntax.sh:
# G2 那个真实案例就躺在上游 master 上,整棵树一律阻断的话,发**任何一个**产品
# (UDisk、UNet……)的 codegen PR 都会被这处与本次发布毫无关系的存量问题判红,
# mergeable_state 变 unstable,自动合并永久失效——那正是这套门禁要解决的问题本身。
# 同源决策见 ucloud-sdk-release/scripts/python-fatal-check.sh(2026-07-31,已被
# pipeline 2507836 实证)。变更集怎么算、拿不到时怎么 fail-closed 退回整棵树,
# 见 scripts/ci-syntax.sh 文件头。本地不设 CI_BASE_SHA,看到的就是整棵树严格判定。
#
# 这里**故意不放** `black --check`,与 go 的 ci-syntax 带 gofmtcheck.sh 不对称,
# 不是漏了:
# · gofmt 的输出多年稳定,版本又由 workflow 里的 setup-go 钉住,两端天然对齐;
# black 每年改一次稳定风格——实测本仓 392 个文件在 24.8.0 / 24.10.0 下全过,
# 到 25.1.0 起有 211 个被判需重排(改了 docstring 首尾空白的处理)。
# · 而生成侧 ucloud-sdk-release 的 python:format job 是 `pip install -U black`
# 之后跑 `make fmt`,永远用当天最新版格式化并提交。校验端无论钉哪个版本,
# 都会在 black 发新版后与生成侧偏斜,把每个 codegen PR 恒判为红——
# 那恰好是自动合并要解决的问题本身。
# · 格式化是生成侧 `make fmt` 的职责,生成时已经跑过,门禁再 --check 一遍
# 不增加保障,只增加版本偏斜的风险。
.PHONY: ci-syntax
ci-syntax:
@bash scripts/ci-syntax.sh

lint:
@flake8 --exclude=ucloud/services ucloud --ignore=E501,F401

Expand Down
139 changes: 139 additions & 0 deletions scripts/ci-syntax.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/env bash
# CI 语法门禁:G1 编译闸(compileall)+ G2 重复闸(dup-check.py)。由 `make ci-syntax` 调用。
#
# ── 为什么「全量扫描」和「严格判定」是两个范围 ────────────────────────────────
# 仓里躺着存量缺陷:ucloud/services/uphost/client.py 有一处重复方法
# get_phost_disk_upgrade_price——已删除 API 的旧快照被 publish 集合(追加式存储)留了
# 下来,python codegen 直读该集合就把幽灵一并生成。它改 SDK 仓库无效,根治在
# ucloud-model 侧补「编辑态已不存在则丢弃」的过滤,属独立任务。
#
# 若整棵树一律阻断,发**任何一个**产品(UDisk、UNet……)的 codegen PR 都会被这处与本次
# 发布毫无关系的存量问题判红,mergeable_state 随之变 unstable,自动合并永久失效——
# 那恰好是这套门禁要解决的问题本身。
#
# 后果 2026-07-31 已被实证并明确否决:pipeline 2507836 发的是 UHost+UAI-Modelverse、
# 根本没重新生成 uphost,那处重复照样被扫了出来,证明来源是存量代码而非本轮产物。
# 当时的处置是「判定边界取本轮变更文件,存量只告警」,落在
# ucloud-sdk-release/scripts/python-fatal-check.sh 的文件头。本脚本把同一原则落到
# GitHub Actions 上,两端同源。
#
# 存量仍然**全量扫描**:不阻断不等于不检查。债务要保持可见、可度量,否则收窄判定范围
# 就退化成了掩盖问题。
#
# ── 严格集怎么算 ────────────────────────────────────────────────────────────
# 取环境变量 CI_BASE_SHA(workflow 里 PR 事件给 base.sha、push 事件给 before):
# · 能解析成 commit → 严格集 = `git diff --name-only $CI_BASE_SHA...HEAD` 结果中
# ucloud/ 下的 .py 文件。三点式取的是 merge-base 到 HEAD,正好等于本 PR 引入的改动;
# --diff-filter=d 排除删除项,删掉的文件没法编译。
# · 未设置 / 解析不出(force push 覆盖了原提交、新分支的全零 sha、clone 深度不够、
# 两端无共同祖先)→ 退回整棵树严格判定,并打印退回原因。
# fail-closed:拿不准就严格,绝不静默放行。本地不设该变量看到的就是整棵树严格判定,
# 与 CI 的退回路径完全一致,不引入「本地绿 / CI 红」的分叉。

# 不用 set -e:本脚本要接住 compileall / dup-check 的非零退出码自行分级判定。
set -uo pipefail

ROOT_DIR="ucloud"
MAX_LIST_ECHO=30 # 全量重生成会变更数百个文件,日志里全打出来只是噪声

if [ ! -d "$ROOT_DIR" ]; then

Check failure on line 39 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBZ&open=AaAZDJfcff6KG3E28aBZ&pullRequest=349
echo "FATAL: 未找到 ${ROOT_DIR}/,请在仓库根目录执行(当前目录:$(pwd))。"
exit 1
fi

# ── 第一步:确定严格集 ───────────────────────────────────────────────────────
SUBSET_MODE=0 # 1 = 严格集是子集;0 = 严格集是整棵树
FALLBACK_REASON="" # SUBSET_MODE=0 时说明为什么退回
STRICT_FILES=()

if [ -z "${CI_BASE_SHA:-}" ]; then

Check failure on line 49 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBa&open=AaAZDJfcff6KG3E28aBa&pullRequest=349
FALLBACK_REASON="未设置 CI_BASE_SHA(本地直接执行 make ci-syntax 的常态)"
elif ! git rev-parse --verify --quiet "${CI_BASE_SHA}^{commit}" >/dev/null 2>&1; then
FALLBACK_REASON="CI_BASE_SHA=${CI_BASE_SHA} 解析不出 commit(force push 覆盖了原提交 / 新分支的全零 sha / checkout 没设 fetch-depth: 0 / 不在 git 仓库里)"
elif ! CHANGED="$(git diff --name-only --diff-filter=d "${CI_BASE_SHA}...HEAD" -- "$ROOT_DIR" 2>&1)"; then
FALLBACK_REASON="git diff ${CI_BASE_SHA}...HEAD 执行失败(两端无共同祖先时会这样):${CHANGED}"
else
SUBSET_MODE=1
while IFS= read -r f; do
# 只收 .py;-f 兜底防止 rename/filter 之外的意外让 compileall 拿到不存在的路径
case "$f" in

Check failure on line 59 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default case (*) to handle unexpected values.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBb&open=AaAZDJfcff6KG3E28aBb&pullRequest=349
*.py) [ -f "$f" ] && STRICT_FILES+=("$f") ;;

Check failure on line 60 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBc&open=AaAZDJfcff6KG3E28aBc&pullRequest=349
esac
done <<<"$CHANGED"
fi

echo "════ ci-syntax ════"
if [ "$SUBSET_MODE" -eq 1 ]; then

Check failure on line 66 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBd&open=AaAZDJfcff6KG3E28aBd&pullRequest=349
echo "严格判定范围:本轮变更的 ${#STRICT_FILES[@]} 个文件(${CI_BASE_SHA}...HEAD 下 ${ROOT_DIR}/ 的 .py)"
echo "全量扫描范围:整棵 ${ROOT_DIR}/(存量命中只告警,不计入退出码)"
if [ "${#STRICT_FILES[@]}" -gt 0 ] && [ "${#STRICT_FILES[@]}" -le "$MAX_LIST_ECHO" ]; then

Check failure on line 69 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBf&open=AaAZDJfcff6KG3E28aBf&pullRequest=349

Check failure on line 69 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBe&open=AaAZDJfcff6KG3E28aBe&pullRequest=349
printf ' %s\n' "${STRICT_FILES[@]}"
fi
else
echo "严格判定范围:整棵 ${ROOT_DIR}/"
echo "退回原因:${FALLBACK_REASON}"
fi
echo

# ── 第二步:G1 编译闸 ────────────────────────────────────────────────────────
# compileall 覆盖 ucloud/ 下全部生成代码(lint 显式 --exclude 掉了 ucloud/services,
# 也就是生成代码一直没人查)。真缺陷它抓得住,实测:`def uai-modelverse(self):`
# (连字符产品名回填成非法标识符,真实事故形态)→ exit 1 SyntaxError;
# 而纯格式问题 `def foo( a,b ):` → exit 0。这正是想要的分界线。
echo "─── G1 编译闸 [全量扫描] python -m compileall ${ROOT_DIR} ───"
python -m compileall -q "$ROOT_DIR"
g1_full=$?

if [ "$SUBSET_MODE" -eq 0 ]; then

Check failure on line 87 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBg&open=AaAZDJfcff6KG3E28aBg&pullRequest=349
g1_gate=$g1_full
if [ "$g1_full" -eq 0 ]; then

Check failure on line 89 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBh&open=AaAZDJfcff6KG3E28aBh&pullRequest=349
echo "G1 通过:${ROOT_DIR}/ 全部可编译"
else
echo "G1 失败:整棵树严格判定,上方 *** Error compiling 即阻断项"

Check warning on line 92 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Redirect this error message to stderr (>&2).

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBi&open=AaAZDJfcff6KG3E28aBi&pullRequest=349
fi
else
if [ "$g1_full" -eq 0 ]; then

Check failure on line 95 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBj&open=AaAZDJfcff6KG3E28aBj&pullRequest=349
echo "G1 全量扫描:${ROOT_DIR}/ 全部可编译"
else
echo "⚠️ G1 全量扫描命中(上方 *** Error compiling)。落在本轮变更集之外的命中只告警,"

Check warning on line 98 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Redirect this error message to stderr (>&2).

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBk&open=AaAZDJfcff6KG3E28aBk&pullRequest=349
echo " 不计入退出码;若下面的严格判定同样命中,才会真阻断。"
fi
if [ "${#STRICT_FILES[@]}" -eq 0 ]; then

Check failure on line 101 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBl&open=AaAZDJfcff6KG3E28aBl&pullRequest=349
echo "─── G1 编译闸 [严格判定] 本轮 ${ROOT_DIR}/ 下无变更的 .py,跳过 ───"
g1_gate=0
else
echo "─── G1 编译闸 [严格判定] 本轮变更的 ${#STRICT_FILES[@]} 个文件 ───"
python -m compileall -q "${STRICT_FILES[@]}"
g1_gate=$?
[ "$g1_gate" -eq 0 ] && echo "G1 通过:本轮变更文件全部可编译"

Check failure on line 108 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBm&open=AaAZDJfcff6KG3E28aBm&pullRequest=349
fi
fi
echo

# ── 第三步:G2 重复闸 ────────────────────────────────────────────────────────
# python 里重复的 class/def/import 不是语法错误——后者静默覆盖前者,compileall 一律
# exit 0,只能另起 ast 扫描补上。dup-check.py 一趟扫完整棵树,命中按是否落在严格集里
# 分成阻断 / 告警两类,故这里不需要像 G1 那样跑两遍。
echo "─── G2 重复闸 scripts/dup-check.py ───"
if [ "$SUBSET_MODE" -eq 0 ]; then

Check failure on line 118 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBn&open=AaAZDJfcff6KG3E28aBn&pullRequest=349
python scripts/dup-check.py "$ROOT_DIR"
g2_gate=$?
else
STRICT_LIST_FILE="$(mktemp)"
trap 'rm -f "$STRICT_LIST_FILE"' EXIT
if [ "${#STRICT_FILES[@]}" -gt 0 ]; then

Check failure on line 124 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBo&open=AaAZDJfcff6KG3E28aBo&pullRequest=349
printf '%s\n' "${STRICT_FILES[@]}" >"$STRICT_LIST_FILE"
else
: >"$STRICT_LIST_FILE"
fi
python scripts/dup-check.py --strict-list "$STRICT_LIST_FILE" "$ROOT_DIR"
g2_gate=$?
fi
echo

# ── 汇总 ────────────────────────────────────────────────────────────────────
if [ "$g1_gate" -ne 0 ] || [ "$g2_gate" -ne 0 ]; then

Check failure on line 135 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBq&open=AaAZDJfcff6KG3E28aBq&pullRequest=349

Check failure on line 135 in scripts/ci-syntax.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ucloud_ucloud-sdk-python3&issues=AaAZDJfcff6KG3E28aBp&open=AaAZDJfcff6KG3E28aBp&pullRequest=349
echo "ci-syntax 失败:G1=${g1_gate} G2=${g2_gate}"
exit 1
fi
echo "ci-syntax 通过:G1/G2 在严格判定范围内均无命中"
Loading