diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 0000000000..b359fe93cc --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Keep coverage from unexecuted test groups in affected-input CI reports. +flag_management: + default_rules: + carryforward: true + +comment: + show_carryforward_flags: true diff --git a/.github/scripts/test_ci_policy.py b/.github/scripts/test_ci_policy.py index a60486ebec..a5e9e5301c 100644 --- a/.github/scripts/test_ci_policy.py +++ b/.github/scripts/test_ci_policy.py @@ -346,30 +346,6 @@ def test_real_coordinator_blocks_selection_runtime_failure_and_cancellation(self self.assertEqual({"helm"}, self.coordinator_jobs(full, java=state, result="failure")) self.assertEqual(set(), self.coordinator_jobs(full, cancelled=True)) - def test_legacy_memory_bridge_requires_real_results_and_retires_without_a_runner(self): - docs = self.plan_for(["README.md"]) - self.assertEqual(set(), self.coordinator_jobs(docs)) - docs["legacy_memory_required"] = True - self.assertEqual({"legacy-server-memory"}, self.coordinator_jobs(docs)) - self.assertEqual(set(), self.coordinator_jobs(docs, cancelled=True)) - workflow = (Path(__file__).resolve().parents[1] / "workflows/server-ci.yml").read_text() - bridge = re.search(r"^ legacy-server-memory:\n(.*?)(?=^ [\w-]+:|\Z)", workflow, re.M | re.S).group(1) - self.assertEqual("Server memory tests", re.search(r"^ name: (.+)$", bridge, re.M).group(1)) - script = textwrap.dedent(bridge.split(" run: |\n", 1)[1]) - cases = [("success", "true", "success", "success", True), - ("success", "false", "success", "skipped", True), - ("failure", "false", "success", "skipped", False), - ("success", "", "success", "skipped", False), - ("success", "true", "failure", "skipped", False)] - cases += [("success", "true", "success", result, False) - for result in ["failure", "cancelled", "skipped", ""]] - for selection, selected, java, memory, passes in cases: - with self.subTest(selection=selection, selected=selected, java=java, memory=memory): - result = subprocess.run(["bash", "-eo", "pipefail", "-c", script], capture_output=True, - env={**os.environ, "SELECTION_RESULT": selection, "SERVER_SELECTED": selected, - "JAVA_RESULT": java, "MEMORY_RESULT": memory}) - self.assertEqual(passes, result.returncode == 0, result.stderr) - def test_contract_scripts_reach_their_actual_inner_jobs_and_steps(self): workflows = Path(__file__).resolve().parents[1] / "workflows" cases = [("test-stop-hugegraph-store.sh", {"struct"}), diff --git a/.github/workflows/commons-ci.yml b/.github/workflows/commons-ci.yml index d84c937af4..74087946bd 100644 --- a/.github/workflows/commons-ci.yml +++ b/.github/workflows/commons-ci.yml @@ -63,5 +63,6 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: hugegraph-commons/target/jacoco.xml + flags: commons disable_search: true fail_ci_if_error: false diff --git a/.github/workflows/pd-store-ci.yml b/.github/workflows/pd-store-ci.yml index 00adccfe64..ff53b0f5d4 100644 --- a/.github/workflows/pd-store-ci.yml +++ b/.github/workflows/pd-store-ci.yml @@ -310,6 +310,7 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: ${{ env.REPORT_FILE }} + flags: pd disable_search: true fail_ci_if_error: false @@ -512,6 +513,7 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: ${{ env.REPORT_FILE }} + flags: store disable_search: true fail_ci_if_error: false @@ -835,5 +837,6 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: ${{ env.REPORT_DIR }}/*.xml + flags: hstore disable_search: true fail_ci_if_error: false diff --git a/.github/workflows/server-ci.yml b/.github/workflows/server-ci.yml index d27a83774e..f21f1f73a1 100644 --- a/.github/workflows/server-ci.yml +++ b/.github/workflows/server-ci.yml @@ -35,7 +35,6 @@ jobs: selection_result: ${{ steps.select.outcome }} java_result: ${{ steps.java.outcome }} java_versions: ${{ steps.java.outputs.versions }} - legacy_memory_required: ${{ steps.migration.outputs.required }} server: ${{ steps.select.outputs.server }} commons: ${{ steps.select.outputs.commons }} struct: ${{ steps.select.outputs.struct }} @@ -96,18 +95,6 @@ jobs: retention-days: 7 overwrite: true - - name: Check legacy required context - id: migration - if: ${{ !cancelled() && github.event_name == 'pull_request' && steps.checkout.outcome == 'success' }} - env: - GH_TOKEN: ${{ github.token }} - BASE_REF: ${{ github.event.pull_request.base.ref }} - run: | - BASE_REF=$(python3 -c 'import os, urllib.parse; print(urllib.parse.quote(os.environ["BASE_REF"], safe=""))') - REQUIRED=$(gh api "repos/$GITHUB_REPOSITORY/branches/$BASE_REF" \ - --jq '.protection.required_status_checks.contexts // [] | index("Server memory tests") != null') - echo "required=$REQUIRED" >> "$GITHUB_OUTPUT" - - name: Test CI policy and deployment checks if: ${{ !cancelled() && steps.checkout.outcome == 'success' }} run: python3 -m unittest discover -s .github/scripts -p 'test_*.py' @@ -145,27 +132,6 @@ jobs: java-versions: ${{ needs.preflight.outputs.java_versions }} secrets: inherit - legacy-server-memory: - name: Server memory tests - needs: [preflight, build-server] - if: ${{ !cancelled() && needs.preflight.outputs.legacy_memory_required == 'true' }} - runs-on: ubuntu-slim - timeout-minutes: 5 - env: - SELECTION_RESULT: ${{ needs.preflight.outputs.selection_result }} - SERVER_SELECTED: ${{ needs.preflight.outputs.server }} - JAVA_RESULT: ${{ needs.preflight.outputs.java_result }} - MEMORY_RESULT: ${{ needs.build-server.result }} - steps: - - name: Verify the selected Memory result during protection migration - run: | - test "$SELECTION_RESULT" = success - case "$SERVER_SELECTED" in - true) test "$JAVA_RESULT" = success && test "$MEMORY_RESULT" = success ;; - false) test "$MEMORY_RESULT" = skipped ;; - *) exit 1 ;; - esac - commons: needs: preflight if: ${{ !cancelled() && needs.preflight.outputs.selection_result == 'success' && needs.preflight.outputs.java_result == 'success' && needs.preflight.outputs.commons == 'true' }} diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml index f86d0904bb..b4c65de874 100644 --- a/.github/workflows/server-tests.yml +++ b/.github/workflows/server-tests.yml @@ -15,7 +15,7 @@ permissions: jobs: build-server: - name: server_${{ inputs.backend }} (Java ${{ matrix.JAVA_VERSION }}) + name: Server ${{ inputs.backend }} tests (Java ${{ matrix.JAVA_VERSION }}) runs-on: ubuntu-24.04 env: USE_STAGE: 'false' # Whether to include the stage repository. @@ -204,6 +204,7 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: ${{ env.REPORT_DIR }}/*.xml,hugegraph-server/target/site/jacoco/jacoco.xml + flags: server_${{ inputs.backend }} disable_search: true fail_ci_if_error: false diff --git a/docs/ci.md b/docs/ci.md index a6dd9fc1e5..a9f8866296 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -11,11 +11,27 @@ is merged and synchronized by Gitbox; verify live protection then. Failed tests real failed results. Valid selection and Java outputs allow selected tests to run even when the preflight license checks fail. -For migration, preflight keeps the existing `check-license` check name on the same runner. -A temporary `Server memory tests` check verifies the selected Memory result while live protection -still requires that name. It uses one lightweight `ubuntu-slim` runner and repeats no tests. -After Gitbox applies the new configuration, this bridge skips without allocating a runner; -no Infra intervention or change to review protection is needed. +Preflight keeps its real `check-license` name. The temporary `Server memory tests` +protection bridge has been removed after confirming both ASF and org master required +contexts are empty. Actual backend jobs are named `Server memory tests (Java ...)` +and `Server rocksdb tests (Java ...)`; their native checks report real execution. + +## Coverage with selective tests + +Each coverage upload has a stable test-group flag. The [Codecov configuration](../.github/codecov.yml) +enables [carryforward](https://docs.codecov.com/docs/carryforward-flags). When Codecov can +find an earlier flagged report in its recorded parent chain, it preserves that historical +report for unexecuted groups such as Commons, PD/Store and backends. +The PR comment explicitly marks carried-forward data. It is historical coverage, +not evidence that a skipped test ran; native job failures remain failures. + +New flags need a complete initial baseline. The existing weekly full run supplies every +flagged group for that commit. Master pushes remain smoke-only and upload no coverage; +those commits can break Codecov's recorded parent chain. A fresh selective PR based on +such a commit is not guaranteed to inherit the weekly baseline, and its project report +may still be incomplete. Carryforward within an existing reported PR chain does not +prove this works for a fresh PR. Full and selected runs retain explicit report paths and +uploads; no extra collector runner or repeated master coverage tests are added. ## What runs @@ -85,7 +101,7 @@ Plans and selection summaries describe this run; previous results are never reus A new PR head cancels the previous PR run, including its called workflows. Manual and weekly runs remain independent. Each job reports its own result; there are no separate post-test -aggregation runners after the protection migration or end-of-run metadata checks. +aggregation runners or end-of-run metadata checks. Startup contracts run inside RocksDB validation, and Store stop contracts run inside Struct. Docker's static checks, deployment contracts and current-image validation share one runner. diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/test-codecov-upload-config.sh b/hugegraph-server/hugegraph-dist/src/assembly/travis/test-codecov-upload-config.sh index 2aa0782f15..0a5137ad6f 100755 --- a/hugegraph-server/hugegraph-dist/src/assembly/travis/test-codecov-upload-config.sh +++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/test-codecov-upload-config.sh @@ -41,6 +41,8 @@ expected_files = { "build-server": "${{ env.REPORT_DIR }}/*.xml,hugegraph-server/target/site/jacoco/jacoco.xml", }, } +expected_flags = {"build-commons": "commons", "pd": "pd", "store": "store", "hstore": "hstore", + "build-server": "server_${{ inputs.backend }}"} action_pattern = re.compile( r"^(?P\s*)(?P-\s+)?uses:\s*" r"(?:(?P['\"])codecov/codecov-action@" @@ -176,7 +178,7 @@ for workflow_path in workflow_paths: if not files_match(uploads, expected_workflow_files): errors.append(f"{relative_path}: unexpected Codecov files inputs") - for line_number, _, version, inputs in uploads: + for line_number, job, version, inputs in uploads: version_match = version_pattern.match(version) if version_match is None or int(version_match.group("major")) < 5: errors.append( @@ -189,6 +191,8 @@ for workflow_path in workflow_paths: f"{relative_path}:{line_number}: Codecov upload must pass " "secrets.CODECOV_TOKEN for trusted runs" ) + if inputs.get("flags") != expected_flags.get(job): + errors.append(f"{relative_path}:{line_number}: unexpected Codecov flag for {job}") if inputs.get("disable_search") != "true": errors.append( f"{relative_path}:{line_number}: Codecov upload must set "