From 90a6052f93c3629ad9c519f9f8d90e655346a288 Mon Sep 17 00:00:00 2001 From: Episkey Date: Tue, 18 Aug 2026 04:18:21 -0700 Subject: [PATCH 1/2] =?UTF-8?q?CI:=20=E5=8A=A0=20PR=20=E9=97=A8=E7=A6=81?= =?UTF-8?q?=20ci-gate=EF=BC=8C=E5=88=A0=20codecov.yml=EF=BC=8Csonar=20?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E9=9D=9E=E9=98=BB=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit codegen 机器人开的 PR 现在无法自动合并,两个原因叠在一起: 一是本仓 PR 上没有任何能回答「生成的代码到底编不编得过」的 check; 二是 sonar 因 SONAR_TOKEN 403 已连续 8 次全红,PR 的 mergeable_state 被它钉死在 unstable、永远到不了 clean。 本次改动: - Makefile 新增 ci-syntax(mvn -B -DskipTests compile)。它一次覆盖 51 个 module, 同时充当两道闸:生成代码编译不过要失败;生成代码里的重复方法、重复 也是编译期错误,天然被抓住。已知缺口:重复 在 maven 里只有 WARNING、不会失败,本 target 对它无闸;补它需要 maven-enforcer-plugin, 经评估决定不引入,缺口在注释里如实记录,不要以为这条闸是全的。 - 新增 ci.yml:JDK 17 下跑 ci-syntax / lint / test-cov 三个 job,汇总为 ci-gate。 分支保护只需把 ci-gate 配成 required check,其余 job 增删都不影响它。 注意 lint 目前是 echo "skipped" 空壳,留着只为将来填实时位置已在; 门禁的有效性完全由 ci-syntax + test 承担 —— 注释已写明, 不要把「有 lint job」读成「java 做了 lint 把关」。 - 新增 compat.yml:JDK 8/17 矩阵,回答「pom 声明的 maven.compiler.source=1.8 还成不成立」。只挂 schedule 与 workflow_dispatch,刻意不挂 pull_request/push: 每在 codegen PR 上多一个 check,就多一个卡住自动合并的地方, 而这个问题定期回答一次就够,不必每个 PR 都答。 - 删 codecov.yml:它的 mvn test 与 ci.yml 的 test job 完全重复;且它用 JDK 11、 sonar 用 17,同一份代码两个版本各测各的,出分歧时谁准说不清。 覆盖率上传并入 ci.yml 的 test job,作为 continue-on-error 的 step, 且不进 ci-gate 的 needs —— codecov 服务抖动不该把 PR 卡死。 - sonar.yml 缩为纯分析(mvn verify → -DskipTests compile,测试和打包 ci.yml 已做), 并给「Build and analyze」加 step 级 continue-on-error:step 仍然红、问题不被掩盖, 但 job 结论为 success,不再拖住合并。它从此是质量看板而非门禁,token 另行修。 job 显示名 Build 保持不变——它可能已是分支保护的 required check, 改名会让那条 check 永远 pending、把所有 PR 卡死。 顺带升版 checkout@v2→v7、setup-java@v1→v5、cache@v3→v6。 本地验证(JDK 17.0.20,先清空全部 target/ 模拟全新 checkout): make ci-syntax exit 0(50 个 module、2301 个源文件真实编译)、 make lint exit 0、make test-cov exit 0(10 tests 全过、jacoco.xml 已生成)。 另用 javac --release 8 对 2301 个 reactor 源文件单独验过 exit 0, 即源码确实只用 Java 8 API,compat.yml 的下界取 8 有据。 同内容已同步到模板仓 opensdk-java 的 template/files/, 否则下一次 codegen 会把这里的改动整个覆盖掉。 --- .github/workflows/ci.yml | 87 +++++++++++++++++++++++++++++++++++ .github/workflows/codecov.yml | 26 ----------- .github/workflows/compat.yml | 42 +++++++++++++++++ .github/workflows/sonar.yml | 40 +++++++++++++--- Makefile | 13 ++++++ 5 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/codecov.yml create mode 100644 .github/workflows/compat.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..d3d30170d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,87 @@ +name: CI + +# PR 门禁。只保两件事(详见 Makefile 的 ci-syntax): +# G1 生成的代码能被编译 +# G2 生成的代码没有重复项(重复方法、重复 都是 mvn compile 的编译期错误) +# 代码风格不进门禁:风格问题不影响 SDK 能否使用。 +# +# **本仓的 lint 目前是空壳**:Makefile 里 `lint` 就是 `echo "skipped"`,exit 0 但什么都没检查。 +# 之所以还留着这个 job,是为了将来填实时位置已经在、不用再动 workflow; +# 但它的绿色不代表任何东西 —— 本仓门禁的有效性完全由 ci-syntax + test 两个 job 承担。 +# 不要把「java 有 lint job」读成「java 做了 lint 把关」。 +# +# JDK 统一为 17。此前 codecov.yml 用 11、sonar.yml 用 17,同一份代码两个版本各测各的, +# 出分歧时谁是准的说不清;codecov.yml 已随本次改动删除,覆盖率上传并进 test job, +# 从此全仓只有 17 这一个门禁版本。声明下界 1.8 的兼容性验证移交 compat.yml。 +# +# 分支保护只需把 `ci-gate` 配成 required check,其余 job 增删都不影响它。 + +on: + pull_request: + branches: [master] + push: + branches: [master] + +permissions: + contents: read + +jobs: + ci-syntax: + name: ci-syntax + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: temurin + # 51 个 module 每个 job 都重下一遍依赖太慢,交给 setup-java 自带的 ~/.m2 缓存。 + cache: maven + - run: make ci-syntax + + lint: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: temurin + cache: maven + # 注意:这一步当前恒绿且什么都没做,见文件头部说明。 + - run: make lint + + test: + name: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: temurin + cache: maven + - run: make test-cov + # 覆盖率上传是看板不是门禁:codecov 服务抖动不该把 PR 卡死, + # 故 step 级 continue-on-error,且 ci-gate 的 needs 里也没有它。 + - name: Upload coverage + continue-on-error: true + uses: codecov/codecov-action@v7 + 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: 全部通过" diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml deleted file mode 100644 index d1d0b70ec..000000000 --- a/.github/workflows/codecov.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Codecov - -on: - push: - branches: - - master - - release/* - pull_request: - types: [opened, synchronize, reopened] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v2 - with: - java-version: '11' - distribution: 'adopt' - - name: Run tests - run: mvn --batch-mode --update-snapshots test - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - with: - fail_ci_if_error: false diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml new file mode 100644 index 000000000..a4830c4d9 --- /dev/null +++ b/.github/workflows/compat.yml @@ -0,0 +1,42 @@ +name: Compat + +# JDK 兼容性矩阵,**不是门禁**。 +# +# 触发只留 schedule 与手动:codegen 机器人开的 PR 要靠 check 全绿才能自动合并, +# 这里每多一个 check 就多一个卡住它的机会,而「声明的 JDK 下界还活着吗」这个问题 +# 并不需要每个 PR 都回答一次,定期回答就够了。 +# +# 矩阵取 8 与 17 两端: +# 8 —— pom 声明的 maven.compiler.source/target 是 1.8,这一格就是在验证该声明还成立。 +# 已本地用 `javac --release 8` 对全部 2301 个 reactor 源文件验过 exit 0, +# 即源码确实只用了 Java 8 的 API;但**整条 maven 插件链在 JDK 8 运行时下能否跑通 +# 未在本地验证过**(本机没有 JDK 8),这一格首次调度跑红是可能的, +# 红了说明真实下界已经高于声明值,应据实改声明或改代码,不要直接把这一格删掉。 +# 17 —— ci.yml 的门禁版本,作为对照基线。 +# +# fail-fast: false —— 8 挂了也必须看到 17 的结果,否则矩阵只剩一个信号,等于没矩阵。 + +on: + schedule: + - cron: '17 2 * * 1' + workflow_dispatch: + +permissions: + contents: read + +jobs: + compat: + name: compat (JDK ${{ matrix.java }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + java: ['8', '17'] + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-java@v5 + with: + java-version: ${{ matrix.java }} + distribution: temurin + cache: maven + - run: make ci-syntax diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index b47da867f..b46042a87 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -1,4 +1,23 @@ name: Sonar + +# 这个 workflow 现在是**非阻断的质量看板,不是门禁**。 +# +# 起因:SONAR_TOKEN 已失效,「Build and analyze」这一步 403 恒失败(最近 8 次全红)。 +# 只要它是红的,PR 的 mergeable_state 就恒为 unstable、永远到不了 clean, +# codegen PR 的自动合并会被这条与代码质量无关的红叉挡死。 +# 处置:给该 step 加 step 级 continue-on-error —— step 仍然会红、问题不被掩盖, +# 但 job 结论是 success,不再拖住合并。**修好 token 是另一件事,不在本次范围内。** +# +# job 的显示名 `Build` 必须保持不变:它可能已经被配进分支保护的 required check, +# 改名会让那条 required check 永远 pending、把所有 PR 卡死。 +# (job key 仍叫 `lint` 是历史遗留,与代码风格检查无关;本仓真正的 lint 见 ci.yml, +# 且那个目前是空壳。) +# +# 已从原来的 `mvn verify` 缩为只跑到 compile:verify 会把测试和打包再跑一遍, +# 而这两件事 ci.yml 已经做了,重复跑既费时又让「哪个结果算数」变得含糊。 +# sonar 分析本身只需要有编译产物即可。 +# 原来的 -Dgpg.skip 一并去掉:gpg 签名绑在 verify 阶段,跑到 compile 根本到不了那里。 + on: push: branches: @@ -6,32 +25,41 @@ on: - release/* pull_request: types: [opened, synchronize, reopened] + +permissions: + contents: read + jobs: lint: name: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 17 - uses: actions/setup-java@v1 + uses: actions/setup-java@v5 with: - java-version: 17 + java-version: '17' + distribution: temurin - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v6 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v6 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 + # continue-on-error 加在 step 上而不是 job 上: + # job 级会把整个 job 标成 success 却看不出哪里出了问题, + # step 级则是这一步红、job 绿,红叉仍留在 Actions 页面上等人去修 token。 - name: Build and analyze + continue-on-error: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dgpg.skip -Dsonar.projectKey=ucloud_ucloud-sdk-java + run: mvn -B -DskipTests compile org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=ucloud_ucloud-sdk-java diff --git a/Makefile b/Makefile index fe25a2580..d728e5394 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,19 @@ build: fmt: google-java-format --aosp -r ${JAVA_FILES} +# CI 语法闸。只保两件事,都由 mvn compile 一次覆盖全部产品 module: +# G1 生成的代码能被编译 —— 编译不过直接失败。 +# G2 生成的代码没有重复项 —— 重复方法、重复 都是编译期错误,天然被抓住。 +# 已知缺口(如实记录,不要以为这条闸是全的): +# 重复的 在 maven 里只有 WARNING、不会让构建失败,本 target 对它无闸。 +# 要补需引入 maven-enforcer-plugin 的 banDuplicatePomDependencyVersions, +# 经评估后决定不引入,故该缺口保留。 +.PHONY: ci-syntax +ci-syntax: + mvn -B -DskipTests compile + +# 警告:当前是空壳,exit 0 但什么都没检查,不要把它的通过当成风格已过检。 +# 填实需要先跑一次全仓 google-java-format(见 fmt),是个独立的大 diff,不在 CI 改造范围内。 .PHONY: lint lint: echo "skipped" From 85e97f9dc2a54b33811984ac674c667b6a44171e Mon Sep 17 00:00:00 2001 From: Episkey Date: Wed, 19 Aug 2026 01:43:28 -0700 Subject: [PATCH 2/2] =?UTF-8?q?ci:=20=E5=8E=BB=E6=8E=89=20compat.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 兼容矩阵是纯巡检,不参与门禁判定,也没人会盯一个非阻断的定时任务。 声明下界还成不成立是另一个问题,要验的时候手工跑一次即可, 不必为它常驻一条每天运行的 workflow。 --- .github/workflows/ci.yml | 5 ++++- .github/workflows/compat.yml | 42 ------------------------------------ 2 files changed, 4 insertions(+), 43 deletions(-) delete mode 100644 .github/workflows/compat.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3d30170d..ba6f6fff7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,10 @@ name: CI # # JDK 统一为 17。此前 codecov.yml 用 11、sonar.yml 用 17,同一份代码两个版本各测各的, # 出分歧时谁是准的说不清;codecov.yml 已随本次改动删除,覆盖率上传并进 test job, -# 从此全仓只有 17 这一个门禁版本。声明下界 1.8 的兼容性验证移交 compat.yml。 +# 从此全仓只有 17 这一个门禁版本。 +# +# pom 声明的下界是 1.8,本门禁不验证它——那是「声明还成不成立」的问题, +# 与本次改动是否正确无关,不该占用每个 PR 的时间。要验的时候手工跑一次即可。 # # 分支保护只需把 `ci-gate` 配成 required check,其余 job 增删都不影响它。 diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml deleted file mode 100644 index a4830c4d9..000000000 --- a/.github/workflows/compat.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Compat - -# JDK 兼容性矩阵,**不是门禁**。 -# -# 触发只留 schedule 与手动:codegen 机器人开的 PR 要靠 check 全绿才能自动合并, -# 这里每多一个 check 就多一个卡住它的机会,而「声明的 JDK 下界还活着吗」这个问题 -# 并不需要每个 PR 都回答一次,定期回答就够了。 -# -# 矩阵取 8 与 17 两端: -# 8 —— pom 声明的 maven.compiler.source/target 是 1.8,这一格就是在验证该声明还成立。 -# 已本地用 `javac --release 8` 对全部 2301 个 reactor 源文件验过 exit 0, -# 即源码确实只用了 Java 8 的 API;但**整条 maven 插件链在 JDK 8 运行时下能否跑通 -# 未在本地验证过**(本机没有 JDK 8),这一格首次调度跑红是可能的, -# 红了说明真实下界已经高于声明值,应据实改声明或改代码,不要直接把这一格删掉。 -# 17 —— ci.yml 的门禁版本,作为对照基线。 -# -# fail-fast: false —— 8 挂了也必须看到 17 的结果,否则矩阵只剩一个信号,等于没矩阵。 - -on: - schedule: - - cron: '17 2 * * 1' - workflow_dispatch: - -permissions: - contents: read - -jobs: - compat: - name: compat (JDK ${{ matrix.java }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - java: ['8', '17'] - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-java@v5 - with: - java-version: ${{ matrix.java }} - distribution: temurin - cache: maven - - run: make ci-syntax