Skip to content

Commit b67989a

Browse files
committed
Merge branch 'master' into fix/respect-backend-payload-encoding
2 parents 6aa0ef5 + 3a11886 commit b67989a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+5364
-437
lines changed

.github/workflows/frontend-verify.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ on:
77
paths:
88
- "frontend/**"
99
- ".github/workflows/frontend-verify.yml"
10-
branches-ignore:
11-
- "dependabot/**"
12-
- "snyk-upgrade-**"
13-
- "gh-readonly-queue/**"
1410
pull_request:
1511
paths:
1612
- "frontend/**"
@@ -204,10 +200,10 @@ jobs:
204200
- name: Install Playwright browsers
205201
run: bun run install:chromium
206202
- name: Install Go dependencies
207-
working-directory: ../backend/cmd/api
203+
working-directory: backend/cmd/api
208204
run: go get .
209205
- name: Build Go server
210-
working-directory: ../backend/cmd/api
206+
working-directory: backend/cmd/api
211207
run: go build -v ./...
212208
- name: Log networks
213209
if: runner.debug == '1'

backend/pkg/console/incremental_alter_topic_configs.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package console
1111

1212
import (
1313
"context"
14+
"errors"
1415

1516
"github.com/twmb/franz-go/pkg/kmsg"
1617
)
@@ -30,6 +31,17 @@ func (s *Service) EditTopicConfig(ctx context.Context, topicName string, configs
3031
req := kmsg.NewIncrementalAlterConfigsRequest()
3132
req.Resources = []kmsg.IncrementalAlterConfigsRequestResource{alterResource}
3233

33-
_, err = req.RequestWith(ctx, cl)
34-
return err
34+
response, err := req.RequestWith(ctx, cl)
35+
if err != nil {
36+
return err
37+
}
38+
39+
var kafkaErrs error
40+
for _, resource := range response.Resources {
41+
kafkaErr := newKafkaErrorWithDynamicMessage(resource.ErrorCode, resource.ErrorMessage)
42+
if kafkaErr != nil {
43+
kafkaErrs = errors.Join(kafkaErrs, kafkaErr)
44+
}
45+
}
46+
return kafkaErrs
3547
}

frontend/bun.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
"@testing-library/dom": "^10.4.1",
116116
"@testing-library/jest-dom": "^6.9.1",
117117
"@testing-library/react": "^16.3.0",
118+
"@testing-library/user-event": "^14.6.1",
118119
"@types/json-bigint": "^1.0.4",
119120
"@types/node": "^22.19.1",
120121
"@types/react": "^18.3.26",
@@ -926,6 +927,8 @@
926927

