Skip to content
This repository was archived by the owner on Jun 26, 2026. It is now read-only.

Commit 5ba901c

Browse files
matejvasekclaude
andcommitted
fix: match deployment to latest ready revision
The merge logic used deployments.find() with the function.knative.dev/name label to locate the Deployment for each function. After a redeployment Knative keeps the old Revision's Deployment (scaled to 0) alongside the new one, and both carry the same label. find() returned the old Deployment, so deriveStatus saw replicas=0 and reported ScaledToZero instead of Running. Use ksvc.status.latestReadyRevisionName to identify the active Revision, then match the Deployment via its serving.knative.dev/revision label. Falls back to the original function-name match when no revision name is set (initial deploy before any revision is ready). Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Matej Vašek <matejvasek@gmail.com>
1 parent 8490efb commit 5ba901c

3 files changed

Lines changed: 52 additions & 7 deletions

File tree

src/services/cluster/useClusterService.test.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const mockKsvc = {
2121
},
2222
status: {
2323
url: 'https://my-func-demo.apps.example.com',
24+
latestReadyRevisionName: 'my-func-00001',
2425
conditions: [{ type: 'Ready', status: 'True' }],
2526
},
2627
};
@@ -31,7 +32,10 @@ const mockDeployment = {
3132
metadata: {
3233
name: 'my-func-00001-deployment',
3334
namespace: 'demo',
34-
labels: { 'function.knative.dev/name': 'my-func' },
35+
labels: {
36+
'function.knative.dev/name': 'my-func',
37+
'serving.knative.dev/revision': 'my-func-00001',
38+
},
3539
},
3640
spec: { replicas: 1 },
3741
status: { readyReplicas: 1 },

src/views/FunctionsListPage.test.tsx

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ function ksvcFixture(
8383
name: string,
8484
readyStatus: string,
8585
url = `https://${name}-demo.apps.example.com`,
86+
revision = `${name}-00001`,
8687
) {
8788
return {
8889
apiVersion: 'serving.knative.dev/v1',
@@ -94,19 +95,28 @@ function ksvcFixture(
9495
},
9596
status: {
9697
url,
98+
latestReadyRevisionName: revision,
9799
conditions: [{ type: 'Ready', status: readyStatus }],
98100
},
99101
};
100102
}
101103

102-
function deploymentFixture(name: string, specReplicas: number, readyReplicas: number) {
104+
function deploymentFixture(
105+
name: string,
106+
specReplicas: number,
107+
readyReplicas: number,
108+
revision = `${name}-00001`,
109+
) {
103110
return {
104111
apiVersion: 'apps/v1',
105112
kind: 'Deployment',
106113
metadata: {
107-
name: `${name}-00001-deployment`,
114+
name: `${revision}-deployment`,
108115
namespace: 'demo',
109-
labels: { 'function.knative.dev/name': name },
116+
labels: {
117+
'function.knative.dev/name': name,
118+
'serving.knative.dev/revision': revision,
119+
},
110120
},
111121
spec: { replicas: specReplicas },
112122
status: { readyReplicas },
@@ -381,6 +391,32 @@ describe('FunctionsListPage', () => {
381391
expect(await screen.findByTestId('fn-status')).toHaveTextContent('Error');
382392
});
383393

394+
it('picks latest revision deployment when multiple revisions exist', async () => {
395+
renderAuthenticated();
396+
mockUseSourceControl.mockReturnValue({
397+
listFunctionRepos: vi.fn().mockResolvedValue([repoFixture('my-func')]),
398+
fetchFileContent: vi.fn().mockResolvedValue('name: my-func\nruntime: go\nnamespace: demo\n'),
399+
});
400+
mockUseClusterService.mockReturnValue(
401+
clusterData({
402+
knativeServices: [ksvcFixture('my-func', 'True', undefined, 'my-func-00002')],
403+
deployments: [
404+
deploymentFixture('my-func', 0, 0, 'my-func-00001'),
405+
deploymentFixture('my-func', 1, 1, 'my-func-00002'),
406+
],
407+
}),
408+
);
409+
410+
render(
411+
<MemoryRouter>
412+
<FunctionsListPage />
413+
</MemoryRouter>,
414+
);
415+
416+
expect(await screen.findByTestId('fn-status')).toHaveTextContent('Running');
417+
expect(screen.getByTestId('fn-replicas')).toHaveTextContent('1');
418+
});
419+
384420
it('passes function names to useClusterService', async () => {
385421
renderAuthenticated();
386422
mockUseSourceControl.mockReturnValue({

src/views/FunctionsListPage.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,14 @@ function useFunctionListPage(): {
161161
const ksvc = knativeServices.find(
162162
(s) => s.metadata?.labels?.['function.knative.dev/name'] === item.name,
163163
);
164-
const deployment = deployments.find(
165-
(d) => d.metadata?.labels?.['function.knative.dev/name'] === item.name,
166-
);
164+
const latestRevision = ksvc?.status?.latestReadyRevisionName;
165+
const deployment = latestRevision
166+
? deployments.find(
167+
(d) => d.metadata?.labels?.['serving.knative.dev/revision'] === latestRevision,
168+
)
169+
: deployments.find(
170+
(d) => d.metadata?.labels?.['function.knative.dev/name'] === item.name,
171+
);
167172
return ksvc && deployment ? enrichItem(item, ksvc, deployment) : item;
168173
}),
169174
[functionItems, knativeServices, deployments],

0 commit comments

Comments
 (0)