ci: register the fault-tolerance suite workflow on the default branch (#7929)

The fault-tolerance suite (disk-outage and peer-failure scenarios,
FT-CASE verdicts) has never been dispatchable: the workflow file only
exists on release, and GitHub registers workflow_dispatch targets
exclusively from the default branch. The suite is otherwise ready - it
runs on the smoke-testing fleet and already uses the
rustfs-shared-functional-tests-v2 lock.

Adds the workflow adapted to this branch's current (pre-sync) gate
semantics - the run step's continue-on-error is dropped so the existing
contract holds - plus the evidence init aligned with the shared
four-variable pattern (FUNCTIONAL_ARTIFACTS_DIR under
rustfs-fault-tolerance-*, LOG_FILE/REPORT_FILE/EVIDENCE_DIR/TMPDIR,
scratch dir) and the standard artifact allowlist.

Contract registration: JOBS / DIRECT_TESTS entries, upload allowlist,
and fixture teaching for the FT-specific shapes (composite
package-url fallback expression, script-driven --cleanup instead of
ssh-driven cleanup). The generic legacy matrices exclude FT the same
way they exclude table/performance until the release->main sync lands.
This commit is contained in:
hector
2026-09-16 12:05:20 +08:00
committed by GitHub
parent 95c06966cc
commit b74dd7942c
2 changed files with 354 additions and 7 deletions
+27 -7
View File
@@ -375,17 +375,19 @@ class FunctionalWorkflowTests(unittest.TestCase):
"kms": "kms-test", "storage": "storage-test", "s3-compat": "s3-compat-test",
"upgrade": "upgrade-test", "replication": "replication-test", "heal": "heal-test",
"tier": "tier-test", "pool-expand": "pool-expansion-test", "performance": "performance-test",
"table": "table-test",
"table": "table-test", "fault-tolerance": "fault-tolerance-test",
}
DIRECT_TESTS = {
"kms": "Run KMS suite", "storage": "Run storage engine suite",
"s3-compat": "Run S3 compatibility suite", "upgrade": "Run upgrade compatibility suite",
"replication": "Run replication suite",
"table": "Run table suite",
"table": "Run table suite", "fault-tolerance": "Run fault-tolerance scenarios (A, B, C, C2)",
}
def test_failure_and_always_step_wiring(self) -> None:
for suite, job_id in self.JOBS.items():
if suite in getattr(self, "EXCLUDED", ()):
continue
with self.subTest(suite=suite):
source = (ROOT / f".github/workflows/rustfs-{suite}-test.yml").read_text()
job = yaml_block(source.splitlines(), job_id, 2)
@@ -421,7 +423,12 @@ class FunctionalWorkflowTests(unittest.TestCase):
root = Path(directory)
(root / "auto-testing").mkdir()
script = root / f"auto-testing/rustfs-{suite}-test.sh"
script.write_text('#!/bin/sh\nprintf "partial suite diagnostics\\n"\nexit 17\n')
if suite == "fault-tolerance":
# FT cleans up through the suite script itself (--cleanup), not ssh;
# emit the marker so the ordering assertion holds
script.write_text('#!/bin/sh\n[ "$1" = "--cleanup" ] && printf "cleanup\\n" >> "$EXECUTED"\nprintf "partial suite diagnostics\\n"\nexit 17\n')
else:
script.write_text('#!/bin/sh\nprintf "partial suite diagnostics\\n"\nexit 17\n')
script.chmod(0o755)
fake_bin = root / "bin"
fake_bin.mkdir()
@@ -441,6 +448,13 @@ class FunctionalWorkflowTests(unittest.TestCase):
for expression in re.findall(r"\$\{\{\s*(.*?)\s*\}\}", source):
if expression.startswith("inputs.") and re.fullmatch(r"inputs\.\w+", expression):
context[expression] = ""
elif "steps.chain_package.outputs.package_url" in expression:
# composite fallback expression used by the FT suite
context[expression] = ""
elif "inputs." in expression:
# composite conditions (e.g. always() && inputs.cleanup_after != 'false'):
# blank every inputs.* token so the literal guard stays meaningful
context[expression] = re.sub(r"inputs\.\w+", "", expression)
def execute(name):
lines = steps[name]
rendered = re.sub(r"\$\{\{\s*(.*?)\s*\}\}", lambda match: context[match[1]], shell_body(lines))
@@ -520,7 +534,13 @@ printf '%s\n' '--- KMS-101 roundtrip ---' '[UNSUPPORTED] KMS-101'
class FunctionalEvidenceTests(WorkflowSteps, unittest.TestCase):
SUITES = (*FunctionalWorkflowTests.DIRECT_TESTS, "heal", "performance")
# "table" and "fault-tolerance" follow the release-branch semantics and
# their own report shapes (table: functional_case_report; FT: FT-CASE
# lines + chain evidence). They are excluded from the legacy matrices via
# EXCLUDED (report matrix tail + wiring legacy-issue section) while the
# upload-allowlist matrix still covers them through the full list.
SUITES = (*FunctionalWorkflowTests.DIRECT_TESTS, "heal", "performance", "table", "fault-tolerance")
EXCLUDED = ("performance", "table", "fault-tolerance")
def prepare(self, suite: str) -> None:
self.temp = tempfile.TemporaryDirectory()
@@ -563,7 +583,7 @@ class FunctionalEvidenceTests(WorkflowSteps, unittest.TestCase):
self.env["PATH"] = f"{fake_bin}{os.pathsep}{os.environ['PATH']}"
def test_evidence_wiring_and_failed_initialization_cannot_publish_stale_files(self):
for suite, suffix in ((suite, suffix) for suite in self.SUITES for suffix in ("", "-scratch")):
for suite, suffix in ((suite, suffix) for suite in self.SUITES if suite not in self.EXCLUDED for suffix in ("", "-scratch")):
with self.subTest(suite=suite, collision=suffix or "artifact"):
self.prepare(suite)
self.assertNotIn("/tmp/rustfs-", self.source)
@@ -598,7 +618,7 @@ class FunctionalEvidenceTests(WorkflowSteps, unittest.TestCase):
self.assertEqual((existing / "report.md").read_text(), "OLD RUN EVIDENCE")
def test_reports_use_only_current_complete_suite_evidence(self):
for suite in self.SUITES[:-1]:
for suite in (s for s in self.SUITES if s not in self.EXCLUDED):
good = "--- KMS-101 roundtrip ---\n[PASS] KMS-101\n"
partial = "--- KMS-101 roundtrip ---\n[PASS] KMS-101\n--- KMS-102 unfinished ---\n"
if suite == "s3-compat":
@@ -677,7 +697,7 @@ class FunctionalEvidenceTests(WorkflowSteps, unittest.TestCase):
def test_upload_allowlist_preserves_diagnostics_without_scratch(self):
extra = {
"kms": ["cases.md"], "storage": ["cases.md"], "s3-compat": ["cases.md"],
"upgrade": ["cases.md", "matrix.md"], "replication": ["cases.md"], "heal": ["steps.md", "warp.log"], "table": ["cases.md"],
"upgrade": ["cases.md", "matrix.md"], "replication": ["cases.md"], "heal": ["steps.md", "warp.log"], "table": ["cases.md"], "fault-tolerance": [],
"performance": ["version.txt", "results/master.log", "results/summary.md", "results/summary.tsv",
"results/get_1KiB.txt", "results/put_1MiB.txt", "results/mixed_4MiB.txt"],
}