Merge branch 'master' into master

Signed-off-by: Jason Díaz G. <jasondiazg@gmail.com>
This commit is contained in:
Jason Díaz G.
2024-07-29 20:41:46 -06:00
committed by GitHub
626 changed files with 14175 additions and 2997 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

+1 -3
View File
@@ -67,8 +67,6 @@ auth:
clientSecret: ${AZURE_CLIENT_SECRET}
tenantId: ${AZURE_TENANT_ID}
domainHint: ${AZURE_TENANT_ID}
additionalScopes:
- Mail.Send
signIn:
resolvers:
# typically you would pick one of these
@@ -86,7 +84,7 @@ The Microsoft provider is a structure with three mandatory configuration keys:
Leave blank if your app registration is multi tenant.
When specified, this reduces login friction for users with accounts in multiple tenants by automatically filtering away accounts from other tenants.
For more details, see [Home Realm Discovery](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/home-realm-discovery-policy)
- `additionalScopes` (optional): List of scopes for the App Registration. The default and mandatory value is ['user.read'].
- `additionalScopes` (optional): List of scopes for the App Registration, to be requested in addition to the required ones.
### Resolvers
@@ -497,7 +497,7 @@ catalog:
providers:
githubOrg:
- id: production
githubUrl: 'https://github.com',
githubUrl: 'https://github.com'
orgs: ['backstage']
schedule:
frequency: PT30M
@@ -536,8 +536,8 @@ catalog:
providers:
githubOrg:
- id: production
githubUrl: 'https://github.com',
orgs: ['org-a', 'org-b'],
githubUrl: 'https://github.com'
orgs: ['org-a', 'org-b']
schedule:
frequency: PT30M
timeout: PT15M
+15 -10
View File
@@ -92,11 +92,14 @@ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
yarn install --frozen-lockfile --production --network-timeout 300000
# This will include the examples, if you don't need these simply remove this line
COPY --chown=node:node examples ./examples
# Then copy the rest of the backend bundle, along with any other files we might want.
COPY --chown=node:node packages/backend/dist/bundle.tar.gz app-config*.yaml ./
RUN tar xzf bundle.tar.gz && rm bundle.tar.gz
CMD ["node", "packages/backend", "--config", "app-config.yaml"]
CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
```
For more details on how the `backend:bundle` command and the `skeleton.tar.gz`
@@ -251,12 +254,15 @@ RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid
COPY --from=build --chown=node:node /app/packages/backend/dist/bundle/ ./
# Copy any other files that we need at runtime
COPY --chown=node:node app-config.yaml ./
COPY --chown=node:node app-config*.yaml ./
# This will include the examples, if you don't need these simply remove this line
COPY --chown=node:node examples ./examples
# This switches many Node.js dependencies to production mode.
ENV NODE_ENV production
CMD ["node", "packages/backend", "--config", "app-config.yaml"]
CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
```
Note that a newly created Backstage app will typically not have a `plugins/`
@@ -277,6 +283,7 @@ packages/*/dist
packages/*/node_modules
plugins/*/dist
plugins/*/node_modules
*.local.yaml
```
Once you have added both the `Dockerfile` and `.dockerignore` to the root of
@@ -312,14 +319,12 @@ first step in doing so is to remove the `app-backend` plugin from the backend
package, which is done as follows:
1. Delete `packages/backend/src/plugins/app.ts`
2. Remove the following lines from `packages/backend/src/index.ts`:
```tsx
import app from './plugins/app';
// ...
const appEnv = useHotMemoize(module, () => createEnv('app'));
// ...
.addRouter('', await app(appEnv));
2. Remove the following line from `packages/backend/src/index.ts`:
```ts
backend.add(import('@backstage/plugin-app-backend/alpha'));
```
3. Remove the `@backstage/plugin-app-backend` and the app package dependency
(e.g. `app`) from `packages/backend/package.json`. If you don't remove the
app package dependency the app will still be built and bundled with the
+101 -34
View File
@@ -5,40 +5,37 @@ sidebar_label: Heroku
description: How to deploy Backstage to Heroku
---
Heroku is a Platform as a Service (PaaS) designed to handle application
deployment in a hands-off way. Heroku supports container deployment of Docker
images, a natural fit for Backstage.
Heroku is a Platform as a Service (PaaS) designed to simplify application deployment.
## Configuring the CLI
## Create App
First, install the
[heroku-cli](https://devcenter.heroku.com/articles/heroku-cli) and login:
Starting with an existing Backstage app or follow the [getting started guide](https://backstage.io/docs/getting-started/) to create a new one.
Install the
[Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) and create a new Heroku app:
```shell
$ heroku login
cd your-app/
heroku apps:create <your-app>
```
If you have not yet created a project through the Heroku interface, you can create it through the CLI.
## Domain
Get Heroku app URL:
```shell
$ heroku create <your-app>
heroku domains -a <your-app>
<your-app-123>.herokuapp.com
```
You _might_ also need to set your Heroku app's stack to `container`:
```bash
$ heroku stack:set container -a <your-app>
```
Configuring your `app-config.yaml`:
The core [app-backend plugin](https://www.npmjs.com/package/@backstage/plugin-app-backend) allows a single Heroku app to serve the frontend and backend. To make this work you need to update the `baseUrl` and `port` in `app-config.production.yaml`:
```yaml
app:
# Should be the same as backend.baseUrl when using the `app-backend` plugin
baseUrl: https://<your-app>.herokuapp.com
baseUrl: https://<your-app-123>.herokuapp.com
backend:
baseUrl: https://<your-app>.herokuapp.com
baseUrl: https://<your-app-123>.herokuapp.com
listen:
port:
$env: PORT
@@ -46,28 +43,98 @@ backend:
# https://devcenter.heroku.com/articles/dynos#web-dynos
```
> Make sure your file is being copied into your container in the `Dockerfile`.
## Build Script
Before building the Docker image, run the [backstage host build commands](https://backstage.io/docs/deployment/docker#host-build). They must be run whenever you are going to publish a new image.
Add a build script in `package.json` to compile frontend during deployment:
Heroku runs a container registry on `registry.heroku.com`. To push Backstage
Docker images, log in to the container registry also:
```json
"scripts": {
"build": "yarn build:backend --config ../../app-config.yaml --config ../../app-config.production.yaml"
```
## Start Command
Create a [Procfile](https://devcenter.heroku.com/articles/procfile) in the app's root:
```shell
$ heroku container:login
echo "web: yarn workspace backend start --config ../../app-config.yaml --config ../../app-config.production.yaml" > Procfile
```
## Push and deploy a Docker image
## Database
Now we can push a Backstage [Docker image](docker.md) to Heroku's container
registry and release it to the `web` worker:
Provision a [Heroku Postgres](https://elements.heroku.com/addons/heroku-postgresql) database:
```bash
$ docker image build . -f packages/backend/Dockerfile --tag registry.heroku.com/<your-app>/web
$ docker push registry.heroku.com/<your-app>/web
$ heroku container:release web -a <your-app>
```shell
heroku addons:create heroku-postgresql -a <your-app>
```
Now you should have Backstage up and running! 🎉
Update `database` in `app-config.production.yaml`:
```yaml
backend:
database:
client: pg
pluginDivisionMode: schema
ensureExists: false
ensureSchemaExists: true
connection: ${DATABASE_URL}
```
Allow postgres self-signed certificates:
```shell
heroku config:set PGSSLMODE=no-verify -a <your-app>
```
## Deployment
Commit changes and push to Heroku to build and deploy:
```shell
git add Procfile && git commit -am "configure heroku"
git push heroku main
```
View the app in the browser:
```shell
heroku open -a <your-app>
```
View logs:
```shell
heroku logs -a <your-app>
```
## Docker
As an alternative to git deploys, Heroku also [supports container images](https://devcenter.heroku.com/articles/container-registry-and-runtime).
Login to Heroku's container registry:
```shell
heroku container:login
```
Configure the Heroku app to run a container image:
```shell
heroku stack:set container -a <your-app>
```
Locally run the [host build commands](https://backstage.io/docs/deployment/docker/#host-build), they must be run whenever you are going to publish a new image:
```shell
yarn install --frozen-lockfile
yarn tsc
yarn build:backend --config ../../app-config.yaml --config ../../app-config.production.yaml
```
Build, push, and release the container image to the `web` dyno:
```shell
docker image build . -f packages/backend/Dockerfile --tag registry.heroku.com/<your-app>/web
docker push registry.heroku.com/<your-app>/web
heroku container:release web -a <your-app>
```
@@ -58,6 +58,20 @@ catalog:
target: ../../examples/all.yaml
```
:::note
There might be cases where you need to test some `file` configurations in a Docker container. In a case like this, as the backend is serving the frontend in a default setup, the path would be from the root. Also, you need to **make sure to copy your files into your container**.
Using the example above that would look like this:
```yaml
catalog:
locations:
- type: file
target: ./examples/all.yaml
```
:::
### Integration Processors
Integrations may simply provide a mechanism to handle `url` location type for an
@@ -26,6 +26,25 @@ parameters:
ui:help: 'Hint: additional description...'
```
#### Custom validation error message
```yaml
parameters:
- title: Fill in some steps
properties:
name:
title: Simple text input
type: string
description: Description about input
maxLength: 8
pattern: '^([a-zA-Z][a-zA-Z0-9]*)(-[a-zA-Z0-9]+)*$'
ui:autofocus: true
ui:help: 'Hint: additional description...'
errorMessage:
properties:
name: '1-8 alphanumeric tokens (first starts with letter) delimited by -'
```
### Multi line text input
```yaml
@@ -533,6 +533,11 @@ catalogFilter:
metadata.annotations.github.com/team-slug: { exists: true }
```
#### Custom validation messages
You may specify custom JSON Schema validation messages as supported by the
[ajv-errors](https://github.com/ajv-validator/ajv-errors) plugin library to [ajv](https://github.com/ajv-validator/ajv).
## `spec.steps` - `Action[]`
The `steps` is an array of the things that you want to happen part of this
@@ -91,7 +91,9 @@ To create a new extension data reference to represent a type of shared extension
```ts
export const reactElementExtensionDataRef =
createExtensionDataRef<React.JSX.Element>('my-plugin.reactElement');
createExtensionDataRef<React.JSX.Element>().with({
id: 'my-plugin.reactElement',
});
```
The `ExtensionDataRef` can then be used to describe an output property of the extension. This will enforce typing on the return value of the extension factory:
@@ -98,9 +98,9 @@ export interface SearchResultItemExtensionData {
}
export const searchResultItemExtensionDataRef =
createExtensionDataRef<SearchResultItemExtensionData>(
'search.search-result-item',
);
createExtensionDataRef<SearchResultItemExtensionData>().with({
id: 'search.search-result-item',
});
```
#### Grouped Extension Data
@@ -109,8 +109,12 @@ This way of defining extension data is similar to the standalone way, but it use
```ts
export const coreExtensionData = {
reactElement: createExtensionDataRef<ReactElement>('core.react-element'),
routePath: createExtensionDataRef<string>('core.route-path'),
reactElement: createExtensionDataRef<ReactElement>().with({
id: 'core.react-element',
}),
routePath: createExtensionDataRef<string>().with({
id: 'core.route-path',
}),
};
```
@@ -125,9 +129,9 @@ export function createGraphiQLEndpointExtension(options) {
// Use a TypeScript namespace to merge the extension data references with the extension creator
export namespace createGraphiQLEndpointExtension {
export const endpointDataRef = createExtensionDataRef</* ... */>(
'graphiql.graphiql-endpoint.endpoint',
);
export const endpointDataRef = createExtensionDataRef</* ... */>().with({
id: 'graphiql.graphiql-endpoint.endpoint',
});
}
```
@@ -45,6 +45,7 @@ This extension is the first extension attached to the extension tree. It is resp
| themes | The app themes list. | [createThemeExtension.themeDataRef](https://backstage.io/docs/reference/frontend-plugin-api.createthemeextension.themedataref) | false | See [default themes](#default-theme-extensions). | [createThemeExtension](https://backstage.io/docs/reference/frontend-plugin-api.createthemeextension) |
| components | The app components list. | [createComponentExtension.componentDataRef](https://backstage.io/docs/reference/frontend-plugin-api.createcomponentextension.componentdataref) | false | See [default components](#default-components-extensions). | [createComponentExtension](https://backstage.io/docs/reference/frontend-plugin-api.createcomponentextension) |
| translations | The app translations list. | [createTranslationExtension.translationDataRef](https://backstage.io/docs/reference/frontend-plugin-api.createtranslationextension.translationdataref) | false | - | [createTranslationExtension](https://backstage.io/docs/reference/frontend-plugin-api.createtranslationextension) |
| icons | The app icons list. | [IconBundleBlueprint.dataRefs.icons](https://backstage.io/docs/reference/frontend-plugin-api.iconbundleblueprint.dataRefs.icons) | true | - | [IconBundleBlueprint](https://backstage.io/docs/reference/frontend-plugin-api.iconbundleblueprint) |
#### Default theme extensions
@@ -314,6 +314,31 @@ const app = createApp({
});
```
### `icons`
Icons are now installed as extensions, using the `IconBundleBlueprint` to make new instances which can be added to the app.
```ts
import { IconBundleBlueprint } from '@backstage/frontend-plugin-api';
const exampleIconBundle = IconBundleBlueprint.make({
name: 'example-bundle',
params: {
icons: {
user: MyOwnUserIcon,
},
},
});
const app = createApp({
features: [
createExtensionOverrides({
extensions: [exampleIconBundle],
}),
],
});
```
### `bindRoutes`
Route bindings can still be done using this option, but you now also have the ability to bind routes using static configuration instead. See the section on [binding routes](../architecture/07-routes.md#binding-external-route-references) for more information.
@@ -38,6 +38,10 @@ Sign-in page extension have a single purpose - to implement a custom sign-in pag
Theme extensions provide custom themes for the app. They are always attached to the app extension and you can have any number of themes extensions installed in an app at once, letting the user choose which theme to use.
### Icons - [Reference](../../reference/frontend-plugin-api.iconbundleblueprint.md)
Icon bundle extensions provide the ability to replace or provide new icons to the app. You can use the above blueprint to make new extension instances which can be installed into the app.
### Translation - [Reference](../../reference/frontend-plugin-api.createtranslationextension.md)
Translation extension provide custom translation messages for the app. They can be used both to override the default english messages to custom ones, as well as provide translations for additional languages.
@@ -50,7 +50,6 @@ Open `packages/app/src/App.tsx` and below the last `import` line, add:
```typescript title="packages/app/src/App.tsx"
import { githubAuthApiRef } from '@backstage/core-plugin-api';
import { SignInPage } from '@backstage/core-components';
```
Search for `const app = createApp({` in this file, and below `apis,` add:
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: index
title: Installing a standalone server
title: Creating your Backstage App
sidebar_label: Introduction
description: How to install Backstage for your own use.
---
@@ -63,18 +63,16 @@ When a given dependency version is the _same_ between different packages, the
dependency is hoisted to the main `node_modules` folder in the monorepo root to
be shared between packages. When _different_ versions of the same dependency are
encountered, Yarn creates a `node_modules` folder within a particular package.
This can lead to multiple versions of the same package being installed and used
in the same app.
This can lead to confusing situations with type definitions, or anything with
global state. React [Context](https://reactjs.org/docs/context.html), for
example, depends on global referential equality. This can cause problems in
Backstage with API lookup, or config loading.
All Backstage core packages are implemented in such as way that package
duplication is **not** a problem. For example, duplicate installations of
packages like `@backstage/core-plugin-api`, `@backstage/core-components`,
`@backstage/plugin-catalog-react`, and `@backstage/backend-plugin-api` are all
acceptable.
To help resolve these situations, the Backstage CLI has
[versions:check](https://backstage.io/docs/tooling/cli/03-commands#versionscheck). This
will validate versions of `@backstage` packages in your app to check for
duplicate definitions:
```bash
# Add --fix to attempt automatic resolution in yarn.lock
yarn backstage-cli versions:check
```
While package duplication might be acceptable in many cases, you might want to
deduplicate packages for the purpose of optimizing bundle size and installation
speed. We recommend using deduplication utilities such as `yarn dedupe` to trim
down the number of duplicate packages.
+2
View File
@@ -20,6 +20,8 @@ Run your Backstage app with `yarn dev`. Navigate to `http://localhost:3000`.
If you're not already logged in, you should see a login screen like this,
![Screenshot of the login screen](../assets/getting-started/login-screen.png)
To login, you should choose the "Github" provider and click the "Sign in" button. This will redirect you to a Github OAuth page. Verify that the scopes mentioned on that page match the setup you did in [the authentication tutorial](./config/authentication.md). Once you click "Confirm", you will be brought back to the Backstage interface and signed in!
If you are already logged in, you will be automatically brought to your Backstage instance.
+1
View File
@@ -153,6 +153,7 @@ catalog:
group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole instance will be scanned
entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml`
projectPattern: '[\s\S]*' # Optional. Filters found projects based on provided patter. Defaults to `[\s\S]*`, which means to not filter anything
excludeRepos: [] # Optional. A list of project paths that should be excluded from discovery, e.g. group/subgroup/repo. Should not start or end with a slash.
schedule: # Same options as in TaskScheduleDefinition. Optional for the Legacy Backend System
# supports cron, ISO duration, "human duration" as used in code
frequency: { minutes: 30 }
File diff suppressed because it is too large Load Diff
+1 -20
View File
@@ -26,7 +26,6 @@ repo [command] Command that run across an entire
package [command] Lifecycle scripts for individual packages
migrate [command] Migration utilities
versions:bump [options] Bump Backstage packages to the latest versions
versions:check [options] Check Backstage package versioning
clean Delete cache directories [DEPRECATED]
build-workspace <workspace-dir> [packages...] Builds a temporary dist workspace from the provided
packages
@@ -327,8 +326,7 @@ Options:
## versions\:bump
Bump all `@backstage` packages to the latest versions. This checks for updates
in the package registry, and will update entries both in `yarn.lock` and
`package.json` files when necessary.
in the package registry, and will update entries `package.json` files when necessary.
```text
Usage: backstage-cli versions:bump [options]
@@ -339,23 +337,6 @@ Options:
--release <version|next|main> Bump to a specific Backstage release line or version (default: "main")
```
## versions\:check
Validate `@backstage` dependencies within the repo, making sure that there are
no duplicates of packages that might lead to breakages.
By supplying the `--fix` flag the command will attempt to fix any conflict that
can be resolved by editing `yarn.lock`, but will not attempt to search for
remote updates or modify any `package.json` files.
```text
Usage: backstage-cli versions:check [options]
Options:
--fix Fix any auto-fixable versioning problems
-h, --help display help for command
```
## build-workspace
Builds a mirror of the workspace using the packaged production version of each
+44
View File
@@ -100,3 +100,47 @@ With that, Backstage's cli and backend will detect public entry point and serve
5. Finally, as soon as you log in, you will be redirected to the main app home page (inspect the page and see that the protected bundle was served from the app backend after the redirect).
That's it!
## New Frontend System
If your app uses the new frontend system, you can still use the public entry point feature. The `index-public-experimental.tsx` file does end up looking a bit different in this case:
```tsx title="in packages/app/src/index-public-experimental.tsx"
import React from 'react';
import ReactDOM from 'react-dom/client';
import { CookieAuthRedirect } from '@backstage/plugin-auth-react';
import { createApp } from '@backstage/frontend-app-api';
import {
coreExtensionData,
createExtension,
createExtensionOverrides,
createSignInPageExtension,
} from '@backstage/frontend-plugin-api';
const signInPage = createSignInPageExtension({
name: 'guest',
loader: async () => props => <SignInPage {...props} providers={['guest']} />,
});
const authRedirectExtension = createExtension({
namespace: 'app',
name: 'layout',
attachTo: { id: 'app/root', input: 'children' },
output: {
element: coreExtensionData.reactElement,
},
factory: () => ({
element: <CookieAuthRedirect />,
}),
});
const app = createApp({
features: [
createExtensionOverrides({
extensions: [signInPage, authRedirectExtension],
}),
],
});
ReactDOM.createRoot(document.getElementById('root')!).render(app.createRoot());
```