927928
"@testing-library/react": ["@testing-library/[email protected]", "", { "dependencies": { "@babel/runtime": "^7.12.5" }, "peerDependencies": { "@testing-library/dom": "^10.0.0", "@types/react": "^18.0.0 || ^19.0.0", "@types/react-dom": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw=="],
928929

930+
"@testing-library/user-event": ["@testing-library/[email protected]", "", { "peerDependencies": { "@testing-library/dom": ">=7.21.4" } }, "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw=="],
931+
929932
"@textea/json-viewer": ["@textea/[email protected]", "", { "dependencies": { "clsx": "^2.1.1", "copy-to-clipboard": "^3.3.3", "zustand": "^4.5.5" }, "peerDependencies": { "@emotion/react": "^11", "@emotion/styled": "^11", "@mui/material": "^6", "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, "sha512-7FH4ti3kVNyKhe/gl85w+8KllXJY9XQalY2KZnBn9ST1CjhqZQCWJLkYf24aX2FOv2D/8cvAllYkFX46A7C9KQ=="],
930933

931934
"@tootallnate/once": ["@tootallnate/[email protected]", "", {}, "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="],

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
"@testing-library/jest-dom": "^6.9.1",
151151
"@testing-library/react": "^16.3.0",
152152
"@types/json-bigint": "^1.0.4",
153+
"@testing-library/user-event": "^14.6.1",
153154
"@types/node": "^22.19.1",
154155
"@types/react": "^18.3.26",
155156
"@types/react-beautiful-dnd": "^13.1.8",

frontend/src/components/pages/mcp-servers/details/remote-mcp-toggle-button.test.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ vi.mock('config', () => ({
3838

3939
import { RemoteMCPToggleButton } from './remote-mcp-toggle-button';
4040

41-
const START_BUTTON_REGEX = /start/i;
42-
4341
describe('RemoteMCPToggleButton', () => {
4442
test('should stop a running MCP server from the details page', async () => {
4543
const serverId = 'server-1';
@@ -253,7 +251,7 @@ describe('RemoteMCPToggleButton', () => {
253251
);
254252

255253
await waitFor(() => {
256-
const startButton = screen.getByRole('button', { name: START_BUTTON_REGEX });
254+
const startButton = screen.getByTestId('start-mcp-server-button');
257255
expect(startButton).toBeVisible();
258256
expect(startButton).toBeDisabled();
259257
});
@@ -294,7 +292,7 @@ describe('RemoteMCPToggleButton', () => {
294292
);
295293

296294
await waitFor(() => {
297-
const startButton = screen.getByRole('button', { name: /start/i });
295+
const startButton = screen.getByRole('button', { name: 'Start' });
298296
expect(startButton).toBeVisible();
299297
expect(startButton).toBeEnabled();
300298
});

frontend/src/components/pages/secrets/create-secret-modal.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,7 @@ export const CreateSecretModal = ({ isOpen, onClose, customSecretSchema, helperT
5454
};
5555

5656
// Form type
57-
type Secret = {
58-
id: string;
59-
value: string;
60-
labels: string[];
61-
scopes: Scope[];
62-
};
57+
type Secret = z.infer<typeof finalSchema>;
6358

6459
const defaultValues: Secret = {
6560
id: '',
@@ -71,6 +66,7 @@ export const CreateSecretModal = ({ isOpen, onClose, customSecretSchema, helperT
7166
const formOpts = formOptions({
7267
defaultValues,
7368
validators: {
69+
// @ts-expect-error - Zod schema type incompatibility with @tanstack/react-form validators
7470
onChange: finalSchema,
7571
},
7672
onSubmit: async ({ value }) => {
@@ -169,8 +165,10 @@ export const CreateSecretModal = ({ isOpen, onClose, customSecretSchema, helperT
169165
<FormErrorMessage>
170166
<UnorderedList>
171167
{state.meta.errors?.map((error) => (
172-
<li key={error.path}>
173-
<Text color="red.500">{error.message}</Text>
168+
// biome-ignore lint/suspicious/noExplicitAny: error type from @tanstack/react-form is not properly typed
169+
<li key={(error as any)?.path ?? ''}>
170+
{/* biome-ignore lint/suspicious/noExplicitAny: error type from @tanstack/react-form is not properly typed */}
171+
<Text color="red.500">{(error as any)?.message ?? 'Validation error'}</Text>
174172
</li>
175173
))}
176174
</UnorderedList>

frontend/src/components/pages/secrets/update-secret-modal.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export const UpdateSecretModal = ({ isOpen, onClose, secretId }: UpdateSecretMod
6161
.map(([key, value]) => ({ key, value }))
6262
: [{ key: '', value: '' }];
6363

64+
const updateSchema = secretSchema(z.string().optional());
65+
6466
const formOpts = formOptions({
6567
defaultValues: {
6668
id: secretId,
@@ -69,7 +71,8 @@ export const UpdateSecretModal = ({ isOpen, onClose, secretId }: UpdateSecretMod
6971
labels: existingLabels.length > 0 ? existingLabels : [],
7072
},
7173
validators: {
72-
onChange: secretSchema(z.string().optional()),
74+
// @ts-expect-error - Zod schema type incompatibility with @tanstack/react-form validators
75+
onChange: updateSchema,
7376
},
7477
onSubmit: async ({ value }) => {
7578
const labelsMap: { [key: string]: string } = {};
@@ -141,8 +144,10 @@ export const UpdateSecretModal = ({ isOpen, onClose, secretId }: UpdateSecretMod
141144
<FormErrorMessage>
142145
<UnorderedList>
143146
{state.meta.errors?.map((error) => (
144-
<li key={error.path}>
145-
<Text color="red.500">{error.message}</Text>
147+
// biome-ignore lint/suspicious/noExplicitAny: error type from @tanstack/react-form is not properly typed
148+
<li key={(error as any)?.path ?? ''}>
149+
{/* biome-ignore lint/suspicious/noExplicitAny: error type from @tanstack/react-form is not properly typed */}
150+
<Text color="red.500">{(error as any)?.message ?? 'Validation error'}</Text>
146151
</li>
147152
))}
148153
</UnorderedList>

frontend/src/components/pages/shadowlinks/create/configuration/acl-filter-resume.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const ACLFilterResume = ({ index }: { index: number }) => {
3636
<div className="font-medium text-sm">ACL Filter {index + 1}</div>
3737
<div className="grid grid-cols-2 gap-x-6 gap-y-2 text-sm md:grid-cols-3">
3838
<div>
39-
<span className="text-muted-foreground">Resource Type:</span>{' '}
39+
<span className="text-muted-foreground">Resource type:</span>{' '}
4040
<Badge size="sm" variant="blue">
4141
{getResourceTypeLabel(resourceType)}
4242
</Badge>
@@ -48,7 +48,7 @@ export const ACLFilterResume = ({ index }: { index: number }) => {
4848
</Badge>
4949
</div>
5050
<div>
51-
<span className="text-muted-foreground">Resource Name:</span>{' '}
51+
<span className="text-muted-foreground">Resource name:</span>{' '}
5252
<Badge size="sm" variant="blue">
5353
{resourceName || 'All'}
5454
</Badge>

frontend/src/components/pages/shadowlinks/create/configuration/acls-step.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export const AclsStep = () => {
152152
{fields.map((field, index) => (
153153
<Card data-testid={`acl-filter-${index}`} key={field.id} size="full" variant="elevated">
154154
<CardHeader>
155-
<CardTitle className="text-base">ACL Filter {index + 1}</CardTitle>
155+
<CardTitle className="text-base">ACL filter {index + 1}</CardTitle>
156156
<CardAction>
157157
<Button
158158
data-testid={`delete-acl-filter-${index}`}
@@ -174,7 +174,7 @@ export const AclsStep = () => {
174174
name={`aclFilters.${index}.resourceType`}
175175
render={({ field: resourceTypeField }) => (
176176
<FormItem data-testid={`acl-filter-${index}-resource-type`}>
177-
<FormLabel>Resource Type</FormLabel>
177+
<FormLabel>Resource type</FormLabel>
178178
<Select
179179
onValueChange={(v) => resourceTypeField.onChange(Number(v))}
180180
value={
@@ -247,7 +247,7 @@ export const AclsStep = () => {
247247
name={`aclFilters.${index}.resourceName`}
248248
render={({ field: resourceNameField }) => (
249249
<FormItem className="md:col-span-2">
250-
<FormLabel>Resource Name</FormLabel>
250+
<FormLabel>Resource name</FormLabel>
251251
<FormControl>
252252
<Input placeholder="All" {...resourceNameField} />
253253
</FormControl>
@@ -269,7 +269,11 @@ export const AclsStep = () => {
269269
<FormItem>
270270
<FormLabel>Principal</FormLabel>
271271
<FormControl>
272-
<Input placeholder="All" {...principalField} />
272+
<Input
273+
placeholder="All"
274+
testId={`acl-filter-${index}-principal`}
275+
{...principalField}
276+
/>
273277
</FormControl>
274278
<FormDescription>Empty matches all principals</FormDescription>
275279
<FormMessage />

frontend/src/components/pages/shadowlinks/create/configuration/consumer-offset-step.tsx

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import { FilterItem } from './filter-item';
2424
import type { FormValues } from '../model';
2525

2626
export const ConsumerOffsetStep = () => {
27-
const { control, setValue } = useFormContext<FormValues>();
27+
const {
28+
control,
29+
setValue,
30+
formState: { errors },
31+
} = useFormContext<FormValues>();
2832
const [isOpen, setIsOpen] = useState(false);
2933

3034
const consumersMode = useWatch({ control, name: 'consumersMode' });
@@ -82,18 +86,23 @@ export const ConsumerOffsetStep = () => {
8286
{/* Resume/summary view when collapsed */}
8387
{!isOpen && consumersMode === 'specify' && fields.length > 0 && (
8488
<div className="mt-4 space-y-2">
85-
{fields.map((field, index) => (
86-
<FilterItem
87-
control={control}
88-
fieldNamePrefix="consumers"
89-
index={index}
90-
key={field.id}
91-
onRemove={() => remove(index)}
92-
viewType={false}
93-
>
94-
{null}
95-
</FilterItem>
96-
))}
89+
{fields.map((field, index) => {
90+
const fieldError = errors.consumers?.[index];
91+
const errorMessage = fieldError?.name?.message;
92+
return (
93+
<FilterItem
94+
control={control}
95+
errorMessage={errorMessage}
96+
fieldNamePrefix="consumers"
97+
index={index}
98+
key={field.id}
99+
onRemove={() => remove(index)}
100+
viewType={false}
101+
>
102+
{null}
103+
</FilterItem>
104+
);
105+
})}
97106
</div>
98107
)}
99108

@@ -125,7 +134,11 @@ export const ConsumerOffsetStep = () => {
125134
render={({ field: nameField }) => (
126135
<FormItem className="flex-1">
127136
<FormControl>
128-
<Input placeholder="e.g., my-consumer-group or prefix-*" {...nameField} />
137+
<Input
138+
placeholder="e.g., my-consumer-group or prefix-*"
139+
testId={`consumer-filter-${index}-name`}
140+
{...nameField}
141+
/>
129142
</FormControl>
130143
<FormMessage />
131144
</FormItem>

0 commit comments

Comments
 (0)