Merge branch 'master' of github.com:Niksko/backstage into github-discovery-validate

This commit is contained in:
Nikolas Skoufis
2022-10-20 11:02:03 +11:00
753 changed files with 18903 additions and 3516 deletions
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
View File
@@ -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
+11
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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({
+2 -6
View File
@@ -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
+13
View File
@@ -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,
}),
);
```
+25 -8
View File
@@ -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,
+ }),
+);
```
+25 -11
View File
@@ -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
+12 -4
View File
@@ -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.
+29 -12
View File
@@ -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
+8
View File
@@ -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,
}),
);
```
+15 -9
View File
@@ -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
}),
);
}
```
+6 -6
View File
@@ -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
+125
View File
@@ -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`
+6 -6
View File
@@ -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