From f29455b32b986e410fbfbfbd9c76665437075a18 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Wed, 15 Jul 2026 15:46:31 +0800 Subject: [PATCH] ci: add e2e-full merge-gate job running the full single-node e2e suite (#4847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: add e2e-full merge-gate job (single-node full e2e via nextest) Adds the [profile.e2e-full] nextest profile and a matching e2e-full job in ci.yml (push main + merge_group + workflow_dispatch) that runs the never-automated user-visible e2e suites (KMS, object_lock, multipart_auth, quota, checksum, encryption, security-boundary, ...) the fast PR e2e-smoke subset skips. The filter is the whole e2e_test crate minus the sets other lanes own: protocols:: (ci-6/ci-7), the 6 RustFSTestClusterEnvironment cluster suites (ci-7 nightly), replication_extension_test (repl-1's smoke + repl-nightly lanes), and #[ignore]d tests (ci-13). The 4-disk reliability tests are serialized, mirroring the ci profile. Reuses the downloaded debug binary and uploads junit. backlog#1149 ci-5. * ci: exclude characterized known-failures from e2e-full with tracked issues First-ever automated run of the full suite (dispatch 29381309848: 341 ran / 32 failed / 460s) surfaced five real product-bug families, each now tracked: rustfs#4842 (extract 500s, mtime=0 OffsetDateTime), rustfs#4843 (path-limit vs ignore-errors), rustfs#4844 (anonymous POST SSE-S3 500), rustfs#4845 (object-lock POST + list metadata=true 403), rustfs#4846 (lock quorum misclassified as timeout under load). Deterministic failures cannot be retried away, so each family is excluded with its OPEN issue cited and the fixing PR contract to delete the exclusion — passing negative-path siblings stay in as regression guards. --- .config/nextest.toml | 76 ++++++++++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 53 ++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/.config/nextest.toml b/.config/nextest.toml index 027d52e21..c901e9480 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -217,3 +217,79 @@ fail-fast = false # Emitted to target/nextest/e2e-repl-nightly/junit.xml; uploaded by the nightly # workflow as the failure-triage artifact. path = "junit.xml" + +# --------------------------------------------------------------------------- +# e2e-full profile — merge-gate full single-node e2e lane (backlog#1149 ci-5) +# --------------------------------------------------------------------------- +# The merge gate (ci.yml `e2e-full` job: push main + merge_group + +# workflow_dispatch). Runs the never-automated user-visible suites — KMS (40), +# object_lock (33), multipart_auth (109), quota, checksum, encryption, +# security-boundary, ... — that the fast PR `e2e-smoke` subset deliberately +# skips. Budget <= 45 min; authority for the suite count is `cargo nextest list +# --profile e2e-full` (see docs/testing/e2e-suite-inventory.md). +# +# The filter is "the whole e2e_test crate MINUS the sets owned by other lanes": +# * protocols:: — FTPS/SFTP/WebDAV, still pinned to --test-threads=1 by fixed +# ports; they join a scheduled lane once ci-6 randomises the ports (ci-7). +# * the 6 cluster suites that spin up a RustFSTestClusterEnvironment +# (cluster_concurrency, stale_multipart_cleanup_cluster, +# namespace_lock_quorum, heal_erasure_disk_rebuild, admin_timeout_regression, +# object_lambda) — too heavy for the merge budget; they run in ci-7's +# nightly 4-node lane. +# * replication_extension_test — repl-1 already splits it into the PR +# `e2e-smoke` (20 fast) and `e2e-repl-nightly` (20 slow) lanes and reserves +# it for those, so e2e-full does not double-run it. +# * #[ignore]d tests — nextest skips them by default (no --run-ignored); the +# manual-localhost:9000 reliant/policy tests are ci-13's migration. +# +# Each e2e test spawns its own single-node rustfs server on a random port with +# an isolated temp dir (crates/e2e_test/src/common.rs), so the set is +# parallel-safe — the same property e2e-smoke relies on. The exception is the +# 4-disk reliability / degraded-read fault-injection tests, serialized below +# (identical to the ci profile) so several 4-disk servers never run at once. +# KNOWN-FAILURE EXCLUSIONS (characterization run 29381309848, 2026-07-15: +# 341 ran / 32 failed on the suites' first automated run ever). Deterministic +# product failures cannot be quarantined away with retries, so each family is +# excluded here with its tracking issue, under the same discipline as the +# ci-profile quarantine (docs/testing/README.md): every entry MUST cite one +# OPEN issue, and the fixing PR MUST delete the exclusion. The passing +# negative-path siblings of each family stay in as regression guards. +# * rustfs#4842 — extract/snowball expand pipeline 500s (mtime=0 +# OffsetDateTime deserialization + same-path failures). +# * rustfs#4843 — over-limit archive entry paths hard-reject the whole +# archive even under ignore-errors semantics. +# * rustfs#4844 — anonymous POST-object with SSE-S3 / bucket-default SSE +# returns 500. +# * rustfs#4845 — 403 on allowed anonymous POST object-lock fields and on +# the list metadata=true extension. +# * rustfs#4846 — distributed-lock quorum tests misclassify as timeout +# under parallel load (multi-node in-process clusters; natural home is +# ci-7's nightly cluster lane). +[profile.e2e-full] +default-filter = """ + package(e2e_test) + & !test(/^protocols::/) + & !test(/^(admin_timeout_regression_test|cluster_concurrency_test|heal_erasure_disk_rebuild_test|namespace_lock_quorum_test|object_lambda_test|stale_multipart_cleanup_cluster_test)::/) + & !test(/^replication_extension_test::/) + & !test(/^multipart_auth_test::test_signed_put_object_extract_(accepts_compat_header|expands_tar_entries_with_prefix_headers|expands_tar_gz_archive|expands_tbz2_archive|expands_tgz_archive|expands_txz_archive|expands_tzst_archive|normalizes_prefix_header_value|preserves_directory_markers_by_default|preserves_object_lock_legal_hold|preserves_object_lock_retention|preserves_pax_metadata_and_version_id|preserves_request_metadata_on_extracted_objects|preserves_sse_c|preserves_sse_s3_and_redirect|preserves_storage_class|uses_bucket_default_sse_s3)$/) + & !test(/^snowball_auto_extract_test::tests::snowball_auto_extract_(prefers_exact_minio_prefix_over_suffix_fallback|supports_minio_prefix_and_directory_markers)$/) + & !test(/^multipart_auth_test::test_signed_put_object_extract_skips_invalid_entry_when_ignore_errors_enabled$/) + & !test(/^snowball_auto_extract_test::tests::snowball_auto_extract_(ignores_invalid_entries_when_requested|supports_standard_headers_with_combined_extract_options)$/) + & !test(/^multipart_auth_test::test_anonymous_post_object_(accepts_sse_s3|rejects_sse_s3_missing_from_policy_conditions|uses_bucket_default_sse_kms|uses_bucket_default_sse_s3)$/) + & !test(/^multipart_auth_test::test_anonymous_post_object_(accepts_object_lock_legal_hold_field|accepts_object_lock_retention_fields)$/) + & !test(/^list_object(s_v2|_versions)_metadata_extension_test::/) + & !test(/^reliant::lock::test_distributed_lock_(2_nodes_grpc_read_survives_failed_node|4_nodes_grpc_read_write_quorum_split_with_two_failed_nodes)$/) +""" +fail-fast = false + +[profile.e2e-full.junit] +# Emitted to target/nextest/e2e-full/junit.xml; uploaded by the e2e-full job. +path = "junit.xml" + +# Serialize the 4-disk reliability / degraded-read e2e tests under e2e-full too +# (see the e2e-reliability test-group note near the top of this file). Not a +# quarantine: no retries, just single-threaded so several 4-disk servers never +# run concurrently. +[[profile.e2e-full.overrides]] +filter = 'package(e2e_test) & test(/^(reliability_disk_fault|degraded_read_eof_regression)_test::/)' +test-group = 'e2e-reliability' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b998266ab..b9d7f52d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -478,6 +478,59 @@ jobs: path: ${{ runner.temp }}/rustfs-e2e-*/rustfs.log retention-days: 3 + e2e-full: + name: End-to-End Tests (full merge gate) + # Merge gate only (backlog#1149 ci-5): the never-automated user-visible + # suites — KMS, object_lock, multipart_auth, quota, checksum, encryption, + # security-boundary, ... — via the e2e-full nextest profile. Too heavy for + # every PR, so it is gated to main pushes, the merge queue, and manual + # dispatch. protocols / the 6 cluster suites / replication / #[ignore] are + # owned by other lanes (see .config/nextest.toml profile.e2e-full). + if: >- + github.event_name == 'workflow_dispatch' || + github.event_name == 'merge_group' || + (github.event_name == 'push' && github.ref == 'refs/heads/main') + needs: [ build-rustfs-debug-binary ] + runs-on: sm-standard-2 + timeout-minutes: 55 + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + + - name: Setup Rust environment + uses: ./.github/actions/setup + with: + rust-version: stable + cache-shared-key: ci-e2e + github-token: ${{ secrets.GITHUB_TOKEN }} + cache-save-if: ${{ github.ref == 'refs/heads/main' }} + + # Download after the cache restore so the freshly built binary from the + # build job always wins over anything restored into target/debug. + - name: Download debug binary + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 + with: + name: rustfs-debug-binary + path: target/debug + + - name: Make binary executable + run: chmod +x ./target/debug/rustfs + + # Full single-node e2e lane (backlog#1149 ci-5). The e2e-full + # default-filter in .config/nextest.toml is the single wiring mechanism — + # extend that filter, never add ad-hoc e2e jobs here. Reuses the downloaded + # debug binary; each test spawns its own rustfs server on a random port. + - name: Run e2e full suite + run: cargo nextest run --profile e2e-full -p e2e_test + + - name: Upload junit + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: e2e-full-junit-${{ github.run_number }} + path: target/nextest/e2e-full/junit.xml + retention-days: 7 + e2e-tests-rio-v2: name: End-to-End Tests (rio-v2) needs: [ build-rustfs-debug-binary-rio-v2 ]