Class: Perfgate::Storage::Filesystem

Inherits:
Adapter
  • Object
show all
Defined in:
lib/perfgate/storage/filesystem.rb

Overview

Default MVP storage adapter (spec section 18.2). Layout:

<root>/runs/<run-id>/manifest.json
<root>/runs/<run-id>/run.json
<root>/runs/<run-id>/checksums.json
<root>/comparisons/<comparison-id>.json

Instance Method Summary collapse

Constructor Details

#initialize(root:) ⇒ Filesystem

Returns a new instance of Filesystem.



19
20
21
22
# File 'lib/perfgate/storage/filesystem.rb', line 19

def initialize(root:)
  super()
  @root = root
end

Instance Method Details

#export_archive(run_id, into: @root) ⇒ Object

Packs a run bundle's directory into the portable baseline-run-.tar.gz format (spec 18.2), for manual transfer or storage outside the filesystem adapter's own root (e.g. as a CI artifact). Returns the archive's path.



69
70
71
72
73
74
75
76
77
# File 'lib/perfgate/storage/filesystem.rb', line 69

def export_archive(run_id, into: @root)
  dir = run_directory(run_id)
  raise Perfgate::ResultBundleError, "no run bundle found at #{dir}" unless File.directory?(dir)

  FileUtils.mkdir_p(into)
  archive_path = File.join(into, "baseline-run-#{run_id}.tar.gz")
  Archive.write(archive_path, dir, run_id)
  archive_path
end

#import_archive(archive_path, into: @root) ⇒ Object

Unpacks a baseline-run-.tar.gz archive into into, rejecting any entry that would escape the destination directory (spec 22: reject path traversal in archives). Returns the extracted run directory path.



83
84
85
86
# File 'lib/perfgate/storage/filesystem.rb', line 83

def import_archive(archive_path, into: @root)
  Archive.extract(archive_path, into)
  File.join(into, "runs", File.basename(archive_path, ".tar.gz").sub(/^baseline-run-/, ""))
end

#list_runs(filters = {}) ⇒ Object

rubocop:disable Lint/UnusedMethodArgument



47
48
49
50
51
52
# File 'lib/perfgate/storage/filesystem.rb', line 47

def list_runs(filters = {}) # rubocop:disable Lint/UnusedMethodArgument
  base = File.join(@root, "runs")
  return [] unless File.directory?(base)

  Dir.children(base).sort
end

#load_run(reference) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/perfgate/storage/filesystem.rb', line 37

def load_run(reference)
  dir = File.directory?(reference) ? reference : run_directory(reference)
  run_json_path = File.join(dir, "run.json")

  raise Perfgate::ResultBundleError, "no run result found at #{run_json_path}" unless File.exist?(run_json_path)

  verify_checksum!(dir, run_json_path)
  JSON.parse(File.read(run_json_path))
end

#save_comparison(comparison_result) ⇒ Object



54
55
56
57
58
59
60
61
62
63
# File 'lib/perfgate/storage/filesystem.rb', line 54

def save_comparison(comparison_result)
  dir = File.join(@root, "comparisons")
  FileUtils.mkdir_p(dir)

  comparison_id = SecureRandom.uuid
  path = File.join(dir, "#{comparison_id}.json")
  File.write(path, JSON.pretty_generate(comparison_result))

  path
end

#save_run(run_result) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/perfgate/storage/filesystem.rb', line 24

def save_run(run_result)
  run_id = run_result.fetch("run_id")
  dir = run_directory(run_id)
  FileUtils.mkdir_p(dir)

  run_json = JSON.pretty_generate(run_result)
  File.write(File.join(dir, "run.json"), run_json)
  File.write(File.join(dir, "manifest.json"), JSON.pretty_generate(manifest_for(run_result)))
  File.write(File.join(dir, "checksums.json"), JSON.pretty_generate(checksums_for(run_json)))

  dir
end