Merge branch 'master' of github.com:Niksko/backstage into github-discovery-validate
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 132 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 40 KiB |
+2
-2
@@ -243,8 +243,8 @@ need this as well) to support user sessions.
|
||||
### The Sign In provider
|
||||
|
||||
The last step is to add the provider to the `SignInPage` so users can sign in with your
|
||||
new provider, please follow the [Sing In Configuration][3] docs, here's where you import
|
||||
and use the API ref we defined earlier.
|
||||
new provider, please follow the [Sign In Configuration][3] docs, here's where you import
|
||||
and use the API reference we defined earlier.
|
||||
|
||||
## Note
|
||||
|
||||
|
||||
@@ -23,6 +23,17 @@ Each package is searched for a schema at a single point of entry, a top-level
|
||||
inlined JSON schema, or a relative path to a schema file. Supported schema file
|
||||
formats are `.json` or `.d.ts`.
|
||||
|
||||
```jsonc title="package.json"
|
||||
{
|
||||
// ...
|
||||
"files": [
|
||||
// ...
|
||||
"config.d.ts"
|
||||
],
|
||||
"configSchema": "config.d.ts"
|
||||
}
|
||||
```
|
||||
|
||||
> When defining a schema file, be sure to include the file in your
|
||||
> `package.json` > `"files"` field as well!
|
||||
|
||||
|
||||
+41
-19
@@ -61,13 +61,18 @@ FROM node:16-bullseye-slim
|
||||
|
||||
# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
|
||||
# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
|
||||
RUN apt-get update && \
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
yarn config set python /usr/bin/python3
|
||||
|
||||
# From here on we use the least-privileged `node` user to run the backend.
|
||||
USER node
|
||||
|
||||
# This should create the app dir as `node`.
|
||||
# If it is instead created as `root` then the `tar` command below will fail: `can't create directory 'packages/': Permission denied`.
|
||||
# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`) so the app dir is correctly created as `node`.
|
||||
WORKDIR /app
|
||||
|
||||
# This switches many Node.js dependencies to production mode.
|
||||
@@ -79,7 +84,8 @@ ENV NODE_ENV production
|
||||
COPY --chown=node:node yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./
|
||||
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
|
||||
|
||||
RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)"
|
||||
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
|
||||
yarn install --frozen-lockfile --production --network-timeout 300000
|
||||
|
||||
# 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 ./
|
||||
@@ -163,53 +169,68 @@ RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf {
|
||||
# Stage 2 - Install dependencies and build packages
|
||||
FROM node:16-bullseye-slim AS build
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=packages /app .
|
||||
|
||||
# install sqlite3 dependencies
|
||||
RUN apt-get update && \
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
|
||||
yarn config set python /usr/bin/python3
|
||||
|
||||
RUN yarn install --frozen-lockfile --network-timeout 600000 && rm -rf "$(yarn cache dir)"
|
||||
USER node
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
COPY --from=packages --chown=node:node /app .
|
||||
|
||||
# Stop cypress from downloading it's massive binary.
|
||||
ENV CYPRESS_INSTALL_BINARY=0
|
||||
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
|
||||
yarn install --frozen-lockfile --network-timeout 600000
|
||||
|
||||
COPY --chown=node:node . .
|
||||
|
||||
RUN yarn tsc
|
||||
RUN yarn --cwd packages/backend build
|
||||
# If you have not yet migrated to package roles, use the following command instead:
|
||||
# RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies
|
||||
|
||||
RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \
|
||||
&& tar xzf packages/backend/dist/skeleton.tar.gz -C packages/backend/dist/skeleton \
|
||||
&& tar xzf packages/backend/dist/bundle.tar.gz -C packages/backend/dist/bundle
|
||||
|
||||
# Stage 3 - Build the actual backend image and install production dependencies
|
||||
FROM node:16-bullseye-slim
|
||||
|
||||
# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
|
||||
# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
|
||||
RUN apt-get update && \
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
yarn config set python /usr/bin/python3
|
||||
|
||||
# From here on we use the least-privileged `node` user to run the backend.
|
||||
USER node
|
||||
|
||||
# This should create the app dir as `node`.
|
||||
# If it is instead created as `root` then the `tar` command below will fail: `can't create directory 'packages/': Permission denied`.
|
||||
# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`) so the app dir is correctly created as `node`.
|
||||
WORKDIR /app
|
||||
|
||||
# This switches many Node.js dependencies to production mode.
|
||||
ENV NODE_ENV production
|
||||
|
||||
# Copy the install dependencies from the build stage and context
|
||||
COPY --from=build --chown=node:node /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton.tar.gz ./
|
||||
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
|
||||
COPY --from=build --chown=node:node /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton/ ./
|
||||
|
||||
RUN yarn install --frozen-lockfile --production --network-timeout 600000 && rm -rf "$(yarn cache dir)"
|
||||
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
|
||||
yarn install --frozen-lockfile --production --network-timeout 600000
|
||||
|
||||
# Copy the built packages from the build stage
|
||||
COPY --from=build --chown=node:node /app/packages/backend/dist/bundle.tar.gz .
|
||||
RUN tar xzf bundle.tar.gz && rm bundle.tar.gz
|
||||
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 ./
|
||||
|
||||
# This switches many Node.js dependencies to production mode.
|
||||
ENV NODE_ENV production
|
||||
|
||||
CMD ["node", "packages/backend", "--config", "app-config.yaml"]
|
||||
```
|
||||
|
||||
@@ -225,6 +246,7 @@ however ignore any existing build output or dependencies on the host. For our
|
||||
new `.dockerignore`, replace the contents of your existing one with this:
|
||||
|
||||
```text
|
||||
dist-types
|
||||
node_modules
|
||||
packages/*/dist
|
||||
packages/*/node_modules
|
||||
|
||||
@@ -62,7 +62,7 @@ This is an array used to determine where to retrieve cluster configuration from.
|
||||
Valid cluster locator methods are:
|
||||
|
||||
- [`catalog`](#catalog)
|
||||
- [`localKubectlProxy`](#localKubectlProxy)
|
||||
- [`localKubectlProxy`](#localkubectlproxy)
|
||||
- [`config`](#config)
|
||||
- [`gke`](#gke)
|
||||
- [custom `KubernetesClustersSupplier`](#custom-kubernetesclusterssupplier)
|
||||
|
||||
@@ -110,7 +110,7 @@ metadata:
|
||||
backstage.io/edit-url: https://github.com/my-org/catalog/edit/master/my-service.jsonnet
|
||||
```
|
||||
|
||||
These annotations allow customising links from the catalog pages. The view URL
|
||||
These annotations allow customizing links from the catalog pages. The view URL
|
||||
should point to the canonical metadata YAML that governs this entity. The edit
|
||||
URL should point to the source file for the metadata. In the example above,
|
||||
`my-org` generates its catalog data from Jsonnet files in a monorepo, so the
|
||||
@@ -159,11 +159,11 @@ metadata:
|
||||
github.com/project-slug: backstage/backstage
|
||||
```
|
||||
|
||||
The value of this annotation is the so-called slug that identifies a project on
|
||||
The value of this annotation is the so-called slug that identifies a repository on
|
||||
[GitHub](https://github.com) (either the public one, or a private GitHub
|
||||
Enterprise installation) that is related to this entity. It is on the format
|
||||
`<organization>/<project>`, and is the same as can be seen in the URL location
|
||||
bar of the browser when viewing that project.
|
||||
`<organization or owner>/<repository>`, and is the same as can be seen in the URL location
|
||||
bar of the browser when viewing that repository.
|
||||
|
||||
Specifying this annotation will enable GitHub related features in Backstage for
|
||||
that entity.
|
||||
|
||||
@@ -81,8 +81,7 @@ import {
|
||||
scaffolderPlugin,
|
||||
createScaffolderFieldExtension,
|
||||
} from '@backstage/plugin-scaffolder';
|
||||
import { MyCustomExtension } from './MyCustomExtension';
|
||||
import { myCustomValidation } from './validation';
|
||||
import { MyCustomExtension, myCustomValidation } from './MyCustomExtension';
|
||||
|
||||
export const MyCustomFieldExtension = scaffolderPlugin.provide(
|
||||
createScaffolderFieldExtension({
|
||||
|
||||
@@ -51,14 +51,10 @@ create a subdirectory inside your current working directory.
|
||||
npx @backstage/create-app
|
||||
```
|
||||
|
||||
The wizard will ask you
|
||||
|
||||
- The name of the app, which will also be the name of the directory
|
||||
- The database type to use for the backend. For this guide, you'll be using the
|
||||
SQLite option.
|
||||
The wizard will ask you for the name of the app, which will also be the name of the directory
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/wizard.png' alt='Screenshot of the wizard asking for a name for the app, and a selection menu for the database.' />
|
||||
<img src='../assets/getting-started/wizard.png' alt='Screenshot of the wizard asking for a name for the app.' />
|
||||
</p>
|
||||
|
||||
### Run the Backstage app
|
||||
|
||||
@@ -32,6 +32,11 @@ catalog:
|
||||
bucketName: sample-bucket
|
||||
prefix: prefix/ # optional
|
||||
region: us-east-2 # optional, uses the default region otherwise
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
```
|
||||
|
||||
For simple setups, you can omit the provider ID at the config
|
||||
@@ -47,6 +52,11 @@ catalog:
|
||||
bucketName: sample-bucket
|
||||
prefix: prefix/ # optional
|
||||
region: us-east-2 # optional, uses the default region otherwise
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
```
|
||||
|
||||
As this provider is not one of the default providers, you will first need to install
|
||||
@@ -69,10 +79,13 @@ const builder = await CatalogBuilder.create(env);
|
||||
builder.addEntityProvider(
|
||||
AwsS3EntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
// optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 30 },
|
||||
timeout: { minutes: 3 },
|
||||
}),
|
||||
// optional: alternatively, use schedule
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
@@ -42,12 +42,17 @@ catalog:
|
||||
project: myproject
|
||||
repository: service-* # this will match all repos starting with service-*
|
||||
path: /catalog-info.yaml
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
anotherProviderId: # another identifier
|
||||
organization: myorg
|
||||
project: myproject
|
||||
repository: '*' # this will match all repos
|
||||
path: /src/*/catalog-info.yaml # this will search for files deep inside the /src folder
|
||||
yetAotherProviderId: # guess, what? Another one :)
|
||||
yetAnotherProviderId: # guess, what? Another one :)
|
||||
host: selfhostedazure.yourcompany.com
|
||||
organization: myorg
|
||||
project: myproject
|
||||
@@ -55,11 +60,20 @@ catalog:
|
||||
|
||||
The parameters available are:
|
||||
|
||||
- `host:` Leave empty for Cloud hosted, otherwise set to your self-hosted instance host.
|
||||
- `organization:` Your Organization slug (or Collection for on-premise users). Required.
|
||||
- `project:` Your project slug. Required.
|
||||
- `repository:` The repository name. Wildcards are supported as show on the examples above. If not set, all repositories will be searched.
|
||||
- `path:` Where to find catalog-info.yaml files. Defaults to /catalog-info.yaml.
|
||||
- **`host:`** _(optional)_ Leave empty for Cloud hosted, otherwise set to your self-hosted instance host.
|
||||
- **`organization:`** Your Organization slug (or Collection for on-premise users). Required.
|
||||
- **`project:`** Your project slug. Required.
|
||||
- **`repository:`** _(optional)_ The repository name. Wildcards are supported as show on the examples above. If not set, all repositories will be searched.
|
||||
- **`path:`** _(optional)_ Where to find catalog-info.yaml files. Defaults to /catalog-info.yaml.
|
||||
- **`schedule`** _(optional)_:
|
||||
- **`frequency`**:
|
||||
How often you want the task to run. The system does its best to avoid overlapping invocations.
|
||||
- **`timeout`**:
|
||||
The maximum amount of time that a single task invocation can take.
|
||||
- **`initialDelay`** _(optional)_:
|
||||
The amount of time that should pass before the first invocation happens.
|
||||
- **`scope`** _(optional)_:
|
||||
`'global'` or `'local'`. Sets the scope of concurrency control.
|
||||
|
||||
_Note:_ the path parameter follows the same rules as the search on Azure DevOps
|
||||
web interface. For more details visit the
|
||||
@@ -84,10 +98,13 @@ const builder = await CatalogBuilder.create(env);
|
||||
+builder.addEntityProvider(
|
||||
+ AzureDevOpsEntityProvider.fromConfig(env.config, {
|
||||
+ logger: env.logger,
|
||||
+ // optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
+ schedule: env.scheduler.createScheduledTaskRunner({
|
||||
+ frequency: Duration.fromObject({ minutes: 30 }),
|
||||
+ timeout: Duration.fromObject({ minutes: 3 }),
|
||||
+ frequency: { minutes: 30 },
|
||||
+ timeout: { minutes: 3 },
|
||||
+ }),
|
||||
+ // optional: alternatively, use schedule
|
||||
+ scheduler: env.scheduler,
|
||||
+ }),
|
||||
+);
|
||||
```
|
||||
|
||||
@@ -37,10 +37,13 @@ And then add the entity provider to your catalog builder:
|
||||
+ builder.addEntityProvider(
|
||||
+ BitbucketServerEntityProvider.fromConfig(env.config, {
|
||||
+ logger: env.logger,
|
||||
+ // optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
+ schedule: env.scheduler.createScheduledTaskRunner({
|
||||
+ frequency: { minutes: 30 },
|
||||
+ timeout: { minutes: 3 },
|
||||
+ }),
|
||||
+ // optional: alternatively, use schedule
|
||||
+ scheduler: env.scheduler,
|
||||
+ }),
|
||||
+ );
|
||||
|
||||
@@ -66,19 +69,33 @@ catalog:
|
||||
filters: # optional
|
||||
projectKey: '^apis-.*$' # optional; RegExp
|
||||
repoSlug: '^service-.*$' # optional; RegExp
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
```
|
||||
|
||||
- **host**:
|
||||
- **`host`**:
|
||||
The host of the Bitbucket Server instance, **note**: the host needs to registered as an integration as well, see [location](locations.md).
|
||||
- **`catalogPath`** _(optional)_:
|
||||
Default: `/catalog-info.yaml`.
|
||||
Path where to look for `catalog-info.yaml` files.
|
||||
When started with `/`, it is an absolute path from the repo root.
|
||||
- **filters** _(optional)_:
|
||||
- **`filters`** _(optional)_:
|
||||
- **`projectKey`** _(optional)_:
|
||||
Regular expression used to filter results based on the project key.
|
||||
- **repoSlug** _(optional)_:
|
||||
- **`repoSlug`** _(optional)_:
|
||||
Regular expression used to filter results based on the repo slug.
|
||||
- **`schedule`** _(optional)_:
|
||||
- **`frequency`**:
|
||||
How often you want the task to run. The system does its best to avoid overlapping invocations.
|
||||
- **`timeout`**:
|
||||
The maximum amount of time that a single task invocation can take.
|
||||
- **`initialDelay`** _(optional)_:
|
||||
The amount of time that should pass before the first invocation happens.
|
||||
- **`scope`** _(optional)_:
|
||||
`'global'` or `'local'`. Sets the scope of concurrency control.
|
||||
|
||||
## Custom location processing
|
||||
|
||||
@@ -93,18 +110,15 @@ repository.
|
||||
```typescript
|
||||
const provider = BitbucketServerEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 30 },
|
||||
timeout: { minutes: 3 },
|
||||
}),
|
||||
schedule: env.scheduler,
|
||||
parser: async function* customLocationParser(options: {
|
||||
location: LocationSpec,
|
||||
client: BitbucketServerClient,
|
||||
location: LocationSpec;
|
||||
client: BitbucketServerClient;
|
||||
}) {
|
||||
// Custom logic for interpreting the matching repository
|
||||
// See defaultBitbucketServerLocationParser for an example
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Alternative
|
||||
|
||||
@@ -32,10 +32,13 @@ const builder = await CatalogBuilder.create(env);
|
||||
builder.addEntityProvider(
|
||||
GerritEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
// optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 30 },
|
||||
timeout: { minutes: 3 },
|
||||
}),
|
||||
// optional: alternatively, use schedule
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
```
|
||||
@@ -54,6 +57,11 @@ catalog:
|
||||
host: gerrit-your-company.com
|
||||
branch: master # Optional
|
||||
query: 'state=ACTIVE&prefix=webapps'
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
backend:
|
||||
host: gerrit-your-company.com
|
||||
branch: master # Optional
|
||||
@@ -62,8 +70,8 @@ catalog:
|
||||
|
||||
The provider configuration is composed of three parts:
|
||||
|
||||
- host, the host of the Gerrit integration to use.
|
||||
- branch, the branch where we will look for catalog entities (defaults to "master").
|
||||
- query, this string is directly used as the argument to the "List Project" API.
|
||||
Typically you will want to have some filter here to exclude projects that will
|
||||
- **`host`**: the host of the Gerrit integration to use.
|
||||
- **`branch`** _(optional)_: the branch where we will look for catalog entities (defaults to "master").
|
||||
- **`query`**: this string is directly used as the argument to the "List Project" API.
|
||||
Typically, you will want to have some filter here to exclude projects that will
|
||||
never contain any catalog files.
|
||||
|
||||
@@ -30,19 +30,22 @@ And then add the entity provider to your catalog builder:
|
||||
|
||||
```diff
|
||||
// In packages/backend/src/plugins/catalog.ts
|
||||
+ import { GitHubEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
|
||||
+ import { GithubEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
+ builder.addEntityProvider(
|
||||
+ GitHubEntityProvider.fromConfig(env.config, {
|
||||
+ GithubEntityProvider.fromConfig(env.config, {
|
||||
+ logger: env.logger,
|
||||
+ // optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
+ schedule: env.scheduler.createScheduledTaskRunner({
|
||||
+ frequency: { minutes: 30 },
|
||||
+ timeout: { minutes: 3 },
|
||||
+ }),
|
||||
+ // optional: alternatively, use schedule
|
||||
+ scheduler: env.scheduler,
|
||||
+ }),
|
||||
+ );
|
||||
|
||||
@@ -68,6 +71,11 @@ catalog:
|
||||
filters:
|
||||
branch: 'main' # string
|
||||
repository: '.*' # Regex
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
customProviderId:
|
||||
organization: 'new-org' # string
|
||||
catalogPath: '/custom/path/catalog-info.yaml' # string
|
||||
@@ -119,32 +127,41 @@ This provider supports multiple organizations via unique provider IDs.
|
||||
Path where to look for `catalog-info.yaml` files.
|
||||
You can use wildcards - `*` or `**` - to search the path and/or the filename.
|
||||
Wildcards cannot be used if the `validateLocationsExist` option is set to `true`.
|
||||
- **filters** _(optional)_:
|
||||
- **branch** _(optional)_:
|
||||
- **`filters`** _(optional)_:
|
||||
- **`branch`** _(optional)_:
|
||||
String used to filter results based on the branch name.
|
||||
- **repository** _(optional)_:
|
||||
- **`repository`** _(optional)_:
|
||||
Regular expression used to filter results based on the repository name.
|
||||
- **topic** _(optional)_:
|
||||
- **`topic`** _(optional)_:
|
||||
Both of the filters below may be used at the same time but the exclusion filter has the highest priority.
|
||||
In the example above, a repository with the `backstage-include` topic would still be excluded
|
||||
if it were also carrying the `experiments` topic.
|
||||
- **include** _(optional)_:
|
||||
- **`include`** _(optional)_:
|
||||
An array of strings used to filter in results based on their associated GitHub topics.
|
||||
If configured, only repositories with one (or more) topic(s) present in the inclusion filter will be ingested
|
||||
- **exclude** _(optional)_:
|
||||
- **`exclude`** _(optional)_:
|
||||
An array of strings used to filter out results based on their associated GitHub topics.
|
||||
If configured, all repositories _except_ those with one (or more) topics(s) present in the exclusion filter will be ingested.
|
||||
- **organization**:
|
||||
- **`host`** _(optional)_:
|
||||
The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md).
|
||||
- **`organization`**:
|
||||
Name of your organization account/workspace.
|
||||
If you want to add multiple organizations, you need to add one provider config each.
|
||||
- **host** _(optional)_:
|
||||
The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md).
|
||||
- **validateLocationsExist** _(optional)_:
|
||||
- **`validateLocationsExist`** _(optional)_:
|
||||
Whether to validate locations that exist before emitting them.
|
||||
This option avoids generating locations for catalog info files that do not exist in the source repository.
|
||||
Defaults to `false`.
|
||||
Due to limitations in the GitHub API's ability to query for repository objects, this option cannot be used in
|
||||
conjunction with wildcards in the `catalogPath`.
|
||||
- **`schedule`** _(optional)_:
|
||||
- **`frequency`**:
|
||||
How often you want the task to run. The system does its best to avoid overlapping invocations.
|
||||
- **`timeout`**:
|
||||
The maximum amount of time that a single task invocation can take.
|
||||
- **`initialDelay`** _(optional)_:
|
||||
The amount of time that should pass before the first invocation happens.
|
||||
- **`scope`** _(optional)_:
|
||||
`'global'` or `'local'`. Sets the scope of concurrency control.
|
||||
|
||||
## GitHub API Rate Limits
|
||||
|
||||
|
||||
@@ -25,6 +25,11 @@ catalog:
|
||||
group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole project 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]*/`, what means to not filter anything
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
```
|
||||
|
||||
As this provider is not one of the default providers, you will first need to install
|
||||
@@ -47,10 +52,13 @@ const builder = await CatalogBuilder.create(env);
|
||||
builder.addEntityProvider(
|
||||
...GitlabDiscoveryEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
// optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 30 },
|
||||
timeout: { minutes: 3 },
|
||||
}),
|
||||
// optional: alternatively, use schedule
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
@@ -14,12 +14,18 @@ Plugins should export a rule factory that provides type-safety that ensures comp
|
||||
import type { Entity } from '@backstage/plugin-catalog-model';
|
||||
import { createCatalogPermissionRule } from '@backstage/plugin-catalog-backend/alpha';
|
||||
import { createConditionFactory } from '@backstage/plugin-permission-node';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const isInSystemRule = createCatalogPermissionRule({
|
||||
name: 'IS_IN_SYSTEM',
|
||||
description: 'Checks if an entity is part of the system provided',
|
||||
resourceType: 'catalog-entity',
|
||||
apply: (resource: Entity, systemRef: string) => {
|
||||
paramsSchema: z.object({
|
||||
systemRef: z
|
||||
.string()
|
||||
.describe('SystemRef to check the resource is part of'),
|
||||
}),
|
||||
apply: (resource: Entity, { systemRef }) => {
|
||||
if (!resource.relations) {
|
||||
return false;
|
||||
}
|
||||
@@ -28,9 +34,9 @@ export const isInSystemRule = createCatalogPermissionRule({
|
||||
.filter(relation => relation.type === 'partOf')
|
||||
.some(relation => relation.targetRef === systemRef);
|
||||
},
|
||||
toQuery: (systemRef: string) => ({
|
||||
toQuery: ({ systemRef }) => ({
|
||||
key: 'relations.partOf',
|
||||
value: systemRef,
|
||||
values: [systemRef],
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -85,14 +91,14 @@ class TestPermissionPolicy implements PermissionPolicy {
|
||||
if (isResourcePermission(request.permission, 'catalog-entity')) {
|
||||
return createCatalogConditionalDecision(
|
||||
request.permission,
|
||||
- catalogConditions.isEntityOwner(
|
||||
- user?.identity.ownershipEntityRefs ?? [],
|
||||
- ),
|
||||
- catalogConditions.isEntityOwner({
|
||||
- claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
- }),
|
||||
+ {
|
||||
+ anyOf: [
|
||||
+ catalogConditions.isEntityOwner(
|
||||
+ user?.identity.ownershipEntityRefs ?? []
|
||||
+ ),
|
||||
+ catalogConditions.isEntityOwner({
|
||||
+ claims: user?.identity.ownershipEntityRefs ?? []
|
||||
+ }),
|
||||
+ isInSystem('interviewing')
|
||||
+ ]
|
||||
+ }
|
||||
|
||||
@@ -84,6 +84,7 @@ Create a new `plugins/todo-list-backend/src/service/rules.ts` file and append th
|
||||
```typescript
|
||||
import { makeCreatePermissionRule } from '@backstage/plugin-permission-node';
|
||||
import { TODO_LIST_RESOURCE_TYPE } from '@internal/plugin-todo-list-common';
|
||||
import { z } from 'zod';
|
||||
import { Todo, TodoFilter } from './todos';
|
||||
|
||||
export const createTodoListPermissionRule = makeCreatePermissionRule<
|
||||
@@ -95,10 +96,13 @@ export const isOwner = createTodoListPermissionRule({
|
||||
name: 'IS_OWNER',
|
||||
description: 'Should allow only if the todo belongs to the user',
|
||||
resourceType: TODO_LIST_RESOURCE_TYPE,
|
||||
apply: (resource: Todo, userId: string) => {
|
||||
paramsSchema: z.object({
|
||||
userId: z.string().describe('User ID to match on the resource')
|
||||
})
|
||||
apply: (resource: Todo, { userId }) => {
|
||||
return resource.author === userId;
|
||||
},
|
||||
toQuery: (userId: string) => {
|
||||
toQuery: ({ userId }) => {
|
||||
return {
|
||||
property: 'author',
|
||||
values: [userId],
|
||||
@@ -223,7 +227,9 @@ Let's go back to the permission policy's handle function and try to authorize ou
|
||||
+ if (isPermission(request.permission, todoListUpdatePermission)) {
|
||||
+ return createTodoListConditionalDecision(
|
||||
+ request.permission,
|
||||
+ todoListConditions.isOwner(user?.identity.userEntityRef),
|
||||
+ todoListConditions.isOwner({
|
||||
+ userId: user?.identity.userEntityRef ?? '',
|
||||
+ }),
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
|
||||
@@ -144,7 +144,9 @@ import {
|
||||
+ ) {
|
||||
return createTodoListConditionalDecision(
|
||||
request.permission,
|
||||
todoListConditions.isOwner(user?.identity.userEntityRef),
|
||||
todoListConditions.isOwner({
|
||||
userId: user?.identity.userEntityRef
|
||||
}),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -70,9 +70,9 @@ Let's change the policy to the following:
|
||||
- };
|
||||
+ return createCatalogConditionalDecision(
|
||||
+ request.permission,
|
||||
+ catalogConditions.isEntityOwner(
|
||||
+ user?.identity.ownershipEntityRefs ?? [],
|
||||
+ ),
|
||||
+ catalogConditions.isEntityOwner({
|
||||
+ claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
+ }),
|
||||
+ );
|
||||
}
|
||||
|
||||
@@ -119,9 +119,9 @@ class TestPermissionPolicy implements PermissionPolicy {
|
||||
+ if (isResourcePermission(request.permission, 'catalog-entity')) {
|
||||
return createCatalogConditionalDecision(
|
||||
request.permission,
|
||||
catalogConditions.isEntityOwner(
|
||||
user?.identity.ownershipEntityRefs ?? [],
|
||||
),
|
||||
catalogConditions.isEntityOwner({
|
||||
claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,125 @@
|
||||
---
|
||||
id: v1.7.0
|
||||
title: v1.7.0
|
||||
description: Backstage Release v1.7.0
|
||||
---
|
||||
|
||||
These are the release notes for the v1.7.0 release of
|
||||
[Backstage](https://backstage.io/).
|
||||
|
||||
A huge thanks to the whole team of maintainers and contributors as well as the
|
||||
amazing Backstage Community for the hard work in getting this release developed
|
||||
and done.
|
||||
|
||||
## Highlights
|
||||
|
||||
### GitHub Catalog Import now Powered by the Backend
|
||||
|
||||
The analysis performed during catalog imports (i.e. when supplying the URL of a
|
||||
repository rather than an individual YAML file in the Create flow) is now
|
||||
powered by the backend rather than frontend code. This means that the catalog
|
||||
backend needs to be supplied with a location analyzer for this use case to
|
||||
continue to function.
|
||||
|
||||
If you want to make use of this feature, check out the installation instructions
|
||||
in [the
|
||||
changelog](https://github.com/backstage/backstage/blob/master/plugins/catalog-import/CHANGELOG.md#090).
|
||||
|
||||
Contributed by [@kissmikijr](https://github.com/kissmikijr) in
|
||||
[#13800](https://github.com/backstage/backstage/pull/13800)
|
||||
|
||||
### Permission Rule Changes
|
||||
|
||||
When defining permission rules, it's now necessary to provide a [Zod
|
||||
Schema](https://github.com/colinhacks/zod) that specifies the parameters the
|
||||
rule expects. This has been added to help better describe the parameters in the
|
||||
response of the metadata endpoint and to validate the parameters before a rule
|
||||
is executed. The signatures of the rule methods (`apply` and `toQuery`) have
|
||||
changed slightly as well.
|
||||
|
||||
You can read more about this in [the permissions
|
||||
documentation](https://backstage.io/docs/permissions/overview) and [the
|
||||
changelog](https://github.com/backstage/backstage/blob/master/plugins/permission-node/CHANGELOG.md#070).
|
||||
|
||||
### Migration: `jest` v29
|
||||
|
||||
Both `jest`, `jest-runtime`, and `jest-environment-jsdom` as used by the
|
||||
Backstage CLI were bumped to version 29. This is up from version 27, so check
|
||||
out both the [v28](https://jestjs.io/docs/28.x/upgrading-to-jest28) and
|
||||
[v29](https://jestjs.io/docs/upgrading-to-jest29) (later
|
||||
[here](https://jestjs.io/docs/29.x/upgrading-to-jest29)) migration guides, since
|
||||
your existing tests may be affected.
|
||||
|
||||
Particular changes that were encountered in the main Backstage repository are:
|
||||
|
||||
- The updated snapshot format.
|
||||
- `jest.useFakeTimers('legacy')` is now `jest.useFakeTimers({ legacyFakeTimers: true })`.
|
||||
- Error objects collected by `withLogCollector` from `@backstage/test-utils` are
|
||||
now objects with a `detail` property rather than a string.
|
||||
|
||||
### Migration: `react-router` v6
|
||||
|
||||
Newly created Backstage repositories now use the stable version 6 of
|
||||
`react-router`, just like the main repository does.
|
||||
|
||||
Migrating to the stable version of `react-router` is optional for the time
|
||||
being; Backstage has support for both versions. But if you want to do the same
|
||||
for your existing repository, please follow [this
|
||||
guide](https://backstage.io/docs/tutorials/react-router-stable-migration).
|
||||
Support for the beta version will be removed in a later release.
|
||||
|
||||
### Support for `__mocks__` and `__testUtils__` directories
|
||||
|
||||
The Backstage CLI now has built-in support for `__mocks__` and `__testUtils__`
|
||||
directories in your code. These can be used for mocks and shared utilities in
|
||||
tests.
|
||||
|
||||
### New Arguments for the Router of `@backstage/plugin-bazaar-backend`
|
||||
|
||||
The bazaar-backend `createRouter` function now requires that the `identityApi`
|
||||
is passed to the router.
|
||||
|
||||
### Deprecated plugin: `@backstage/plugin-catalog-backend-module-bitbucket`
|
||||
|
||||
This has been deprecated and split into
|
||||
`@backstage/plugin-catalog-backend-module-bitbucket-cloud` and
|
||||
`@backstage/plugin-catalog-backend-module-bitbucket-server`, for BitBucket Cloud
|
||||
and BitBucket Server respectively. Please update your dependencies accordingly,
|
||||
depending on which product you use.
|
||||
|
||||
The original package will be removed in a future release.
|
||||
|
||||
Contributed by [@pjungermann](https://github.com/pjungermann) in
|
||||
[#14070](https://github.com/backstage/backstage/pull/14070)
|
||||
|
||||
## Security Fixes
|
||||
|
||||
This release does not contain any security fixes.
|
||||
|
||||
## Upgrade path
|
||||
|
||||
We recommend that you keep your Backstage project up to date with this latest
|
||||
release. For more guidance on how to upgrade, check out the documentation for
|
||||
[keeping Backstage
|
||||
updated](https://backstage.io/docs/getting-started/keeping-backstage-updated).
|
||||
|
||||
## Links and References
|
||||
|
||||
Below you can find a list of links and references to help you learn about and
|
||||
start using this new release.
|
||||
|
||||
- [Backstage official website](https://backstage.io/),
|
||||
[documentation](https://backstage.io/docs/), and [getting started
|
||||
guide](https://backstage.io/docs/getting-started/)
|
||||
- [GitHub repository](https://github.com/backstage/backstage)
|
||||
- Backstage's [versioning and support
|
||||
policy](https://backstage.io/docs/overview/versioning-policy)
|
||||
- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support
|
||||
- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.7.0-changelog.md)
|
||||
- Backstage [Demos](https://backstage.io/demos),
|
||||
[Blog](https://backstage.io/blog),
|
||||
[Roadmap](https://backstage.io/docs/overview/roadmap) and
|
||||
[Plugins](https://backstage.io/plugins)
|
||||
|
||||
Sign up for our [newsletter](https://mailchi.mp/spotify/backstage-community) if
|
||||
you want to be informed about what is happening in the world of Backstage.
|
||||
@@ -178,7 +178,7 @@ When migrating over to React Router v6 stable, you might also see browser consol
|
||||
|
||||
```diff
|
||||
- <Navigate key="/" to="catalog" />
|
||||
+ <Route path="/" element={<Navigate to="/catalog" />} />
|
||||
+ <Route path="/" element={<Navigate to="catalog" />} />
|
||||
```
|
||||
|
||||
### `NavLink`
|
||||
|
||||
@@ -72,6 +72,12 @@ backend:
|
||||
+ port: ${POSTGRES_PORT}
|
||||
+ user: ${POSTGRES_USER}
|
||||
+ password: ${POSTGRES_PASSWORD}
|
||||
+ # https://node-postgres.com/features/ssl
|
||||
+ # you can set the sslmode configuration option via the `PGSSLMODE` environment variable
|
||||
+ # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
|
||||
+ # ssl:
|
||||
+ # ca: # if you have a CA file and want to verify it you can uncomment this section
|
||||
+ # $file: <file-path>/ca/server.crt
|
||||
+ # Refer to Tarn docs for default values on PostgreSQL pool configuration - https://github.com/Vincit/tarn.js
|
||||
+ knexConfig:
|
||||
+ pool:
|
||||
@@ -79,12 +85,6 @@ backend:
|
||||
+ max: 12
|
||||
+ acquireTimeoutMillis: 60000
|
||||
+ idleTimeoutMillis: 60000
|
||||
+ # https://node-postgres.com/features/ssl
|
||||
+ # you can set the sslmode configuration option via the `PGSSLMODE` environment variable
|
||||
+ # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
|
||||
+ # ssl:
|
||||
+ # ca: # if you have a CA file and want to verify it you can uncomment this section
|
||||
+ # $file: <file-path>/ca/server.crt
|
||||
```
|
||||
|
||||
### Using a single database
|
||||
|
||||
Reference in New Issue
Block a user