From 9e59823f9bd977b8ecf894f29d94513bfe2690fc Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 18 Apr 2024 19:00:26 +0200 Subject: [PATCH 1/9] Add new parameter to set the visibility of the repository created Signed-off-by: cmoulliard --- .../package.json | 2 +- .../src/actions/gitea.examples.ts | 18 +++++ .../src/actions/gitea.test.ts | 73 +++++++++++++++++++ .../src/actions/gitea.ts | 23 +++++- 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend-module-gitea/package.json b/plugins/scaffolder-backend-module-gitea/package.json index 1751a1a6ce..1d8ad190bc 100644 --- a/plugins/scaffolder-backend-module-gitea/package.json +++ b/plugins/scaffolder-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitea", - "version": "0.1.7", + "version": "0.1.8", "description": "The gitea module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.examples.ts b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.examples.ts index ccf0f4ddf6..dd4d038ead 100644 --- a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.examples.ts +++ b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.examples.ts @@ -50,6 +50,23 @@ export const examples: TemplateExample[] = [ ], }), }, + { + description: 'Initializes a private Gitea repository ', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitea', + name: 'Publish to Gitea', + input: { + repoUrl: 'gitea.com?repo=repo&owner=owner', + defaultBranch: 'main', + repoVisibility: 'private', + }, + }, + ], + }), + }, { description: 'Initializes a Gitea repository with a default Branch, if not set defaults to main', @@ -150,6 +167,7 @@ export const examples: TemplateExample[] = [ gitAuthorName: 'John Doe', gitAuthorEmail: 'johndoe@email.com', sourcePath: 'repository/', + repoVisibility: 'public', }, }, ], diff --git a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts index 8675b1ff97..8a72265df0 100644 --- a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts +++ b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts @@ -53,6 +53,13 @@ describe('publish:gitea', () => { description, }, }); + const mockContextWithPublicRepoVisibility = createMockActionContext({ + input: { + repoUrl: 'gitea.com?repo=repo&owner=owner', + description, + private: false, + }, + }); const server = setupServer(); setupRequestMockHandlers(server); @@ -111,6 +118,7 @@ describe('publish:gitea', () => { ); expect(req.body).toEqual({ name: 'repo', + private: false, description, }); return res( @@ -148,6 +156,71 @@ describe('publish:gitea', () => { ); }); + it('should create a Gitea repository where visibility is public', async () => { + server.use( + rest.get('https://gitea.com/api/v1/orgs/org1', (_req, res, ctx) => { + return res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json({ + id: 1, + name: 'org1', + visibility: 'public', + repo_admin_change_team_access: false, + username: 'org1', + }), + ); + }), + rest.get( + 'https://gitea.com/org1/repo/src/branch/main', + (_req, res, ctx) => { + return res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json({}), + ); + }, + ), + rest.post('https://gitea.com/api/v1/orgs/org1/repos', (req, res, ctx) => { + // Basic auth must match the user and password defined part of the config + expect(req.headers.get('Authorization')).toBe( + 'basic Z2l0ZWFfdXNlcjpnaXRlYV9wYXNzd29yZA==', + ); + expect(req.body).toEqual({ + name: 'repo', + private: false, + description, + }); + return res( + ctx.status(201), + ctx.set('Content-Type', 'application/json'), + ctx.json({}), + ); + }), + ); + + await action.handler({ + ...mockContextWithPublicRepoVisibility, + input: { + ...mockContextWithPublicRepoVisibility.input, + repoUrl: 'gitea.com?repo=repo&owner=org1', + }, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContextWithPublicRepoVisibility.workspacePath, + remoteUrl: 'https://gitea.com/org1/repo.git', + defaultBranch: 'main', + auth: { username: 'gitea_user', password: 'gitea_password' }, + logger: mockContextWithPublicRepoVisibility.logger, + commitMessage: expect.stringContaining('initial commit\n\nChange-Id:'), + gitAuthorInfo: { + email: undefined, + name: undefined, + }, + }); + }); + afterEach(() => { jest.resetAllMocks(); }); diff --git a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts index 089f9b2669..03ac364538 100644 --- a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts +++ b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts @@ -96,10 +96,11 @@ const createGiteaProject = async ( options: { projectName: string; owner?: string; + repoVisibility?: string; description: string; }, ): Promise => { - const { projectName, description, owner } = options; + const { projectName, description, owner, repoVisibility } = options; /* Several options exist to create a repository using either the user or organisation @@ -112,12 +113,23 @@ const createGiteaProject = async ( This is the default scenario that we support currently */ let response: Response; + let visibility: boolean; + + if (repoVisibility === 'private') { + visibility = true; + } else if (repoVisibility === 'public') { + visibility = false; + } else { + // Provide a default value if repoVisibility is neither "private" nor "public" + visibility = false; + } const postOptions: RequestInit = { method: 'POST', body: JSON.stringify({ name: projectName, description, + private: visibility, }), headers: { ...getGiteaRequestOptions(config).headers, @@ -202,6 +214,7 @@ export function createPublishGiteaAction(options: { repoUrl: string; description: string; defaultBranch?: string; + repoVisibility?: 'private' | 'public'; gitCommitMessage?: string; gitAuthorName?: string; gitAuthorEmail?: string; @@ -229,6 +242,12 @@ export function createPublishGiteaAction(options: { type: 'string', description: `Sets the default branch on the repository. The default value is 'main'`, }, + repoVisibility: { + title: 'Repository Visibility', + description: `Sets the visibility of the repository. The default value is 'public'.`, + type: 'string', + enum: ['private', 'public'], + }, gitCommitMessage: { title: 'Git Commit Message', type: 'string', @@ -274,6 +293,7 @@ export function createPublishGiteaAction(options: { repoUrl, description, defaultBranch = 'main', + repoVisibility = 'public', gitAuthorName, gitAuthorEmail, gitCommitMessage = 'initial commit', @@ -301,6 +321,7 @@ export function createPublishGiteaAction(options: { await createGiteaProject(integrationConfig.config, { description, + repoVisibility, owner: owner, projectName: repo, }); From 6eaba9fb98179ed528693c9d3a8c0ab060492cc7 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 19 Apr 2024 12:16:25 +0200 Subject: [PATCH 2/9] Review the README to better explain how to integrate gitea in a template. Include parseRepoUrl to get the host name provided by the user. Add a warning to tell to the user that they should define the allowedOwners according to the gitea organisation. Include the new field: repoVisibility Signed-off-by: cmoulliard --- .../scaffolder-backend-module-gitea/README.md | 78 +++++++++---------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/plugins/scaffolder-backend-module-gitea/README.md b/plugins/scaffolder-backend-module-gitea/README.md index 7eff6130db..7133f33393 100644 --- a/plugins/scaffolder-backend-module-gitea/README.md +++ b/plugins/scaffolder-backend-module-gitea/README.md @@ -10,6 +10,13 @@ To use this action, you will have to add the package using the following command yarn --cwd packages/backend add @backstage/plugin-scaffolder-backend-module-gitea ``` +Alternatively, if you use the new backend system, then register it like this: + +```typescript +// packages/backend/src/index.ts +backend.add(import('@backstage/plugin-scaffolder-backend-module-gitea')); +``` + Configure the action (if not yet done): (you can check the [docs](https://backstage.io/docs/features/software-templates/writing-custom-actions#registering-custom-actions) to see all options): @@ -27,29 +34,29 @@ integrations: password: '' ``` -**Important**: As backstage will issue HTTPS/TLS requests to the gitea instance, it is needed to configure `gitea` with a valid certificate or at least with a -self-signed certificate `gitea cert --host localhost -ca` trusted by a CA authority. Don't forget to set the env var `NODE_EXTRA_CA_CERTS` to point to the CA file before launching backstage ! +**Important**: As backstage will issue `HTTPS/TLS` requests to the gitea instance, it is needed to configure `gitea` with a valid certificate or at least with a +self-signed certificate `gitea cert --host localhost -ca` trusted by a CA authority. Don't forget to set the env var `NODE_EXTRA_CA_CERTS` to point to the CA file before launching backstage or to ignore using the following Node.js parameter: `NODE_TLS_REJECT_UNAUTHORIZED=0` ! When done, you can create a template which: -- Declare the `RepoUrlPicker` within the `spec/parameters` section to select the gitea hosts -- Include a step able to publish by example the newly generated project using the action `action: publish:gitea` +- Declare the `RepoUrlPicker` within the `spec/parameters` section to select the gitea host and to provide the name of the repository +- Add an enum list allowing the user to define the visibility about the repository to be created: `public` or `private`. If this field is omitted, `public` is then used by the action. +- Include in a step the action: `publish:gitea` + +**Warning**: The list of the `allowedOwners` of the `repoUrlPicker` must match the list of the `organizations` which are available on the gitea host ! ```yaml -apiVersion: scaffolder.backstage.io/v1beta3 kind: Template metadata: - name: quarkus-web-template - title: Quarkus Hello world - description: Create a simple microservice using Quarkus - tags: - - java - - quarkus + name: simple-gitea-project + title: Create a gitea repository + description: Create a gitea repository spec: - owner: quarkus + owner: guests type: service + parameters: - - title: Git repository Information + - title: Choose a location required: - repoUrl properties: @@ -58,42 +65,33 @@ spec: type: string ui:field: RepoUrlPicker ui:options: + allowedOwners: + - qteam + - qshift allowedHosts: - - gitea.: - - localhost: + - gitea.localtest.me:3333 + + repoVisibility: + title: Visibility of the repository + type: string + default: 'public' + enum: + - 'public' + - 'private' + enumNames: + - 'public' + - 'private' steps: - - id: template - name: Generating component - action: fetch:template - input: - url: ./skeleton - values: - name: ${{ parameters.name }} - + ... - id: publish name: Publishing to a gitea git repository action: publish:gitea input: - description: This is ${{ parameters.component_id }} + description: This is ${{ parameters.repoUrl | parseRepoUrl | pick('repo') }} + repoVisibility: ${{ parameters.repoVisibility }} repoUrl: ${{ parameters.repoUrl }} defaultBranch: main - - - id: register - if: ${{ parameters.dryRun !== true }} - name: Register - action: catalog:register - input: - repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }} - catalogInfoPath: 'main/catalog-info.yaml' - - output: - links: - - title: Source Code Repository - url: ${{ steps.publish.output.remoteUrl }} - - title: Open Component in catalog - icon: catalog - entityRef: ${{ steps.register.output.entityRef }} ``` Access the newly gitea repository created using the `repoContentsUrl` ;-) From 64e36f5f473573cfe5bf96a2ed31ad828a422d4e Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 19 Apr 2024 12:18:12 +0200 Subject: [PATCH 3/9] Changed how we log the error using the message and cause.code. Otherwise it is not possible to know if the gitea server replies Signed-off-by: cmoulliard --- plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts index 03ac364538..deda1b77bb 100644 --- a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts +++ b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts @@ -81,7 +81,7 @@ const checkGiteaOrg = async ( ); } catch (e) { throw new Error( - `Unable to get the Organization: ${owner}; Error cause: ${e.cause.message}`, + `Unable to get the Organization: ${owner}; Error cause: ${e.message}, code: ${e.cause.code}`, ); } if (response.status !== 200) { From 554af738c52c29e8af394e9ac7dc5148bcff9e1d Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 19 Apr 2024 12:25:27 +0200 Subject: [PATCH 4/9] Add the changeset file Signed-off-by: cmoulliard --- .changeset/cool-elephants-march.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cool-elephants-march.md diff --git a/.changeset/cool-elephants-march.md b/.changeset/cool-elephants-march.md new file mode 100644 index 0000000000..2396f9553d --- /dev/null +++ b/.changeset/cool-elephants-march.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-gitea': patch +--- + +Allow defining `repoVisibility` field for the action `publish:gitea` From af6c03e2481fdfa600d50bf341eda47331d8f598 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 19 Apr 2024 12:49:45 +0200 Subject: [PATCH 5/9] Updating the API report as a new property has been added Signed-off-by: cmoulliard --- plugins/scaffolder-backend-module-gitea/api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/scaffolder-backend-module-gitea/api-report.md b/plugins/scaffolder-backend-module-gitea/api-report.md index 373cc6258c..b5e20b7b13 100644 --- a/plugins/scaffolder-backend-module-gitea/api-report.md +++ b/plugins/scaffolder-backend-module-gitea/api-report.md @@ -18,6 +18,7 @@ export function createPublishGiteaAction(options: { repoUrl: string; description: string; defaultBranch?: string | undefined; + repoVisibility?: 'private' | 'public' | undefined; gitCommitMessage?: string | undefined; gitAuthorName?: string | undefined; gitAuthorEmail?: string | undefined; From c3fbfe67690111cf3c6adbf46ea23fdc7b1d7aed Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 09:59:43 +0200 Subject: [PATCH 6/9] Don't bump the package version as the changeset will make the job Signed-off-by: cmoulliard --- plugins/scaffolder-backend-module-gitea/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-gitea/package.json b/plugins/scaffolder-backend-module-gitea/package.json index 1d8ad190bc..1751a1a6ce 100644 --- a/plugins/scaffolder-backend-module-gitea/package.json +++ b/plugins/scaffolder-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitea", - "version": "0.1.8", + "version": "0.1.7", "description": "The gitea module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module" From 6574d91f700f968c848be721844065e9f869240a Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 10:48:12 +0200 Subject: [PATCH 7/9] Highlighting the enum word Signed-off-by: cmoulliard --- plugins/scaffolder-backend-module-gitea/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-gitea/README.md b/plugins/scaffolder-backend-module-gitea/README.md index 7133f33393..09b43fea1e 100644 --- a/plugins/scaffolder-backend-module-gitea/README.md +++ b/plugins/scaffolder-backend-module-gitea/README.md @@ -40,7 +40,7 @@ self-signed certificate `gitea cert --host localhost -ca` trusted by a CA author When done, you can create a template which: - Declare the `RepoUrlPicker` within the `spec/parameters` section to select the gitea host and to provide the name of the repository -- Add an enum list allowing the user to define the visibility about the repository to be created: `public` or `private`. If this field is omitted, `public` is then used by the action. +- Add an `enum` list allowing the user to define the visibility about the repository to be created: `public` or `private`. If this field is omitted, `public` is then used by the action. - Include in a step the action: `publish:gitea` **Warning**: The list of the `allowedOwners` of the `repoUrlPicker` must match the list of the `organizations` which are available on the gitea host ! From c0c0f7cb330f5de73811ac44d7a26587d974f393 Mon Sep 17 00:00:00 2001 From: Charles Moulliard Date: Mon, 22 Apr 2024 17:17:52 +0200 Subject: [PATCH 8/9] Update plugins/scaffolder-backend-module-gitea/README.md Co-authored-by: Ben Lambert Signed-off-by: Charles Moulliard --- plugins/scaffolder-backend-module-gitea/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-gitea/README.md b/plugins/scaffolder-backend-module-gitea/README.md index 09b43fea1e..5c6aa59b66 100644 --- a/plugins/scaffolder-backend-module-gitea/README.md +++ b/plugins/scaffolder-backend-module-gitea/README.md @@ -35,7 +35,7 @@ integrations: ``` **Important**: As backstage will issue `HTTPS/TLS` requests to the gitea instance, it is needed to configure `gitea` with a valid certificate or at least with a -self-signed certificate `gitea cert --host localhost -ca` trusted by a CA authority. Don't forget to set the env var `NODE_EXTRA_CA_CERTS` to point to the CA file before launching backstage or to ignore using the following Node.js parameter: `NODE_TLS_REJECT_UNAUTHORIZED=0` ! +self-signed certificate `gitea cert --host localhost -ca` trusted by a CA authority. Don't forget to set the env var `NODE_EXTRA_CA_CERTS` to point to the CA file before launching backstage or you can set temporarily `NODE_TLS_REJECT_UNAUTHORIZED=0` but this is not recommended for production! When done, you can create a template which: From 504ca2d99c19ba9b8cea8d8b9614341ffbbb4f22 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 17:23:40 +0200 Subject: [PATCH 9/9] Rename the boolean visibility to isPrivate Signed-off-by: cmoulliard --- .../src/actions/gitea.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts index deda1b77bb..6b29ff2a4c 100644 --- a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts +++ b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.ts @@ -113,15 +113,15 @@ const createGiteaProject = async ( This is the default scenario that we support currently */ let response: Response; - let visibility: boolean; + let isPrivate: boolean; if (repoVisibility === 'private') { - visibility = true; + isPrivate = true; } else if (repoVisibility === 'public') { - visibility = false; + isPrivate = false; } else { // Provide a default value if repoVisibility is neither "private" nor "public" - visibility = false; + isPrivate = false; } const postOptions: RequestInit = { @@ -129,7 +129,7 @@ const createGiteaProject = async ( body: JSON.stringify({ name: projectName, description, - private: visibility, + private: isPrivate, }), headers: { ...getGiteaRequestOptions(config).headers,