Route selected release runtime through gateway
This commit is contained in:
@@ -48,6 +48,7 @@ import Swal from "sweetalert2";
|
||||
import { SubuserGrants } from "@/components/session/token/SessionUser/Objects/SubuserGrants.vue";
|
||||
import { Subusers } from "@/components/session/token/SessionUser/Objects/Subusers.vue";
|
||||
import { configureReleaseRuntime } from "@/services/releaseTimeline.js";
|
||||
import { fetchReleaseRuntime } from "@/services/releaseBootstrap.js";
|
||||
import {
|
||||
isReleaseChannelApiAvailabilityError,
|
||||
markReleaseChannelApiUnavailable,
|
||||
@@ -128,9 +129,9 @@ const applyReleaseRuntimeConfig = (runtime) => {
|
||||
};
|
||||
|
||||
export const refreshReleaseRuntime = async () => {
|
||||
return authenticatedRequest("/release/runtime", "GET", releaseChannelRuntimeRequestParams())
|
||||
.then((response) => {
|
||||
applyReleaseRuntimeConfig(response?.data?.data || response?.data || {});
|
||||
return fetchReleaseRuntime()
|
||||
.then((runtime) => {
|
||||
applyReleaseRuntimeConfig(runtime || {});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn("Could not refresh release runtime", error);
|
||||
|
||||
@@ -26,6 +26,9 @@ export const API_URL = normalizeApiUrl(
|
||||
export const RELEASE_MANAGER_CONTROL_API_URL = normalizeApiUrl(
|
||||
import.meta.env.VITE_RELEASE_MANAGER_CONTROL_API_URL || API_URL
|
||||
);
|
||||
export const RELEASE_PUBLIC_GATEWAY_API_URL = normalizeApiUrl(
|
||||
import.meta.env.VITE_RELEASE_PUBLIC_GATEWAY_API_URL || "https://api-v2.truckwash.io"
|
||||
);
|
||||
export const RELEASE_MANAGER_CONTROL_API_FALLBACK_URLS = String(
|
||||
import.meta.env.VITE_RELEASE_MANAGER_CONTROL_API_FALLBACK_URLS ||
|
||||
(IS_DEV ? "https://api.truckwash.io:4433,https://api.truckwash.io" : "")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { API_URL } from "@/config.js";
|
||||
import { API_URL, RELEASE_PUBLIC_GATEWAY_API_URL } from "@/config.js";
|
||||
import { buildReleaseHeaders } from "@/services/releaseHeaders.js";
|
||||
|
||||
export const RELEASE_RUNTIME_GLOBAL_KEY = "__TRUCKWASH_RELEASE_RUNTIME__";
|
||||
@@ -30,6 +30,20 @@ const browserStorage = () => {
|
||||
const readSelectedReleaseChannel = () =>
|
||||
normalizeReleaseChannelSlug(browserStorage()?.getItem(RELEASE_CHANNEL_SELECTION_STORAGE_KEY) || "");
|
||||
|
||||
const releaseChannelGatewayApiBaseUrl = (channelSlug, gatewayBaseUrl = RELEASE_PUBLIC_GATEWAY_API_URL) => {
|
||||
const slug = normalizeReleaseChannelSlug(channelSlug);
|
||||
if (!slug || slug === "stable") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const baseUrl = normalizeBaseUrl(gatewayBaseUrl);
|
||||
if (!baseUrl || !/^https?:\/\//i.test(baseUrl)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return new URL(`${slug}/api/`, `${baseUrl}/`).href.replace(/\/+$/, "");
|
||||
};
|
||||
|
||||
const buildRuntimeHeaders = () => {
|
||||
const storage = browserStorage();
|
||||
const headers = {
|
||||
@@ -47,9 +61,11 @@ const buildRuntimeHeaders = () => {
|
||||
return headers;
|
||||
};
|
||||
|
||||
export const runtimeApiUrl = (apiBaseUrl = API_URL) => {
|
||||
const url = new URL("release/runtime", `${normalizeBaseUrl(apiBaseUrl)}/`);
|
||||
export const runtimeApiUrl = (apiBaseUrl = API_URL, gatewayBaseUrl = RELEASE_PUBLIC_GATEWAY_API_URL) => {
|
||||
const selectedChannel = readSelectedReleaseChannel();
|
||||
const selectedChannelApiBaseUrl = releaseChannelGatewayApiBaseUrl(selectedChannel, gatewayBaseUrl);
|
||||
const runtimeBaseUrl = selectedChannelApiBaseUrl || normalizeBaseUrl(apiBaseUrl);
|
||||
const url = new URL("release/runtime", `${runtimeBaseUrl}/`);
|
||||
if (selectedChannel) {
|
||||
url.searchParams.set("release_channel", selectedChannel);
|
||||
}
|
||||
@@ -71,12 +87,16 @@ const parseJsonResponse = async (response, label) => {
|
||||
return response?.json?.();
|
||||
};
|
||||
|
||||
export const fetchReleaseRuntime = async ({ fetchFn = globalThis.fetch, apiBaseUrl = API_URL } = {}) => {
|
||||
export const fetchReleaseRuntime = async ({
|
||||
fetchFn = globalThis.fetch,
|
||||
apiBaseUrl = API_URL,
|
||||
gatewayBaseUrl = RELEASE_PUBLIC_GATEWAY_API_URL,
|
||||
} = {}) => {
|
||||
if (typeof fetchFn !== "function") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const response = await fetchFn(runtimeApiUrl(apiBaseUrl), {
|
||||
const response = await fetchFn(runtimeApiUrl(apiBaseUrl, gatewayBaseUrl), {
|
||||
method: "GET",
|
||||
headers: buildRuntimeHeaders(),
|
||||
credentials: "omit",
|
||||
|
||||
@@ -15,6 +15,7 @@ const json = (body, status = 200) => ({
|
||||
test("non-default release frontend loads from api-v2.truckwash.io without redirecting", async ({ page }) => {
|
||||
const releaseApiRequests = [];
|
||||
const releaseEntryRequests = [];
|
||||
const runtimeRequests = [];
|
||||
const runtime = {
|
||||
generated_at: "2026-05-20T10:00:00.000Z",
|
||||
trace_id: "trace-release-bootstrap",
|
||||
@@ -46,7 +47,12 @@ test("non-default release frontend loads from api-v2.truckwash.io without redire
|
||||
},
|
||||
};
|
||||
|
||||
await page.route("**/release/runtime**", async (route) => {
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("release_channel_selected_slug", "canary");
|
||||
});
|
||||
|
||||
await page.route("https://api-v2.truckwash.io/canary/api/release/runtime**", async (route) => {
|
||||
runtimeRequests.push(route.request().url());
|
||||
await route.fulfill(json({ data: runtime }));
|
||||
});
|
||||
await page.route("https://api-v2.truckwash.io/canary/frontend/release-entry.json", async (route) => {
|
||||
@@ -89,6 +95,7 @@ test("non-default release frontend loads from api-v2.truckwash.io without redire
|
||||
const currentOrigin = await page.evaluate(() => window.location.origin);
|
||||
expect(page.url()).toContain("/shared/passkey-safe-link");
|
||||
expect(page.url()).not.toContain("api-v2.truckwash.io");
|
||||
expect(runtimeRequests).toEqual(["https://api-v2.truckwash.io/canary/api/release/runtime?release_channel=canary"]);
|
||||
expect(releaseEntryRequests).toEqual(["https://api-v2.truckwash.io/canary/frontend/release-entry.json"]);
|
||||
await expect.poll(() => releaseApiRequests.length).toBe(1);
|
||||
expect(releaseApiRequests[0]).toBe("https://api-v2.truckwash.io/canary/api/ping");
|
||||
|
||||
@@ -26,7 +26,15 @@ describe("release bootstrap", () => {
|
||||
localStorage.setItem("release_channel_selected_slug", "Canary Preview!");
|
||||
|
||||
expect(runtimeApiUrl("https://api.truckwash.io")).toBe(
|
||||
"https://api.truckwash.io/release/runtime?release_channel=canary-preview"
|
||||
"https://api-v2.truckwash.io/canary-preview/api/release/runtime?release_channel=canary-preview"
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps stable runtime requests on the configured control API", () => {
|
||||
localStorage.setItem("release_channel_selected_slug", "stable");
|
||||
|
||||
expect(runtimeApiUrl("https://api.truckwash.io")).toBe(
|
||||
"https://api.truckwash.io/release/runtime?release_channel=stable"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -38,9 +46,10 @@ describe("release bootstrap", () => {
|
||||
json: async () => ({ data: { channel: { slug: "internal" } } }),
|
||||
}));
|
||||
|
||||
await fetchReleaseRuntime({ fetchFn, apiBaseUrl: "https://api-v2.truckwash.io" });
|
||||
await fetchReleaseRuntime({ fetchFn, apiBaseUrl: "https://api.truckwash.io" });
|
||||
|
||||
const [, options] = fetchFn.mock.calls[0];
|
||||
const [url, options] = fetchFn.mock.calls[0];
|
||||
expect(url).toBe("https://api-v2.truckwash.io/internal/api/release/runtime?release_channel=internal");
|
||||
expect(options.headers).toMatchObject({
|
||||
"X-Release-Trace": "trace-runtime",
|
||||
"X-Release-Channel": "internal",
|
||||
|
||||
Reference in New Issue
Block a user