Merge pull request #24383 from ch007m/add-new-parameters-gitea
Add new parameter: repoVisibility for the action: publish:gitea
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitea': patch
|
||||
---
|
||||
|
||||
Allow defining `repoVisibility` field for the action `publish:gitea`
|
||||
@@ -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: '<GITEA_LOCALHOST_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 you can set temporarily `NODE_TLS_REJECT_UNAUTHORIZED=0` but this is not recommended for production!
|
||||
|
||||
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.<YOUR_DOMAIN>:<PORT>
|
||||
- localhost:<PORT>
|
||||
- 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` ;-)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
@@ -96,10 +96,11 @@ const createGiteaProject = async (
|
||||
options: {
|
||||
projectName: string;
|
||||
owner?: string;
|
||||
repoVisibility?: string;
|
||||
description: string;
|
||||
},
|
||||
): Promise<void> => {
|
||||
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 isPrivate: boolean;
|
||||
|
||||
if (repoVisibility === 'private') {
|
||||
isPrivate = true;
|
||||
} else if (repoVisibility === 'public') {
|
||||
isPrivate = false;
|
||||
} else {
|
||||
// Provide a default value if repoVisibility is neither "private" nor "public"
|
||||
isPrivate = false;
|
||||
}
|
||||
|
||||
const postOptions: RequestInit = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name: projectName,
|
||||
description,
|
||||
private: isPrivate,
|
||||
}),
|
||||
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,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user