DIGEST_KEY
DIGEST_KEY = 'strata.code.digest'
State key holding the digest of the site's own code at the last pass.
Captures the code a site owns, and the reference that stands in for the code it does not.
Runs on cron rather than on a hook, because code changes when someone deploys and a deploy is not an event Drupal dispatches. A pass compares the site's own code against the digest recorded last time and does nothing when nothing moved, so the ordinary case costs one walk and no writes.
Three things are captured and they are not the same kind of thing:
settings.php, redacted. The configuration a restore needs, without the credentials that
must not leave the server.vendor/. 41 KiB of composer.lock against
18 MB of compressed core bytes, and it reproduces the tree exactly rather than approximately.And one thing is watched rather than captured: the vendor tree's fingerprint. When it moves without the lock moving, a dependency was patched by hand, the lock no longer reproduces the tree, and the drifted files are captured as bytes. That check is the only thing standing between the 440x saving and a backup silently missing a patch.
$scanner : \Drupal\strata\Code\CodeScanner
$vendor : \Drupal\strata\Code\VendorDriftDetector
$journal : \Drupal\strata\Journal\JournalInterface
$scope : \Drupal\strata\Capture\CaptureScope
$tripwires : \Drupal\strata\Health\TripwireRegistry
$ledger : \Drupal\strata\Health\HealthLedgerInterface
__construct(\Drupal\strata\Code\CodeScanner $scanner, \Drupal\strata\Code\VendorDriftDetector $vendor, \Drupal\strata\Journal\JournalInterface $journal, \Drupal\strata\Capture\CaptureScope $scope, \Drupal\Core\State\StateInterface $state, \Drupal\strata\Health\TripwireRegistry $tripwires, \Drupal\strata\Health\HealthLedgerInterface $ledger, \Psr\Log\LoggerInterface $logger) : mixed
Constructs a capture.
| \Drupal\strata\Code\CodeScanner | $scanner | Walks the site's own code. |
| \Drupal\strata\Code\VendorDriftDetector | $vendor | Watches the dependency tree. |
| \Drupal\strata\Journal\JournalInterface | $journal | Where operations are appended. |
| \Drupal\strata\Capture\CaptureScope | $scope | Decides whether the code realm is captured. |
| \Drupal\Core\State\StateInterface | $state | Remembers what the last pass saw. |
| \Drupal\strata\Health\TripwireRegistry | $tripwires | Runs the drift check. |
| \Drupal\strata\Health\HealthLedgerInterface | $ledger | Where drift is recorded. |
| \Psr\Log\LoggerInterface | $logger | Records what a pass did. |
acceptVendorState() : void
Records the vendor tree as it stands, so later passes have something to compare against.
Called after a deploy, and by the first pass on a site. Taking the fingerprint and the lock digest together is what makes "the tree moved but the lock did not" a meaningful statement.
captureLockfiles() : int
Appends one operation per lockfile.
The lock's own bytes are stored, not just its digest. A digest identifies a lock; only the
contents reproduce a tree, and reproducing the tree is the entire reason vendor/ is not
stored.
How many lockfiles were captured.
captureDrifted(array{drifted: bool, reason: string, lockChanged: bool, fingerprint: string} $drift) : int
Appends the files a patched dependency changed.
Only the drifted files, which is what makes a patched dependency cost the patch rather than the tree.
| array{drifted: bool, reason: string, lockChanged: bool, fingerprint: string} | $drift | What the comparison found. |
How many files were captured.