ops(web): bound immutable release history
This commit is contained in:
53
vehicle-data-platform/deploy/prune-release-history.py
Executable file
53
vehicle-data-platform/deploy/prune-release-history.py
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Keep a bounded number of immutable platform releases.')
|
||||
parser.add_argument('root')
|
||||
parser.add_argument('limit', type=int)
|
||||
parser.add_argument('protected', nargs='*')
|
||||
args = parser.parse_args()
|
||||
|
||||
root = Path(args.root).resolve()
|
||||
releases = (root / 'releases').resolve()
|
||||
if root == Path('/') or releases.parent != root or not releases.is_dir():
|
||||
raise SystemExit('unsafe or missing release root: {}'.format(releases))
|
||||
if args.limit < 2:
|
||||
raise SystemExit('release history limit must be at least 2')
|
||||
|
||||
protected = set()
|
||||
for value in args.protected:
|
||||
path = Path(value).resolve()
|
||||
if path.parent != releases or not path.is_dir():
|
||||
raise SystemExit('protected release is outside the release root: {}'.format(path))
|
||||
protected.add(path)
|
||||
|
||||
candidates = [path.resolve() for path in releases.iterdir() if path.is_dir() and not path.is_symlink()]
|
||||
candidates.sort(key=lambda path: path.stat().st_mtime, reverse=True)
|
||||
keep = set(protected)
|
||||
for path in candidates:
|
||||
if len(keep) >= args.limit:
|
||||
break
|
||||
keep.add(path)
|
||||
|
||||
removed = 0
|
||||
for path in candidates:
|
||||
if path in keep:
|
||||
continue
|
||||
if path.parent != releases:
|
||||
raise SystemExit('refusing to remove a nested or escaped path: {}'.format(path))
|
||||
shutil.rmtree(str(path))
|
||||
removed += 1
|
||||
|
||||
print('release_prune=ok before={} kept={} removed={}'.format(len(candidates), len(keep), removed))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user