Files
windmill/cli/test/deploy_labels_unit.test.ts
hugocasaandClaude Opus 5 94e4fb1c84 fix: carry labels when deploying variables, resources and folders (#11222)
* fix: carry labels when deploying variables, resources and folders across workspaces

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix: clear a folder's labels in the target when the source has none

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* test: pin that the frontend deploy adapter carries variable labels

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-25 18:15:08 +02:00

85 lines
2.3 KiB
TypeScript

import { expect, test } from "bun:test";
import { deployItem } from "../windmill-utils-internal/src/deploy.ts";
// Variables, resources and folders are deployed from a body built field by field rather than
// spread from the source item, so any field left out of it is silently dropped in the target.
test("deployItem: carries labels for variables, resources and folders", async () => {
const labels = ["prod", "billing"];
const writes: [string, any][] = [];
const provider = (exists: boolean) =>
({
existsVariable: async () => exists,
existsResource: async () => exists,
existsFolder: async () => exists,
getVariable: async () => ({ value: "v", is_secret: false, labels }),
getResource: async () => ({
value: {},
resource_type: "postgresql",
labels,
}),
getFolder: async () => ({
name: "x",
owners: [],
extra_perms: {},
labels,
}),
...Object.fromEntries(
[
"createVariable",
"updateVariable",
"createResource",
"updateResource",
"createFolder",
"updateFolder",
].map((fn) => [
fn,
async (p: any) => void writes.push([fn, p.requestBody]),
]),
),
}) as any;
for (const exists of [false, true]) {
for (const [kind, path] of [
["variable", "f/x/v"],
["resource", "f/x/r"],
["folder", "f/x"],
]) {
const result = await deployItem(
provider(exists),
kind as any,
path,
"src",
"dst",
);
expect(result).toEqual({ success: true });
}
}
expect(writes.map(([fn]) => fn).sort()).toEqual([
"createFolder",
"createResource",
"createVariable",
"updateFolder",
"updateResource",
"updateVariable",
]);
for (const [, body] of writes) expect(body.labels).toEqual(labels);
});
test("deployItem: clears a folder's labels when the source has none", async () => {
let body: any;
await deployItem(
{
existsFolder: async () => true,
// A folder with cleared labels reads back without the field at all.
getFolder: async () => ({ name: "x", owners: [], extra_perms: {} }),
updateFolder: async (p: any) => void (body = p.requestBody),
} as any,
"folder",
"f/x",
"src",
"dst",
);
expect(body.labels).toEqual([]);
});