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.
This commit is contained in:
2026-08-10 11:16:17 +02:00
parent 2a94fc785f
commit 03a51a5b30
13 changed files with 442 additions and 33 deletions
@@ -8,23 +8,26 @@ module WarpEngine
api :GET, "/api/download", "Download a file by path"
param :path, String, required: true, desc: "File path to download"
returns code: 200, desc: "File binary data"
returns code: 302, desc: "Redirect to the storage location (non-local storage adapter)"
error code: 400, desc: "Path is blank"
error code: 404, desc: "File not found"
def show
path = params[:path]
return render(json: { error: "Path is required" }, status: :bad_request) if path.blank?
full_path = WarpEngine::DownloadService.new.create(
location = WarpEngine::DownloadService.new.locate(
path: path,
ip: request.remote_ip,
user_agent: request.user_agent,
referer: request.referer
)
if full_path
send_file full_path, disposition: "attachment", type: resolve_mime(full_path)
else
if location.nil?
render json: { error: "Not found" }, status: :not_found
elsif location.redirect?
redirect_to location.url, allow_other_host: true
else
send_file location.path, disposition: "attachment", type: resolve_mime(location.path)
end
end
end