fix(devtools): urlencode task IDs when calling trigger route

Signed-off-by: thomvaill <thomvaill@bluebricks.dev>
This commit is contained in:
thomvaill
2026-02-26 16:50:57 +01:00
parent a6b28199e5
commit afabb37104
3 changed files with 55 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-devtools': patch
---
Fixed URL encoding of task IDs for the trigger feature (tasks that contained a "/" in their ID were not triggered)
@@ -0,0 +1,49 @@
/*
* Copyright 2026 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DevToolsClient } from './DevToolsClient';
describe('DevToolsClient', () => {
const mockBaseUrl = 'http://backstage/api/catalog';
const discoveryApi = {
getBaseUrl: async (pluginId: string) => `${mockBaseUrl}/${pluginId}`,
};
const mockFetch = jest.fn();
const fetchApi = { fetch: mockFetch };
let client: DevToolsClient;
beforeEach(() => {
mockFetch.mockResolvedValue({
ok: true,
json: async () => ({ status: 'triggered' }),
});
client = new DevToolsClient({ discoveryApi, fetchApi });
});
afterEach(() => jest.resetAllMocks());
it('should URL-encode the taskId when triggering a scheduled task', async () => {
await client.triggerScheduledTask(
'my-plugin',
'task/with/slashes:and-special-chars',
);
expect(mockFetch).toHaveBeenCalledWith(
`${mockBaseUrl}/my-plugin/.backstage/scheduler/v1/tasks/task%2Fwith%2Fslashes%3Aand-special-chars/trigger`,
{ method: 'POST' },
);
});
});
+1 -1
View File
@@ -70,7 +70,7 @@ export class DevToolsClient implements DevToolsApi {
): Promise<TriggerScheduledTask> {
const baseUrl = `${await this.discoveryApi.getBaseUrl(plugin)}/`;
const url = new URL(
`.backstage/scheduler/v1/tasks/${taskId}/trigger`,
`.backstage/scheduler/v1/tasks/${encodeURIComponent(taskId)}/trigger`,
baseUrl,
);