mirror of
https://github.com/rustfs/rustfs.git
synced 2026-10-31 16:22:06 +00:00
4a63e53161
* test(validation): add pinned auto-testing manual lane * Install pinned ILM client for canonical validation lane * Prepare Python client for pool validation cases * Install validation client for replication cases * test(validation): provide the Python client for Heal cases * test(validation): build the candidate-bound Heal inspector artifact * test(validation): expose tool artifacts through the existing manual lane * test(validation): verify pinned Heal tools before fleet execution * test(validation): verify Heal tools against released shard captures * ci: audit retained validation environments before finalization * test(validation): add optional native Heal regression tooling * test(validation): route native tools through the existing driver * Run validation tool resolution on hosted Linux without acquiring the fleet lock * test(validation): bind C07 to pinned native authority evidence * test(validation): build optional C10 fixture codec on hosted Linux * test(ci): bind C10 execution to the verified shared codec * feat(ci): expose read-only validation fleet inventory * docs(ci): describe supported validation recovery * test(ci): add isolated manager native validation builds * test(ci): expose manager regressions through tools-only dispatch * ci(validation): consume pinned manager native prerequisites * fix(heal): preserve typed bucket errors for bounded retries * fix(heal): preserve typed errors and SSE-C response headers * ci(validation): publish isolated immutable candidate packages * test(validation): enforce private candidate manifest schema * test(validation): verify isolated package publication failures * ci(validation): dispatch isolated packages through the driver * fix(heal): deeply verify read repair payload failures * test(ecstore): verify incarnation fence at repair commit * ci(validation): verify C11 native storage evidence * fix(ci): isolate validation package publication credentials * test(ci): archive scoped F07 directory fsync evidence * fix(ecstore): retain typed quorum errors for missing parts * chore(ecstore): shrink typed-error ratchet baseline * fix(ecstore): retain below-quorum data during no-remove heal * fix(ci): allow recovery of completed cancelled validation runs * fix(heal): retain exhausted admin batch repair receipts * fix(observability): retain typed object error diagnostics * fix(s3): map typed RPC unavailability to service refusal * fix(filemeta): classify supported inline framing damage as corrupt * test(ecstore): exercise heal during committed overwrite cleanup * ci(validation): admit source-bound G01 native evidence before fleet execution * test(ecstore): fence version races and bind cleanup slots * ci(validation): require complete race native runtime preflight * test(ecstore): fence marker and batch deletes during heal * ci(validation): require G04 native and runtime admission * test(ecstore): fence multipart continue complete and abort during heal * test(ecstore): cover default heal owners and copy metadata races * ci(validation): admit source-bound owner and copy race proofs * test(scanner): assert typed corruption after metadata truncation * fix(ci): require complete native admission for multipart races * test(validation): wire I05 queued-successor native prerequisites * fix(scanner): bind object heals to the scanning disk scope * test(scanner): reuse storage boundary for scope regression * style: format RPC digest precedence assertion * fix(heal): query automatic tasks on their owning node * test(admin): reuse error facade in heal query regression * fix(heal): retain cancellation after successful bucket storage I/O * fix(ci): retain validation evidence outside runner temp * fix(heal): retain resolved object identity on terminal failures * test(scanner): adapt scope regression to admission receipts * ci(validation): inspect shared runner without fleet access * ci(validation): prepare Python before creating client environments * ci(validation): isolate each client virtual environment * ci(validation): retain interrupted evidence without fleet recovery * ci(validation): bind recovery to retained runner evidence * ci(validation): wire persistence and lock source plans * fix(validation): align read-only dispatch defaults --------- Co-authored-by: Chris <anzhengchao@gmail.com>
63 lines
3.0 KiB
Python
63 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Retain self-hosted validation evidence outside Actions' temporary cleanup."""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import stat
|
|
import sys
|
|
|
|
MINIMUM_FREE_BYTES = 10 * 1024**3
|
|
MINIMUM_FREE_INODES = 50000
|
|
|
|
|
|
def initialize(environ=None):
|
|
env = os.environ if environ is None else environ
|
|
run, attempt = env['GITHUB_RUN_ID'], env['GITHUB_RUN_ATTEMPT']
|
|
if not all(re.fullmatch(r'[1-9][0-9]*', value) for value in (run, attempt)):
|
|
raise ValueError('Evidence requires numeric workflow run and attempt identities')
|
|
tools_only = env['VALIDATION_TOOLS_ONLY']
|
|
if tools_only not in {'true', 'false'}:
|
|
raise ValueError('Evidence requires an explicit tools-only selection')
|
|
temporary = Path(env['RUNNER_TEMP'])
|
|
if not temporary.is_absolute() or temporary.resolve(strict=True) != temporary or not temporary.is_dir():
|
|
raise ValueError('Runner temporary directory must be an existing canonical absolute directory')
|
|
parent = temporary if tools_only == 'true' else temporary.parent / 'rustfs-validation-evidence'
|
|
if tools_only == 'false':
|
|
parent.mkdir(mode=0o700, exist_ok=True)
|
|
info = parent.lstat()
|
|
if not stat.S_ISDIR(info.st_mode) or info.st_uid != os.getuid() or stat.S_IMODE(info.st_mode) != 0o700:
|
|
raise ValueError('Persistent evidence parent must be a private runner-owned directory')
|
|
root = parent / f'rustfs-validation-{run}-{attempt}'
|
|
root.mkdir(mode=0o700)
|
|
observations = []
|
|
for path in dict.fromkeys((temporary, parent)):
|
|
usage = os.statvfs(path)
|
|
observations.append({'path': str(path), 'availableBytes': usage.f_bavail * usage.f_frsize,
|
|
'availableInodes': usage.f_favail, 'minimumFreeBytes': MINIMUM_FREE_BYTES,
|
|
'minimumFreeInodes': MINIMUM_FREE_INODES})
|
|
ready = all(item['availableBytes'] >= MINIMUM_FREE_BYTES and item['availableInodes'] >= MINIMUM_FREE_INODES
|
|
for item in observations)
|
|
report = {'schemaVersion': 1, 'runId': run, 'runAttempt': attempt, 'evidenceRoot': str(root),
|
|
'persistentOutsideRunnerTemp': tools_only == 'false', 'storage': observations, 'ready': ready,
|
|
'automaticEvidenceDeletion': False, 'canonicalPassClaimed': False}
|
|
with (root / 'runner-storage-preflight.json').open('x') as stream:
|
|
json.dump(report, stream, indent=2)
|
|
stream.write(chr(10))
|
|
with Path(env['GITHUB_ENV']).open('a') as stream:
|
|
if any(character in str(root) for character in (chr(10), chr(13))):
|
|
raise ValueError('Evidence path cannot contain environment-file delimiters')
|
|
stream.write('VALIDATION_ROOT=' + str(root) + chr(10))
|
|
print(json.dumps(report, sort_keys=True))
|
|
if not ready:
|
|
raise ValueError('Validation requires at least 10 GiB and 50000 free inodes on runner storage')
|
|
return root
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
initialize()
|
|
except (OSError, ValueError, KeyError) as error:
|
|
print(f'Validation evidence initialization failed: {error}', file=sys.stderr)
|
|
sys.exit(1)
|