Do not let a response header take the API down

The version header was set from WarpEngine::VERSION_HEADER, a constant introduced in the
same commit. The deploy that followed ran these controllers with an older `lib/`, so the
before_action raised NameError on every request and every engine endpoint answered 500 —
the catalog, the images, the file server and the config extension Woodpecker calls, which
is how it surfaced: a pipeline could no longer fetch its own configuration.

The controller now spells the header name out. A response header is not worth a dependency
that can take the API down when one half of a deploy is older than the other, and the
constant remains the documented name with a spec holding the two in step.

Confirmed in production mode against the same code that failed: 200 with the header.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 20:20:39 +02:00
co-authored by Claude Opus 5
parent b652615e32
commit ccf38bd9fd
2 changed files with 13 additions and 1 deletions
@@ -31,7 +31,13 @@ module WarpEngine
private
def set_version_header
response.headers[WarpEngine::VERSION_HEADER] = WarpEngine::VERSION
# The name is spelled out here rather than taken from WarpEngine::VERSION_HEADER on
# purpose. A deployed process can end up with these controllers and an older
# `lib/` — it happened on the first deploy of this feature — and a controller that
# needs a constant from the newer half answers 500 to every request instead of
# serving the catalog. A response header is not worth that fragility. The constant
# is still the documented name, and a spec holds the two together.
response.headers["WarpEngine-Version"] = WarpEngine::VERSION
end
def resolve_mime(path)
+6
View File
@@ -3,6 +3,12 @@ require "rails_helper"
# Every response the engine serves carries the version that served it, so a client can
# branch on the engine's age without asking a separate endpoint for it.
RSpec.describe "the WarpEngine-Version header", type: :request do
# The controller writes the name as a literal so that it cannot depend on a constant a
# half-updated deploy might not have. This is what keeps the two in step.
it "is the name the constant documents" do
expect(WarpEngine::VERSION_HEADER).to eq("WarpEngine-Version")
end
it "is on a normal response" do
create(:software)