Merge branch 'cloudbuild-plugin' of github.com:ebarriosjr/backstage into cloudbuild-plugin
This commit is contained in:
@@ -7,3 +7,5 @@
|
||||
**/.git/**
|
||||
**/public/**
|
||||
**/microsite/**
|
||||
**/templates/**
|
||||
**/sample-templates/**
|
||||
|
||||
+26
-1
@@ -57,10 +57,22 @@ catalog:
|
||||
rules:
|
||||
- allow: [Component, API, Group, Template, Location]
|
||||
processors:
|
||||
githubApi:
|
||||
github:
|
||||
privateToken:
|
||||
$secret:
|
||||
env: GITHUB_PRIVATE_TOKEN
|
||||
githubApi:
|
||||
providers:
|
||||
- target: https://github.com
|
||||
token:
|
||||
$secret:
|
||||
env: GITHUB_PRIVATE_TOKEN
|
||||
# Example for how to add your GitHub Enterprise instance:
|
||||
# - target: https://ghe.example.net
|
||||
# apiBaseUrl: https://ghe.example.net/api/v3
|
||||
# token:
|
||||
# $secret:
|
||||
# env: GHE_PRIVATE_TOKEN
|
||||
bitbucketApi:
|
||||
username:
|
||||
$secret:
|
||||
@@ -98,6 +110,19 @@ catalog:
|
||||
- type: github
|
||||
target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml
|
||||
|
||||
scaffolder:
|
||||
github:
|
||||
token:
|
||||
$secret:
|
||||
env: GITHUB_ACCESS_TOKEN
|
||||
visibility: public # or 'internal' or 'private'
|
||||
gitlab:
|
||||
api:
|
||||
baseUrl: https://gitlab.com
|
||||
token:
|
||||
$secret:
|
||||
env: GITLAB_ACCESS_TOKEN
|
||||
|
||||
auth:
|
||||
providers:
|
||||
google:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: FAQ
|
||||
title: FAQ
|
||||
description: All FAQ related to Backstage
|
||||
---
|
||||
|
||||
## Product FAQ
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: backend
|
||||
title: Backend
|
||||
description: About Backend
|
||||
---
|
||||
|
||||
## TODO
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: utility-apis
|
||||
title: Utility APIs
|
||||
description: Backstage Utility APIs
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr001
|
||||
title: ADR001: Architecture Decision Record (ADR) log
|
||||
sidebar_label: ADR001
|
||||
description: Architecture Decision Record (ADR) logs as a reference point for the team
|
||||
---
|
||||
|
||||
| Created | Status |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr002
|
||||
title: ADR002: Default Software Catalog File Format
|
||||
sidebar_label: ADR002
|
||||
description: Architecture Decision Record (ADR) log on Default Software Catalog File Format
|
||||
---
|
||||
|
||||
| Created | Status |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr003
|
||||
title: ADR003: Avoid Default Exports and Prefer Named Exports
|
||||
sidebar_label: ADR003
|
||||
description: Architecture Decision Record (ADR) log on Avoid Default Exports and Prefer Named Exports
|
||||
---
|
||||
|
||||
| Created | Status |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr004
|
||||
title: ADR004: Module Export Structure
|
||||
sidebar_label: ADR004
|
||||
description: Architecture Decision Record (ADR) log on Module Export Structure
|
||||
---
|
||||
|
||||
| Created | Status |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr005
|
||||
title: ADR005: Catalog Core Entities
|
||||
sidebar_label: ADR005
|
||||
description: Architecture Decision Record (ADR) log on Catalog Core Entities
|
||||
---
|
||||
|
||||
| Created | Status |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr006
|
||||
title: ADR006: Avoid React.FC and React.SFC
|
||||
sidebar_label: ADR006
|
||||
description: Architecture Decision Record (ADR) log on Avoid React.FC and React.SFC
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr007
|
||||
title: ADR007: Use MSW to mock http requests
|
||||
sidebar_label: ADR007
|
||||
description: Architecture Decision Record (ADR) log on Use MSW to mock http requests
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: adrs-adr008
|
||||
title: ADR008: Default Catalog File Name
|
||||
sidebar_label: ADR008
|
||||
description: Architecture Decision Record (ADR) log on Default Catalog File Name
|
||||
---
|
||||
|
||||
## Background
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
id: adrs-overview
|
||||
title: Architecture Decision Records (ADR)
|
||||
sidebar_label: Overview
|
||||
description: Overview of Architecture Decision Records (ADR)
|
||||
---
|
||||
|
||||
The substantial architecture decisions made in the Backstage project live here.
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: add-auth-provider
|
||||
title: Adding authentication providers
|
||||
description: Documentation on Adding authentication providers
|
||||
---
|
||||
|
||||
## Passport
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: auth-backend-classes
|
||||
title: Auth backend classes
|
||||
description: Documentation on Auth backend classes
|
||||
---
|
||||
|
||||
## How Does Authentication Work?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: auth-backend
|
||||
title: Auth backend
|
||||
description: Documentation on Auth backend
|
||||
---
|
||||
|
||||
## TODO
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: glossary
|
||||
title: Glossary
|
||||
description: All Glossaries related to auth
|
||||
---
|
||||
|
||||
- **Popup** - A separate browser window opened on top of the previous one.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: index
|
||||
title: User Authentication and Authorization in Backstage
|
||||
description: Documentation on User Authentication and Authorization in Backstage
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
+5
-2
@@ -1,6 +1,9 @@
|
||||
---
|
||||
id: oauth
|
||||
title: OAuth and OpenID Connect
|
||||
description: This section describes how Backstage allows plugins to request
|
||||
OAuth Access Tokens and OpenID Connect ID Tokens on behalf of the user, to be
|
||||
used for auth to various third party APIs
|
||||
---
|
||||
|
||||
This section describes how Backstage allows plugins to request OAuth Access
|
||||
@@ -104,10 +107,10 @@ request an access token.
|
||||
|
||||
The following diagram visualizes the flow described in the previous section.
|
||||
|
||||

|
||||

|
||||
|
||||
<!--
|
||||
@startuml oauth-popup-flow
|
||||
@startuml /../assets/auth/oauth-popup-flow
|
||||
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: defining
|
||||
title: Defining Configuration for your Plugin
|
||||
description: Documentation on Defining Configuration for your Plugin
|
||||
---
|
||||
|
||||
There is currently no tooling support or helpers for defining plugin
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: index
|
||||
title: Static Configuration in Backstage
|
||||
description: Documentation on Static Configuration in Backstage
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: reading
|
||||
title: Reading Backstage Configuration
|
||||
description: Documentation on Reading Backstage Configuration
|
||||
---
|
||||
|
||||
## Config API
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: writing
|
||||
title: Writing Backstage Configuration Files
|
||||
description: Documentation on Writing Backstage Configuration Files
|
||||
---
|
||||
|
||||
## File Format
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: contributing-to-storybook
|
||||
title: Contributing to Storybook
|
||||
description: Documentation on How to Contribute to Storybook
|
||||
---
|
||||
|
||||
You find our storybook at
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: design
|
||||
title: Design
|
||||
description: Documentation on Design
|
||||
---
|
||||
|
||||

|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: figma
|
||||
title: Figma
|
||||
description: Documentation on using Figma to build your own plugins for
|
||||
Backstage
|
||||
---
|
||||
|
||||
We have a [Figma component library](https://www.figma.com/@backstage) that you
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: software-catalog-api
|
||||
title: API
|
||||
description: Documentation on Software Catalog API
|
||||
---
|
||||
|
||||
## TODO
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: software-catalog-configuration
|
||||
title: Catalog Configuration
|
||||
description: Documentation on Software Catalog Configuration
|
||||
---
|
||||
|
||||
## Static Location Configuration
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
id: descriptor-format
|
||||
title: Descriptor Format of Catalog Entities
|
||||
sidebar_label: YAML File Format
|
||||
description: Documentation on Descriptor Format of Catalog Entities which
|
||||
describes the default data shape and semantics of catalog entities
|
||||
---
|
||||
|
||||
This section describes the default data shape and semantics of catalog entities.
|
||||
@@ -471,6 +473,7 @@ Describes the following entity kind:
|
||||
An API describes an interface that can be exposed by a component. The API can be
|
||||
defined in different formats, like [OpenAPI](https://swagger.io/specification/),
|
||||
[AsyncAPI](https://www.asyncapi.com/docs/specifications/latest/),
|
||||
[GraphQL](https://graphql.org/learn/schema/),
|
||||
[gRPC](https://developers.google.com/protocol-buffers), or other formats.
|
||||
|
||||
Descriptor files for this kind may look as follows.
|
||||
@@ -483,6 +486,8 @@ metadata:
|
||||
description: Retrieve artist details
|
||||
spec:
|
||||
type: openapi
|
||||
lifecycle: production
|
||||
owner: artist-relations@example.com
|
||||
definition: |
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
@@ -527,6 +532,41 @@ The current set of well-known and common values for this field is:
|
||||
[Protocol Buffers](https://developers.google.com/protocol-buffers) to use with
|
||||
[gRPC](https://grpc.io/).
|
||||
|
||||
### `spec.lifecycle` [required]
|
||||
|
||||
The lifecycle state of the API, e.g. `production`. This field is required.
|
||||
|
||||
The software catalog accepts any lifecycle value, but an organization should
|
||||
take great care to establish a proper taxonomy for these.
|
||||
|
||||
The current set of well-known and common values for this field is:
|
||||
|
||||
- `experimental` - an experiment or early, non-production API, signaling that
|
||||
users may not prefer to consume it over other more established APIs, or that
|
||||
there are low or no reliability guarantees
|
||||
- `production` - an established, owned, maintained API
|
||||
- `deprecated` - an API that is at the end of its lifecycle, and may disappear
|
||||
at a later point in time
|
||||
|
||||
### `spec.owner` [required]
|
||||
|
||||
The owner of the API, e.g. `artist-relations@example.com`. This field is
|
||||
required.
|
||||
|
||||
In Backstage, the owner of an API is the singular entity (commonly a team) that
|
||||
bears ultimate responsibility for the API, and has the authority and capability
|
||||
to develop and maintain it. They will be the point of contact if something goes
|
||||
wrong, or if features are to be requested. The main purpose of this field is for
|
||||
display purposes in Backstage, so that people looking at catalog items can get
|
||||
an understanding of to whom this API belongs. It is not to be used by automated
|
||||
processes to for example assign authorization in runtime systems. There may be
|
||||
others that also develop or otherwise touch the API, but there will always be
|
||||
one ultimate owner.
|
||||
|
||||
Apart from being a string, the software catalog leaves the format of this field
|
||||
open to implementers to choose. Most commonly, it is set to the ID or email of a
|
||||
group of people in an organizational structure.
|
||||
|
||||
### `spec.definition` [required]
|
||||
|
||||
The definition of the API, based on the format defined by `spec.type`. This
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: extending-the-model
|
||||
title: Extending the model
|
||||
description: Documentation on Extending the model
|
||||
---
|
||||
|
||||
Backstage natively supports tracking of the following component
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: external-integrations
|
||||
title: External integrations
|
||||
description: Documentation on External integrations to integrate systems
|
||||
with Backstage
|
||||
---
|
||||
|
||||
Backstage natively supports storing software components in
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
id: software-catalog-overview
|
||||
title: Backstage Service Catalog (alpha)
|
||||
sidebar_label: Overview
|
||||
description: The Backstage Service Catalog — actually, a software catalog, since
|
||||
it includes more than just services
|
||||
---
|
||||
|
||||
## What is a Service Catalog?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: installation
|
||||
title: Installing in your Backstage App
|
||||
description: Documentation on How to install Backstage Plugin
|
||||
---
|
||||
|
||||
The catalog plugin comes in two packages, `@backstage/plugin-catalog` and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: system-model
|
||||
title: System Model
|
||||
description: Documentation on System Model
|
||||
---
|
||||
|
||||
We believe that a strong shared understanding and terminology around software
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
id: well-known-annotations
|
||||
title: Well-known Annotations on Catalog Entities
|
||||
sidebar_label: Well-known Annotations
|
||||
description: Documentation on lists a number of well known Annotations, that
|
||||
have defined semantics. They can be attached to catalog entities and consumed
|
||||
by plugins as needed
|
||||
---
|
||||
|
||||
This section lists a number of well known
|
||||
@@ -51,13 +54,13 @@ The value of this annotation is a location reference string (see above). If this
|
||||
annotation is specified, it is expected to point to a repository that the
|
||||
TechDocs system can read and generate docs from.
|
||||
|
||||
### backstage.io/jenkins-github-folder
|
||||
### jenkins.io/github-folder
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
backstage.io/jenkins-github-folder: folder-name/job-name
|
||||
jenkins.io/github-folder: folder-name/job-name
|
||||
```
|
||||
|
||||
The value of this annotation is the path to a job on Jenkins, that builds this
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adding-templates
|
||||
title: Adding your own Templates
|
||||
description: Documentation on Adding your own Templates
|
||||
---
|
||||
|
||||
Templates are stored in the **Service Catalog** under a kind `Template`. The
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: extending-preparer
|
||||
title: Create your own Preparer
|
||||
description: Documentation on Creating your own Preparer
|
||||
---
|
||||
|
||||
Preparers are responsible for reading the location of the definition of a
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: extending-publisher
|
||||
title: Create your own Publisher
|
||||
description: Documentation on Creating your own Publisher
|
||||
---
|
||||
|
||||
Publishers are responsible for pushing and storing the templated skeleton after
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: extending-templater
|
||||
title: Creating your own Templater
|
||||
description: Documentation on Creating your own Templater
|
||||
---
|
||||
|
||||
Templaters are responsible for taking the directory path for the skeleton
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
id: software-templates-index
|
||||
title: Backstage Software Templates
|
||||
sidebar_label: Overview
|
||||
description: The Software Templates part of Backstage is a tool that can help
|
||||
you create Components inside Backstage
|
||||
---
|
||||
|
||||
The Software Templates part of Backstage is a tool that can help you create
|
||||
Components inside Backstage. By default, it has the ability to load skeletons of
|
||||
code, template in some variables, and then publish the template to some location
|
||||
like GitHub.
|
||||
code, template in some variables, and then publish the template to some
|
||||
locations like GitHub or GitLab.
|
||||
|
||||
<video width="100%" height="100%" controls>
|
||||
<source src="https://backstage.io/blog/assets/2020-08-05/feature.mp4" type="video/mp4">
|
||||
@@ -38,8 +40,10 @@ internally.
|
||||
|
||||
After filling in these variables, you'll get some more fields to fill out which
|
||||
are required for backstage usage: the owner, (which is a `user` in the backstage
|
||||
system), the `storePath` (which right now must be a GitHub Organisation), and a
|
||||
non-existing github repository name in the format `organisation/reponame`.
|
||||
system), the `storePath` (which right now must be a GitHub Organisation or
|
||||
GitHub user), a non-existing github repository name in the format
|
||||
`organisation/reponame`, and a GitHub team or user account which should be
|
||||
granted admin access to the repository.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: installation
|
||||
title: Installing in your Backstage App
|
||||
description: Documentation on How to install Backstage App
|
||||
---
|
||||
|
||||
The scaffolder plugin comes in two packages, `@backstage/plugin-scaffolder` and
|
||||
@@ -86,41 +87,74 @@ import {
|
||||
createRouter,
|
||||
FilePreparer,
|
||||
GithubPreparer,
|
||||
GitlabPreparer,
|
||||
Preparers,
|
||||
Publishers,
|
||||
GithubPublisher,
|
||||
GitlabPublisher,
|
||||
CreateReactAppTemplater,
|
||||
Templaters,
|
||||
RepoVisilityOptions,
|
||||
} from '@backstage/plugin-scaffolder-backend';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { Gitlab } from '@gitbeaker/node';
|
||||
import type { PluginEnvironment } from '../types';
|
||||
import Docker from 'dockerode';
|
||||
|
||||
export default async function createPlugin({ logger }: PluginEnvironment) {
|
||||
export default async function createPlugin({
|
||||
logger,
|
||||
config,
|
||||
}: PluginEnvironment) {
|
||||
const cookiecutterTemplater = new CookieCutter();
|
||||
const craTemplater = new CreateReactAppTemplater();
|
||||
const templaters = new Templaters();
|
||||
|
||||
// Register default templaters
|
||||
templaters.register('cookiecutter', cookiecutterTemplater);
|
||||
templaters.register('cra', craTemplater);
|
||||
|
||||
const filePreparer = new FilePreparer();
|
||||
const githubPreparer = new GithubPreparer();
|
||||
const gitlabPreparer = new GitlabPreparer(config);
|
||||
const preparers = new Preparers();
|
||||
|
||||
// Register default preparers
|
||||
preparers.register('file', filePreparer);
|
||||
preparers.register('github', githubPreparer);
|
||||
preparers.register('gitlab', gitlabPreparer);
|
||||
preparers.register('gitlab/api', gitlabPreparer);
|
||||
|
||||
// Create GitHub client with your access token from environment variables
|
||||
const githubClient = new Octokit({ auth: process.env.GITHUB_ACCESS_TOKEN });
|
||||
const publisher = new GithubPublisher({ client: githubClient });
|
||||
const publishers = new Publishers();
|
||||
|
||||
const githubToken = config.getString('scaffolder.github.token');
|
||||
const repoVisibility = config.getString(
|
||||
'scaffolder.github.visibility',
|
||||
) as RepoVisilityOptions;
|
||||
|
||||
const githubClient = new Octokit({ auth: githubToken });
|
||||
const githubPublisher = new GithubPublisher({
|
||||
client: githubClient,
|
||||
token: githubToken,
|
||||
repoVisibility,
|
||||
});
|
||||
publishers.register('file', githubPublisher);
|
||||
publishers.register('github', githubPublisher);
|
||||
|
||||
const gitLabConfig = config.getOptionalConfig('scaffolder.gitlab.api');
|
||||
|
||||
if (gitLabConfig) {
|
||||
const gitLabToken = gitLabConfig.getString('token');
|
||||
const gitLabClient = new Gitlab({
|
||||
host: gitLabConfig.getOptionalString('baseUrl'),
|
||||
token: gitLabToken,
|
||||
});
|
||||
const gitLabPublisher = new GitlabPublisher(gitLabClient, gitLabToken);
|
||||
publishers.register('gitlab', gitLabPublisher);
|
||||
publishers.register('gitlab/api', gitLabPublisher);
|
||||
}
|
||||
|
||||
const dockerClient = new Docker();
|
||||
return await createRouter({
|
||||
preparers,
|
||||
templaters,
|
||||
publisher,
|
||||
publishers,
|
||||
logger,
|
||||
dockerClient,
|
||||
});
|
||||
@@ -167,7 +201,7 @@ catalog:
|
||||
target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml
|
||||
```
|
||||
|
||||
### Runtime Dependencies
|
||||
### Runtime Dependencies / Configuration
|
||||
|
||||
For the scaffolder backend plugin to function, it needs a GitHub access token,
|
||||
and access to a running Docker daemon. You can create a GitHub access token
|
||||
@@ -177,8 +211,37 @@ docs on creating private GitHub access tokens is available
|
||||
Note that the need for private GitHub access tokens will be replaced with GitHub
|
||||
Apps integration further down the line.
|
||||
|
||||
The GitHub access token is passed along using the `GITHUB_ACCESS_TOKEN`
|
||||
environment variable.
|
||||
#### Github
|
||||
|
||||
The Github access token is retrieved from environment variables via the config.
|
||||
The config file needs to specify what environment variable the token is
|
||||
retrieved from. Your config should have the following objects.
|
||||
|
||||
#### Gitlab
|
||||
|
||||
For Gitlab, we currently support the configuration of the GitLab publisher and
|
||||
allows to configure the private access token and the base URL of a GitLab
|
||||
instance:
|
||||
|
||||
```yaml
|
||||
scaffolder:
|
||||
github:
|
||||
token:
|
||||
$secret:
|
||||
env: GITHUB_ACCESS_TOKEN
|
||||
visibility: public # or 'internal' or 'private'
|
||||
gitlab:
|
||||
api:
|
||||
baseUrl: https://gitlab.com
|
||||
token:
|
||||
$secret:
|
||||
env: SCAFFOLDER_GITLAB_PRIVATE_TOKEN
|
||||
```
|
||||
|
||||
You can configure who can see the new repositories that the scaffolder creates
|
||||
by specifying `visibility` option. Valid options are `public`, `private` and
|
||||
`internal`. `internal` options is for GitHub Enterprise clients, which means
|
||||
public within the organization.
|
||||
|
||||
### Running the Backend
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
id: faqs
|
||||
title: TechDocs FAQ
|
||||
sidebar_label: FAQ
|
||||
description: This page answers frequently asked questions about TechDocs
|
||||
---
|
||||
|
||||
This page answers frequently asked questions about [TechDocs](README.md).
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
id: techdocs-overview
|
||||
title: TechDocs Documentation
|
||||
sidebar_label: Overview
|
||||
description: TechDocs is Spotify’s homegrown docs-like-code solution built
|
||||
directly into Backstage
|
||||
---
|
||||
|
||||
## What is it?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: architecture
|
||||
title: Architecture
|
||||
description: Documentation on Architecture
|
||||
---
|
||||
|
||||

|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: concepts
|
||||
title: Concepts
|
||||
description: Documentation on concepts that are introduced with
|
||||
Spotify's docs-like-code solution in Backstage
|
||||
---
|
||||
|
||||
This page describes concepts that are introduced with Spotify's docs-like-code
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
id: creating-and-publishing
|
||||
title: Creating and publishing your docs
|
||||
sidebar_label: Creating and Publishing Documentation
|
||||
description: Guidance on how to create and publish documentation
|
||||
---
|
||||
|
||||
This section will guide you through:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: getting-started
|
||||
title: Getting Started
|
||||
description: Getting Started Guidelines
|
||||
---
|
||||
|
||||
TechDocs functions as a plugin to Backstage, so you will need to use Backstage
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: app-custom-theme
|
||||
title: Customize the look-and-feel of your App
|
||||
description: Documentation on Customizing look and feel of the App
|
||||
---
|
||||
|
||||
Backstage ships with a default theme with a light and dark mode variant. The
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: configure-app-with-plugins
|
||||
title: Configuring App with plugins
|
||||
description: Documentation on How Configuring App with plugins
|
||||
---
|
||||
|
||||
## Adding existing plugins to your app
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: create-an-app
|
||||
title: Create an App
|
||||
description: Documentation on Creating an App
|
||||
---
|
||||
|
||||
To get set up quickly with your own Backstage project you can create a Backstage
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: deployment-k8s
|
||||
title: Kubernetes
|
||||
description: Documentation on Kubernetes and K8s Deployment
|
||||
---
|
||||
|
||||
Coming soon!
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: deployment-other
|
||||
title: Other
|
||||
description: Documentation on different ways of Deployment
|
||||
---
|
||||
|
||||
## Deploying Locally
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: development-environment
|
||||
title: Development Environment
|
||||
description: Documentation on how to get set up for doing development on
|
||||
the Backstage repository
|
||||
---
|
||||
|
||||
This section describes how to get set up for doing development on the Backstage
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: index
|
||||
title: Getting Started
|
||||
description: Documentation on How to get started with Backstage
|
||||
---
|
||||
|
||||
There are two different ways to get started with Backstage, either by creating a
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: installation
|
||||
title: Installation
|
||||
description: Documentation on Installation
|
||||
---
|
||||
|
||||
Coming soon!
|
||||
|
||||
@@ -1,23 +1,42 @@
|
||||
---
|
||||
id: running-backstage-locally
|
||||
title: Running Backstage Locally
|
||||
description: Documentation on How to run Backstage Locally
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js
|
||||
|
||||
First make sure you are using NodeJS with an Active LTS Release, currently v12.
|
||||
This is made easy with a version manager such as
|
||||
[nvm](https://github.com/nvm-sh/nvm) which allows for version switching.
|
||||
|
||||
```bash
|
||||
# Checking your version
|
||||
node --version
|
||||
> v14.7.0
|
||||
|
||||
# Adding a second node version
|
||||
# Installing a new version
|
||||
nvm install 12
|
||||
> Downloading and installing node v12.18.3...
|
||||
> Now using node v12.18.3 (npm v6.14.6)
|
||||
|
||||
# Checking your version
|
||||
node --version
|
||||
> v12.18.3
|
||||
```
|
||||
|
||||
- yarn
|
||||
|
||||
Please refer to the
|
||||
[installation instructions for yarn](https://classic.yarnpkg.com/en/docs/install/).
|
||||
|
||||
- Docker
|
||||
|
||||
We use Docker for few of our core features. So, you will need Docker installed
|
||||
locally to use features like Software Templates and TechDocs. Please refer to
|
||||
the
|
||||
[installation instructions for Docker](https://docs.docker.com/engine/install/).
|
||||
|
||||
## Clone and Build
|
||||
|
||||
To get up and running with a local Backstage to evaluate it, let's clone it off
|
||||
of GitHub and run an initial build.
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: adopting
|
||||
title: Strategies for adopting
|
||||
description: Documentation on some general best practices that have been key
|
||||
to Backstage's success inside Spotify
|
||||
---
|
||||
|
||||
This document outlines some general best practices that have been key to
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: architecture-overview
|
||||
title: Architecture overview
|
||||
description: Documentation on Architecture overview
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: architecture-terminology
|
||||
title: Architecture terminology
|
||||
description: Documentation on Architecture terminology
|
||||
---
|
||||
|
||||
Backstage is constructed out of three parts. We separate Backstage in this way
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: background
|
||||
title: The Spotify Story
|
||||
description: Documentation on Background and Story behind making of Backstage
|
||||
---
|
||||
|
||||
Backstage was born out of necessity at Spotify. We found that as we grew, our
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
id: logos
|
||||
title: Logos
|
||||
sidebar_label: Logo assets
|
||||
description: Guidelines for how to use the Backstage logos and icons
|
||||
---
|
||||
|
||||
Guidelines for how to use the Backstage logo and icon can be found
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: roadmap
|
||||
title: Project roadmap
|
||||
description: Roadmap of Backstage Project
|
||||
---
|
||||
|
||||
## Current status
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: support
|
||||
title: Support and community
|
||||
description: Support and Community Details and Links
|
||||
---
|
||||
|
||||
- [Discord chatroom](https://discord.gg/MUpMjP2) - Get support or discuss the
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: vision
|
||||
title: Vision
|
||||
description: Goal is to provide engineers with the best developer experience in
|
||||
the world
|
||||
---
|
||||
|
||||
Our goal is to provide engineers with the best developer experience in the
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: what-is-backstage
|
||||
title: What is Backstage?
|
||||
description: Backsatge is an open platform for building developer portals.
|
||||
Powered by a centralized service catalog, Backstage restores order to your microservices and infrastructure
|
||||
---
|
||||
|
||||

|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: add-to-marketplace
|
||||
title: Add to Marketplace
|
||||
description: Documentation on Adding Plugin to Marketplace
|
||||
---
|
||||
|
||||
## Adding a Plugin to the Marketplace
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: backend-plugin
|
||||
title: Backend plugin
|
||||
description: Documentation on Backend plugin
|
||||
---
|
||||
|
||||
## TODO
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
id: call-existing-api
|
||||
title: Call Existing API
|
||||
description: Describes the various options that Backstage frontend plugins have,
|
||||
in communicating with service APIs that already exist
|
||||
---
|
||||
|
||||
This article describes the various options that Backstage frontend plugins have,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: create-a-plugin
|
||||
title: Create a Backstage Plugin
|
||||
description: Documentation on How to Create a Backstage Plugin
|
||||
---
|
||||
|
||||
A Backstage Plugin adds functionality to Backstage.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: existing-plugins
|
||||
title: Existing plugins
|
||||
description: Lists of existing open source plugins
|
||||
---
|
||||
|
||||
## Open source plugins
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: index
|
||||
title: Intro to plugins
|
||||
description: Documentation on Introduction to Plugins
|
||||
---
|
||||
|
||||
Backstage is a single-page application composed of a set of plugins.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: integrating-plugin-into-service-catalog
|
||||
title: Integrate into the Service Catalog
|
||||
description: Documentation on How to integrate plugin into service catalog
|
||||
---
|
||||
|
||||
> This is an advanced use case and currently is an experimental feature. Expect
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: plugin-development
|
||||
title: Plugin Development
|
||||
description: Documentation on Plugin Development
|
||||
---
|
||||
|
||||
Backstage plugins provide features to a Backstage App.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: proxying
|
||||
title: Proxying
|
||||
description: Documentation on Proxying
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: publish-private
|
||||
title: Publish private
|
||||
description: Documentation on How to Publish private
|
||||
---
|
||||
|
||||
## TODO
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: publishing
|
||||
title: Publishing
|
||||
description: Documentation on Publishing NPM packages
|
||||
---
|
||||
|
||||
## NPM
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: structure-of-a-plugin
|
||||
title: Structure of a Plugin
|
||||
description: Details about structure of a plugin
|
||||
---
|
||||
|
||||
Nice, you have a new plugin! We'll soon see how we can develop it into doing
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: testing
|
||||
title: Testing with Jest
|
||||
description: Documentation on How to do unit testing with Jest
|
||||
---
|
||||
|
||||
Backstage uses [Jest](https://facebook.github.io/jest/) for all our unit testing
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: createPlugin-feature-flags
|
||||
title: createPlugin - feature flags
|
||||
description: Documentation on createPlugin - feature flags
|
||||
---
|
||||
|
||||
The `featureFlags` object passed to the `register` function makes it possible
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: createPlugin-router
|
||||
title: createPlugin - router
|
||||
description: Documentation on createPlugin - router
|
||||
---
|
||||
|
||||
The router that is passed to the `register` function makes it possible for
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: createPlugin
|
||||
title: createPlugin
|
||||
description: Documentation on createPlugin
|
||||
---
|
||||
|
||||
Taking a plugin config as argument and returns a new plugin.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: journey
|
||||
title: Future developer journey
|
||||
description: This document describes a possible journey of a future Backstage
|
||||
---
|
||||
|
||||
> This document describes a possible journey of a **_future_** Backstage plugin
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
---
|
||||
id: quickstart-app-auth
|
||||
title: Monorepo App Setup With Authentication
|
||||
---
|
||||
|
||||
###### September 15th 2020 - @backstage/create-app - v0.1.1-alpha.21
|
||||
|
||||
<br />
|
||||
|
||||
> This document takes you through setting up a backstage app that runs in your
|
||||
> own environment. It starts with a skeleton install and verifying of the
|
||||
> monorepo's functionality. Next, GitHub authentication is added and tested.
|
||||
>
|
||||
> This document assumes you have NodeJS 12 active along with Yarn. Please note,
|
||||
> that at the time of this writing, the current version is 0.1.1-alpha.21. This
|
||||
> guide can still be used with future versions, just, verify as you go. If you
|
||||
> run into issues, you can compare your setup with mine here >
|
||||
> [simple-backstage-app](https://github.com/johnson-jesse/simple-backstage-app).
|
||||
|
||||
# The Skeleton Application
|
||||
|
||||
From the terminal:
|
||||
|
||||
1. Create a (monorepo) application: `npx @backstage/create-app`
|
||||
1. Enter an `id` for your new app like `mybiz-backstage` I went with
|
||||
`simple-backstage-app`
|
||||
1. Choose `SQLite` as your database. This is the quickest way to get started as
|
||||
PostgreSQL requires additional setup not covered here.
|
||||
1. Start your backend: `yarn --cwd packages/backend start`
|
||||
|
||||
```zsh
|
||||
# You should see positive verbiage in your terminal output
|
||||
2020-09-11T22:20:26.712Z backstage info Listening on :7000
|
||||
```
|
||||
|
||||
5. Finally, start the frontend. Open a new terminal window and from the root of
|
||||
your project, run: `yarn start`
|
||||
|
||||
```zsh
|
||||
# You should see positive verbiage in your terminal output
|
||||
ℹ 「wds」: Project is running at http://localhost:3000/
|
||||
```
|
||||
|
||||
Once the app compiles, a browser window should have popped with your stand alone
|
||||
application loaded at `localhost:3000`. This could take a couple minutes.
|
||||
|
||||
```zsh
|
||||
# You should see positive verbiage in your terminal output
|
||||
ℹℹ 「wdm」: Compiled successfully.
|
||||
```
|
||||
|
||||
Since there is no auth currently configured, you are automatically entered as a
|
||||
guest. Let's fix that now and add auth.
|
||||
|
||||
# The Auth Configuration
|
||||
|
||||
1. Open `app-config.yaml` and change it as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers: {}
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers:
|
||||
github:
|
||||
development:
|
||||
clientId:
|
||||
$secret:
|
||||
env: AUTH_GITHUB_CLIENT_ID
|
||||
clientSecret:
|
||||
$secret:
|
||||
env: AUTH_GITHUB_CLIENT_SECRET
|
||||
## uncomment the following three lines if using enterprise
|
||||
# enterpriseInstanceUrl:
|
||||
# $secret:
|
||||
# env: AUTH_GITHUB_ENTERPRISE_INSTANCE_URL
|
||||
```
|
||||
|
||||
2. Set environment variables in whatever fashion is easiest for you. I chose to
|
||||
add mine to my `.zshrc` profile.
|
||||
|
||||
```zsh
|
||||
# For macOS Catalina & Z Shell
|
||||
# ------ simple-backstage-app GitHub
|
||||
export AUTH_GITHUB_CLIENT_ID=xxx
|
||||
export AUTH_GITHUB_CLIENT_SECRET=xxx
|
||||
# export AUTH_GITHUB_ENTERPRISE_INSTANCE_URL=https://github.{MY_BIZ}.com
|
||||
```
|
||||
|
||||
3. And of course I need to source that file.
|
||||
|
||||
```zsh
|
||||
# Loading the new variables
|
||||
% source ~/.zshrc
|
||||
|
||||
# Any other currently opened terminals need to be restarted to pick up the new values
|
||||
# verify your setup by running env
|
||||
% env
|
||||
# should output something like
|
||||
> ...
|
||||
> AUTH_GITHUB_CLIENT_ID=xxx
|
||||
> AUTH_GITHUB_CLIENT_SECRET=xxx
|
||||
> ...
|
||||
```
|
||||
|
||||
4. The values to replace `xxx` above come from your oauth app setup.
|
||||
|
||||
```
|
||||
> Log into http://github.com
|
||||
> Navigate to (Settings > Developer Settings > OAuth Apps > New OAuth App)[https://github.com/settings/applications/new]
|
||||
> Set Homepage URL = http://localhost:3000
|
||||
> Set Callback URL = http://localhost:7000/auth/github
|
||||
> Click [Register application]
|
||||
> On the next page, copy and paste your new Client ID and Client Secret to the environment variables above, `AUTH_GITHUB_CLIENT_ID` & `AUTH_GITHUB_CLIENT_SECRET`
|
||||
> Don't forget to `source` that profile file again if necessary.
|
||||
```
|
||||
|
||||
5. Open and change _root > packages > app > src >_`App.tsx` as follows
|
||||
|
||||
```tsx
|
||||
// Add the following imports to the existing list from core
|
||||
import { githubAuthApiRef, SignInPage } from '@backstage/core';
|
||||
```
|
||||
|
||||
6. In the same file, change the createApp function as follows
|
||||
|
||||
```tsx
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
return (
|
||||
<SignInPage
|
||||
{...props}
|
||||
providers={[
|
||||
{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Simple Backstage Application Login',
|
||||
apiRef: githubAuthApiRef,
|
||||
},
|
||||
]}
|
||||
align="center"
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
6. Open and change _root > packages > app > src >_ `apis.ts` as follows
|
||||
|
||||
```ts
|
||||
// Add the following imports to the existing list from core
|
||||
import { githubAuthApiRef, GithubAuth } from '@backstage/core';
|
||||
```
|
||||
|
||||
7. In the same file, change the builder block for oauthRequestApiRef as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```ts
|
||||
builder.add(oauthRequestApiRef, new OAuthRequestManager());
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```ts
|
||||
const oauthRequestApi = builder.add(
|
||||
oauthRequestApiRef,
|
||||
new OAuthRequestManager(),
|
||||
);
|
||||
|
||||
builder.add(
|
||||
githubAuthApiRef,
|
||||
GithubAuth.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
> Start the backend and frontend as before. When the browser loads, you should
|
||||
> be presented with a login page for GitHub. Login as usual with your GitHub
|
||||
> account. If this is your first time, you will be asked to authorize and then
|
||||
> are redirected to the catalog page if all is well.
|
||||
|
||||
# Where to go from here
|
||||
|
||||
> You're probably eager to write your first custom plugin. Follow this next
|
||||
> tutorial for an in-depth look at a custom GitHub repository browser plugin.
|
||||
> [Adding Custom Plugin to Existing Monorepo App](quickstart-app-plugin.md).
|
||||
@@ -0,0 +1,487 @@
|
||||
---
|
||||
id: quickstart-app-plugin
|
||||
title: Adding Custom Plugin to Existing Monorepo App
|
||||
---
|
||||
|
||||
###### September 15th 2020 - v0.1.1-alpha.21
|
||||
|
||||
<br />
|
||||
|
||||
> This document takes you through setting up a new plugin for your existing
|
||||
> monorepo with a _GitHub provider already setup_. If you don't have either of
|
||||
> those, you can clone
|
||||
> [simple-backstage-app](https://github.com/johnson-jesse/simple-backstage-app)
|
||||
> which this document builds on.
|
||||
>
|
||||
> This document does not cover authoring a plugin for sharing with the Backstage
|
||||
> community. That will have to be a later discussion.
|
||||
>
|
||||
> We start with a skeleton plugin install. And after verifying its
|
||||
> functionality, extend the Sidebar to make our life easy. Finally, we add
|
||||
> custom code to display GitHub repository information.
|
||||
>
|
||||
> This document assumes you have NodeJS 12 active along with Yarn. Please note,
|
||||
> that at the time of this writing, the current version is 0.1.1-alpha.21. This
|
||||
> guide can still be used with future versions, just, verify as you go. If you
|
||||
> run into issues, you can compare your setup with mine here >
|
||||
> [simple-backstage-app-plugin](https://github.com/johnson-jesse/simple-backstage-app-plugin).
|
||||
|
||||
# The Skeleton Plugin
|
||||
|
||||
1. Start by using the built in creator. From the terminal and root of your
|
||||
project run: `yarn create-plugin`
|
||||
1. Enter a plugin ID. I used `github-playground`
|
||||
1. When the process finishes, let's start the backend:
|
||||
`yarn --cwd packages/backend start`
|
||||
1. If you see errors starting, refer to
|
||||
[Auth Configuration](https://github.com/johnson-jesse/simple-backstage-app/blob/master/README.md#the-auth-configuration)
|
||||
for more information on environment variables.
|
||||
1. And now the frontend, from a new terminal window and the root of your
|
||||
project: `yarn start`
|
||||
1. As usual, a browser window should popup loading the App.
|
||||
1. Now manually navigate to our plugin page from your browser:
|
||||
`http://localhost:3000/github-playground`
|
||||
1. You should see successful verbiage for this endpoint,
|
||||
`Welcome to github-playground!`
|
||||
|
||||
# The Shortcut
|
||||
|
||||
Let's add a shortcut.
|
||||
|
||||
1. Open and modify `root: packages > app > src > sidebar.tsx` with the
|
||||
following:
|
||||
|
||||
```tsx
|
||||
import GitHubIcon from '@material-ui/icons/GitHub';
|
||||
...
|
||||
<SidebarItem icon={GitHubIcon} to="github-playground" text="GitHub Repository" />
|
||||
```
|
||||
|
||||
Simple! The App will reload with your changes automatically. You should now see
|
||||
a github icon displayed in the sidebar. Clicking that will link to our new
|
||||
plugin. And now, the API fun begins.
|
||||
|
||||
# The Identity
|
||||
|
||||
Our first modification will be to extract information from the Identity API.
|
||||
|
||||
1. Start by opening
|
||||
`root: plugins > github-playground > src > components > ExampleComponent > ExampleComponent.tsx`
|
||||
1. Add two new imports
|
||||
|
||||
```tsx
|
||||
// Add identityApiRef to the list of imported from core
|
||||
import { identityApiRef } from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
```
|
||||
|
||||
3. Adjust the ExampleComponent from inline to block
|
||||
|
||||
_from inline:_
|
||||
|
||||
```tsx
|
||||
const ExampleComponent: FC<{}> = () => ( ... )
|
||||
```
|
||||
|
||||
_to block:_
|
||||
|
||||
```tsx
|
||||
const ExampleComponent: FC<{}> = () => {
|
||||
|
||||
return (
|
||||
...
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
4. Now add our hook and const data before the return statement
|
||||
|
||||
```tsx
|
||||
// our API hook
|
||||
const identityApi = useApi(identityApiRef);
|
||||
|
||||
// data to use
|
||||
const userId = identityApi.getUserId();
|
||||
const profile = identityApi.getProfile();
|
||||
```
|
||||
|
||||
5. Finally, update the InfoCard's jsx to use our new data
|
||||
|
||||
```tsx
|
||||
<InfoCard title={userId}>
|
||||
<Typography variant="body1">
|
||||
{`${profile.displayName} | ${profile.email}`}
|
||||
</Typography>
|
||||
</InfoCard>
|
||||
```
|
||||
|
||||
If everything is saved, you should see your name, id, and email on the
|
||||
github-playground page. Our data accessed is synchronous. So we just grab and
|
||||
go.
|
||||
|
||||
6. Here is the entire file for reference
|
||||
<details><summary>Complete ExampleComponent.tsx</summary>
|
||||
<p>
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { Typography, Grid } from '@material-ui/core';
|
||||
import {
|
||||
InfoCard,
|
||||
Header,
|
||||
Page,
|
||||
pageTheme,
|
||||
Content,
|
||||
ContentHeader,
|
||||
HeaderLabel,
|
||||
SupportButton,
|
||||
identityApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import ExampleFetchComponent from '../ExampleFetchComponent';
|
||||
|
||||
const ExampleComponent: FC<{}> = () => {
|
||||
const identityApi = useApi(identityApiRef);
|
||||
const userId = identityApi.getUserId();
|
||||
const profile = identityApi.getProfile();
|
||||
|
||||
return (
|
||||
<Page theme={pageTheme.tool}>
|
||||
<Header
|
||||
title="Welcome to github-playground!"
|
||||
subtitle="Optional subtitle"
|
||||
>
|
||||
<HeaderLabel label="Owner" value="Team X" />
|
||||
<HeaderLabel label="Lifecycle" value="Alpha" />
|
||||
</Header>
|
||||
<Content>
|
||||
<ContentHeader title="Plugin title">
|
||||
<SupportButton>A description of your plugin goes here.</SupportButton>
|
||||
</ContentHeader>
|
||||
<Grid container spacing={3} direction="column">
|
||||
<Grid item>
|
||||
<InfoCard title={userId}>
|
||||
<Typography variant="body1">
|
||||
{`${profile.displayName} | ${profile.email}`}
|
||||
</Typography>
|
||||
</InfoCard>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<ExampleFetchComponent />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExampleComponent;
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
# The Wipe
|
||||
|
||||
The last file we will touch is ExampleFetchComponent. Because of the number of
|
||||
changes, let's start by wiping this component clean.
|
||||
|
||||
1. Start by opening
|
||||
`root: plugins > github-playground > src > components > ExampleFetchComponent > ExampleFetchComponent.tsx`
|
||||
1. Replace everyting in the file with the following:
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import {
|
||||
Table,
|
||||
TableColumn,
|
||||
Progress,
|
||||
githubAuthApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import { graphql } from '@octokit/graphql';
|
||||
|
||||
const ExampleFetchComponent: FC<{}> = () => {
|
||||
return <div>Nothing to see yet</div>;
|
||||
};
|
||||
|
||||
export default ExampleFetchComponent;
|
||||
```
|
||||
|
||||
3. Save that and ensure you see no errors. Comment out the unused imports if
|
||||
your linter gets in the way.
|
||||
|
||||
###### We will add a lot to this file for the sake of ease. Please don't do this in productional code!
|
||||
|
||||
# The Graph Model
|
||||
|
||||
GitHub has a graphql API available for interacting. Let's start by adding our
|
||||
basic repository query
|
||||
|
||||
1. Add the query const statement outside ExampleFetchComponent
|
||||
|
||||
```tsx
|
||||
const query = `{
|
||||
viewer {
|
||||
repositories(first: 100) {
|
||||
totalCount
|
||||
nodes {
|
||||
name
|
||||
createdAt
|
||||
description
|
||||
diskUsage
|
||||
isFork
|
||||
}
|
||||
pageInfo {
|
||||
endCursor
|
||||
hasNextPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
```
|
||||
|
||||
2. Using this structure as a guide, we will break our query into type parts
|
||||
3. Add the following outside of ExampleFetchComponent
|
||||
|
||||
```tsx
|
||||
type Node = {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
description: string;
|
||||
diskUsage: number;
|
||||
isFork: boolean;
|
||||
};
|
||||
|
||||
type Viewer = {
|
||||
repositories: {
|
||||
totalCount: number;
|
||||
nodes: Node[];
|
||||
pageInfo: {
|
||||
endCursor: string;
|
||||
hasNextPage: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
# The Tabel Model
|
||||
|
||||
Using Backstage's own component library, let's define a custom table. This
|
||||
component will get used if we have data to display.
|
||||
|
||||
1. Add the following outside of ExampleFetchComponent
|
||||
|
||||
```tsx
|
||||
type DenseTableProps = {
|
||||
viewer: Viewer;
|
||||
};
|
||||
|
||||
export const DenseTable: FC<DenseTableProps> = ({ viewer }) => {
|
||||
const columns: TableColumn[] = [
|
||||
{ title: 'Name', field: 'name' },
|
||||
{ title: 'Created', field: 'createdAt' },
|
||||
{ title: 'Description', field: 'description' },
|
||||
{ title: 'Disk Usage', field: 'diskUsage' },
|
||||
{ title: 'Fork', field: 'isFork' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={columns}
|
||||
data={viewer.repositories.nodes}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
# The Fetch
|
||||
|
||||
We're ready to flush out our fetch component
|
||||
|
||||
1. Add our api hook inside ExampleFetchComponent
|
||||
|
||||
```tsx
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
```
|
||||
|
||||
2. The access token we need to make our GitHub request and the request itself is
|
||||
obtained in an asynchronous manner.
|
||||
3. Add the useAsync block inside the ExampleFetchComponent
|
||||
|
||||
```tsx
|
||||
const { value, loading, error } = useAsync(async (): Promise<any> => {
|
||||
const token = await auth.getAccessToken();
|
||||
|
||||
const gqlEndpoint = graphql.defaults({
|
||||
// Uncomment baseUrl if using enterprise
|
||||
// baseUrl: 'https://github.MY-BIZ.com/api',
|
||||
headers: {
|
||||
authorization: `token ${token}`,
|
||||
},
|
||||
});
|
||||
const { viewer } = await gqlEndpoint(query);
|
||||
return viewer;
|
||||
}, []);
|
||||
```
|
||||
|
||||
4. The resolved data is conventiently destructured with value containing our
|
||||
Viewer type. loading as a boolean, self explainatory. And error which is
|
||||
present only if necessary. So let's use those as the first 3 of 4 multi
|
||||
return statements.
|
||||
5. Add the _if return_ blocks below our async block
|
||||
|
||||
```tsx
|
||||
if (loading) return <Progress />;
|
||||
if (error) return <Alert severity="error">{error.message}</Alert>;
|
||||
if (value && value.repositories) return <DenseTable viewer={value} />;
|
||||
```
|
||||
|
||||
6. The third line here utilizes our custom table accepting our Viewer type.
|
||||
7. Finally, we add our _else return_ block to catch any other scenarios.
|
||||
|
||||
```tsx
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={[]}
|
||||
data={[]}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
8. After saving that, and given we don't have any errors, you should see a table
|
||||
with basic information on your repositories.
|
||||
9. Here is the entire file for reference
|
||||
<details><summary>Complete ExampleFetchComponent.tsx</summary>
|
||||
<p>
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import {
|
||||
Table,
|
||||
TableColumn,
|
||||
Progress,
|
||||
githubAuthApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import { graphql } from '@octokit/graphql';
|
||||
|
||||
const query = `{
|
||||
viewer {
|
||||
repositories(first: 100) {
|
||||
totalCount
|
||||
nodes {
|
||||
name
|
||||
createdAt
|
||||
description
|
||||
diskUsage
|
||||
isFork
|
||||
}
|
||||
pageInfo {
|
||||
endCursor
|
||||
hasNextPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
type Node = {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
description: string;
|
||||
diskUsage: number;
|
||||
isFork: boolean;
|
||||
};
|
||||
|
||||
type Viewer = {
|
||||
repositories: {
|
||||
totalCount: number;
|
||||
nodes: Node[];
|
||||
pageInfo: {
|
||||
endCursor: string;
|
||||
hasNextPage: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type DenseTableProps = {
|
||||
viewer: Viewer;
|
||||
};
|
||||
|
||||
export const DenseTable: FC<DenseTableProps> = ({ viewer }) => {
|
||||
const columns: TableColumn[] = [
|
||||
{ title: 'Name', field: 'name' },
|
||||
{ title: 'Created', field: 'createdAt' },
|
||||
{ title: 'Description', field: 'description' },
|
||||
{ title: 'Disk Usage', field: 'diskUsage' },
|
||||
{ title: 'Fork', field: 'isFork' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={columns}
|
||||
data={viewer.repositories.nodes}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const ExampleFetchComponent: FC<{}> = () => {
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
|
||||
const { value, loading, error } = useAsync(async (): Promise<any> => {
|
||||
const token = await auth.getAccessToken();
|
||||
|
||||
const gqlEndpoint = graphql.defaults({
|
||||
// Uncomment baseUrl if using enterprise
|
||||
// baseUrl: 'https://github.MY-BIZ.com/api',
|
||||
headers: {
|
||||
authorization: `token ${token}`,
|
||||
},
|
||||
});
|
||||
const { viewer } = await gqlEndpoint(query);
|
||||
return viewer;
|
||||
}, []);
|
||||
|
||||
if (loading) return <Progress />;
|
||||
if (error) return <Alert severity="error">{error.message}</Alert>;
|
||||
if (value && value.repositories) return <DenseTable viewer={value} />;
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={[]}
|
||||
data={[]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExampleFetchComponent;
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
10. We finished! If there are no errors, you should see your own GitHub
|
||||
repoistory information displayed in a basic table. If you run into issues,
|
||||
you can compare the repo that backs this documdnt,
|
||||
[simple-backstage-app-plugin](https://github.com/johnson-jesse/simple-backstage-app-plugin)
|
||||
|
||||
# Where to go from here
|
||||
|
||||
> Break apart ExampleFetchComponent into smaller logical parts contained in
|
||||
> their own files. Rename your components to something other than ExampleXxx.
|
||||
>
|
||||
> You might be real proud of a plugin you develop. Follow this next tutorial for
|
||||
> an in-depth look at publishing and including that for the entire Backstage
|
||||
> community. [TODO](#).
|
||||
@@ -462,6 +462,19 @@ class Index extends React.Component {
|
||||
Contribute
|
||||
</ActionBlock.Link>
|
||||
</ActionBlock>
|
||||
|
||||
<Block small className="bg-black-grey cncf-block">
|
||||
<Block.Container center>
|
||||
<Block.SmallTitle small>
|
||||
Backstage is a{' '}
|
||||
<a href="https://www.cncf.io">
|
||||
Cloud Native Computing Foundation
|
||||
</a>{' '}
|
||||
sandbox project
|
||||
</Block.SmallTitle>
|
||||
<div className="cncf-logo" />
|
||||
</Block.Container>
|
||||
</Block>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -143,7 +143,11 @@
|
||||
"ids": ["api/backend"]
|
||||
}
|
||||
],
|
||||
"Tutorials": ["tutorials/journey"],
|
||||
"Tutorials": [
|
||||
"tutorials/journey",
|
||||
"tutorials/quickstart-app-auth",
|
||||
"tutorials/quickstart-app-plugin"
|
||||
],
|
||||
"Architecture Decision Records (ADRs)": [
|
||||
"architecture-decisions/adrs-overview",
|
||||
"architecture-decisions/adrs-adr001",
|
||||
|
||||
@@ -1070,3 +1070,14 @@ code {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.cncf-block {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cncf-logo {
|
||||
background: center no-repeat url(../img/cncf-white.svg);
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="-2.82 -4.07 419.64 80.14"><style>svg {enable-background:new 0 0 414 73}</style><path d="M101.2 32c3.3 0 5.9-1.3 8-3.9l4.2 4.4c-3.4 3.8-7.3 5.7-11.9 5.7-4.6 0-8.3-1.4-11.3-4.3s-4.4-6.5-4.4-10.9 1.5-8.1 4.5-11c3-2.9 6.7-4.4 11.1-4.4 4.9 0 9 1.9 12.2 5.6l-4.1 4.7c-2.1-2.6-4.7-3.9-7.8-3.9-2.5 0-4.6.8-6.4 2.4-1.8 1.6-2.7 3.8-2.7 6.6s.8 5 2.5 6.7c1.7 1.4 3.7 2.3 6.1 2.3zm17.5 5.8V8.1h6.6v23.8H138v5.9zm48.3-4.1c-3 2.9-6.7 4.4-11.1 4.4-4.4 0-8.1-1.5-11.1-4.4-3-2.9-4.5-6.6-4.5-10.9s1.5-8 4.5-10.9c3-2.9 6.7-4.4 11.1-4.4 4.4 0 8.1 1.5 11.1 4.4 3 2.9 4.5 6.6 4.5 10.9s-1.5 8-4.5 10.9zm-2.3-10.9c0-2.6-.9-4.9-2.5-6.8-1.7-1.9-3.8-2.8-6.3-2.8s-4.6.9-6.3 2.8c-1.7 1.9-2.6 4.1-2.6 6.8s.9 4.9 2.6 6.8c1.7 1.9 3.8 2.8 6.3 2.8s4.6-.9 6.3-2.8 2.5-4.1 2.5-6.8zm20.3 7.4c1.1 1.4 2.6 2.1 4.5 2.1s3.4-.7 4.4-2.1c1.1-1.4 1.6-3.3 1.6-5.6V8.1h6.6v16.6c0 4.3-1.2 7.6-3.6 9.9-2.4 2.3-5.4 3.5-9.1 3.5-3.7 0-6.8-1.2-9.2-3.5-2.4-2.3-3.6-5.6-3.6-9.9V8.1h6.6v16.4c.1 2.4.7 4.3 1.8 5.7zM231.7 12c2.8 2.6 4.3 6.2 4.3 10.8s-1.4 8.3-4.1 11c-2.8 2.7-7 4-12.6 4H209V8.1h10.5c5.3 0 9.4 1.3 12.2 3.9zm-4.8 17.7c1.6-1.5 2.4-3.8 2.4-6.7 0-2.9-.8-5.2-2.4-6.7-1.6-1.6-4.1-2.4-7.5-2.4h-3.7V32h4.2c3 0 5.3-.8 7-2.3zm46.8-21.6h6.7v29.7h-6.7l-14.1-18.6v18.6h-6.7V8.1h6.3l14.5 19.2zm35.1 29.7l-2.8-6.4h-12.5l-2.8 6.4h-7.1l12.8-29.7h6.4l12.8 29.7h-6.8zM299.9 17l-3.7 8.6h7.4l-3.7-8.6zm29.9-3.1v23.9h-6.7V13.9h-8.4V8.1h23.5v5.8zM343 8.1h6.6v29.7H343zM367.9 27l7.6-18.9h7.2l-12 29.7h-5.6L353.2 8.1h7.2zm39.7-18.9V14h-14.8v6.2h13.3v5.6h-13.3V32h15.3v5.8h-21.9V8.1zm-314 55c1.8 0 3.3-.7 4.5-2.2l2.4 2.5c-1.9 2.1-4.1 3.2-6.7 3.2s-4.7-.8-6.3-2.4c-1.7-1.6-2.5-3.7-2.5-6.1 0-2.5.8-4.5 2.5-6.2s3.8-2.5 6.2-2.5c2.7 0 5 1 6.9 3.1l-2.3 2.6c-1.2-1.5-2.6-2.2-4.4-2.2-1.4 0-2.6.5-3.6 1.4-1 .9-1.5 2.1-1.5 3.7s.5 2.8 1.4 3.7c.9 1 2.1 1.4 3.4 1.4zm23.4 1c-1.7 1.6-3.8 2.5-6.2 2.5s-4.5-.8-6.2-2.5c-1.7-1.6-2.5-3.7-2.5-6.1s.8-4.5 2.5-6.1c1.7-1.6 3.8-2.5 6.2-2.5s4.5.8 6.2 2.5c1.7 1.6 2.5 3.7 2.5 6.1s-.8 4.5-2.5 6.1zm-1.2-6.1c0-1.5-.5-2.8-1.4-3.8-1-1-2.1-1.6-3.5-1.6s-2.6.5-3.5 1.6c-1 1-1.4 2.3-1.4 3.8s.5 2.7 1.4 3.8c1 1 2.1 1.6 3.5 1.6s2.6-.5 3.5-1.6c.9-1 1.4-2.3 1.4-3.8zm21.8-2.1l-4.5 9.2h-2.2l-4.5-9.2v10.5h-3.7V49.8h5l4.3 9.1 4.3-9.1h5v16.6h-3.7zm19.3-4.6c1.2 1 1.8 2.5 1.8 4.6s-.6 3.6-1.8 4.5c-1.2 1-3 1.4-5.5 1.4h-2.2v4.6h-3.7V49.8h5.9c2.5 0 4.3.5 5.5 1.5zm-2.7 6.5c.4-.5.7-1.2.7-2.2s-.3-1.6-.9-2c-.6-.4-1.5-.6-2.7-.6h-2.1v5.6h2.5c1.2 0 2-.3 2.5-.8zm11.8 4.3c.6.8 1.5 1.2 2.5 1.2s1.9-.4 2.5-1.2c.6-.8.9-1.8.9-3.2v-9.2h3.7V59c0 2.4-.7 4.3-2 5.6-1.3 1.3-3 1.9-5.1 1.9s-3.8-.7-5.1-2-2-3.2-2-5.6v-9.3h3.7V59c0 1.3.3 2.4.9 3.1zm20.5-9.1v13.4h-3.7V53h-4.7v-3.2h13.1V53zm7.5-3.2h3.7v16.7H194zm19.4 0h3.7v16.6h-3.7L205.5 56v10.4h-3.7V49.8h3.4l8.2 10.7zm18.7 8.2h3.7v5.9c-1.7 1.8-3.9 2.8-6.9 2.8-2.4 0-4.5-.8-6.2-2.4-1.7-1.6-2.5-3.7-2.5-6.1 0-2.5.8-4.5 2.5-6.2s3.7-2.5 6.1-2.5c2.4 0 4.5.8 6.2 2.4l-1.9 2.8c-.7-.7-1.4-1.1-2.1-1.3-.6-.2-1.3-.4-2-.4-1.4 0-2.6.5-3.6 1.4-1 1-1.5 2.2-1.5 3.8 0 1.6.5 2.8 1.4 3.8.9.9 2 1.4 3.3 1.4 1.3 0 2.4-.2 3.2-.7l.3-4.7zm24.7-8.2V53h-7.7v3.6h7.4v3.3h-7.4v6.5h-3.7V49.8zM274 64.1c-1.7 1.6-3.8 2.5-6.2 2.5-2.5 0-4.5-.8-6.2-2.5-1.7-1.6-2.5-3.7-2.5-6.1s.8-4.5 2.5-6.1c1.7-1.6 3.8-2.5 6.2-2.5 2.5 0 4.5.8 6.2 2.5 1.7 1.6 2.5 3.7 2.5 6.1s-.8 4.5-2.5 6.1zm-1.3-6.1c0-1.5-.5-2.8-1.4-3.8-1-1-2.1-1.6-3.5-1.6s-2.6.5-3.5 1.6c-1 1-1.4 2.3-1.4 3.8s.5 2.7 1.4 3.8c1 1 2.1 1.6 3.5 1.6s2.6-.5 3.5-1.6c1-1 1.4-2.3 1.4-3.8zm11.4 4.1c.6.8 1.5 1.2 2.5 1.2s1.9-.4 2.5-1.2c.6-.8.9-1.8.9-3.2v-9.2h3.7V59c0 2.4-.7 4.3-2 5.6-1.3 1.3-3 1.9-5.1 1.9s-3.8-.7-5.1-2c-1.3-1.3-2-3.2-2-5.6v-9.3h3.7V59c-.1 1.3.3 2.4.9 3.1zm25.1-12.3h3.7v16.6h-3.7L301.3 56v10.4h-3.7V49.8h3.4l8.2 10.7zm20.5 2.2c1.6 1.5 2.4 3.5 2.4 6.1 0 2.6-.8 4.6-2.3 6.1-1.5 1.5-3.9 2.3-7.1 2.3H317V49.8h5.9c3 0 5.3.7 6.8 2.2zm-2.7 9.9c.9-.9 1.4-2.1 1.4-3.7s-.5-2.9-1.4-3.8c-.9-.9-2.3-1.3-4.2-1.3h-2.1v10.1h2.4c1.7-.1 3-.5 3.9-1.3zm19.7 4.5l-1.5-3.6h-7l-1.5 3.6h-4l7.2-16.7h3.6l7.2 16.7h-4zm-5-11.7l-2.1 4.8h4.2l-2.1-4.8zm16.8-1.7v13.4h-3.8V53H350v-3.2h13.2V53zm7.4-3.2h3.7v16.7h-3.7zm21.8 14.3c-1.7 1.6-3.8 2.5-6.2 2.5-2.5 0-4.5-.8-6.2-2.5-1.7-1.6-2.5-3.7-2.5-6.1s.8-4.5 2.5-6.1c1.7-1.6 3.8-2.5 6.2-2.5 2.5 0 4.5.8 6.2 2.5 1.7 1.6 2.5 3.7 2.5 6.1s-.8 4.5-2.5 6.1zm-1.2-6.1c0-1.5-.5-2.8-1.4-3.8-1-1-2.1-1.6-3.5-1.6s-2.6.5-3.5 1.6c-1 1-1.4 2.3-1.4 3.8s.5 2.7 1.4 3.8c1 1 2.1 1.6 3.5 1.6s2.6-.5 3.5-1.6c.9-1 1.4-2.3 1.4-3.8zm18.5-8.2h3.8v16.6H405L397.1 56v10.4h-3.7V49.8h3.5l8.1 10.7z"/><path fill="#446ca9" d="M14.5 46.7H5.4v21.4h21.3v-9.2H14.5zm45.8.1v12.1H48.1v-.1 9.3h21.3V46.7h-9.2zM5.4 25.4h9.2l-.1-.1V13.2h12.2V4H5.4zM48.1 4v9.2h12.2v12.2h9.1V4z"/><path fill="#76c4d5" d="M46.9 25.4L34.7 13.2h13.4V4H26.7v9.2l12.2 12.2zm-11 21.3h-8L38 56.8l2 2.1H26.7v9.2h21.4v-9.3l-6.1-6zm24.4-21.3v13.3l-2.1-2.1-10.1-10.1v8.1l6 6 6.1 6.1h9.2V25.4zM26.7 37.5L14.6 25.4H5.4v21.3h9.1V33.4l12.2 12.2z"/></svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.3 KiB |
@@ -35,8 +35,6 @@ import {
|
||||
SidebarSearchField,
|
||||
SidebarSpace,
|
||||
SidebarUserSettings,
|
||||
SidebarThemeToggle,
|
||||
SidebarPinButton,
|
||||
DefaultProviderSettings,
|
||||
} from '@backstage/core';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
@@ -103,9 +101,7 @@ const Root: FC<{}> = ({ children }) => (
|
||||
/>
|
||||
<SidebarSpace />
|
||||
<SidebarDivider />
|
||||
<SidebarThemeToggle />
|
||||
<SidebarUserSettings providerSettings={<DefaultProviderSettings />} />
|
||||
<SidebarPinButton />
|
||||
</Sidebar>
|
||||
{children}
|
||||
</SidebarPage>
|
||||
|
||||
@@ -21,6 +21,11 @@ import {
|
||||
Router as CloudbuildRouter,
|
||||
isPluginApplicableToEntity as isCloudbuildAvailable,
|
||||
} from '@backstage/plugin-cloudbuild';
|
||||
import {
|
||||
Router as JenkinsRouter,
|
||||
isPluginApplicableToEntity as isJenkinsAvailable,
|
||||
LatestRunCard as JenkinsLatestRunCard,
|
||||
} from '@backstage/plugin-jenkins';
|
||||
import {
|
||||
Router as CircleCIRouter,
|
||||
isPluginApplicableToEntity as isCircleCIAvailable,
|
||||
@@ -42,6 +47,8 @@ const CICDSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
// This component is just an example of how you can implement your company's logic in entity page.
|
||||
// You can for example enforce that all components of type 'service' should use GitHubActions
|
||||
switch (true) {
|
||||
case isJenkinsAvailable(entity):
|
||||
return <JenkinsRouter entity={entity} />;
|
||||
case isGitHubActionsAvailable(entity):
|
||||
return <GitHubActionsRouter entity={entity} />;
|
||||
case isCircleCIAvailable(entity):
|
||||
@@ -63,6 +70,11 @@ const OverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid item>
|
||||
<AboutCard entity={entity} />
|
||||
</Grid>
|
||||
{isJenkinsAvailable(entity) && (
|
||||
<Grid item sm={4}>
|
||||
<JenkinsLatestRunCard branch="master" />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.21",
|
||||
"@backstage/plugin-sentry-backend": "^0.1.1-alpha.21",
|
||||
"@backstage/plugin-techdocs-backend": "^0.1.1-alpha.21",
|
||||
"@gitbeaker/node": "^23.5.0",
|
||||
"@octokit/rest": "^18.0.0",
|
||||
"dockerode": "^3.2.0",
|
||||
"example-app": "^0.1.1-alpha.21",
|
||||
|
||||
@@ -19,16 +19,24 @@ import {
|
||||
createRouter,
|
||||
FilePreparer,
|
||||
GithubPreparer,
|
||||
GitlabPreparer,
|
||||
Preparers,
|
||||
Publishers,
|
||||
GithubPublisher,
|
||||
GitlabPublisher,
|
||||
CreateReactAppTemplater,
|
||||
Templaters,
|
||||
RepoVisilityOptions,
|
||||
} from '@backstage/plugin-scaffolder-backend';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { Gitlab } from '@gitbeaker/node';
|
||||
import type { PluginEnvironment } from '../types';
|
||||
import Docker from 'dockerode';
|
||||
|
||||
export default async function createPlugin({ logger }: PluginEnvironment) {
|
||||
export default async function createPlugin({
|
||||
logger,
|
||||
config,
|
||||
}: PluginEnvironment) {
|
||||
const cookiecutterTemplater = new CookieCutter();
|
||||
const craTemplater = new CreateReactAppTemplater();
|
||||
const templaters = new Templaters();
|
||||
@@ -37,19 +45,77 @@ export default async function createPlugin({ logger }: PluginEnvironment) {
|
||||
|
||||
const filePreparer = new FilePreparer();
|
||||
const githubPreparer = new GithubPreparer();
|
||||
const gitlabPreparer = new GitlabPreparer(config);
|
||||
const preparers = new Preparers();
|
||||
|
||||
preparers.register('file', filePreparer);
|
||||
preparers.register('github', githubPreparer);
|
||||
preparers.register('gitlab', gitlabPreparer);
|
||||
preparers.register('gitlab/api', gitlabPreparer);
|
||||
|
||||
const githubClient = new Octokit({ auth: process.env.GITHUB_ACCESS_TOKEN });
|
||||
const publisher = new GithubPublisher({ client: githubClient });
|
||||
const publishers = new Publishers();
|
||||
|
||||
const githubConfig = config.getOptionalConfig('scaffolder.github');
|
||||
|
||||
if (githubConfig) {
|
||||
try {
|
||||
const repoVisibility = githubConfig.getString(
|
||||
'visibility',
|
||||
) as RepoVisilityOptions;
|
||||
|
||||
const githubToken = githubConfig.getString('token');
|
||||
const githubClient = new Octokit({ auth: githubToken });
|
||||
const githubPublisher = new GithubPublisher({
|
||||
client: githubClient,
|
||||
token: githubToken,
|
||||
repoVisibility,
|
||||
});
|
||||
publishers.register('file', githubPublisher);
|
||||
publishers.register('github', githubPublisher);
|
||||
} catch (e) {
|
||||
const providerName = 'github';
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
throw new Error(
|
||||
`Failed to initialize ${providerName} scaffolding provider, ${e.message}`,
|
||||
);
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Skipping ${providerName} scaffolding provider, ${e.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const gitLabConfig = config.getOptionalConfig('scaffolder.gitlab.api');
|
||||
if (gitLabConfig) {
|
||||
try {
|
||||
const gitLabToken = gitLabConfig.getString('token');
|
||||
const gitLabClient = new Gitlab({
|
||||
host: gitLabConfig.getOptionalString('baseUrl'),
|
||||
token: gitLabToken,
|
||||
});
|
||||
const gitLabPublisher = new GitlabPublisher(gitLabClient, gitLabToken);
|
||||
publishers.register('gitlab', gitLabPublisher);
|
||||
publishers.register('gitlab/api', gitLabPublisher);
|
||||
} catch (e) {
|
||||
const providerName = 'gitlab';
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
throw new Error(
|
||||
`Failed to initialize ${providerName} scaffolding provider, ${e.message}`,
|
||||
);
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Skipping ${providerName} scaffolding provider, ${e.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const dockerClient = new Docker();
|
||||
return await createRouter({
|
||||
preparers,
|
||||
templaters,
|
||||
publisher,
|
||||
publishers,
|
||||
logger,
|
||||
dockerClient,
|
||||
});
|
||||
|
||||
@@ -5,6 +5,8 @@ metadata:
|
||||
description: Hello World example for gRPC
|
||||
spec:
|
||||
type: grpc
|
||||
lifecycle: deprecated
|
||||
owner: grpc@example.com
|
||||
definition: |
|
||||
// Copyright 2015 gRPC authors.
|
||||
//
|
||||
|
||||
@@ -3,8 +3,13 @@ kind: API
|
||||
metadata:
|
||||
name: petstore
|
||||
description: The petstore API
|
||||
tags:
|
||||
- store
|
||||
- rest
|
||||
spec:
|
||||
type: openapi
|
||||
lifecycle: experimental
|
||||
owner: pets@example.com
|
||||
definition: |
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
|
||||
@@ -3,6 +3,9 @@ kind: Component
|
||||
metadata:
|
||||
name: playback-order
|
||||
description: Playback Order
|
||||
tags:
|
||||
- java
|
||||
- playback
|
||||
spec:
|
||||
type: service
|
||||
lifecycle: production
|
||||
|
||||
@@ -4,9 +4,11 @@ metadata:
|
||||
name: streetlights
|
||||
description: The Smartylighting Streetlights API allows you to remotely manage the city lights.
|
||||
tags:
|
||||
- unstable
|
||||
- mqtt
|
||||
spec:
|
||||
type: asyncapi
|
||||
lifecycle: production
|
||||
owner: streetlights@example.com
|
||||
definition: |
|
||||
asyncapi: 2.0.0
|
||||
info:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user