diff --git a/.changeset/chilly-parrots-pay.md b/.changeset/chilly-parrots-pay.md new file mode 100644 index 0000000000..f6f19f5f64 --- /dev/null +++ b/.changeset/chilly-parrots-pay.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Fix accessibility issue in `SearchCheckbox` component, making it possible to use the field via keyboard. diff --git a/.changeset/cold-pillows-mix.md b/.changeset/cold-pillows-mix.md new file mode 100644 index 0000000000..12dc9422aa --- /dev/null +++ b/.changeset/cold-pillows-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Swap `ImportStepper` and `InfoCard` order to fix tab order in `catalog-import`. diff --git a/.changeset/create-app-1686056275.md b/.changeset/create-app-1686056275.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1686056275.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/fifty-shirts-brush.md b/.changeset/fifty-shirts-brush.md new file mode 100644 index 0000000000..98cd7b885c --- /dev/null +++ b/.changeset/fifty-shirts-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Add `TargetBranchName` variable and output for the `publish:gitlab:merge-request` and `publish:github:pull-request` s'cascaffolder actions. diff --git a/.changeset/fuzzy-pots-worry.md b/.changeset/fuzzy-pots-worry.md new file mode 100644 index 0000000000..f84531b502 --- /dev/null +++ b/.changeset/fuzzy-pots-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +K8s proxy HEADER_KUBERNETES_CLUSTER is now optional in single-cluster setups. diff --git a/.changeset/good-sloths-pretend.md b/.changeset/good-sloths-pretend.md new file mode 100644 index 0000000000..a0d8859707 --- /dev/null +++ b/.changeset/good-sloths-pretend.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Enhance the sidebar item accessibility by using appropriate header semantics. diff --git a/.changeset/hot-apples-cross.md b/.changeset/hot-apples-cross.md new file mode 100644 index 0000000000..3284c0ca8f --- /dev/null +++ b/.changeset/hot-apples-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Tweaked `UnifiedThemeProvider` to avoid overlapping JSS class names in production. diff --git a/.changeset/hot-tables-yawn.md b/.changeset/hot-tables-yawn.md new file mode 100644 index 0000000000..f78a2fa129 --- /dev/null +++ b/.changeset/hot-tables-yawn.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-events-backend-module-aws-sqs': patch +'@backstage/plugin-catalog-backend-module-aws': patch +'@backstage/integration-aws-node': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/backend-common': patch +'@backstage/plugin-techdocs-node': patch +--- + +Fix SNYK-JS-FASTXMLPARSER-5668858 (`fast-xml-parser`) by upgrading aws-sdk to at least the current latest version. diff --git a/.changeset/nice-peaches-reflect.md b/.changeset/nice-peaches-reflect.md new file mode 100644 index 0000000000..45c9f0ed6f --- /dev/null +++ b/.changeset/nice-peaches-reflect.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Set the expiration time of oidc `idToken` to be less than backstage session expiration time. diff --git a/.changeset/perfect-donkeys-cry.md b/.changeset/perfect-donkeys-cry.md new file mode 100644 index 0000000000..744dc19d64 --- /dev/null +++ b/.changeset/perfect-donkeys-cry.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added `exact` prop to `SidebarSubmenuItem` which causes it to only highlight if the current location is an exact match. diff --git a/.changeset/pre.json b/.changeset/pre.json index fedefe5ccf..4824e0494f 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -240,6 +240,7 @@ "clean-months-bake", "clean-years-whisper", "create-app-1684855417", + "create-app-1686056275", "curvy-years-smoke", "dull-bottles-teach", "famous-days-kneel", @@ -248,11 +249,16 @@ "few-games-swim", "few-oranges-complain", "few-pugs-jam", + "five-turtles-play", "gentle-turtles-applaud", "giant-maps-compete", + "good-rabbits-exist", + "gorgeous-timers-act", "grumpy-carrots-sin", "heavy-ravens-fold", + "hot-apples-cross", "hot-badgers-double", + "hungry-lies-drop", "itchy-mirrors-greet", "khaki-radios-teach", "lazy-dancers-begin", @@ -261,16 +267,23 @@ "long-lobsters-brake", "lovely-impalas-sell", "lucky-keys-behave", + "mean-insects-hope", + "modern-dancers-sit", + "nice-peaches-reflect", "nice-readers-heal", "nine-bags-dream", "ninety-jeans-scream", "ninety-turkeys-knock", "olive-carpets-explode", "orange-taxis-exercise", + "perfect-donkeys-cry", "perfect-readers-attack", "pink-goats-talk", "plenty-roses-raise", + "poor-months-switch", + "rare-bugs-chew", "real-donuts-brush", + "renovate-de04315", "selfish-carrots-sneeze", "selfish-mugs-study", "selfish-olives-end", @@ -279,22 +292,28 @@ "shaggy-terms-travel", "short-seahorses-kiss", "shy-numbers-try", + "silent-garlics-drum", + "silent-kangaroos-pay", "silver-cars-type", "silver-ducks-drum", "smart-berries-wash", "sour-papayas-wink", "strange-geese-argue", + "tame-buttons-smell", "tasty-oranges-sleep", "three-guests-beam", + "tiny-hounds-cross", "twenty-suns-breathe", "two-mayflies-tell", "violet-pots-push", + "warm-hornets-fetch", "weak-rats-serve", "weak-snails-spar", "weak-snails-spark", "weak-snails-sparkl", "weak-snails-sparkle", "wet-vans-drive", + "wise-bats-repair", "yellow-crews-float" ] } diff --git a/.changeset/rude-bags-count.md b/.changeset/rude-bags-count.md new file mode 100644 index 0000000000..e2498f4abf --- /dev/null +++ b/.changeset/rude-bags-count.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Add a scaffolder action that pull-requests for bitbucket server diff --git a/.changeset/smart-ads-rush.md b/.changeset/smart-ads-rush.md new file mode 100644 index 0000000000..369e5ab25b --- /dev/null +++ b/.changeset/smart-ads-rush.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-techdocs': patch +--- + +Make the documentation pages printable (also handy for exporting to PDF) diff --git a/.changeset/strange-dolls-decide.md b/.changeset/strange-dolls-decide.md new file mode 100644 index 0000000000..97dc99d2c9 --- /dev/null +++ b/.changeset/strange-dolls-decide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Added `github:deployKey:create` and `github:environment:create` scaffolder actions. You will need to add `read/write` permissions to your GITHUB_TOKEN and/or Github Backstage App for Repository `Administration` (for deploy key functionality) and `Environments` (for Environment functionality) diff --git a/.changeset/tiny-shrimps-beam.md b/.changeset/tiny-shrimps-beam.md new file mode 100644 index 0000000000..b538d465f9 --- /dev/null +++ b/.changeset/tiny-shrimps-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Adding in type and kind entity details to catalog table title for user clarity diff --git a/.changeset/two-cobras-shake.md b/.changeset/two-cobras-shake.md new file mode 100644 index 0000000000..173d68e626 --- /dev/null +++ b/.changeset/two-cobras-shake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-explore': patch +--- + +Enhance the tools card accessibility by using appropriate header semantics. diff --git a/.changeset/warm-hornets-fetch.md b/.changeset/warm-hornets-fetch.md new file mode 100644 index 0000000000..eb84a72f0a --- /dev/null +++ b/.changeset/warm-hornets-fetch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Keyboard navigation to open EntityContextMenu now focus visible the first element. diff --git a/.changeset/wise-bats-repair.md b/.changeset/wise-bats-repair.md new file mode 100644 index 0000000000..fc383eb11d --- /dev/null +++ b/.changeset/wise-bats-repair.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes': patch +--- + +Add proposed fix dialog for pod errors diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index e9fc74b874..2c50b55219 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -434,3 +434,5 @@ zod Zolotusky zoomable zsh +Pulumi +Lightsail diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index f02ecc3525..9cadf12b4f 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -29,7 +29,7 @@ jobs: ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.6.3 + - uses: backstage/actions/changeset-feedback@v0.6.4 name: Generate feedback with: diff-ref: 'origin/master' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec0a791dcb..3e9b079e9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -66,7 +66,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -188,7 +188,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 3164fd138e..ef8906818f 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,7 +8,7 @@ jobs: cron: runs-on: ubuntu-latest steps: - - uses: backstage/actions/cron@v0.6.3 + - uses: backstage/actions/cron@v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 4cd296827d..6fdfd5d5a4 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -26,7 +26,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index 2a9c91b820..e48a6b97ab 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -22,7 +22,7 @@ jobs: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 836d33398f..ce9a2648ee 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -145,7 +145,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 4d7f345391..89595db189 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -10,4 +10,4 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Issue sync - uses: backstage/actions/issue-sync@v0.6.3 + uses: backstage/actions/issue-sync@v0.6.4 diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 73c4b64dca..0930c75ddd 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -35,7 +35,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.6.3 + - uses: backstage/actions/re-review@v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 72393b1c28..a92effbd14 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,7 +18,7 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: PR sync - uses: backstage/actions/pr-sync@v0.6.3 + uses: backstage/actions/pr-sync@v0.6.4 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 412fbfe59d..6471b265bc 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -20,7 +20,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index b3c8291b65..6b55609bd5 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -19,7 +19,7 @@ jobs: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 1b031f50ad..fc62d36563 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -27,7 +27,7 @@ jobs: registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: linux-v16 diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index cf7b750c54..11c0ca41b6 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -25,7 +25,7 @@ jobs: with: node-version: 16.x - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v16.x - name: run Lighthouse CI diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index 87056957f5..c05339f595 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -30,7 +30,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index b4a969bb47..33cc4f83ec 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -52,7 +52,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 92d6222b52..b1d370ec3f 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -37,7 +37,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.3 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install diff --git a/docs/deployment/backstage-deploy/aws.md b/docs/deployment/backstage-deploy/aws.md new file mode 100644 index 0000000000..957dc27437 --- /dev/null +++ b/docs/deployment/backstage-deploy/aws.md @@ -0,0 +1,180 @@ +--- +id: aws-lightsail +title: Deploying Backstage on AWS Lightsail +sidebar_label: AWS Lightsail +description: How to deploy Backstage on AWS Lightsail +--- + +> **DISCLAIMER: The `deploy` command is in alpha and still experimental. Do not use the `deploy` command for production deployments.** + +Getting started with Backstage often involves setting up an instance on a cloud provider and sharing it with your team so they can experiment. To make this cloud deployment easier, we've built a `deploy` command to stand up a proof-of-concept instance on AWS (using Lightsail). + +## What is AWS Lightsail + +:::tip + +AWS offers a free tier for up to three months on $10 USD/month Container service (Micro -1 node). By default we use the `nano` node, so if you are a new user this approach shouldn't cost you anything. For more information, refer to the [pricing](https://aws.amazon.com/lightsail/pricing/) documentation. + +::: + +AWS Lightsail offers a simple way to run containers in the cloud. To learn more about AWS Lightsail, please refer to the [official documentation](https://lightsail.aws.amazon.com/ls/docs/en_us/articles/amazon-lightsail-container-services-deployments). + +## Creating user in AWS + +- Open the AWS console and navigate to the IAM section +- In the left side menu click on `Users` and then click on `Add users` +- Specify a username and then click on `Next` +- Afterwards you can assign permissions, select `Attach policies directly` and then click on `Create policy`. + This should take you to a new window in which you can create a new policy based on `JSON`. + Copy over the following: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "ecr:DescribeImageReplicationStatus", + "ecr:ListTagsForResource", + "ecr:UploadLayerPart", + "ecr:BatchGetRepositoryScanningConfiguration", + "ecr:DeleteRepository", + "ecr:GetRegistryScanningConfiguration", + "ecr:CompleteLayerUpload", + "ecr:TagResource", + "ecr:DescribeRepositories", + "ecr:DeleteRepositoryPolicy", + "ecr:BatchCheckLayerAvailability", + "ecr:GetLifecyclePolicy", + "ecr:GetRegistryPolicy", + "ecr:PutLifecyclePolicy", + "ecr:DescribeImageScanFindings", + "ecr:GetLifecyclePolicyPreview", + "ecr:CreateRepository", + "ecr:DescribeRegistry", + "ecr:GetDownloadUrlForLayer", + "ecr:GetAuthorizationToken", + "ecr:DeleteLifecyclePolicy", + "ecr:PutImage", + "ecr:UntagResource", + "ecr:SetRepositoryPolicy", + "ecr:BatchGetImage", + "ecr:InitiateLayerUpload", + "ecr:GetRepositoryPolicy", + "lightsail:CreateContainerService", + "lightsail:GetKeyPair", + "lightsail:GetContainerServiceDeployments", + "lightsail:CreateContainerServiceRegistryLogin", + "lightsail:GetContainerImages", + "lightsail:UntagResource", + "lightsail:RegisterContainerImage", + "lightsail:GetContainerServices", + "lightsail:GetContainerServicePowers", + "lightsail:GetKeyPairs", + "lightsail:CreateContainerServiceDeployment", + "lightsail:GetContainerServiceMetricData", + "lightsail:GetContainerAPIMetadata", + "lightsail:DeleteContainerService", + "lightsail:GetContainerLog", + "lightsail:TagResource" + ], + "Resource": "*" + }, + { + "Sid": "Statement1", + "Effect": "Allow", + "Action": [], + "Resource": [] + } + ] +} +``` + +Then click on `Next` and give the policy a name and a description of your liking. Afterwards, click on `Create policy`. + +- Navigate back to the user creation window and press on the refresh button and search for the policy you just created. Now, create the user. +- Now you will be redirected to all users, click on the user you just created and click on `Security credentials` +- Scroll below and click on `Create access key` +- Choose `Command Line Interface (CLI)` +- Now export the following values + +```bash +$ export AWS_ACCESS_KEY_ID=... (first value) +$ export AWS_SECRET_ACCESS_KEY=.... (second secret value) +``` + +## Configuring the Pulumi CLI + +Second, install the [Pulumi CLI](https://www.pulumi.com/docs/get-started/install/). + +Then we need to execute the following commands, to set Pulumi up: + +:::tip + +Make sure to store your passphrase somewhere safe as it is used to encrypt/decrypt your Pulumi config. + +::: + +```bash +$ pulumi login --local +$ export PULUMI_CONFIG_PASSPHRASE="" +``` + +By using `pulumi login --local` we are making sure that Pulumi stores our state on the local file disk. The environment variable `PULUMI_CONFIG_PASSPHRASE` is used by Pulumi to generate a unique key for your stack + +## Deploying your instance on Lightsail + +:::warning + +Make sure that [Docker](https://docs.docker.com/) is running before you start this section. + +::: + +After you have made your changes to your local instance, it's time to deploy it on Lightsail. + +First, we need to configure a new `app-config` file and update the `baseUrl`. + +```bash +$ touch app-config.deployment.yaml +``` + +And then update the file with the following yaml: + +```yaml +app: + baseUrl: ${BACKSTAGE_HOST} + +backend: + baseUrl: ${BACKSTAGE_HOST} +``` + +The environment variable `BACKSTAGE_HOST` will be set to the endpoint that AWS Lightsail creates. + +Now we can deploy our instance! + +```bash +$ npx backstage-deploy aws --stack backstage-poc --create-dockerfile +``` + +In the first part of the command, we are specifying that we want to deploy our instance on AWS. With the [`--stack`](https://www.pulumi.com/docs/reference/cli/pulumi_stack/) option, we are providing Pulumi a reference to our container deployment. Furthermore, with the `--create-dockerfile` option, there will be a `Dockerfile` and `.dockerignore` created in the root of the project. + +After running the command, Pulumi will start creating the following resources for you in AWS: + +- ECR Repository +- Lightsail Container Service +- Lightsail Container Service Deployment +- Policy that allows Lightsail to pull from ECR + +If it's the first time building the Docker image, it might take a while for everything to be fully provisioned. After the command is finished running, your Backstage instance should be up and running on AWS Lightsail! 🎉 + +### Cleaning up resources + +Cleaning up the resources is also done with the deploy command. + +```bash +$ npx backstage-deploy aws --stack backstage-poc --destroy +``` + +This will delete everything that was originally created by the `deploy` command. diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index f01085dd86..46d59cbf1b 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -94,7 +94,7 @@ export default async function createPlugin( scheduler: env.scheduler, }); env.eventBroker.subscribe(githubProvider); - builder.addEntityProvider(demoProvider); + builder.addEntityProvider(githubProvider); /* highlight-add-end */ const { processingEngine, router } = await builder.build(); await processingEngine.start(); diff --git a/docs/integrations/github/github-apps.md b/docs/integrations/github/github-apps.md index 3cad69f56d..cc84704799 100644 --- a/docs/integrations/github/github-apps.md +++ b/docs/integrations/github/github-apps.md @@ -138,3 +138,4 @@ integration: - `Commit statuses`: `Read-only` - `Variables`: `Read & write` (if templates include GitHub Action Repository Variables) - `Secrets`: `Read & write` (if templates include GitHub Action Repository Secrets) + - `Environments`: `Read & write` (if templates include GitHub Environments) diff --git a/docs/local-dev/cli-commands.md b/docs/local-dev/cli-commands.md index 66a1855fca..29cc8635aa 100644 --- a/docs/local-dev/cli-commands.md +++ b/docs/local-dev/cli-commands.md @@ -10,55 +10,64 @@ and where to use them. ## help This command displays a help summary or detailed help screens for each command. -Below is a cleaned up output of `yarn backstage-cli --help` +Below is a cleaned up output of `yarn backstage-cli --help`: ```text -repo [command] Command that run across an entire Backstage project -package [command] Lifecycle scripts for individual packages -migrate [command] Migration utilities - -create Open up an interactive guide to creating new things in your app - -config:docs Browse the configuration reference documentation -config:print Print the app configuration for the current package -config:check Validate that the given configuration loads and matches schema -config:schema Dump the app configuration schema - -versions:bump Bump Backstage packages to the latest versions -versions:check Check Backstage package versioning - -build-workspace Builds a temporary dist workspace from the provided packages -create-github-app Create new GitHub App in your organization (experimental) - -info Show helpful information for debugging and reporting bugs -help [command] display help for command +new [options] Open up an interactive guide to creating new things in + your app +test Run tests, forwarding args to Jest, defaulting to watch + mode [DEPRECATED] +config:docs [options] Browse the configuration reference documentation +config:print [options] Print the app configuration for the current package +config:check [options] Validate that the given configuration loads and matches + schema +config:schema [options] Print configuration schema +repo [command] Command that run across an entire Backstage project +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 [packages...] Builds a temporary dist workspace from the provided + packages +create-github-app Create new GitHub App in your organization. +info Show helpful information for debugging and reporting bugs +help [command] display help for command ``` -The `package` command category, `yarn backstage-cli package --help` +The `package` command category, `yarn backstage-cli package --help`: ```text -start [options] Start a package for local development -build [options] Build a package for production deployment or publishing -lint [options] Lint a package -test Run tests, forwarding args to Jest, defaulting to watch mode -clean Delete cache directories -prepack Prepares a package for packaging before publishing -postpack Restores the changes made by the prepack command +start [options] Start a package for local development +build [options] Build a package for production deployment or publishing +lint [options] [directories...] Lint a package +test Run tests, forwarding args to Jest, defaulting to watch mode +clean Delete cache directories +prepack Prepares a package for packaging before publishing +postpack Restores the changes made by the prepack command +help [command] display help for command ``` -The `repo` command category, `yarn backstage-cli repo --help` +The `repo` command category, `yarn backstage-cli repo --help`: ```text -build [options] Build packages in the project, excluding bundled app and backend packages. -lint [options] Lint all packages in the project +build [options] Build packages in the project, excluding bundled app and backend packages. +lint [options] Lint all packages in the project +clean Delete cache and output directories +list-deprecations [options] List deprecations +test [options] Run tests, forwarding args to Jest, defaulting to watch mode +help [command] display help for command ``` -The `migrate` command category, `yarn backstage-cli migrate --help` +The `migrate` command category, `yarn backstage-cli migrate --help`: ```text package-roles Add package role field to packages that don't have it package-scripts Set package scripts according to each package role +package-exports Synchronize package subpath export definitions package-lint-configs Migrates all packages to use @backstage/cli/config/eslint-factory +react-router-deps Migrates the react-router dependencies for all packages to be peer dependencies +help [command] display help for command ``` ## repo build @@ -235,7 +244,7 @@ Options: -h, --help display help for command ``` -## config:docs +## config\:docs This commands opens up the reference documentation of your apps local configuration schema in the browser. This is useful to get an overview of what @@ -252,7 +261,7 @@ Options: -h, --help display help for command ``` -## config:print +## config\:print Print the static configuration, defaulting to reading `app-config.yaml` in the repo root, using schema collected from all local packages in the repo. @@ -277,7 +286,7 @@ Options: -h, --help display help for command ``` -## config:check +## config\:check Validate that static configuration loads and matches schema, defaulting to reading `app-config.yaml` in the repo root and using schema collected from all @@ -296,7 +305,7 @@ Options: -h, --help display help for command ``` -## config:schema +## config\:schema Dump the configuration schema that was collected from all local packages in the repo. @@ -315,7 +324,7 @@ Options: -h, --help display help for command ``` -## versions:bump +## 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 @@ -330,7 +339,7 @@ Options: --release Bump to a specific Backstage release line or version (default: "main") ``` -## versions:check +## versions\:check Validate `@backstage` dependencies within the repo, making sure that there are no duplicates of packages that might lead to breakages. diff --git a/docs/releases/v1.15.0-next.2-changelog.md b/docs/releases/v1.15.0-next.2-changelog.md new file mode 100644 index 0000000000..9a3edcadba --- /dev/null +++ b/docs/releases/v1.15.0-next.2-changelog.md @@ -0,0 +1,1165 @@ +# Release v1.15.0-next.2 + +## @backstage/app-defaults@1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## @backstage/core-components@0.13.2-next.2 + +### Patch Changes + +- 66ae4d8ca380: Added `exact` prop to `SidebarSubmenuItem` which causes it to only highlight if the current location is an exact match. +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/create-app@0.5.2-next.2 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/dev-utils@1.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/app-defaults@1.4.0-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/integration-react@1.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/test-utils@1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## @backstage/theme@0.4.0-next.1 + +### Patch Changes + +- 5065a5e8ebd6: Tweaked `UnifiedThemeProvider` to avoid overlapping JSS class names in production. + +## @backstage/plugin-adr@0.6.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-airbrake@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/dev-utils@1.0.16-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-allure@0.1.35-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-analytics-module-ga@0.1.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-analytics-module-ga4@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-apache-airflow@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-api-docs@0.9.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-apollo-explorer@0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-auth-backend@0.18.4-next.2 + +### Patch Changes + +- d0f5b0c886c2: Set the expiration time of oidc `idToken` to be less than backstage session expiration time. +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-azure-devops@0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-azure-sites@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-badges@0.2.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-badges-backend@0.2.1-next.2 + +### Patch Changes + +- 4474f44c5ee7: Adding migrations to the packages.json +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-bazaar@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/cli@0.22.8-next.1 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-bitrise@0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-catalog@1.11.1-next.2 + +### Patch Changes + +- 47b01e4c5315: Keyboard navigation to open EntityContextMenu now focus visible the first element. +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.3.1-next.2 + +### Patch Changes + +- b9a6d1348d96: Properly handle `async` event callback +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-backend-module-gitlab@0.2.2-next.2 + +### Patch Changes + +- f31fd1f8fd98: Fixed bug that caused ingestion errors when a user's name or profile picture is undefined. +- 66261b4ab441: Added option to skip forked repos +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-graph@0.2.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-catalog-import@0.9.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-catalog-react@1.7.0-next.2 + +### Patch Changes + +- d68692aee97e: Make `useRelatedEntities` use `getEntitiesByRefs` under the hood +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-cicd-statistics@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.21-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-circleci@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-cloudbuild@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-code-climate@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-code-coverage@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-code-coverage-backend@0.2.12-next.2 + +### Patch Changes + +- a83cb4e5624e: Updated dependency `xml2js` to `^0.6.0`. +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-codescene@0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-config-schema@0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-cost-insights@0.12.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-devtools@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## @backstage/plugin-dynatrace@6.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-entity-feedback@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-entity-validation@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-explore@0.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/plugin-explore-react@0.0.29-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-firehydrant@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-fossa@0.2.51-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-gcalendar@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-gcp-projects@0.3.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-git-release-manager@0.3.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-github-actions@0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-github-deployments@0.1.50-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-github-issues@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-github-pull-requests-board@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-gitops-profiles@0.3.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-gocd@0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-graphiql@0.2.51-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-graphql-voyager@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-home@0.5.3-next.2 + +### Patch Changes + +- 2ff94da135a4: bump `rjsf` dependencies to 5.7.3 +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-home-react@0.1.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-home-react@0.1.0-next.2 + +### Patch Changes + +- 2ff94da135a4: bump `rjsf` dependencies to 5.7.3 +- Updated dependencies + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-ilert@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-jenkins@0.8.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-kafka@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-kubernetes@0.9.2-next.2 + +### Patch Changes + +- 73cc0deee48a: Add proposed fix dialog for pod errors +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-kubernetes-backend@0.11.1-next.2 + +### Patch Changes + +- 4249f4214f9f: Fixed bug in KubernetesProxy where Host header was not propagated, leading to certificate issues +- 5e4879d80f4d: Fixed wrong `pluginID` in the `kubernetes` alpha backend support, that made the `kubernetes` plugin fail with the new experimental backend. +- 73cc0deee48a: Add proposed fix dialog for pod errors +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/integration-aws-node@0.1.4-next.0 + +## @backstage/plugin-lighthouse@0.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-linguist@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-microsoft-calendar@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-newrelic@0.3.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-newrelic-dashboard@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-octopus-deploy@0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-org@0.6.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-org-react@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-pagerduty@0.5.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-home-react@0.1.0-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-periskop@0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-playlist@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## @backstage/plugin-puppetdb@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-rollbar@0.4.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-scaffolder@1.13.2-next.2 + +### Patch Changes + +- 2ff94da135a4: bump `rjsf` dependencies to 5.7.3 +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-scaffolder-react@1.5.0-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## @backstage/plugin-scaffolder-backend@1.15.0-next.2 + +### Patch Changes + +- 11e0f625583f: Fix wrong gitlabUrl format in repoUrl input description +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.1-next.2 + +### Patch Changes + +- 30e6edd7f6a5: Add support for dry run for `gitlab:group:ensureExists` action. +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-react@1.5.0-next.2 + +### Patch Changes + +- cf34311cdbe1: Extract `ui:*` fields from conditional `then` and `else` schema branches. +- 2ff94da135a4: bump `rjsf` dependencies to 5.7.3 +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-search@1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-search-react@1.6.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-sentry@0.5.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-shortcuts@0.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-sonarqube@0.6.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-splunk-on-call@0.4.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-stack-overflow@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-home-react@0.1.0-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-stackstorm@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-tech-insights@0.3.11-next.2 + +### Patch Changes + +- c03307ded3e6: The check description is now rendered with markdown. +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-tech-radar@0.6.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-techdocs@1.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/plugin-techdocs@1.6.3-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-techdocs-react@1.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-todo@0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-user-settings@0.7.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-vault@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @backstage/plugin-xcmetrics@0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + +## example-app@0.2.84-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-tech-insights@0.3.11-next.2 + - @backstage/plugin-scaffolder-react@1.5.0-next.2 + - @backstage/plugin-scaffolder@1.13.2-next.2 + - @backstage/plugin-home@0.5.3-next.2 + - @backstage/plugin-kubernetes@0.9.2-next.2 + - @backstage/app-defaults@1.4.0-next.2 + - @backstage/cli@0.22.8-next.1 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-adr@0.6.1-next.2 + - @backstage/plugin-airbrake@0.3.19-next.2 + - @backstage/plugin-api-docs@0.9.4-next.2 + - @backstage/plugin-azure-devops@0.3.1-next.2 + - @backstage/plugin-azure-sites@0.1.8-next.2 + - @backstage/plugin-badges@0.2.43-next.2 + - @backstage/plugin-catalog-graph@0.2.31-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.0-next.1 + - @backstage/plugin-circleci@0.3.19-next.2 + - @backstage/plugin-cloudbuild@0.3.19-next.2 + - @backstage/plugin-code-coverage@0.2.12-next.2 + - @backstage/plugin-cost-insights@0.12.8-next.2 + - @backstage/plugin-devtools@0.1.1-next.2 + - @backstage/plugin-dynatrace@6.0.0-next.2 + - @backstage/plugin-entity-feedback@0.2.2-next.2 + - @backstage/plugin-explore@0.4.4-next.2 + - @backstage/plugin-gcalendar@0.3.15-next.2 + - @backstage/plugin-gcp-projects@0.3.38-next.2 + - @backstage/plugin-github-actions@0.6.0-next.2 + - @backstage/plugin-gocd@0.1.25-next.2 + - @backstage/plugin-graphiql@0.2.51-next.2 + - @backstage/plugin-jenkins@0.8.1-next.2 + - @backstage/plugin-kafka@0.3.19-next.2 + - @backstage/plugin-lighthouse@0.4.4-next.2 + - @backstage/plugin-linguist@0.1.4-next.2 + - @backstage/plugin-microsoft-calendar@0.1.4-next.2 + - @backstage/plugin-newrelic@0.3.37-next.2 + - @backstage/plugin-octopus-deploy@0.2.1-next.2 + - @backstage/plugin-org@0.6.9-next.2 + - @backstage/plugin-pagerduty@0.5.12-next.2 + - @backstage/plugin-playlist@0.1.10-next.2 + - @backstage/plugin-puppetdb@0.1.2-next.2 + - @backstage/plugin-rollbar@0.4.19-next.2 + - @backstage/plugin-search@1.3.1-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/plugin-sentry@0.5.4-next.2 + - @backstage/plugin-shortcuts@0.3.11-next.2 + - @backstage/plugin-stack-overflow@0.1.16-next.2 + - @backstage/plugin-stackstorm@0.1.3-next.2 + - @backstage/plugin-tech-radar@0.6.5-next.2 + - @backstage/plugin-techdocs@1.6.3-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.14-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/plugin-todo@0.2.21-next.2 + - @backstage/plugin-user-settings@0.7.4-next.2 + - @internal/plugin-catalog-customized@0.0.11-next.2 + - @backstage/plugin-catalog-import@0.9.9-next.2 + - @backstage/plugin-newrelic-dashboard@0.2.12-next.2 + - @backstage/plugin-apache-airflow@0.2.12-next.2 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + +## example-backend@0.2.84-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-backend@0.11.1-next.2 + - @backstage/plugin-badges-backend@0.2.1-next.2 + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + - @backstage/plugin-auth-backend@0.18.4-next.2 + - @backstage/plugin-code-coverage-backend@0.2.12-next.2 + - example-app@0.2.84-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.1.3-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.15-next.2 + - @backstage/config@1.0.7 + +## example-backend-next@0.0.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-backend@0.11.1-next.2 + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + +## e2e-test@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.2-next.2 + +## techdocs-cli-embedded-app@0.2.83-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/app-defaults@1.4.0-next.2 + - @backstage/cli@0.22.8-next.1 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/plugin-techdocs@1.6.3-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + +## @internal/plugin-catalog-customized@0.0.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + +## @internal/plugin-todo-list@1.0.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 diff --git a/microsite/blog/2023-05-06-backstage-deploy-alpha.mdx b/microsite/blog/2023-05-06-backstage-deploy-alpha.mdx new file mode 100644 index 0000000000..1a783b026a --- /dev/null +++ b/microsite/blog/2023-05-06-backstage-deploy-alpha.mdx @@ -0,0 +1,79 @@ +--- +title: 'Welcome: Backstage Deploy CLI (Alpha)' +author: Djamaile Rahamat, Spotify +authorURL: https://github.com/djamaile +authorImageURL: https://avatars.githubusercontent.com/u/15789670?v=4 +--- + +_This blog post is co-authored by Emma White ([@ewhite1997](https://github.com/ewhite1997)), Spotify._ + +![Backstage Deploy banner](assets/2023-05-06/Welcome-Backstage-Deploy.png) + +TL;DR: Backstage released a new CLI earlier this year as part of a [new Backstage project](https://github.com/backstage/backstage-deploy). This new capability allows early adopters to deploy their Backstage proof of concept faster than before. In this blog, you’ll learn a little bit more about the Deploy CLI and how you can get started with it. + +{/* truncate */} + +## Why Backstage Deploy + +We’ve heard from Backstage adopters that before reaching widespread adoption at their organizations, teams test out a Backstage proof of concept (POC). To create the POC, teams scaffold an instance, set up the catalog, and change the UI to suit their company’s branding. Once these milestones are completed, there's just one last step before showing off the awesomeness of a Backstage POC internally... deploying the Backstage POC from a local machine to the cloud. This final step often introduces a lot of questions that attempt to determine the easiest and fastest way to do that. + +Let’s say you’re at this last step: your POC is ready for deployment, but you have some lingering questions. + +For example: + +- What Dockerfile should you use? +- Should the POC be deployed on Kubernetes? +- How do you deploy the POC on my cloud provider? + +To address these questions and reduce friction from deploying a POC, we built a [new CLI](https://github.com/backstage/backstage-deploy). The CLI is simply called `deploy` and is invokable with `npx`. With this new CLI, you can generate a Dockerfile and deploy a Backstage instance onto a preferred cloud provider. While the package’s infrastructure is built to support all cloud providers, currently the CLI only offers an AWS implementation. In the future, we plan to add additional cloud providers to the package and [welcome any contributions](https://github.com/backstage/backstage/blob/6996b3338d678efc03307112524060e9dc2ad769/CONTRIBUTING.md) extending the suite of cloud provider implementations! + +**So, what about Kubernetes?** Since the CLI is designed specifically for the POC phase, we believe that Kubernetes isn’t the right fit – as Kubernetes is better suited for production workloads. So, we explored lightweight, container-based solutions, and landed on [Amazon Lightsail](https://docs.aws.amazon.com/lightsail/index.html) as a hosting service for the POC. +Amazon Lightsail supports [lightweight container](https://lightsail.aws.amazon.com/ls/docs/en_us/articles/amazon-lightsail-container-services) deployments [at a low cost](https://aws.amazon.com/lightsail/pricing/), and has a [free trial for new users](https://aws.amazon.com/lightsail/pricing/?loc=ft#AWS_Free_Tier)! Given Lightsail’s ease of use and affordability, we recommend using Lightsail over Kubernetes to test out your Backstage POC. + +With the Dockerfile and Kubernetes questions answered, we just have to address how to actually deploy the POC. And that is where the new CLI comes in. + +## Get started with Deploy CLI + +It's now time to put the Deploy CLI into action and deploy a Backstage POC. The following steps guide you through the deployment process. + +Deploy CLI makes use of [Pulumi](https://www.pulumi.com/docs/) which is an infrastructure-as-code tool that helps provision resources in the cloud. Before you get started, ensure you have the [Pulumi CLI](https://www.pulumi.com/docs/cli/) and [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed on your local machine. + +You can find the step-by-step installation documentation for Pulumi under the [Deployment section](https://backstage.io/docs/deployment/backstage-deploy/aws-lightsail). + +But we summarize the steps to deploy your POC here. You can invoke the the CLI you can use the following command: + +```bash +$ npx backstage-deploy aws --create-dockerfile +Starting Pulumi +successfully initialized stack +installing aws plugin... +plugins installed +setting up config +refreshing stack... +Refreshing (backstage): + +Instance will live at: +https://backstage-container-service.xxx.us-east-1.cs.amazonlightsail.com/ +``` + +Once you kick off the command it will create a Dockerfile for you in the root and Pulumi will start provisioning resources in AWS. +Pulumi will then create a container based deployment in Amazon Lightsail. + +After you’re done with the POC, it’s easy to delete the AWS resources you provisioned and save you costs within AWS. You can do so with the following command: + +```bash +$ npx backstage-deploy aws --destroy +``` + +## Looking ahead + +As mentioned earlier in this blog, we released the Backstage Deploy CLI with an AWS implementation only. In the next few months, we are excited to collect feedback from our end users to understand how the AWS implementation works. With those learnings, we plan to iterate on the Deploy CLI and build out implementations for other cloud providers. Of course, contributions are always welcome! + +So, please try this new CLI out and let us know what you think on [Discord](https://discord.com/channels/687207715902193673/995973463208644678)! + +Useful links: + +- [Backstage Deploy](https://github.com/backstage/backstage-deploy) +- [Documentation](https://backstage.io/docs/deployment/backstage-deploy/aws-lightsail) +- [Pulumi docs](https://www.pulumi.com/docs/) +- [#deployment](https://discord.com/channels/687207715902193673/995973463208644678) channel in Discord diff --git a/microsite/blog/assets/2023-05-06/Welcome-Backstage-Deploy.png b/microsite/blog/assets/2023-05-06/Welcome-Backstage-Deploy.png new file mode 100644 index 0000000000..403f12f2bb Binary files /dev/null and b/microsite/blog/assets/2023-05-06/Welcome-Backstage-Deploy.png differ diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 972a67f424..f612e7b880 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -325,7 +325,12 @@ "deployment/scaling", "deployment/docker", "deployment/k8s", - "deployment/heroku" + "deployment/heroku", + { + "type": "category", + "label": "Using Backstage Deploy (alpha)", + "items": ["deployment/backstage-deploy/aws-lightsail"] + } ], "Designing for Backstage": [ "dls/design", diff --git a/package.json b/package.json index 2dcb3cf2ff..eb88e9f268 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.15.0-next.1", + "version": "1.15.0-next.2", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index ca76401e4e..561c108f6e 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + ## 1.4.0-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 26c0e8e382..cb9abc78e8 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.4.0-next.1", + "version": "1.4.0-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 70eb793ab5..7bc4caca1a 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,75 @@ # example-app +## 0.2.84-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-tech-insights@0.3.11-next.2 + - @backstage/plugin-scaffolder-react@1.5.0-next.2 + - @backstage/plugin-scaffolder@1.13.2-next.2 + - @backstage/plugin-home@0.5.3-next.2 + - @backstage/plugin-kubernetes@0.9.2-next.2 + - @backstage/app-defaults@1.4.0-next.2 + - @backstage/cli@0.22.8-next.1 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-adr@0.6.1-next.2 + - @backstage/plugin-airbrake@0.3.19-next.2 + - @backstage/plugin-api-docs@0.9.4-next.2 + - @backstage/plugin-azure-devops@0.3.1-next.2 + - @backstage/plugin-azure-sites@0.1.8-next.2 + - @backstage/plugin-badges@0.2.43-next.2 + - @backstage/plugin-catalog-graph@0.2.31-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.0-next.1 + - @backstage/plugin-circleci@0.3.19-next.2 + - @backstage/plugin-cloudbuild@0.3.19-next.2 + - @backstage/plugin-code-coverage@0.2.12-next.2 + - @backstage/plugin-cost-insights@0.12.8-next.2 + - @backstage/plugin-devtools@0.1.1-next.2 + - @backstage/plugin-dynatrace@6.0.0-next.2 + - @backstage/plugin-entity-feedback@0.2.2-next.2 + - @backstage/plugin-explore@0.4.4-next.2 + - @backstage/plugin-gcalendar@0.3.15-next.2 + - @backstage/plugin-gcp-projects@0.3.38-next.2 + - @backstage/plugin-github-actions@0.6.0-next.2 + - @backstage/plugin-gocd@0.1.25-next.2 + - @backstage/plugin-graphiql@0.2.51-next.2 + - @backstage/plugin-jenkins@0.8.1-next.2 + - @backstage/plugin-kafka@0.3.19-next.2 + - @backstage/plugin-lighthouse@0.4.4-next.2 + - @backstage/plugin-linguist@0.1.4-next.2 + - @backstage/plugin-microsoft-calendar@0.1.4-next.2 + - @backstage/plugin-newrelic@0.3.37-next.2 + - @backstage/plugin-octopus-deploy@0.2.1-next.2 + - @backstage/plugin-org@0.6.9-next.2 + - @backstage/plugin-pagerduty@0.5.12-next.2 + - @backstage/plugin-playlist@0.1.10-next.2 + - @backstage/plugin-puppetdb@0.1.2-next.2 + - @backstage/plugin-rollbar@0.4.19-next.2 + - @backstage/plugin-search@1.3.1-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/plugin-sentry@0.5.4-next.2 + - @backstage/plugin-shortcuts@0.3.11-next.2 + - @backstage/plugin-stack-overflow@0.1.16-next.2 + - @backstage/plugin-stackstorm@0.1.3-next.2 + - @backstage/plugin-tech-radar@0.6.5-next.2 + - @backstage/plugin-techdocs@1.6.3-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.14-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/plugin-todo@0.2.21-next.2 + - @backstage/plugin-user-settings@0.7.4-next.2 + - @internal/plugin-catalog-customized@0.0.11-next.2 + - @backstage/plugin-catalog-import@0.9.9-next.2 + - @backstage/plugin-newrelic-dashboard@0.2.12-next.2 + - @backstage/plugin-apache-airflow@0.2.12-next.2 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + ## 0.2.84-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 7524f62bfa..dc15f1162a 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.84-next.1", + "version": "0.2.84-next.2", "private": true, "backstage": { "role": "frontend" diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index e1192dac00..65e4488db6 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -46,10 +46,10 @@ "test:kubernetes": "backstage-cli package test -t KubernetesContainerRunner --no-watch" }, "dependencies": { - "@aws-sdk/abort-controller": "^3.310.0", - "@aws-sdk/client-s3": "^3.310.0", - "@aws-sdk/credential-providers": "^3.310.0", - "@aws-sdk/types": "^3.310.0", + "@aws-sdk/abort-controller": "^3.347.0", + "@aws-sdk/client-s3": "^3.350.0", + "@aws-sdk/credential-providers": "^3.350.0", + "@aws-sdk/types": "^3.347.0", "@backstage/backend-app-api": "workspace:^", "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", @@ -114,7 +114,7 @@ } }, "devDependencies": { - "@aws-sdk/util-stream-node": "^3.310.0", + "@aws-sdk/util-stream-node": "^3.350.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/archiver": "^5.1.0", diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 9dcd3de104..3717628d4b 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,13 @@ # example-backend-next +## 0.0.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-backend@0.11.1-next.2 + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + ## 0.0.12-next.1 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 6d3ecc9823..78b1638c57 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.12-next.1", + "version": "0.0.12-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 312144e7a2..0d60cc67c9 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,20 @@ # example-backend +## 0.2.84-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-backend@0.11.1-next.2 + - @backstage/plugin-badges-backend@0.2.1-next.2 + - @backstage/plugin-scaffolder-backend@1.15.0-next.2 + - @backstage/plugin-auth-backend@0.18.4-next.2 + - @backstage/plugin-code-coverage-backend@0.2.12-next.2 + - example-app@0.2.84-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.1.3-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.15-next.2 + - @backstage/config@1.0.7 + ## 0.2.84-next.1 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 88937a9e6c..0c7511f2af 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.84-next.1", + "version": "0.2.84-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 114778334f..5564031cb3 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-components +## 0.13.2-next.2 + +### Patch Changes + +- 66ae4d8ca380: Added `exact` prop to `SidebarSubmenuItem` which causes it to only highlight if the current location is an exact match. +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.13.2-next.1 ### Patch Changes diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 9f4aca1dcf..df34abdd03 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -1087,6 +1087,7 @@ export type SidebarSubmenuItemProps = { to?: string; icon?: IconComponent; dropdownItems?: SidebarSubmenuItemDropdownItem[]; + exact?: boolean; }; // @public diff --git a/packages/core-components/package.json b/packages/core-components/package.json index be94cc1dfa..25c654e7d5 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.13.2-next.1", + "version": "0.13.2-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index 3d8d0f3bb0..c80e71b609 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -92,6 +92,10 @@ const VARIANT_STYLES = { flexDirection: 'column', height: 'calc(100% - 10px)', // for pages without content header marginBottom: '10px', + breakInside: 'avoid-page', + '@media print': { + height: 'auto', + }, }, }, cardContent: { diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index 00988c475b..e388e0366a 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -33,6 +33,11 @@ const useStyles = makeStyles( [theme.breakpoints.down('xs')]: { height: '100%', }, + '@media print': { + display: 'block', + height: 'auto', + overflowY: 'inherit', + }, }, }), { name: 'BackstagePage' }, diff --git a/packages/core-components/src/layout/Sidebar/Bar.tsx b/packages/core-components/src/layout/Sidebar/Bar.tsx index 815d6bc0d6..8cb43ba007 100644 --- a/packages/core-components/src/layout/Sidebar/Bar.tsx +++ b/packages/core-components/src/layout/Sidebar/Bar.tsx @@ -63,6 +63,9 @@ const useStyles = makeStyles( '&::-webkit-scrollbar': { display: 'none', }, + '@media print': { + display: 'none', + }, }, drawerWidth: props => ({ width: props.sidebarConfig.drawerWidthClosed, diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 924182086f..715e0d4af7 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -411,7 +411,11 @@ const SidebarItemBase = forwardRef((props, ref) => { {itemIcon} {text && ( - + {text} )} diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index 9000c2f10b..bf96703613 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -72,6 +72,9 @@ const useStyles = makeStyles( zIndex: theme.zIndex.snackbar, // SidebarDivider color borderTop: '1px solid #383838', + '@media print': { + display: 'none', + }, }, overlay: props => ({ diff --git a/packages/core-components/src/layout/Sidebar/Page.tsx b/packages/core-components/src/layout/Sidebar/Page.tsx index 5f660547d1..c0107256e1 100644 --- a/packages/core-components/src/layout/Sidebar/Page.tsx +++ b/packages/core-components/src/layout/Sidebar/Page.tsx @@ -51,6 +51,9 @@ const useStyles = makeStyles< [theme.breakpoints.down('xs')]: { paddingBottom: props => props.sidebarConfig.mobileSidebarHeight, }, + '@media print': { + padding: '0px !important', + }, }, content: { zIndex: 0, diff --git a/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx b/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx index 949148d7a1..85ba923672 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx @@ -127,7 +127,7 @@ export const SidebarSubmenu = (props: SidebarSubmenuProps) => { [classes.drawerOpen]: isSubmenuOpen, })} > - + {props.title} {props.children} diff --git a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx index b08647d335..d1925036bb 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx @@ -130,6 +130,7 @@ export type SidebarSubmenuItemProps = { to?: string; icon?: IconComponent; dropdownItems?: SidebarSubmenuItemDropdownItem[]; + exact?: boolean; }; /** @@ -138,7 +139,7 @@ export type SidebarSubmenuItemProps = { * @public */ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => { - const { title, subtitle, to, icon: Icon, dropdownItems } = props; + const { title, subtitle, to, icon: Icon, dropdownItems, exact } = props; const classes = useStyles(); const { setIsHoveredOn } = useContext(SidebarItemWithSubmenuContext); const closeSubmenu = () => { @@ -146,7 +147,7 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => { }; const toLocation = useResolvedPath(to ?? ''); const currentLocation = useLocation(); - let isActive = isLocationMatch(currentLocation, toLocation); + let isActive = isLocationMatch(currentLocation, toLocation, exact); const [showDropDown, setShowDropDown] = useState(false); const handleClickDropdown = () => { @@ -155,7 +156,7 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => { if (dropdownItems !== undefined) { dropdownItems.some(item => { const resolvedPath = resolvePath(item.to); - isActive = isLocationMatch(currentLocation, resolvedPath); + isActive = isLocationMatch(currentLocation, resolvedPath, exact); return isActive; }); return ( @@ -171,11 +172,19 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => { )} > {Icon && } - + {title}
{subtitle && ( - + {subtitle} )} @@ -203,7 +212,7 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => { onClick={closeSubmenu} onTouchStart={e => e.stopPropagation()} > - + {object.title} @@ -229,11 +238,19 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => { onTouchStart={e => e.stopPropagation()} > {Icon && } - + {title}
{subtitle && ( - + {subtitle} )} diff --git a/packages/core-components/src/layout/Sidebar/utils.test.ts b/packages/core-components/src/layout/Sidebar/utils.test.ts index b08dcda0fc..976108a63d 100644 --- a/packages/core-components/src/layout/Sidebar/utils.test.ts +++ b/packages/core-components/src/layout/Sidebar/utils.test.ts @@ -95,4 +95,30 @@ describe('isLocationMatching', () => { toLocation = { pathname: '/catalog', search: '', hash: '' }; expect(isLocationMatch(currentLocation, toLocation)).toBe(true); }); + + describe('exact matching', () => { + it('return false when target query parameters are subset of current location query parameters', async () => { + currentLocation = { + pathname: '/catalog', + search: '?x=foo&y=bar', + state: null, + hash: '', + key: '', + }; + toLocation = { pathname: '/catalog', search: '?x=foo', hash: '' }; + expect(isLocationMatch(currentLocation, toLocation, true)).toBe(false); + }); + + it('return true when target query parameters are exact match with current location query parameters', async () => { + currentLocation = { + pathname: '/catalog', + search: '?x=foo&y=bar', + state: null, + hash: '', + key: '', + }; + toLocation = { pathname: '/catalog', search: '?y=bar&x=foo', hash: '' }; + expect(isLocationMatch(currentLocation, toLocation, true)).toBe(true); + }); + }); }); diff --git a/packages/core-components/src/layout/Sidebar/utils.ts b/packages/core-components/src/layout/Sidebar/utils.ts index 1afebe796d..5dba73f4cd 100644 --- a/packages/core-components/src/layout/Sidebar/utils.ts +++ b/packages/core-components/src/layout/Sidebar/utils.ts @@ -18,7 +18,11 @@ import { Location, Path } from 'history'; import { isEqual, isMatch } from 'lodash'; import qs from 'qs'; -export function isLocationMatch(currentLocation: Location, toLocation: Path) { +export function isLocationMatch( + currentLocation: Location, + toLocation: Path, + exact: boolean = false, +) { const toDecodedSearch = new URLSearchParams(toLocation.search).toString(); const toQueryParameters = qs.parse(toDecodedSearch); @@ -27,9 +31,11 @@ export function isLocationMatch(currentLocation: Location, toLocation: Path) { ).toString(); const currentQueryParameters = qs.parse(currentDecodedSearch); + const queryStringMatcher = exact ? isEqual : isMatch; + const matching = isEqual(toLocation.pathname, currentLocation.pathname) && - isMatch(currentQueryParameters, toQueryParameters); + queryStringMatcher(currentQueryParameters, toQueryParameters); return matching; } diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index a68d706883..496c61ab7a 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/create-app +## 0.5.2-next.2 + +### Patch Changes + +- Bumped create-app version. + ## 0.5.2-next.1 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index d6364fd60d..81130afb4f 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 081441519a..93242e1b83 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/dev-utils +## 1.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/app-defaults@1.4.0-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 1.0.16-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 931728326d..b49eaf79e9 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.16-next.1", + "version": "1.0.16-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 68ca72cd3b..0c2e7b2ea1 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,12 @@ # e2e-test +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.2-next.2 + ## 0.2.4-next.1 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 0c020d8db9..39a6d42361 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.2.4-next.1", + "version": "0.2.4-next.2", "private": true, "backstage": { "role": "cli" diff --git a/packages/integration-aws-node/package.json b/packages/integration-aws-node/package.json index 2903a54a51..9bce0dede6 100644 --- a/packages/integration-aws-node/package.json +++ b/packages/integration-aws-node/package.json @@ -32,10 +32,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@aws-sdk/client-sts": "^3.310.0", - "@aws-sdk/credential-provider-node": "^3.310.0", - "@aws-sdk/credential-providers": "^3.310.0", - "@aws-sdk/types": "^3.310.0", + "@aws-sdk/client-sts": "^3.350.0", + "@aws-sdk/credential-provider-node": "^3.350.0", + "@aws-sdk/credential-providers": "^3.350.0", + "@aws-sdk/types": "^3.347.0", "@aws-sdk/util-arn-parser": "^3.310.0", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^" diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 15d3cbf47b..154b4bb2cd 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/integration-react +## 1.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 1.1.14-next.1 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 3215372892..d6d045b068 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.14-next.1", + "version": "1.1.14-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index bec57f1607..6c0233d4ae 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,23 @@ # techdocs-cli-embedded-app +## 0.2.83-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/app-defaults@1.4.0-next.2 + - @backstage/cli@0.22.8-next.1 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/plugin-techdocs@1.6.3-next.2 + - @backstage/plugin-techdocs-react@1.1.7-next.2 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.2.83-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index c435039eb4..9c9299c880 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.83-next.1", + "version": "0.2.83-next.2", "private": true, "backstage": { "role": "frontend" diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index fc8906e943..b4c1efc64a 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/test-utils +## 1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.1-next.0 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + ## 1.4.0-next.1 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index c8c1676834..4a2d8a634d 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.4.0-next.1", + "version": "1.4.0-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index bb1e52b792..30a9709d59 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.4.0-next.1 + +### Patch Changes + +- 5065a5e8ebd6: Tweaked `UnifiedThemeProvider` to avoid overlapping JSS class names in production. + ## 0.4.0-next.0 ### Minor Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index dd90f5c834..344b890d76 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.4.0-next.0", + "version": "0.4.0-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/theme/src/unified/UnifiedThemeProvider.tsx b/packages/theme/src/unified/UnifiedThemeProvider.tsx index c7054e0e55..613f89d5e0 100644 --- a/packages/theme/src/unified/UnifiedThemeProvider.tsx +++ b/packages/theme/src/unified/UnifiedThemeProvider.tsx @@ -16,7 +16,11 @@ import React, { ReactNode } from 'react'; import './MuiClassNameSetup'; -import { ThemeProvider } from '@material-ui/core/styles'; +import { + ThemeProvider, + StylesProvider, + createGenerateClassName, +} from '@material-ui/core/styles'; import { StyledEngineProvider, ThemeProvider as Mui5Provider, @@ -35,6 +39,14 @@ export interface UnifiedThemeProviderProps { noCssBaseline?: boolean; } +// Background at https://mui.com/x/migration/migration-data-grid-v4/#using-mui-core-v4-with-v5 +// Rather than disabling globals and custom seed, we instead only set a production prefix that +// won't collide with MUI 5 styles. We've already got a separate class name generator for v5 set +// up in MuiClassNameSetup.ts, so only the production JSS needs deduplication. +const generateV4ClassName = createGenerateClassName({ + productionPrefix: 'jss4-', +}); + /** * Provides themes for all MUI versions supported by the provided unified theme. * @@ -61,7 +73,11 @@ export function UnifiedThemeProvider( ); if (v4Theme) { - result = {result}; + result = ( + + {result} + + ); } if (v5Theme) { diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index dc2c2eb461..fc714454fb 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-adr +## 0.6.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.6.1-next.1 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 40837406d8..9f5ec784ef 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.1-next.1", + "version": "0.6.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 484f124645..838426cbd3 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-airbrake +## 0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/dev-utils@1.0.16-next.2 + - @backstage/test-utils@1.4.0-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.3.19-next.1 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 0ddf3d51a0..d600586f00 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.19-next.1", + "version": "0.3.19-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index c602614499..06c88ee633 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-allure +## 0.1.35-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.35-next.1 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 3f0718e1b9..78fcfd30f0 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.35-next.1", + "version": "0.1.35-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 69b641e8ca..d8f2136567 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga +## 0.1.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.30-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index c2e34774c2..13a6e91d2b 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.30-next.1", + "version": "0.1.30-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index 7f64c178c1..3947864fa5 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index d3b8f51fa8..4771dd5156 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga4", - "version": "0.1.1-next.1", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index b2b954b8e1..e754f453ea 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apache-airflow +## 0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.2.12-next.1 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 95304c31f9..b434947f42 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.12-next.1", + "version": "0.2.12-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 2072d4d257..abaa71eb28 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-api-docs +## 0.9.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.9.4-next.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index ea79b9b7a2..b7b4bd80c4 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.9.4-next.1", + "version": "0.9.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx index f89897524d..e3723dba5b 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx @@ -168,7 +168,7 @@ describe('DefaultApiExplorerPage', () => { const { findByTitle, findByText } = await renderWrapped( , ); - expect(await findByText(/All \(1\)/)).toBeInTheDocument(); + expect(await findByText(/All apis \(1\)/)).toBeInTheDocument(); expect(await findByTitle(/View/)).toBeInTheDocument(); expect(await findByTitle(/View/)).toBeInTheDocument(); expect(await findByTitle(/Edit/)).toBeInTheDocument(); @@ -198,7 +198,7 @@ describe('DefaultApiExplorerPage', () => { const { findByTitle, findByText } = await renderWrapped( , ); - expect(await findByText(/All \(1\)/)).toBeInTheDocument(); + expect(await findByText(/All apis \(1\)/)).toBeInTheDocument(); expect(await findByTitle(/Foo Action/)).toBeInTheDocument(); expect(await findByTitle(/Bar Action/)).toBeInTheDocument(); expect((await findByTitle(/Bar Action/)).firstChild).toBeDisabled(); diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index a0b9b5a289..7f98dc0adc 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apollo-explorer +## 0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.12-next.1 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index d3e5d7bb91..7a55d921a8 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.12-next.1", + "version": "0.1.12-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 8b21729c5e..b60e2bbcc2 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend +## 0.18.4-next.2 + +### Patch Changes + +- d0f5b0c886c2: Set the expiration time of oidc `idToken` to be less than backstage session expiration time. +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.18.4-next.1 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index e4e6747277..41ac873b68 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.18.4-next.1", + "version": "0.18.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/src/lib/session/constants.ts b/plugins/auth-backend/src/lib/session/constants.ts new file mode 100644 index 0000000000..0d14987ab2 --- /dev/null +++ b/plugins/auth-backend/src/lib/session/constants.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// BACKSTAGE_SESSION_EXPIRATION the default session expiration time +// TODO: find a less hard-coded way to access this, perhaps by reading it from the configuration. +export const BACKSTAGE_SESSION_EXPIRATION = 3600; diff --git a/plugins/auth-backend/src/lib/session/index.ts b/plugins/auth-backend/src/lib/session/index.ts new file mode 100644 index 0000000000..306d483ae0 --- /dev/null +++ b/plugins/auth-backend/src/lib/session/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { BACKSTAGE_SESSION_EXPIRATION } from './constants'; diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index 7571b4a327..11a71ca018 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -42,12 +42,10 @@ import { OAuthRefreshRequest, } from '../../lib/oauth'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; +import { BACKSTAGE_SESSION_EXPIRATION } from '../../lib/session'; const ACCESS_TOKEN_PREFIX = 'access-token.'; -// TODO(Rugvip): Auth providers need a way to access this in a less hardcoded way -const BACKSTAGE_SESSION_EXPIRATION = 3600; - type PrivateInfo = { refreshToken?: string; }; diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 5d02b7ef61..bc581f6d10 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -51,8 +51,7 @@ import { Logger } from 'winston'; import fetch from 'node-fetch'; import { decodeJwt } from 'jose'; import { Profile as PassportProfile } from 'passport'; - -const BACKSTAGE_SESSION_EXPIRATION = 3600; +import { BACKSTAGE_SESSION_EXPIRATION } from '../../lib/session'; type PrivateInfo = { refreshToken: string; diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index a5196f0930..ed59611f21 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -48,6 +48,7 @@ import { commonByEmailLocalPartResolver, commonByEmailResolver, } from '../resolvers'; +import { BACKSTAGE_SESSION_EXPIRATION } from '../../lib/session'; type PrivateInfo = { refreshToken?: string; @@ -179,17 +180,15 @@ export class OidcAuthProvider implements OAuthHandlers { // Then populate the profile with it private async handleResult(result: OidcAuthResult): Promise { const { profile } = await this.authHandler(result, this.resolverContext); - const response: OAuthResponse = { - providerInfo: { - idToken: result.tokenset.id_token, - accessToken: result.tokenset.access_token!, - scope: result.tokenset.scope!, - expiresInSeconds: result.tokenset.expires_in, - }, - profile, - }; + + const expiresInSeconds = + result.tokenset.expires_in === undefined + ? BACKSTAGE_SESSION_EXPIRATION + : Math.min(result.tokenset.expires_in, BACKSTAGE_SESSION_EXPIRATION); + + let backstageIdentity = undefined; if (this.signInResolver) { - response.backstageIdentity = await this.signInResolver( + backstageIdentity = await this.signInResolver( { result, profile, @@ -198,7 +197,16 @@ export class OidcAuthProvider implements OAuthHandlers { ); } - return response; + return { + backstageIdentity, + providerInfo: { + idToken: result.tokenset.id_token, + accessToken: result.tokenset.access_token!, + scope: result.tokenset.scope!, + expiresInSeconds, + }, + profile, + }; } } diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 2996ff68be..fa8dd95727 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -37,6 +37,7 @@ import passport from 'passport'; import { Minimatch } from 'minimatch'; import { CatalogAuthResolverContext } from '../lib/resolvers'; import { AuthDatabase } from '../database/AuthDatabase'; +import { BACKSTAGE_SESSION_EXPIRATION } from '../lib/session'; /** @public */ export type ProviderFactories = { [s: string]: AuthProviderFactory }; @@ -77,7 +78,7 @@ export async function createRouter( logger, database: authDb, }); - const keyDurationSeconds = 3600; + const keyDurationSeconds = BACKSTAGE_SESSION_EXPIRATION; const tokenIssuer = new TokenFactory({ issuer: authUrl, diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index d680899d33..5b00c429a6 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-azure-devops +## 0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.3.1-next.1 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 54ea85f79e..0bebc02495 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.3.1-next.1", + "version": "0.3.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 917080d458..ba52573335 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-azure-sites +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 491d298c2c..b31ebac2cc 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.8-next.1", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index fb12b9a417..40b87747c8 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-badges-backend +## 0.2.1-next.2 + +### Patch Changes + +- 4474f44c5ee7: Adding migrations to the packages.json +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index be1a606a1a..c3aacd52ed 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.2.1-next.1", + "version": "0.2.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 4bac0de4f6..76f42269de 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-badges +## 0.2.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.2.43-next.1 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 4fbcfe403e..3f79c3a2ce 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.43-next.1", + "version": "0.2.43-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index c7441d31d1..2fbb5de036 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-bazaar +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + - @backstage/cli@0.22.8-next.1 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.2.9-next.1 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 452e732b51..3cdb23e646 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.9-next.1", + "version": "0.2.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 355d21855f..cadece2d2c 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-bitrise +## 0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.46-next.1 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index d40ad141e3..de09d44f77 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.46-next.1", + "version": "0.1.46-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index a79839e5e2..5b875a2f70 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -45,12 +45,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@aws-sdk/client-eks": "^3.310.0", - "@aws-sdk/client-organizations": "^3.310.0", - "@aws-sdk/client-s3": "^3.310.0", - "@aws-sdk/credential-providers": "^3.310.0", - "@aws-sdk/middleware-endpoint": "^3.310.0", - "@aws-sdk/types": "^3.310.0", + "@aws-sdk/client-eks": "^3.350.0", + "@aws-sdk/client-organizations": "^3.350.0", + "@aws-sdk/client-s3": "^3.350.0", + "@aws-sdk/credential-providers": "^3.350.0", + "@aws-sdk/middleware-endpoint": "^3.347.0", + "@aws-sdk/types": "^3.347.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", @@ -69,7 +69,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@aws-sdk/util-stream-node": "^3.310.0", + "@aws-sdk/util-stream-node": "^3.350.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 84ceadf79d..4e74ce65c3 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-github +## 0.3.1-next.2 + +### Patch Changes + +- b9a6d1348d96: Properly handle `async` event callback +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.3.1-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 5ad851d57f..aa12c44ad3 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.3.1-next.1", + "version": "0.3.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index c35a8dd46e..a68d605f9b 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.2.2-next.2 + +### Patch Changes + +- f31fd1f8fd98: Fixed bug that caused ingestion errors when a user's name or profile picture is undefined. +- 66261b4ab441: Added option to skip forked repos +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 73980f568a..133153d0fd 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index 17b1d4be8a..7243b66360 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-catalog-customized +## 0.0.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/plugin-catalog@1.11.1-next.2 + ## 0.0.11-next.1 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index 188d5326a0..785a9a7840 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.11-next.1", + "version": "0.0.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 9de459f2c8..6155584c3e 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-graph +## 0.2.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.2.31-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index b827877330..40effc645c 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.31-next.1", + "version": "0.2.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index c462ee3ecc..a9ac355c57 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-import +## 0.9.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.9.9-next.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index e76b25cab9..227e6295d8 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.9.9-next.1", + "version": "0.9.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index 30cce9603a..c777953808 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -22,7 +22,7 @@ import { SupportButton, } from '@backstage/core-components'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { Grid } from '@material-ui/core'; +import { Grid, useMediaQuery, useTheme } from '@material-ui/core'; import React from 'react'; import { ImportInfoCard } from '../ImportInfoCard'; import { ImportStepper } from '../ImportStepper'; @@ -33,9 +33,21 @@ import { ImportStepper } from '../ImportStepper'; * @public */ export const DefaultImportPage = () => { + const theme = useTheme(); const configApi = useApi(configApiRef); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const contentItems = [ + + + , + + + + , + ]; + return (
@@ -47,14 +59,8 @@ export const DefaultImportPage = () => { - - - - - - - - + + {isMobile ? contentItems : contentItems.reverse()} diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 1b4a36191d..cf21e2b26e 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-react +## 1.7.0-next.2 + +### Patch Changes + +- d68692aee97e: Make `useRelatedEntities` use `getEntitiesByRefs` under the hood +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + - @backstage/plugin-permission-react@0.4.13-next.0 + ## 1.7.0-next.1 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index c3b5777051..be6c89290c 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.7.0-next.1", + "version": "1.7.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index df84c73c7d..2149bc4917 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/core-components@0.13.2-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index d25ebba958..3aa40fe1c0 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.1.0-next.0", + "version": "0.1.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index fc76828391..6bff300488 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog +## 1.11.1-next.2 + +### Patch Changes + +- 47b01e4c5315: Keyboard navigation to open EntityContextMenu now focus visible the first element. +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/integration-react@1.1.14-next.2 + - @backstage/plugin-search-react@1.6.1-next.2 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 1.11.1-next.1 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 7ce5ee9b1c..8d5ed9fe8f 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.11.1-next.1", + "version": "1.11.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index 3411656426..485cb490d8 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -205,7 +205,9 @@ describe('DefaultCatalogPage', () => { it('should render the default actions of an item in the grid', async () => { await renderWrapped(); fireEvent.click(screen.getByTestId('user-picker-owned')); - await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/Owned components \(1\)/), + ).resolves.toBeInTheDocument(); await expect(screen.findByTitle(/View/)).resolves.toBeInTheDocument(); await expect(screen.findByTitle(/Edit/)).resolves.toBeInTheDocument(); await expect( @@ -235,7 +237,9 @@ describe('DefaultCatalogPage', () => { await renderWrapped(); fireEvent.click(screen.getByTestId('user-picker-owned')); - await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/Owned components \(1\)/), + ).resolves.toBeInTheDocument(); await expect(screen.findByTitle(/Foo Action/)).resolves.toBeInTheDocument(); await expect(screen.findByTitle(/Bar Action/)).resolves.toBeInTheDocument(); await expect( @@ -249,14 +253,20 @@ describe('DefaultCatalogPage', () => { it('should render', async () => { await renderWrapped(); fireEvent.click(screen.getByTestId('user-picker-owned')); - await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/Owned components \(1\)/), + ).resolves.toBeInTheDocument(); fireEvent.click(screen.getByTestId('user-picker-all')); - await expect(screen.findByText(/All \(2\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/All components \(2\)/), + ).resolves.toBeInTheDocument(); }, 20_000); it('should set initial filter correctly', async () => { await renderWrapped(); - await expect(screen.findByText(/All \(2\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/All components \(2\)/), + ).resolves.toBeInTheDocument(); }, 20_000); // this test is for fixing the bug after favoriting an entity, the matching @@ -264,7 +274,9 @@ describe('DefaultCatalogPage', () => { it('should render the correct entities filtered on the selected filter', async () => { await renderWrapped(); fireEvent.click(screen.getByTestId('user-picker-owned')); - await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/Owned components \(1\)/), + ).resolves.toBeInTheDocument(); // The "Starred" menu option should initially be disabled, since there // aren't any starred entities. expect(screen.getByTestId('user-picker-starred')).toHaveAttribute( @@ -272,11 +284,15 @@ describe('DefaultCatalogPage', () => { 'true', ); fireEvent.click(screen.getByTestId('user-picker-all')); - await expect(screen.findByText(/All \(2\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/All components \(2\)/), + ).resolves.toBeInTheDocument(); const starredIcons = await screen.findAllByTitle('Add to favorites'); fireEvent.click(starredIcons[0]); - await expect(screen.findByText(/All \(2\)/)).resolves.toBeInTheDocument(); + await expect( + screen.findByText(/All components \(2\)/), + ).resolves.toBeInTheDocument(); // Now that we've starred an entity, the "Starred" menu option should be // enabled. @@ -286,7 +302,7 @@ describe('DefaultCatalogPage', () => { ); fireEvent.click(screen.getByTestId('user-picker-starred')); await expect( - screen.findByText(/Starred \(1\)/), + screen.findByText(/Starred components \(1\)/), ).resolves.toBeInTheDocument(); }, 20_000); diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx index c80b340349..c242372a97 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx @@ -95,6 +95,11 @@ describe('CatalogTable component', () => { () => false, () => false, ), + kind: { + value: 'component', + getCatalogFilters: () => ({ kind: 'component' }), + toQueryValue: () => 'component', + }, }, }} > @@ -107,7 +112,7 @@ describe('CatalogTable component', () => { }, }, ); - expect(screen.getByText(/Owned \(3\)/)).toBeInTheDocument(); + expect(screen.getByText(/Owned components \(3\)/)).toBeInTheDocument(); expect(screen.getByText(/component1/)).toBeInTheDocument(); expect(screen.getByText(/component2/)).toBeInTheDocument(); expect(screen.getByText(/component3/)).toBeInTheDocument(); diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 3d0cc75f7c..67579d5273 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -43,6 +43,7 @@ import { capitalize } from 'lodash'; import React, { ReactNode, useMemo } from 'react'; import { columnFactories } from './columns'; import { CatalogTableRow } from './types'; +import pluralize from 'pluralize'; /** * Props for {@link CatalogTable}. @@ -226,6 +227,11 @@ export const CatalogTable = (props: CatalogTableProps) => { typeColumn.hidden = !showTypeColumn; } const showPagination = rows.length > 20; + const currentKind = filters.kind?.value || ''; + const currentType = filters.type?.value || ''; + const titleDisplay = [titlePreamble, currentType, pluralize(currentKind)] + .filter(s => s) + .join(' '); return ( @@ -241,7 +247,7 @@ export const CatalogTable = (props: CatalogTableProps) => { pageSizeOptions: [20, 50, 100], ...tableOptions, }} - title={`${titlePreamble} (${entities.length})`} + title={`${titleDisplay} (${entities.length})`} data={rows} actions={actions || defaultActions} subtitle={subtitle} diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index 1961fe6cac..5e6e8ff3a9 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -142,7 +142,7 @@ export function EntityContextMenu(props: EntityContextMenuProps) { transformOrigin={{ vertical: 'top', horizontal: 'right' }} aria-labelledby="long-menu" > - + {extraItems} ', () => { }); it('renders props correctly', () => { - const { getByText } = render(wrapInTestApp()); - expect(getByText(minProps.card.title)).toBeInTheDocument(); + const { getByRole, getByText } = render( + wrapInTestApp(), + ); + expect( + getByRole('heading', { name: minProps.card.title }), + ).toBeInTheDocument(); expect(getByText(minProps.card.description)).toBeInTheDocument(); }); diff --git a/plugins/explore/src/components/ToolCard/ToolCard.tsx b/plugins/explore/src/components/ToolCard/ToolCard.tsx index f6137d9c01..a39806dceb 100644 --- a/plugins/explore/src/components/ToolCard/ToolCard.tsx +++ b/plugins/explore/src/components/ToolCard/ToolCard.tsx @@ -74,7 +74,7 @@ export const ToolCard = ({ card, objectFit }: Props) => { })} /> - + {title}{' '} {lifecycle && lifecycle.toLocaleLowerCase('en-US') !== 'ga' && ( { ).rejects.toThrow(NotFoundError); }); + it('should return a ERROR_NOT_FOUND if multi-cluster & no cluster selected', async () => { + clusterSupplier.getClusters.mockResolvedValue([ + { + name: 'local', + url: 'http:/localhost:8001', + authProvider: 'localKubectlProxy', + skipMetricsLookup: true, + } as ClusterDetails, + { + name: 'cluster1', + url: 'https://localhost:9999', + serviceAccountToken: 'tokenA', + authProvider: 'googleServiceAccount', + } as ClusterDetails, + ]); + + permissionApi.authorize.mockReturnValue( + Promise.resolve([{ result: AuthorizeResult.ALLOW }]), + ); + + const req = buildMockRequest(undefined, 'api'); + const { res, next } = getMockRes(); + + await expect( + proxy.createRequestHandler({ permissionApi })(req, res, next), + ).rejects.toThrow(NotFoundError); + }); + + it('should return a ERROR_NOT_FOUND if selected cluster not in config', async () => { + clusterSupplier.getClusters.mockResolvedValue([ + { + name: 'cluster1', + url: 'https://localhost:9999', + serviceAccountToken: 'tokenA', + authProvider: 'googleServiceAccount', + } as ClusterDetails, + ]); + + permissionApi.authorize.mockReturnValue( + Promise.resolve([{ result: AuthorizeResult.ALLOW }]), + ); + + const req = buildMockRequest('test', 'api'); + const { res, next } = getMockRes(); + + await expect( + proxy.createRequestHandler({ permissionApi })(req, res, next), + ).rejects.toThrow(NotFoundError); + }); + it('should pass the exact response from Kubernetes', async () => { const apiResponse = { kind: 'APIVersions', @@ -155,6 +205,55 @@ describe('KubernetesProxy', () => { expect(response.body).toStrictEqual(apiResponse); }); + it('should pass the exact response from Kubernetes default cluster & no cluster selected in single cluster setup', async () => { + const apiResponse = { + kind: 'APIVersions', + versions: ['v1'], + serverAddressByClientCIDRs: [ + { + clientCIDR: '0.0.0.0/0', + serverAddress: '192.168.0.1:3333', + }, + ], + }; + + clusterSupplier.getClusters.mockResolvedValue([ + { + name: 'cluster1', + url: 'https://localhost:9999', + serviceAccountToken: '', + authProvider: 'serviceAccount', + }, + ] as ClusterDetails[]); + + permissionApi.authorize.mockReturnValue( + Promise.resolve([{ result: AuthorizeResult.ALLOW }]), + ); + + authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + name: 'cluster1', + url: 'https://localhost:9999', + serviceAccountToken: '', + authProvider: 'serviceAccount', + } as ClusterDetails); + + const router = Router(); + router.use('/mountpath', proxy.createRequestHandler({ permissionApi })); + const app = express().use(router); + const requestPromise = request(app).get('/mountpath/api'); + worker.use( + rest.get('https://localhost:9999/api', (_: any, res: any, ctx: any) => + res(ctx.status(299), ctx.json(apiResponse)), + ), + rest.all(requestPromise.url, (req: any) => req.passthrough()), + ); + + const response = await requestPromise; + + expect(response.status).toEqual(299); + expect(response.body).toStrictEqual(apiResponse); + }); + it('sets host header to support clusters behind name-based virtual hosts', async () => { worker.use( rest.get( @@ -481,55 +580,6 @@ describe('KubernetesProxy', () => { }); }); - it('should return a 400 error if Backstage-Kubernetes-Cluster field isnt provided in request', async () => { - worker.use( - rest.get('https://localhost:9999/api/v1/namespaces', (_req, res, ctx) => { - return res( - ctx.status(200), - ctx.json({ - kind: 'NamespaceList', - apiVersion: 'v1', - items: [], - }), - ); - }), - ); - - permissionApi.authorize.mockReturnValue( - Promise.resolve([{ result: AuthorizeResult.ALLOW }]), - ); - - clusterSupplier.getClusters.mockResolvedValue([ - { - name: 'cluster1', - url: 'https://localhost:9999', - authProvider: 'googleServiceAccount', - }, - ] as ClusterDetails[]); - - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ - name: 'cluster1', - url: 'https://localhost:9999', - serviceAccountToken: 'tokenA', - authProvider: 'googleServiceAccount', - } as ClusterDetails); - - const router = Router(); - router.use('/mountpath', proxy.createRequestHandler({ permissionApi })); - router.use(errorHandler()); - const app = express().use(router); - - const requestPromise = request(app) - .get('/mountpath/api/v1/namespaces') - .set(HEADER_KUBERNETES_AUTH, 'tokenB'); - - worker.use(rest.all(requestPromise.url, (req: any) => req.passthrough())); - - const response = await requestPromise; - - expect(response.status).toEqual(400); - }); - it('returns a 500 error if authTranslator errors out and Backstage-Kubernetes-Authorization field is not provided', async () => { worker.use( rest.get('https://localhost:9999/api/v1/namespaces', (req, res, ctx) => { diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts index b4ca87d6f0..8e8fd54c77 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts @@ -17,7 +17,6 @@ import { ErrorResponseBody, ForwardedError, - InputError, NotAllowedError, NotFoundError, serializeError, @@ -175,13 +174,23 @@ export class KubernetesProxy { private async getClusterForRequest(req: Request): Promise { const clusterName = req.header(HEADER_KUBERNETES_CLUSTER); - if (!clusterName) { - throw new InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`); + const clusters = await this.clusterSupplier.getClusters(); + + if (!clusters || clusters.length <= 0) { + throw new NotFoundError(`No Clusters configured`); + } + + const hasClusterNameHeader = + typeof clusterName === 'string' && clusterName.length > 0; + + let cluster: ClusterDetails | undefined; + + if (hasClusterNameHeader) { + cluster = clusters.find(c => c.name === clusterName); + } else if (clusters.length === 1) { + cluster = clusters.at(0); } - const cluster = await this.clusterSupplier - .getClusters() - .then(clusters => clusters.find(c => c.name === clusterName)); if (!cluster) { throw new NotFoundError(`Cluster '${clusterName}' not found`); } diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index c322f148a4..814dc839b0 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes +## 0.9.2-next.2 + +### Patch Changes + +- 73cc0deee48a: Add proposed fix dialog for pod errors +- Updated dependencies + - @backstage/theme@0.4.0-next.1 + - @backstage/plugin-catalog-react@1.7.0-next.2 + - @backstage/core-components@0.13.2-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.2-next.0 + ## 0.9.2-next.1 ### Patch Changes diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index 823b9c89a2..e117e3627d 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -6,6 +6,7 @@ /// import { ApiRef } from '@backstage/core-plugin-api'; +import { AsyncState } from 'react-use/lib/useAsyncFn'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; @@ -14,6 +15,9 @@ import { CustomObjectsByEntityRequest } from '@backstage/plugin-kubernetes-commo import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; +import { Event as Event_2 } from 'kubernetes-models/v1'; +import { IContainer } from 'kubernetes-models/v1'; +import { IContainerStatus } from 'kubernetes-models/v1'; import { IdentityApi } from '@backstage/core-plugin-api'; import { IObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; import type { JsonObject } from '@backstage/types'; @@ -21,8 +25,8 @@ import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; import { OpenIdConnectApi } from '@backstage/core-plugin-api'; -import { Pod } from 'kubernetes-models/v1'; -import { Pod as Pod_2 } from 'kubernetes-models/v1/Pod'; +import { Pod } from 'kubernetes-models/v1/Pod'; +import { Pod as Pod_2 } from 'kubernetes-models/v1'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { V1ConfigMap } from '@kubernetes/client-node'; @@ -78,6 +82,25 @@ export interface ClusterLinksFormatterOptions { // @public (undocumented) export const clusterLinksFormatters: Record; +// @public +export const ContainerCard: React_2.FC; + +// @public +export interface ContainerCardProps { + // (undocumented) + containerSpec?: IContainer; + // (undocumented) + containerStatus: IContainerStatus; + // (undocumented) + podScope: PodScope; +} + +// @public +export interface ContainerScope extends PodScope { + // (undocumented) + containerName: string; +} + // Warning: (ae-forgotten-export) The symbol "CronJobsAccordionsProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CronJobsAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -113,7 +136,7 @@ export interface DetectedError { // Warning: (ae-forgotten-export) The symbol "ProposedFix" needs to be exported by the entry point index.d.ts // // (undocumented) - proposedFix: ProposedFix[]; + proposedFix?: ProposedFix; // (undocumented) severity: ErrorSeverity; // Warning: (ae-forgotten-export) The symbol "ResourceRef" needs to be exported by the entry point index.d.ts @@ -144,6 +167,15 @@ export type EntityKubernetesContentProps = { refreshIntervalMs?: number; }; +// @public +export const ErrorList: ({ podAndErrors }: ErrorListProps) => JSX.Element; + +// @public +export interface ErrorListProps { + // (undocumented) + podAndErrors: PodAndErrors[]; +} + // Warning: (ae-forgotten-export) The symbol "ErrorPanelProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ErrorPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -165,6 +197,65 @@ export const ErrorReporting: ({ // @public export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; +// @public +export const Events: ({ + involvedObjectName, + namespace, + clusterName, + warningEventsOnly, +}: EventsProps) => JSX.Element; + +// @public +export const EventsContent: ({ + events, + warningEventsOnly, +}: EventsContentProps) => JSX.Element; + +// @public +export interface EventsContentProps { + // (undocumented) + events: Event_2[]; + // (undocumented) + warningEventsOnly?: boolean; +} + +// @public +export interface EventsOptions { + // (undocumented) + clusterName: string; + // (undocumented) + involvedObjectName: string; + // (undocumented) + namespace: string; +} + +// @public +export interface EventsProps { + // (undocumented) + clusterName: string; + // (undocumented) + involvedObjectName: string; + // (undocumented) + namespace: string; + // (undocumented) + warningEventsOnly?: boolean; +} + +// @public +export const FixDialog: React_2.FC; + +// @public +export interface FixDialogProps { + // (undocumented) + clusterName: string; + // (undocumented) + error: DetectedError; + // (undocumented) + open?: boolean; + // (undocumented) + pod: Pod; +} + // Warning: (ae-forgotten-export) The symbol "FormatClusterLinkOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "formatClusterLink" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -416,12 +507,19 @@ export { kubernetesPlugin as plugin }; // // @public (undocumented) export interface KubernetesProxyApi { + // (undocumented) + getEventsByInvolvedObjectName(request: { + clusterName: string; + involvedObjectName: string; + namespace: string; + }): Promise; // (undocumented) getPodLogs(request: { podName: string; namespace: string; clusterName: string; containerName: string; + previous?: boolean; }): Promise<{ text: string; }>; @@ -436,16 +534,28 @@ export const kubernetesProxyApiRef: ApiRef; export class KubernetesProxyClient { constructor(options: { kubernetesApi: KubernetesApi }); // (undocumented) + getEventsByInvolvedObjectName({ + clusterName, + involvedObjectName, + namespace, + }: { + clusterName: string; + involvedObjectName: string; + namespace: string; + }): Promise; + // (undocumented) getPodLogs({ podName, namespace, clusterName, containerName, + previous, }: { podName: string; namespace: string; clusterName: string; containerName: string; + previous?: boolean; }): Promise<{ text: string; }>; @@ -476,12 +586,62 @@ export const LinkErrorPanel: ({ errorMessage, }: ErrorPanelProps_2) => JSX.Element; +// @public +export const PendingPodContent: ({ + pod, +}: PendingPodContentProps) => JSX.Element; + +// @public +export interface PendingPodContentProps { + // (undocumented) + pod: Pod_2; +} + +// @public +export interface PodAndErrors { + // (undocumented) + clusterName: string; + // (undocumented) + errors: DetectedError[]; + // (undocumented) + pod: Pod_2; +} + // Warning: (ae-forgotten-export) The symbol "PodDrawerProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "PodDrawer" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) +// @public export const PodDrawer: ({ podAndErrors, open }: PodDrawerProps) => JSX.Element; +// @public +export const PodLogs: React_2.FC; + +// @public +export const PodLogsDialog: ({ + containerScope, +}: PodLogsDialogProps) => JSX.Element; + +// @public +export interface PodLogsDialogProps { + // (undocumented) + containerScope: ContainerScope; +} + +// @public +export interface PodLogsOptions { + // (undocumented) + containerScope: ContainerScope; + // (undocumented) + previous?: boolean; +} + +// @public +export interface PodLogsProps { + // (undocumented) + containerScope: ContainerScope; + // (undocumented) + previous?: boolean; +} + // Warning: (ae-missing-release-tag) "PodNamesWithErrorsContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -494,6 +654,16 @@ export const PodNamesWithMetricsContext: React_2.Context< Map >; +// @public +export interface PodScope { + // (undocumented) + clusterName: string; + // (undocumented) + podName: string; + // (undocumented) + podNamespace: string; +} + // Warning: (ae-forgotten-export) The symbol "PodsTablesProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PodsTable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -533,6 +703,13 @@ export const useCustomResources: ( intervalMs?: number, ) => KubernetesObjects; +// @public +export const useEvents: ({ + involvedObjectName, + namespace, + clusterName, +}: EventsOptions) => AsyncState; + // Warning: (ae-missing-release-tag) "useKubernetesObjects" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -540,4 +717,12 @@ export const useKubernetesObjects: ( entity: Entity, intervalMs?: number, ) => KubernetesObjects; + +// @public +export const usePodLogs: ({ + containerScope, + previous, +}: PodLogsOptions) => AsyncState<{ + text: string; +}>; ``` diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index ac15250da1..5318e1dffe 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.9.2-next.1", + "version": "0.9.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes/src/api/KubernetesProxyClient.test.ts b/plugins/kubernetes/src/api/KubernetesProxyClient.test.ts index 6db1e459be..6b0be6de6c 100644 --- a/plugins/kubernetes/src/api/KubernetesProxyClient.test.ts +++ b/plugins/kubernetes/src/api/KubernetesProxyClient.test.ts @@ -14,11 +14,13 @@ * limitations under the License. */ +import { DateTime } from 'luxon'; import { KubernetesProxyClient } from './KubernetesProxyClient'; describe('KubernetesProxyClient', () => { let proxy: KubernetesProxyClient; const callProxyMock = jest.fn(); + const oneHourAgo = DateTime.now().minus({ hours: 1 }).toISO(); beforeEach(() => { jest.resetAllMocks(); @@ -51,4 +53,72 @@ describe('KubernetesProxyClient', () => { path: '/api/v1/namespaces/some-namespace/pods/some-pod/log?container=some-container', }); }); + it('/logs returns log text - crash logs', async () => { + const request = { + podName: 'some-pod', + namespace: 'some-namespace', + clusterName: 'some-cluster', + containerName: 'some-container', + previous: true, + }; + + callProxyMock.mockResolvedValue({ + text: jest.fn().mockResolvedValue('Hello World'), + ok: true, + }); + + const response = await proxy.getPodLogs(request); + await expect(response).toStrictEqual({ text: 'Hello World' }); + expect(callProxyMock).toHaveBeenCalledWith({ + clusterName: 'some-cluster', + init: { + method: 'GET', + }, + path: '/api/v1/namespaces/some-namespace/pods/some-pod/log?container=some-container&previous=', + }); + }); + it('/getEventsByInvolvedObjectName returns events', async () => { + const request = { + clusterName: 'some-cluster', + involvedObjectName: 'some-object', + namespace: 'some-namespace', + }; + const events = [ + { + type: 'Warning', + message: 'uh oh', + reason: 'something happened', + count: 23, + metadata: { + creationTimestamp: oneHourAgo, + }, + }, + { + type: 'Info', + message: 'hello there', + reason: 'something happened', + count: 52, + metadata: { + creationTimestamp: oneHourAgo, + }, + }, + ]; + + callProxyMock.mockResolvedValue({ + json: jest.fn().mockResolvedValue({ + items: events, + }), + ok: true, + }); + + const response = await proxy.getEventsByInvolvedObjectName(request); + await expect(response).toStrictEqual(events); + expect(callProxyMock).toHaveBeenCalledWith({ + clusterName: 'some-cluster', + init: { + method: 'GET', + }, + path: '/api/v1/namespaces/some-namespace/events?fieldSelector=involvedObject.name=some-object', + }); + }); }); diff --git a/plugins/kubernetes/src/api/KubernetesProxyClient.ts b/plugins/kubernetes/src/api/KubernetesProxyClient.ts index 8fd4674ddd..3703d8b180 100644 --- a/plugins/kubernetes/src/api/KubernetesProxyClient.ts +++ b/plugins/kubernetes/src/api/KubernetesProxyClient.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { KubernetesApi } from './types'; +import { Event } from 'kubernetes-models/v1'; /** * A client for common requests through the proxy endpoint of the kubernetes backend plugin. @@ -41,20 +42,63 @@ export class KubernetesProxyClient { return await response.text(); } + private async handleJson(response: Response): Promise { + if (!response.ok) { + const payload = await response.text(); + let message = `Request failed with ${response.status} ${response.statusText}, ${payload}`; + switch (response.status) { + case 404: + message = `Proxy request failed with ${response.status} ${response.statusText}, ${payload}`; + break; + default: + message = `Request failed with ${response.status} ${response.statusText}, ${payload}`; + } + throw new Error(message); + } + + return await response.json(); + } + + async getEventsByInvolvedObjectName({ + clusterName, + involvedObjectName, + namespace, + }: { + clusterName: string; + involvedObjectName: string; + namespace: string; + }): Promise { + return await this.kubernetesApi + .proxy({ + clusterName, + path: `/api/v1/namespaces/${namespace}/events?fieldSelector=involvedObject.name=${involvedObjectName}`, + init: { + method: 'GET', + }, + }) + .then(response => this.handleJson(response)) + .then(eventList => eventList.items); + } + async getPodLogs({ podName, namespace, clusterName, containerName, + previous, }: { podName: string; namespace: string; clusterName: string; containerName: string; + previous?: boolean; }): Promise<{ text: string }> { const params = new URLSearchParams({ container: containerName, }); + if (previous) { + params.append('previous', ''); + } return await this.kubernetesApi .proxy({ clusterName: clusterName, diff --git a/plugins/kubernetes/src/api/types.ts b/plugins/kubernetes/src/api/types.ts index 5dec189982..6065e47169 100644 --- a/plugins/kubernetes/src/api/types.ts +++ b/plugins/kubernetes/src/api/types.ts @@ -21,6 +21,7 @@ import { CustomObjectsByEntityRequest, } from '@backstage/plugin-kubernetes-common'; import { createApiRef } from '@backstage/core-plugin-api'; +import { Event } from 'kubernetes-models/v1'; export const kubernetesApiRef = createApiRef({ id: 'plugin.kubernetes.service', @@ -60,5 +61,11 @@ export interface KubernetesProxyApi { namespace: string; clusterName: string; containerName: string; + previous?: boolean; }): Promise<{ text: string }>; + getEventsByInvolvedObjectName(request: { + clusterName: string; + involvedObjectName: string; + namespace: string; + }): Promise; } diff --git a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx b/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx index f28580b509..3ee755becb 100644 --- a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx +++ b/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx @@ -45,15 +45,13 @@ describe('ErrorList', () => { kind: 'Pod', apiGroup: 'v1', }, - proposedFix: [ - { - type: 'logs', - container: 'some-container', - errorType: 'some error type', - rootCauseExplanation: 'some root cause', - possibleFixes: ['fix1', 'fix2'], - }, - ], + proposedFix: { + type: 'logs', + container: 'some-container', + errorType: 'some error type', + rootCauseExplanation: 'some root cause', + actions: ['fix1', 'fix2'], + }, }, ], }, diff --git a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.tsx b/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.tsx index b7b3418889..4d1d7a3033 100644 --- a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.tsx +++ b/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.tsx @@ -24,8 +24,10 @@ import { makeStyles, Theme, Paper, + Grid, } from '@material-ui/core'; import { PodAndErrors } from '../types'; +import { FixDialog } from '../FixDialog/FixDialog'; const useStyles = makeStyles((_theme: Theme) => createStyles({ @@ -38,10 +40,20 @@ const useStyles = makeStyles((_theme: Theme) => }), ); -interface ErrorListProps { +/** + * Props for ErrorList + * + * @public + */ +export interface ErrorListProps { podAndErrors: PodAndErrors[]; } +/** + * Shows a list of errors found on a Pod + * + * @public + */ export const ErrorList = ({ podAndErrors }: ErrorListProps) => { const classes = useStyles(); return ( @@ -59,10 +71,21 @@ export const ErrorList = ({ podAndErrors }: ErrorListProps) => { > {i > 0 && } - + + + + + + + + ); diff --git a/plugins/kubernetes/src/components/Pods/Events/Events.test.tsx b/plugins/kubernetes/src/components/Pods/Events/Events.test.tsx new file mode 100644 index 0000000000..8323666e66 --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/Events/Events.test.tsx @@ -0,0 +1,96 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { EventsContent } from './Events'; +import { render } from '@testing-library/react'; +import { Event } from 'kubernetes-models/v1'; +import { DateTime } from 'luxon'; + +describe('EventsContent', () => { + const oneHourAgo = DateTime.now().minus({ hours: 1 }).toISO(); + it('should show info events', () => { + const { getByText } = render( + , + ); + expect(getByText('First event 1 hour ago (count: 52)')).toBeInTheDocument(); + expect(getByText('something happened: hello there')).toBeInTheDocument(); + }); + it('should show warning events', () => { + const { getByText } = render( + , + ); + expect(getByText('First event 1 hour ago (count: 23)')).toBeInTheDocument(); + expect(getByText('something happened: uh oh')).toBeInTheDocument(); + }); + + it('should only show warning events when warningEventsOnly set', () => { + const { getByText, queryByText } = render( + , + ); + expect(queryByText('First event 1 hour ago (count: 52)')).toBeNull(); + expect(queryByText('something happened: hello there')).toBeNull(); + expect(getByText('First event 1 hour ago (count: 23)')).toBeInTheDocument(); + expect(getByText('something happened: uh oh')).toBeInTheDocument(); + }); +}); diff --git a/plugins/kubernetes/src/components/Pods/Events/Events.tsx b/plugins/kubernetes/src/components/Pods/Events/Events.tsx new file mode 100644 index 0000000000..9f888d182c --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/Events/Events.tsx @@ -0,0 +1,154 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; + +import { + Avatar, + Container, + Grid, + List, + ListItem, + ListItemAvatar, + ListItemText, + Tooltip, + Typography, +} from '@material-ui/core'; + +import InfoIcon from '@material-ui/icons/Info'; +import WarningIcon from '@material-ui/icons/Warning'; +import { DateTime } from 'luxon'; + +import { useEvents } from './useEvents'; +import { Skeleton } from '@material-ui/lab'; +import { DismissableBanner } from '@backstage/core-components'; +import { Event } from 'kubernetes-models/v1'; + +/** + * Props for Events + * + * @public + */ +export interface EventsContentProps { + warningEventsOnly?: boolean; + events: Event[]; +} + +const getAvatarByType = (type?: string) => { + return ( + + {type === 'Warning' ? : } + + ); +}; + +/** + * Shows given Kubernetes events + * + * @public + */ +export const EventsContent = ({ + events, + warningEventsOnly, +}: EventsContentProps) => { + if (events.length === 0) { + return No events found; + } + + return ( + + + + {events + .filter(event => { + if (warningEventsOnly) { + return event.type === 'Warning'; + } + return true; + }) + .map(event => { + const timeAgo = event.metadata.creationTimestamp + ? DateTime.fromISO(event.metadata.creationTimestamp).toRelative( + { + locale: 'en', + }, + ) + : 'unknown'; + return ( + + + {getAvatarByType(event.type)} + + + + ); + })} + + + + ); +}; + +/** + * Props for Events + * + * @public + */ +export interface EventsProps { + involvedObjectName: string; + namespace: string; + clusterName: string; + warningEventsOnly?: boolean; +} + +/** + * Retrieves and shows Kubernetes events for the given object + * + * @public + */ +export const Events = ({ + involvedObjectName, + namespace, + clusterName, + warningEventsOnly, +}: EventsProps) => { + const { value, error, loading } = useEvents({ + involvedObjectName, + namespace, + clusterName, + }); + + return ( + <> + {error && ( + + )} + {loading && } + {!loading && value !== undefined && ( + + )} + + ); +}; diff --git a/plugins/kubernetes/src/components/Pods/Events/index.ts b/plugins/kubernetes/src/components/Pods/Events/index.ts new file mode 100644 index 0000000000..da6c4102fa --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/Events/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './Events'; +export * from './useEvents'; diff --git a/plugins/kubernetes/src/components/Pods/Events/useEvents.test.tsx b/plugins/kubernetes/src/components/Pods/Events/useEvents.test.tsx new file mode 100644 index 0000000000..15da221f64 --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/Events/useEvents.test.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { useApi } from '@backstage/core-plugin-api'; +import { renderHook } from '@testing-library/react-hooks'; +import { useEvents } from './useEvents'; +import { DateTime } from 'luxon'; + +jest.mock('@backstage/core-plugin-api'); + +jest.mock('@backstage/plugin-kubernetes', () => ({ + kubernetesProxyApiRef: () => jest.fn(), +})); + +const oneHourAgo = DateTime.now().minus({ hours: 1 }).toISO(); + +const response = [ + { + type: 'Info', + message: 'hello there', + reason: 'something happened', + count: 52, + metadata: { + creationTimestamp: oneHourAgo, + }, + }, +] as any; + +describe('Events', () => { + const mockGetEventsByInvolvedObjectName = jest.fn(); + afterEach(() => { + jest.resetAllMocks(); + }); + it('should fetch and show events', async () => { + (useApi as any).mockReturnValue({ + getEventsByInvolvedObjectName: + mockGetEventsByInvolvedObjectName.mockResolvedValue(response), + }); + + const { result, waitForNextUpdate } = renderHook(() => + useEvents({ + involvedObjectName: 'some-objecgt', + namespace: 'some-namespace', + clusterName: 'some-cluster', + }), + ); + + expect(result.current.loading).toEqual(true); + + await waitForNextUpdate(); + + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.value).toStrictEqual(response); + }); +}); diff --git a/plugins/kubernetes/src/components/Pods/Events/useEvents.ts b/plugins/kubernetes/src/components/Pods/Events/useEvents.ts new file mode 100644 index 0000000000..441937507d --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/Events/useEvents.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { kubernetesProxyApiRef } from '../../../api'; + +/** + * Arguments for useEvents + * + * @public + */ +export interface EventsOptions { + involvedObjectName: string; + namespace: string; + clusterName: string; +} + +/** + * Retrieves the events for the given object + * + * @public + */ +export const useEvents = ({ + involvedObjectName, + namespace, + clusterName, +}: EventsOptions) => { + const kubernetesProxyApi = useApi(kubernetesProxyApiRef); + return useAsync(async () => { + return await kubernetesProxyApi.getEventsByInvolvedObjectName({ + involvedObjectName, + namespace, + clusterName, + }); + }, [involvedObjectName, namespace, clusterName]); +}; diff --git a/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.test.tsx b/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.test.tsx new file mode 100644 index 0000000000..e779ab5f0d --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.test.tsx @@ -0,0 +1,159 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; + +import { render } from '@testing-library/react'; + +import { FixDialog } from './FixDialog'; +import { Pod } from 'kubernetes-models/v1/Pod'; + +jest.mock('../Events', () => ({ + Events: () => { + return ; + }, +})); + +jest.mock('../PodLogs', () => ({ + PodLogs: () => { + return ; + }, +})); + +describe('FixDialog', () => { + it('docs link should render', () => { + const { getByText } = render( + , + ); + expect(getByText('Open docs')).toBeInTheDocument(); + expect(getByText('some error message')).toBeInTheDocument(); + expect(getByText('some-pod - some error type')).toBeInTheDocument(); + expect(getByText('some root cause')).toBeInTheDocument(); + expect(getByText('fix1')).toBeInTheDocument(); + expect(getByText('fix2')).toBeInTheDocument(); + }); + it('events button should render', () => { + const { getByText } = render( + , + ); + expect(getByText('Events:')).toBeInTheDocument(); + expect(getByText('some error message')).toBeInTheDocument(); + expect(getByText('some-pod - some error type')).toBeInTheDocument(); + expect(getByText('some root cause')).toBeInTheDocument(); + expect(getByText('fix1')).toBeInTheDocument(); + expect(getByText('fix2')).toBeInTheDocument(); + }); + it('Logs button should render', () => { + const { getByText } = render( + , + ); + expect(getByText('Crash logs:')).toBeInTheDocument(); + expect(getByText('some error message')).toBeInTheDocument(); + expect(getByText('some-pod - some error type')).toBeInTheDocument(); + expect(getByText('some root cause')).toBeInTheDocument(); + expect(getByText('fix1')).toBeInTheDocument(); + expect(getByText('fix2')).toBeInTheDocument(); + }); +}); diff --git a/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.tsx b/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.tsx new file mode 100644 index 0000000000..63ce4af03b --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.tsx @@ -0,0 +1,187 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { useState } from 'react'; + +import { Button, Grid } from '@material-ui/core'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import IconButton from '@material-ui/core/IconButton'; +import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import CloseIcon from '@material-ui/icons/Close'; +import HelpIcon from '@material-ui/icons/Help'; +import OpenInNewIcon from '@material-ui/icons/OpenInNew'; + +import { Pod } from 'kubernetes-models/v1/Pod'; +import { DetectedError } from '../../../error-detection'; +import { PodLogs } from '../PodLogs'; +import { Events } from '../Events'; +import { LinkButton } from '@backstage/core-components'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + closeButton: { + position: 'absolute', + right: theme.spacing(1), + top: theme.spacing(1), + color: theme.palette.grey[500], + }, + }), +); + +/** + * Props for FixDialog + * + * @public + */ +export interface FixDialogProps { + open?: boolean; + clusterName: string; + pod: Pod; + error: DetectedError; +} + +/** + * A dialog for fixing detected Kubernetes errors + * + * @public + */ +export const FixDialog: React.FC = ({ + open, + pod, + error, + clusterName, +}: FixDialogProps) => { + const [isOpen, setOpen] = useState(!!open); + const classes = useStyles(); + + const openDialog = () => { + setOpen(true); + }; + + const closeDialog = () => { + setOpen(false); + }; + + const pf = error.proposedFix; + + const dialogContent = () => { + return ( + + + Detected error: + {error.message} + + + Cause explanation: + + {error.proposedFix?.rootCauseExplanation ?? 'unknown'} + + + + Fix: + +
    + {(error.proposedFix?.actions ?? []).map((fix, i) => { + return ( +
  • + {fix} +
  • + ); + })} +
+
+
+ + {pf && pf.type === 'logs' && ( + <> + + Crash logs: + + + + + + )} + {pf && pf.type === 'events' && ( + <> + + Events: + + + + + + )} +
+ ); + }; + + return ( + <> + + + + {pod.metadata?.name} - {error.type} + + + + + {dialogContent()} + + {pf && pf.type === 'docs' && ( + } + target="_blank" + rel="noopener" + > + Open docs + + )} + + + + ); +}; diff --git a/plugins/kubernetes/src/components/Pods/FixDialog/index.ts b/plugins/kubernetes/src/components/Pods/FixDialog/index.ts new file mode 100644 index 0000000000..35601f9bd6 --- /dev/null +++ b/plugins/kubernetes/src/components/Pods/FixDialog/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './FixDialog'; diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.tsx b/plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.tsx index eac64ae741..970982d7a3 100644 --- a/plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.tsx +++ b/plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.tsx @@ -83,12 +83,22 @@ const ContainerDatetime = ({ prefix, dateTime }: ContainerDatetimeProps) => { ); }; +/** + * Props for ContainerCard + * + * @public + */ export interface ContainerCardProps { podScope: PodScope; containerSpec?: IContainer; containerStatus: IContainerStatus; } +/** + * Shows details about a container within a pod + * + * @public + */ export const ContainerCard: React.FC = ({ podScope, containerSpec, @@ -162,7 +172,7 @@ export const ContainerCard: React.FC = ({
{ +const PodCondition = ({ condition }: PodConditionProps) => { return ( <> {condition.status === 'False' && ( @@ -64,10 +64,20 @@ export const PodCondition = ({ condition }: PodConditionProps) => { ); }; -interface PendingPodContentProps { +/** + * Props for PendingPodContent + * + * @public + */ +export interface PendingPodContentProps { pod: Pod; } +/** + * Shows details about pod's conditions as it starts + * + * @public + */ export const PendingPodContent = ({ pod }: PendingPodContentProps) => { // TODO add PodHasNetwork when it's out of alpha // https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.test.tsx b/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.test.tsx index 64fd38c8d7..2b71976d8a 100644 --- a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.test.tsx +++ b/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.test.tsx @@ -69,7 +69,7 @@ describe('PodDrawer', () => { container: 'some-container', errorType: 'some error type', rootCauseExplanation: 'some root cause', - possibleFixes: ['fix1', 'fix2'], + actions: ['fix1', 'fix2'], }, ], }, diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx b/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx index 5e49410dd4..8e616df14e 100644 --- a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx +++ b/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx @@ -58,11 +58,22 @@ const useDrawerContentStyles = makeStyles((_theme: Theme) => function getContainerSpecByName(pod: Pod, containerName: string) { return pod.spec?.containers.find(c => c.name === containerName); } + +/** + * Props for PodDrawer + * + * @public + */ interface PodDrawerProps { open?: boolean; podAndErrors: PodAndErrors; } +/** + * A Drawer for Kubernetes Pods + * + * @public + */ export const PodDrawer = ({ podAndErrors, open }: PodDrawerProps) => { const classes = useDrawerContentStyles(); diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/index.ts b/plugins/kubernetes/src/components/Pods/PodDrawer/index.ts index 17d50ddfcd..92bb254c48 100644 --- a/plugins/kubernetes/src/components/Pods/PodDrawer/index.ts +++ b/plugins/kubernetes/src/components/Pods/PodDrawer/index.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { PodDrawer } from './PodDrawer'; +export * from './PodDrawer'; +export * from './ContainerCard'; +export * from './PendingPodContent'; diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/PodLogs.tsx b/plugins/kubernetes/src/components/Pods/PodLogs/PodLogs.tsx index 5cff023772..de9341508e 100644 --- a/plugins/kubernetes/src/components/Pods/PodLogs/PodLogs.tsx +++ b/plugins/kubernetes/src/components/Pods/PodLogs/PodLogs.tsx @@ -15,20 +15,39 @@ */ import React from 'react'; -import { DismissableBanner, LogViewer } from '@backstage/core-components'; +import { + DismissableBanner, + EmptyState, + LogViewer, +} from '@backstage/core-components'; import { Paper } from '@material-ui/core'; import { Skeleton } from '@material-ui/lab'; import { ContainerScope } from './types'; import { usePodLogs } from './usePodLogs'; -interface PodLogsProps { - podScope: ContainerScope; +/** + * Props for PodLogs + * + * @public + */ +export interface PodLogsProps { + containerScope: ContainerScope; + previous?: boolean; } -export const PodLogs: React.FC = ({ podScope }: PodLogsProps) => { +/** + * Shows the logs for the given pod + * + * @public + */ +export const PodLogs: React.FC = ({ + containerScope, + previous, +}: PodLogsProps) => { const { value, error, loading } = usePodLogs({ - podScope: podScope, + containerScope, + previous, }); return ( @@ -45,10 +64,20 @@ export const PodLogs: React.FC = ({ podScope }: PodLogsProps) => { )} {loading && } - {!loading && value !== undefined && } + {!loading && + value !== undefined && + (value.text === '' ? ( + + ) : ( + + ))} ); diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/PodLogsDialog.tsx b/plugins/kubernetes/src/components/Pods/PodLogs/PodLogsDialog.tsx index 05d980b26a..48fda2de2a 100644 --- a/plugins/kubernetes/src/components/Pods/PodLogs/PodLogsDialog.tsx +++ b/plugins/kubernetes/src/components/Pods/PodLogs/PodLogsDialog.tsx @@ -43,11 +43,21 @@ const useStyles = makeStyles((theme: Theme) => }), ); -interface PodLogsDialogProps { - podScope: ContainerScope; +/** + * Props for PodLogsDialog + * + * @public + */ +export interface PodLogsDialogProps { + containerScope: ContainerScope; } -export const PodLogsDialog = ({ podScope }: PodLogsDialogProps) => { +/** + * Shows the logs for the given pod in a Dialog + * + * @public + */ +export const PodLogsDialog = ({ containerScope }: PodLogsDialogProps) => { const classes = useStyles(); const [open, setOpen] = useState(false); @@ -62,8 +72,8 @@ export const PodLogsDialog = ({ podScope }: PodLogsDialogProps) => { <> - {podScope.podName} - {podScope.containerName} logs on cluster{' '} - {podScope.clusterName} + {containerScope.podName} - {containerScope.containerName} logs on + cluster {containerScope.clusterName} { - +