Files
warp_engine/spec/services/storage_serving_spec.rb
T
mr.zero 03a51a5b30 warp_engine 0.2.0: pluggable storage adapter and publish notifications
Two seams the hosts needed, both backward compatible.

Storage: artifacts are served through WarpEngine::Storage.adapter instead of
raw filesystem calls. The default :local adapter keeps the previous behaviour
byte for byte, including the path traversal guard. A host can now set
config.storage_adapter to any object answering file?/directory?/locate and
serve builds from an object store - FileService and /api/download both honour
a Location.redirect, so a signing adapter turns them into redirects.
DownloadService#create still returns an absolute path (nil when missing) for
existing callers; #locate is the new entry point that can also return a
redirect. Ingestion (upload, extraction, file manager) stays local for now.

Publish: PublishService emits ActiveSupport::Notifications
("warp_engine.publish") with platform/name/version/software/release, so hosts
can react to a new build without hanging callbacks on the models.
WarpEngine.instruments_publish? lets a host feature-detect and keep its
fallback for older engine versions.
2026-08-10 11:16:17 +02:00

99 lines
3.4 KiB
Ruby

require "rails_helper"
require "tmpdir"
# The serving side (FileService, DownloadService) goes through the storage
# adapter. With :local nothing changes; with a custom adapter the same call
# can hand back a redirect instead of a file.
RSpec.describe "Serving through the storage adapter" do
let(:tmpdir) { Dir.mktmpdir }
# Minimal adapter answering the documented contract.
let(:signing_adapter) do
Class.new do
def file?(_relative) = true
def directory?(_relative) = false
def locate(relative, filename: nil, expires_in: nil)
WarpEngine::Storage::Location.redirect("https://cdn.example/#{relative}?signed=1")
end
end.new
end
before do
allow(WarpEngine.config).to receive(:file_container_path).and_return(tmpdir)
WarpEngine::Storage.reset!
File.write(File.join(tmpdir, "game-1.0.zip"), "zip")
end
after { FileUtils.rm_rf(tmpdir) }
describe WarpEngine::FileService do
it "serves a local file (default adapter)" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(:local)
result = described_class.new.show(WarpEngine::FileShowInputDto.new(path: "game-1.0.zip"))
expect(result.type).to eq(:file)
expect(result.path).to eq(File.join(tmpdir, "game-1.0.zip"))
end
it "redirects a directory to its index.html" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(:local)
FileUtils.mkdir_p(File.join(tmpdir, "game-1.0"))
File.write(File.join(tmpdir, "game-1.0", "index.html"), "<h1>hi</h1>")
result = described_class.new.show(WarpEngine::FileShowInputDto.new(path: "game-1.0"))
expect(result.type).to eq(:redirect)
expect(result.url).to eq("/file/game-1.0/index.html")
end
it "hands back the adapter's redirect when storage is remote" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(signing_adapter)
result = described_class.new.show(WarpEngine::FileShowInputDto.new(path: "game-1.0.zip"))
expect(result.type).to eq(:redirect)
expect(result.url).to eq("https://cdn.example/game-1.0.zip?signed=1")
end
it "reports a missing file" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(:local)
result = described_class.new.show(WarpEngine::FileShowInputDto.new(path: "nope.zip"))
expect(result.type).to eq(:not_found)
end
end
describe WarpEngine::DownloadService do
let(:args) { { ip: "127.0.0.1", user_agent: "rspec", referer: nil } }
it "keeps returning an absolute path from #create (backward compatible)" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(:local)
path = described_class.new.create(path: "game-1.0.zip", **args)
expect(path).to eq(File.join(tmpdir, "game-1.0.zip"))
expect(WarpEngine::Download.count).to eq(1)
end
it "returns nil from #create for a missing file" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(:local)
expect(described_class.new.create(path: "nope.zip", **args)).to be_nil
expect(WarpEngine::Download.count).to eq(0)
end
it "returns a location from #locate and logs the download" do
allow(WarpEngine.config).to receive(:storage_adapter).and_return(signing_adapter)
location = described_class.new.locate(path: "game-1.0.zip", **args)
expect(location).to be_redirect
expect(location.url).to include("signed=1")
expect(WarpEngine::Download.count).to eq(1)
end
end
end