Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ catalog:
target: ../../catalog/catalog.yaml
rules:
- allow: [Component, Group, User]
- type: file
target: ../../catalog/templates/*.yaml
rules:
- allow:
- Template

grafana:
domain: https://giantswarm.grafana.net
167 changes: 167 additions & 0 deletions catalog/templates/go-project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: go-project
title: Go project
description: A Go project without any deployment capabilities, suited best for CLIs or libraries
spec:
owner: team-honeybadger
type: Component

# User input parameters and form details config
parameters:
- title: Basic details
required:
- name
- description
- visibility
- owner
description: Please fill in the required details. Make sure to pick a name carefully, as it will be quite a hassle to change it later.
properties:
name:
title: Name
type: string
description: Unique name of the component and repository
pattern: "[a-z][-a-z0-9]+"
minLength: 2
maxLength: 100
ui:autofocus: true
description:
title: Description
type: string
description: Please give a general description in one sentence, so everybody can understand what this project and repo is for.
visibility:
title: Repository visibility
type: string
default: public
enum:
- public
- private
ui:widget: radio
owner:
type: string
ui:field: OwnerPicker

- title: Integrations
description: Select the technical integrations you need for sure. You can always add integrations later.
properties:
circleci:
type: boolean
title: I want CircleCI checks and builds for this project
default: true
ui:autofocus: true
image_registry:
type: boolean
title: I want a container image repository for this project
default: false
renovate:
type: boolean
title: I want Renovate to help update dependencies in this project
default: true

- title: Additional options
description: For fine-tuning our automations you can set some additional options here. These can also be modified later.
properties:
precommit:
type: boolean
default: true
title: Provide pre-commit framework configuration
ui:autofocus: true
flavors:
type: object
title: Flavours
description: Select the type of repository features you want to enable for your project. Check [the docs](https://devportal.giantswarm.io/docs/default/component/devctl/docs/flavours/) to read more.
properties:
cli:
type: boolean
description: Check this if the project will include a CLI utility.
k8sapi:
type: boolean
description: Check if the project will include a Kubernetes API definition (CRD).

- title: Developer portal catalog
description: Specify how this project will appear in the catalog.
properties:
componentType:
type: string
title: Component type
description: The component type this project should be shown as here in the developer portal catalog-info.yaml
default: unspecified
ui:autofocus: true
enum:
- unspecified
- cli
- library
- service
# system:
# type: string
# title: System
# description: Pick the system your new component belongs to (if any).
# ui:field: EntityPicker
# default: ""
# ui:options:
# catalogFilter:
# - kind: System

# Creation steps
steps:
- id: fetch-base
name: Fetch and adapt template
action: fetch:template
input:
url: https://github.com/giantswarm/template/tree/nunjucks-syntax
copyWithoutTemplating:
- .github/workflows/* # required to prevent the attempt to replace ${{ variables }}
values:
REPOSITORY_NAME: ${{ parameters.name }}
OWNER: ${{ parameters.owner }}
DESCRIPTION: ${{ parameters.description }}
COMPONENT_TYPE: ${{ parameters.componentType }}
SYSTEM: ${{ parameters.system }}
VISIBILITY: ${{ parameters.visibility }}
WANT_CIRCLECI: ${{ parameters.circleci }}
WANT_IMAGE_REGISTRY: ${{ parameters.image_registry }}
RENOVATE: ${{ parameters.renovate }}
FLAVOUR_CLI: ${{ parameters.flavors.cli }}
FLAVOUR_K8SAPI: ${{ parameters.flavors.k8sapi }}

- id: overwrite-codeowners
name: Create CODEOWNERS file
action: github:codeowners:create
input:
organization: giantswarm
team: ${{ parameters.owner }}

- id: publish
name: Publish new repository
action: publish:github
input:
repoUrl: github.com?repo=${{ parameters.name }}&owner=giantswarm
description: ${{ parameters.description }}
access: giantswarm/employees
repoVisibility: ${{ parameters.visibility }}
defaultBranch: main
protectDefaultBranch: true
protectEnforceAdmins: true
deleteBranchOnMerge: true
gitAuthorName: Developer portal
allowMergeCommit: false
allowSquashMerge: true
allowRebaseMerge: false
allowAutoMerge: true
collaborators:
- team: bots
access: push
hasProjects: false
hasWiki: false
hasIssues: false

# Results output
output:
links:
- title: Your new repository
url: ${{ steps['publish'].output.repoContentsUrl }}
text:
- title: Next steps
content: |
**Please read your new repository's README file.** There are some instructions for you regarding how to proceed.
22 changes: 3 additions & 19 deletions packages/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import {
CatalogIndexPage,
catalogPlugin,
} from '@backstage/plugin-catalog';
import {
CatalogImportPage,
catalogImportPlugin,
} from '@backstage/plugin-catalog-import';
import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder';
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha';
import { orgPlugin } from '@backstage/plugin-org';
import { SearchPage } from '@backstage/plugin-search';
import {
Expand All @@ -30,8 +27,6 @@ import { AlertDisplay, OAuthRequestDialog } from '@backstage/core-components';
import { createApp } from '@backstage/app-defaults';
import { AppRouter, FlatRoutes } from '@backstage/core-app-api';
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
import { RequirePermission } from '@backstage/plugin-permission-react';
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';

import { githubAuthApiRef } from '@backstage/core-plugin-api';
import { SignInPage } from '@backstage/core-components';
Expand Down Expand Up @@ -59,9 +54,6 @@ const app = createApp({
createComponent: scaffolderPlugin.routes.root,
viewTechDoc: techdocsPlugin.routes.docRoot,
});
bind(scaffolderPlugin.externalRoutes, {
registerComponent: catalogImportPlugin.routes.importPage,
});
bind(orgPlugin.externalRoutes, {
catalogIndex: catalogPlugin.routes.catalogIndex,
});
Expand Down Expand Up @@ -89,15 +81,7 @@ const routes = (
<ReportIssue />
</TechDocsAddons>
</Route>
<Route path="/create" element={<ScaffolderPage />} />
<Route
path="/catalog-import"
element={
<RequirePermission permission={catalogEntityCreatePermission}>
<CatalogImportPage />
</RequirePermission>
}
/>
<Route path="/create" element={<NextScaffolderPage />} />
<Route path="/search" element={<SearchPage />}>
{searchPage}
</Route>
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/components/Root/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { PropsWithChildren } from 'react';
import { makeStyles } from '@material-ui/core';
import CreateComponentIcon from '@material-ui/icons/AddCircleOutline';
import HomeIcon from '@material-ui/icons/Home';
import LibraryBooks from '@material-ui/icons/LibraryBooks';
import LogoFull from './LogoFull';
Expand Down Expand Up @@ -63,6 +64,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
{/* Global nav, not org-specific */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
<SidebarItem icon={LibraryBooks} to="docs" text="Docs" />
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
{/* End global nav */}
</SidebarGroup>
<SidebarSpace />
Expand Down
5 changes: 4 additions & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@backstage/catalog-client": "^1.4.3",
"@backstage/catalog-model": "^1.4.1",
"@backstage/config": "^1.0.8",
"@backstage/integration": "^1.6.2",
"@backstage/plugin-app-backend": "^0.3.47",
"@backstage/plugin-auth-backend": "^0.18.5",
"@backstage/plugin-auth-node": "^0.2.16",
Expand All @@ -29,6 +30,7 @@
"@backstage/plugin-permission-node": "^0.7.10",
"@backstage/plugin-proxy-backend": "^0.2.41",
"@backstage/plugin-scaffolder-backend": "^1.15.1",
"@backstage/plugin-scaffolder-node": "^0.2.2",
"@backstage/plugin-search-backend": "^1.3.3",
"@backstage/plugin-search-backend-module-pg": "^0.5.8",
"@backstage/plugin-search-backend-node": "^1.2.3",
Expand All @@ -43,7 +45,8 @@
"fs-extra": "^11.1.1",
"js-yaml": "^4.0.0",
"pg": "^8.10.0",
"winston": "^3.2.1"
"winston": "^3.2.1",
"zod": "^3.22.2"
},
"devDependencies": {
"@backstage/cli": "^0.22.9",
Expand Down
16 changes: 15 additions & 1 deletion packages/backend/src/plugins/scaffolder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { CatalogClient } from '@backstage/catalog-client';
import { createRouter } from '@backstage/plugin-scaffolder-backend';
import { createBuiltinActions, createRouter } from '@backstage/plugin-scaffolder-backend';
import { ScmIntegrations } from '@backstage/integration';
import { Router } from 'express';
import type { PluginEnvironment } from '../types';
import { createCodeownersAction } from './scaffolder/actions/custom';

export default async function createPlugin(
env: PluginEnvironment,
Expand All @@ -10,7 +12,19 @@ export default async function createPlugin(
discoveryApi: env.discovery,
});

const integrations = ScmIntegrations.fromConfig(env.config);

const builtInActions = createBuiltinActions({
integrations,
catalogClient,
config: env.config,
reader: env.reader,
});

const actions = [...builtInActions, createCodeownersAction()];

return await createRouter({
actions,
logger: env.logger,
config: env.config,
database: env.database,
Expand Down
43 changes: 43 additions & 0 deletions packages/backend/src/plugins/scaffolder/actions/custom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { writeFile } from 'fs';

export const createCodeownersAction = () => {
return createTemplateAction<{ organization: string; team: string }>({
id: 'github:codeowners:create',
schema: {
input: {
required: ['organization', 'team'],
type: 'object',
properties: {
organization: {
type: 'string',
title: 'Organization',
description: 'The GitHub organization name',
},
team: {
type: 'string',
title: 'Filename',
description: 'The filename of the file that will be created',
},
},
},
},
async handler(ctx) {
const { signal } = ctx;

// Sanitize a string like 'group:default/foobar'
const parts = ctx.input.team.split("/");
const team = parts[parts.length - 1];

let contents = "# generated by giantswarm/github actions - changes will be overwritten\n";
contents += `* @${ctx.input.organization}/${team}\n`;

await writeFile(
`${ctx.workspacePath}/CODEOWNERS`,
contents,
{ signal },
_ => {},
);
},
});
};
Loading