diff --git a/.changeset/lazy-doors-wink.md b/.changeset/lazy-doors-wink.md new file mode 100644 index 0000000000..aafbb3500e --- /dev/null +++ b/.changeset/lazy-doors-wink.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 994d1c580a..dc8e3eb0ee 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -393,4 +393,23 @@ describe('publish:gitlab', () => { visibility: 'private', }); }); + + it('should show proper error message when token has insufficient permissions or namespace not found', async () => { + mockGitlabClient.Namespaces.show.mockRejectedValue({ + response: { + statusCode: 404, + }, + }); + const owner = 'infrastructure/devex'; + const repoName = 'backstage'; + + await expect( + action.handler({ + ...mockContext, + input: { repoUrl: `gitlab.com?owner=${owner}&repo=${repoName}` }, + }), + ).rejects.toThrow( + `The namespace ${owner} is not found or the user doesn't have permissions to access it`, + ); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index dbab7b11b8..25f78452a4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -174,20 +174,33 @@ export function createPublishGitlabAction(options: { [tokenType]: token, }); - let { id: targetNamespace } = (await client.Namespaces.show(owner)) as { - id: number; - }; + let targetNamespaceId; + + try { + const namespaceResponse = (await client.Namespaces.show(owner)) as { + id: number; + }; + + targetNamespaceId = namespaceResponse.id; + } catch (e) { + if (e.response && e.response.statusCode === 404) { + throw new InputError( + `The namespace ${owner} is not found or the user doesn't have permissions to access it`, + ); + } + throw e; + } const { id: userId } = (await client.Users.current()) as { id: number; }; - if (!targetNamespace) { - targetNamespace = userId; + if (!targetNamespaceId) { + targetNamespaceId = userId; } const { id: projectId, http_url_to_repo } = await client.Projects.create({ - namespace_id: targetNamespace, + namespace_id: targetNamespaceId, name: repo, visibility: repoVisibility, ...(topics.length ? { topics } : {}),