From 7b1dce5af05660ffbe1febbe04976af139569a0b Mon Sep 17 00:00:00 2001 From: hugocasa Date: Tue, 27 Oct 2026 00:42:47 +0100 Subject: [PATCH] feat: forward a pinned version through the hub project export proxy (#12022) The proxy rebuilds the hub URL instead of passing the request through, so a `?version=` on it was dropped and the current version exported in its place. Co-authored-by: Claude Opus 5.5 --- backend/windmill-api/openapi.yaml | 7 +++++++ backend/windmill-api/src/hub_publish.rs | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index d016a61976..fa372cc469 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -28424,6 +28424,13 @@ paths: description: folder scoping the Hub project source (`{workspace}:{folder}`) schema: type: string + - name: version + in: query + required: false + description: id of a reviewed project version to export instead of the current one (see the hub's `/projects/{slug}/versions`) + schema: + type: integer + minimum: 1 responses: "200": description: raw Hub response body (status code is passed through from the Hub) diff --git a/backend/windmill-api/src/hub_publish.rs b/backend/windmill-api/src/hub_publish.rs index 633ad88a34..4e79aba943 100644 --- a/backend/windmill-api/src/hub_publish.rs +++ b/backend/windmill-api/src/hub_publish.rs @@ -536,14 +536,26 @@ async fn publish_migrations( .await } +#[derive(Deserialize)] +struct ExportQuery { + version: Option, +} + // Export is owner-scoped only when re-exporting your own draft; approved -// projects are public, so the folder scope is optional here. +// projects are public, so the folder scope is optional here. `version` pins one +// reviewed version instead of the current one; it is forwarded explicitly because +// the hub request is rebuilt rather than proxied, so an unforwarded param would +// silently export the current version instead. async fn get_project_export( ctx: HubPublishCtx, Path((_workspace, slug)): Path<(String, ProjectSlug)>, + Query(query): Query, ) -> Result { - ctx.get_maybe_unscoped(&format!("/projects/{}/export", slug)) - .await + let path = match query.version { + Some(v) => format!("/projects/{}/export?version={}", slug, v), + None => format!("/projects/{}/export", slug), + }; + ctx.get_maybe_unscoped(&path).await } async fn get_project_by_source(ctx: HubPublishCtx) -> Result {