diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a094a10b3..c8c92c57ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,9 +93,11 @@ jobs: if: ${{ steps.yarn-lock.outcome == 'success' }} run: yarn lerna -- run test --since origin/master -- --coverage - - name: test all packages + - name: test all packages (and upload coverage) if: ${{ steps.yarn-lock.outcome == 'failure' }} - run: yarn lerna -- run test -- --coverage + run: | + yarn lerna -- run test -- --coverage + bash <(curl -s https://codecov.io/bash) - name: verify plugin template run: yarn lerna -- run diff -- --check diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 469ef20cda..f99c266241 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -59,8 +59,10 @@ jobs: - name: verify type dependencies run: yarn lint:type-deps - - name: test - run: yarn lerna -- run test -- --coverage + - name: test (and upload coverage) + run: | + yarn lerna -- run test -- --coverage + bash <(curl -s https://codecov.io/bash) # Publishes current version of packages that are not already present in the registry - name: publish diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 853332f74d..0d6a8db50c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,35 +62,7 @@ Have you started using Backstage? Adding your company to [ADOPTERS](ADOPTERS.md) So...feel ready to jump in? Let's do this. ๐Ÿ‘๐Ÿป๐Ÿ’ฏ -To run a Backstage app, you will need to have the following installed: - -- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -- [NodeJS](https://nodejs.org/en/download/) - Active LTS Release, currently v12 -- [yarn](https://classic.yarnpkg.com/en/docs/install) - -After cloning this repo, open a terminal window and start the example app using the following commands from the project root: - -```bash -yarn install # Install dependencies - -yarn start # Start dev server, use --check to enable linting and type-checks -``` - -The final `yarn start` command should open a local instance of Backstage in your browser, otherwise open one of the URLs printed in the terminal. - -Depending on the work you're doing, you often also want to run the example backend. Start the backend in a separate terminal session using the following: - -```bash -cd packages/backend - -yarn start - -yarn lerna run mock-data # Populate the backend with mock data -``` - -And that's it! You are good to go ๐Ÿ‘ - -If you need help, just jump into our [Discord chatroom](https://discord.gg/MUpMjP2). +Start by reading our [Getting Started](https://backstage.io/docs/getting-started/) page. If you need help, just jump into our [Discord chatroom](https://discord.gg/MUpMjP2). # Coding Guidelines diff --git a/README.md b/README.md index 4009864edc..9ef09aee06 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ ![](https://github.com/spotify/backstage/workflows/Frontend%20CI/badge.svg) [![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.gg/EBHEGzX) ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) +[![Codecov](https://img.shields.io/codecov/c/github/spotify/backstage)](https://codecov.io/gh/spotify/backstage) [![](https://img.shields.io/npm/v/@backstage/core?label=Version)](https://github.com/spotify/backstage/releases) ## What is Backstage? @@ -31,33 +32,7 @@ A detailed project roadmap, including already delivered milestones, is available ## Getting Started -There are two different ways to get started with Backstage, either by creating a standalone app, or by cloning this repo. Which method you use depends on what you're planning to do. - -Creating a standalone instance makes it simpler to customize the application for your needs whilst staying up to date with the project. You will also depend on `@backstage` packages from NPM, making the project much smaller. This is the recommended approach if you want to kick the tyres of Backstage or setup your own instance. - -On the other hand, if you want to contribute plugins or to the project in general, it's easier to fork and clone this project. That will let you stay up to date with the latest changes, and gives you an easier path to make Pull Requests towards this repo. - -### Creating a Standalone App - -Backstage provides the `@backstage/create-app` package to scaffold standalone instances of Backstage. You will need to have -[NodeJS](https://nodejs.org/en/download/) Active LTS Release installed -(currently v12), and [yarn](https://classic.yarnpkg.com/en/docs/install). You will also need to have [Docker](https://docs.docker.com/engine/install/) installed to use some features like Software Templates and TechDocs. - -Using `npx` you can then run the following to create an app in a chosen subdirectory of your current working directory: - -```bash -npx @backstage/create-app -``` - -You will be taken through a wizard to create your app, and the output should look something like this. You can read more about this process [here](https://backstage.io/docs/getting-started/create-an-app) - -### Contributing to Backstage - -You can read more in our [CONTRIBUTING.md](./CONTRIBUTING.md#get-started) guide, which can help you get setup with a Backstage development environment. - -### Next steps - -Take a look at the [Getting Started](https://backstage.io/docs/getting-started/index) guide to learn how to set up Backstage, and how to develop on the platform. +Check out [the documentation](https://backstage.io/docs/getting-started) on how to start using Backstage. ## Documentation diff --git a/docs/features/techdocs/FAQ.md b/docs/features/techdocs/FAQ.md index 1a52a35cfb..8c716313bb 100644 --- a/docs/features/techdocs/FAQ.md +++ b/docs/features/techdocs/FAQ.md @@ -12,8 +12,8 @@ to? Edit this file ## Technology -- [What static site generator is TechDocs using?](./#what-static-site-generator-is-techdocs-using) -- [What is the mkdocs-techdocs-core plugin?](./#what-is-the-mkdocs-techdocs-core-plugin) +- [What static site generator is TechDocs using?](#what-static-site-generator-is-techdocs-using) +- [What is the mkdocs-techdocs-core plugin?](#what-is-the-mkdocs-techdocs-core-plugin) #### What static site generator is TechDocs using? diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md index 8bdbd27d3c..a7af6cc503 100644 --- a/docs/features/techdocs/README.md +++ b/docs/features/techdocs/README.md @@ -26,12 +26,12 @@ Spotifyโ€™s developer experience offering with 2,400+ documentation sites and ## Project roadmap -| Version | Description | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| [TechDocs V.0 โœ…][v0] | Read docs in Backstage - Enable anyone to get a reader experience working in Backstage. [See V.0 Use Cases.](./#techdocs-v0) | -| [TechDocs V.1 ๐Ÿšง][v1] | TechDocs end to end (alpha) - Alpha of TechDocs that you can use end to end - and contribute to. [See V.1 Use Cases.](./#techdocs-v1) | -| [TechDocs V.2 ๐Ÿ”ฎโŒ›][v2] | Platform stability and compatibility improvements. [See V.2 Use Cases.](./#techdocs-v2) | -| TechDocs V.3 ๐Ÿ”ฎโŒ› | Widget Architecture - TechDocs widget architecture available, so the community can create their own customized features. | +| Version | Description | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| [TechDocs V.0 โœ…][v0] | Read docs in Backstage - Enable anyone to get a reader experience working in Backstage. [See V.0 Use Cases.](#techdocs-v0) | +| [TechDocs V.1 โœ…][v1] | TechDocs end to end (alpha) - Alpha of TechDocs that you can use end to end - and contribute to. [See V.1 Use Cases.](#techdocs-v1) | +| [TechDocs V.2 ๐Ÿ”ฎโŒ›][v2] | Platform stability and compatibility improvements. [See V.2 Use Cases.](#techdocs-v2) | +| TechDocs V.3 ๐Ÿ”ฎโŒ› | Widget Architecture - TechDocs widget architecture available, so the community can create their own customized features. | [v0]: https://github.com/spotify/backstage/milestone/15 [v1]: https://github.com/spotify/backstage/milestone/16 diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index c1c6ea9231..c528ad34ad 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -1,84 +1,50 @@ --- id: index -title: Running Backstage Locally +title: Getting Started --- -First make sure you are using NodeJS with an Active LTS Release, currently v12. -This is made easy with a version manager such as nvm which allows for version -switching. +There are two different ways to get started with Backstage, either by creating a +standalone app, or by cloning this repo. Which method you use depends on what +you're planning to do. + +Creating a standalone instance makes it simpler to customize the application for +your needs whilst staying up to date with the project. You will also depend on +`@backstage` packages from NPM, making the project much smaller. This is the +recommended approach if you want to kick the tyres of Backstage or setup your +own instance. + +On the other hand, if you want to contribute plugins or to the project in +general, it's easier to fork and clone this project. That will let you stay up +to date with the latest changes, and gives you an easier path to make Pull +Requests towards this repo. + +### Creating a Standalone App + +Backstage provides the `@backstage/create-app` package to scaffold standalone +instances of Backstage. You will need to have +[NodeJS](https://nodejs.org/en/download/) Active LTS Release installed +(currently v12), and [yarn](https://classic.yarnpkg.com/en/docs/install). You +will also need to have [Docker](https://docs.docker.com/engine/install/) +installed to use some features like Software Templates and TechDocs. + +Using `npx` you can then run the following to create an app in a chosen +subdirectory of your current working directory: ```bash -# Checking your version -node --version -> v14.7.0 - -# Adding a second node version -nvm install 12 -> Downloading and installing node v12.18.3... -> Now using node v12.18.3 (npm v6.14.6) +npx @backstage/create-app ``` -To get up and running with a local Backstage to evaluate it, let's clone it off -of GitHub and run an initial build. +You will be taken through a wizard to create your app, and the output should +look something like this. You can read more about this process +[here](https://backstage.io/docs/getting-started/create-an-app). -```bash -# Start from your local development folder -git clone git@github.com:spotify/backstage.git -cd backstage +### Contributing to Backstage -# Fetch our dependencies and run an initial build -yarn install -yarn tsc -yarn build -``` +You can read more in our +[CONTRIBUTING](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md) +guide, which can help you get setup with a Backstage development environment. -Phew! Now you have a local repository that's ready to run and to add any open -source contributions into. +### Next steps -We are now going to launch two things: an example Backstage frontend app, and an -example Backstage backend that the frontend talks to. You are going to need two -terminal windows, both starting from the Backstage project root. - -In the first window, run - -```bash -cd packages/backend -yarn start -``` - -That starts up a backend instance on port 7000. - -In the other window, we will first populate the catalog with some nice mock data -to look at, and then launch the frontend. These commands are run from the -project root, not inside the backend directory. - -```bash -yarn lerna run mock-data -yarn start -``` - -That starts up the frontend on port 3000, and should automatically open a -browser window showing it. - -Congratulations! That should be it. Let us know how it went -[on discord](https://discord.gg/EBHEGzX), file issues for any -[feature](https://github.com/spotify/backstage/issues/new?labels=help+wanted&template=feature_template.md) -or -[plugin suggestions](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME), -or -[bugs](https://github.com/spotify/backstage/issues/new?labels=bug&template=bug_template.md) -you have, and feel free to -[contribute](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md)! - -## Creating a Plugin - -The value of Backstage grows with every new plugin that gets added. Here is a -collection of tutorials that will guide you through setting up and extending an -instance of Backstage with your own plugins. - -- [Development Environment](development-environment.md) -- [Create a Backstage Plugin](../plugins/create-a-plugin.md) -- [Structure of a Plugin](../plugins/structure-of-a-plugin.md) -- [Utility APIs](../api/utility-apis.md) - -[Back to Docs](../README.md) +Take a look at the [Running Backstage Locally](./running-backstage-locally.md) +guide to learn how to set up Backstage, and how to develop on the platform. diff --git a/docs/getting-started/running-backstage-locally.md b/docs/getting-started/running-backstage-locally.md new file mode 100644 index 0000000000..04be6499c6 --- /dev/null +++ b/docs/getting-started/running-backstage-locally.md @@ -0,0 +1,84 @@ +--- +id: running-backstage-locally +title: Running Backstage Locally +--- + +First make sure you are using NodeJS with an Active LTS Release, currently v12. +This is made easy with a version manager such as nvm which allows for version +switching. + +```bash +# Checking your version +node --version +> v14.7.0 + +# Adding a second node version +nvm install 12 +> Downloading and installing node v12.18.3... +> Now using node v12.18.3 (npm v6.14.6) +``` + +To get up and running with a local Backstage to evaluate it, let's clone it off +of GitHub and run an initial build. + +```bash +# Start from your local development folder +git clone git@github.com:spotify/backstage.git +cd backstage + +# Fetch our dependencies and run an initial build +yarn install +yarn tsc +yarn build +``` + +Phew! Now you have a local repository that's ready to run and to add any open +source contributions into. + +We are now going to launch two things: an example Backstage frontend app, and an +example Backstage backend that the frontend talks to. You are going to need two +terminal windows, both starting from the Backstage project root. + +In the first window, run + +```bash +cd packages/backend +yarn start +``` + +That starts up a backend instance on port 7000. + +In the other window, we will first populate the catalog with some nice mock data +to look at, and then launch the frontend. These commands are run from the +project root, not inside the backend directory. + +```bash +yarn lerna run mock-data +yarn start +``` + +That starts up the frontend on port 3000, and should automatically open a +browser window showing it. + +Congratulations! That should be it. Let us know how it went +[on discord](https://discord.gg/EBHEGzX), file issues for any +[feature](https://github.com/spotify/backstage/issues/new?labels=help+wanted&template=feature_template.md) +or +[plugin suggestions](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME), +or +[bugs](https://github.com/spotify/backstage/issues/new?labels=bug&template=bug_template.md) +you have, and feel free to +[contribute](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md)! + +## Creating a Plugin + +The value of Backstage grows with every new plugin that gets added. Here is a +collection of tutorials that will guide you through setting up and extending an +instance of Backstage with your own plugins. + +- [Development Environment](development-environment.md) +- [Create a Backstage Plugin](../plugins/create-a-plugin.md) +- [Structure of a Plugin](../plugins/structure-of-a-plugin.md) +- [Utility APIs](../api/utility-apis.md) + +[Back to Docs](../README.md) diff --git a/docs/plugins/proxying.md b/docs/plugins/proxying.md index 658df3dda1..1951f41763 100644 --- a/docs/plugins/proxying.md +++ b/docs/plugins/proxying.md @@ -52,7 +52,10 @@ configuration will lead to the proxy acting on backend requests to The value inside each route is either a simple URL string, or an object on the format accepted by -[http-proxy-middleware](https://www.npmjs.com/package/http-proxy-middleware). +[http-proxy-middleware](https://www.npmjs.com/package/http-proxy-middleware). It +is also possible to limit the forwarded HTTP methods with the configuration +`allowedMethods`, for example `allowedMethods: ['GET']` to enforce read-only +access. If the value is a string, it is assumed to correspond to: diff --git a/microsite/sidebars.json b/microsite/sidebars.json index a3c11beeac..7b4c852f4d 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -12,6 +12,7 @@ ], "Getting Started": [ "getting-started/index", + "getting-started/running-backstage-locally", "getting-started/installation", "getting-started/development-environment", "getting-started/create-an-app", diff --git a/microsite/siteConfig.js b/microsite/siteConfig.js index cc5ad89e09..f0762dbf09 100644 --- a/microsite/siteConfig.js +++ b/microsite/siteConfig.js @@ -93,8 +93,10 @@ const siteConfig = { cleanUrl: true, // Open Graph and Twitter card images. - ogImage: 'img/logo-gradient-on-dark.svg', - twitterImage: 'img/logo-gradient-on-dark.svg', + ogImage: + 'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png', + twitterImage: + 'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png', // For sites with a sizable amount of content, set collapsible to true. // Expand/collapse the links and subcategories under categories. diff --git a/microsite/static/logo_assets/ai/Backstage Identity_Assets_Artwork_RGB.ai b/microsite/static/logo_assets/ai/Backstage_Identity_Assets_Artwork_RGB.ai similarity index 100% rename from microsite/static/logo_assets/ai/Backstage Identity_Assets_Artwork_RGB.ai rename to microsite/static/logo_assets/ai/Backstage_Identity_Assets_Artwork_RGB.ai diff --git a/microsite/static/logo_assets/jpeg/Backstage Identity_Assets_Artwork_RGB_05 Logo_Black.jpg b/microsite/static/logo_assets/jpeg/Backstage_Identity_Assets_Artwork_RGB_05 Logo_Black.jpg similarity index 100% rename from microsite/static/logo_assets/jpeg/Backstage Identity_Assets_Artwork_RGB_05 Logo_Black.jpg rename to microsite/static/logo_assets/jpeg/Backstage_Identity_Assets_Artwork_RGB_05 Logo_Black.jpg diff --git a/microsite/static/logo_assets/jpeg/Backstage Identity_Assets_Artwork_RGB_06 Icon_Black.jpg b/microsite/static/logo_assets/jpeg/Backstage_Identity_Assets_Artwork_RGB_06_Icon_Black.jpg similarity index 100% rename from microsite/static/logo_assets/jpeg/Backstage Identity_Assets_Artwork_RGB_06 Icon_Black.jpg rename to microsite/static/logo_assets/jpeg/Backstage_Identity_Assets_Artwork_RGB_06_Icon_Black.jpg diff --git a/microsite/static/logo_assets/pdf/Backstage Identity_Assets_Artwork_RGB.pdf b/microsite/static/logo_assets/pdf/Backstage_Identity_Assets_Artwork_RGB.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Backstage Identity_Assets_Artwork_RGB.pdf rename to microsite/static/logo_assets/pdf/Backstage_Identity_Assets_Artwork_RGB.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/01 Logo_White.pdf b/microsite/static/logo_assets/pdf/Individual/01_Logo_White.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/01 Logo_White.pdf rename to microsite/static/logo_assets/pdf/Individual/01_Logo_White.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/02 Icon_White.pdf b/microsite/static/logo_assets/pdf/Individual/02_Icon_White.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/02 Icon_White.pdf rename to microsite/static/logo_assets/pdf/Individual/02_Icon_White.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/03 Logo_Teal.pdf b/microsite/static/logo_assets/pdf/Individual/03_Logo_Teal.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/03 Logo_Teal.pdf rename to microsite/static/logo_assets/pdf/Individual/03_Logo_Teal.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/04 Icon_Teal.pdf b/microsite/static/logo_assets/pdf/Individual/04_Icon_Teal.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/04 Icon_Teal.pdf rename to microsite/static/logo_assets/pdf/Individual/04_Icon_Teal.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/05 Logo_Black.pdf b/microsite/static/logo_assets/pdf/Individual/05_Logo_Black.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/05 Logo_Black.pdf rename to microsite/static/logo_assets/pdf/Individual/05_Logo_Black.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/06 Icon_Black.pdf b/microsite/static/logo_assets/pdf/Individual/06_Icon_Black.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/06 Icon_Black.pdf rename to microsite/static/logo_assets/pdf/Individual/06_Icon_Black.pdf diff --git a/microsite/static/logo_assets/pdf/Individual/07 Large Icon_Gradient.pdf b/microsite/static/logo_assets/pdf/Individual/07_Large Icon_Gradient.pdf similarity index 100% rename from microsite/static/logo_assets/pdf/Individual/07 Large Icon_Gradient.pdf rename to microsite/static/logo_assets/pdf/Individual/07_Large Icon_Gradient.pdf diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_01 Logo_White.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_01_Logo_White.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_01 Logo_White.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_01_Logo_White.png diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_02 Icon_White.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_02_Icon_White.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_02 Icon_White.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_02_Icon_White.png diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_03 Logo_Teal.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_03_Logo_Teal.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_03 Logo_Teal.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_03_Logo_Teal.png diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_04 Icon_Teal.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_04 Icon_Teal.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_05 Logo_Black.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_05_Logo_Black.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_05 Logo_Black.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_05_Logo_Black.png diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_06 Icon_Black.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_06_Icon_Black.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_06 Icon_Black.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_06_Icon_Black.png diff --git a/microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_07 Large Icon_Gradient.png b/microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_07_Large_Icon_Gradient.png similarity index 100% rename from microsite/static/logo_assets/png/Backstage Identity_Assets_Artwork_RGB_07 Large Icon_Gradient.png rename to microsite/static/logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_07_Large_Icon_Gradient.png diff --git a/mkdocs.yml b/mkdocs.yml index bcf4969892..10cd7df9b2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,7 +12,8 @@ nav: - Strategies for adopting: 'overview/adopting.md' - Logo assets: 'overview/logos.md' - Getting started: - - Running Backstage locally: 'getting-started/index.md' + - Getting Started: 'getting-started/index.md' + - Running Backstage locally: 'getting-started/running-backstage-locally.md' - Installation: 'getting-started/installation.md' - Local development: 'getting-started/development-environment.md' - Demo deployment: https://backstage-demo.roadie.io diff --git a/packages/core/src/components/CodeSnippet/CodeSnippet.stories.tsx b/packages/core/src/components/CodeSnippet/CodeSnippet.stories.tsx index c0f57d6330..77f3ca51cc 100644 --- a/packages/core/src/components/CodeSnippet/CodeSnippet.stories.tsx +++ b/packages/core/src/components/CodeSnippet/CodeSnippet.stories.tsx @@ -86,3 +86,9 @@ export const Languages = () => ( ); + +export const CopyCode = () => ( + + + +); diff --git a/packages/core/src/components/CodeSnippet/CodeSnippet.test.tsx b/packages/core/src/components/CodeSnippet/CodeSnippet.test.tsx index 42efbf14af..1a76f84f44 100644 --- a/packages/core/src/components/CodeSnippet/CodeSnippet.test.tsx +++ b/packages/core/src/components/CodeSnippet/CodeSnippet.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, fireEvent } from '@testing-library/react'; import { wrapInTestApp } from '@backstage/test-utils'; import { CodeSnippet } from './CodeSnippet'; @@ -55,4 +55,14 @@ describe('', () => { expect(queryByText(/2/)).toBeInTheDocument(); expect(queryByText(/3/)).toBeInTheDocument(); }); + + it('copy code using button', async () => { + document.execCommand = jest.fn(); + const rendered = render( + wrapInTestApp(), + ); + const button = rendered.getByTitle('Text copied to clipboard'); + fireEvent.click(button); + expect(document.execCommand).toHaveBeenCalled(); + }); }); diff --git a/packages/core/src/components/CodeSnippet/CodeSnippet.tsx b/packages/core/src/components/CodeSnippet/CodeSnippet.tsx index 324d71e936..b6d9b3a5aa 100644 --- a/packages/core/src/components/CodeSnippet/CodeSnippet.tsx +++ b/packages/core/src/components/CodeSnippet/CodeSnippet.tsx @@ -20,19 +20,22 @@ import SyntaxHighlighter from 'react-syntax-highlighter'; import { docco, dark } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; import { useTheme } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; +import { CopyTextButton } from '../CopyTextButton'; type Props = { text: string; language: string; showLineNumbers?: boolean; + showCopyCodeButton?: boolean; }; const defaultProps = { showLineNumbers: false, + showCopyCodeButton: false, }; export const CodeSnippet: FC = props => { - const { text, language, showLineNumbers } = { + const { text, language, showLineNumbers, showCopyCodeButton } = { ...defaultProps, ...props, }; @@ -41,13 +44,20 @@ export const CodeSnippet: FC = props => { const mode = theme.palette.type === 'dark' ? dark : docco; return ( - - {text} - +
+ + {text} + + {showCopyCodeButton && ( +
+ +
+ )} +
); }; @@ -56,4 +66,5 @@ CodeSnippet.propTypes = { text: PropTypes.string.isRequired, language: PropTypes.string.isRequired, showLineNumbers: PropTypes.bool, + showCopyCodeButton: PropTypes.bool, }; diff --git a/packages/core/src/components/CopyTextButton/CopyTextButton.test.tsx b/packages/core/src/components/CopyTextButton/CopyTextButton.test.tsx index e789035b44..cab992e11a 100644 --- a/packages/core/src/components/CopyTextButton/CopyTextButton.test.tsx +++ b/packages/core/src/components/CopyTextButton/CopyTextButton.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, fireEvent } from '@testing-library/react'; import { wrapInTestApp } from '@backstage/test-utils'; import { CopyTextButton } from './CopyTextButton'; import { @@ -76,7 +76,7 @@ describe('', () => { ), ); const button = rendered.getByTitle('mockTooltip'); - button.click(); + fireEvent.click(button); expect(document.execCommand).toHaveBeenCalled(); rendered.getByText('mockTooltip'); }); diff --git a/packages/core/src/components/CopyTextButton/CopyTextButton.tsx b/packages/core/src/components/CopyTextButton/CopyTextButton.tsx index e4773165cc..cb322e5b56 100644 --- a/packages/core/src/components/CopyTextButton/CopyTextButton.tsx +++ b/packages/core/src/components/CopyTextButton/CopyTextButton.tsx @@ -63,7 +63,7 @@ export const CopyTextButton: FC = props => { }; const classes = useStyles(props); const errorApi = useApi(errorApiRef); - const inputRef = useRef(null); + const inputRef = useRef(null); const [open, setOpen] = useState(false); const handleCopyClick: MouseEventHandler = e => { @@ -82,9 +82,8 @@ export const CopyTextButton: FC = props => { return ( <> - diff --git a/packages/create-app/templates/default-app/packages/backend/Dockerfile b/packages/create-app/templates/default-app/packages/backend/Dockerfile index 3e8ba36cec..a7bd814b19 100644 --- a/packages/create-app/templates/default-app/packages/backend/Dockerfile +++ b/packages/create-app/templates/default-app/packages/backend/Dockerfile @@ -2,8 +2,15 @@ FROM node:12 WORKDIR /usr/src/app -COPY . . +# Copy repo skeleton first, to avoid unnecessary docker cache invalidation. +# The skeleton contains the package.json of each package in the monorepo, +# and along with yarn.lock and the root package.json, that's enough to run yarn install. +ADD yarn.lock package.json skeleton.tar ./ RUN yarn install --frozen-lockfile --production +# This will copy the contents of the dist-workspace when running the build-image command. +# Do not use this Dockerfile outside of that command, as it will copy in the source code instead. +COPY . . + CMD ["node", "packages/backend"] diff --git a/plugins/api-docs/src/catalog/EntityPageApi/EntityPageApi.tsx b/plugins/api-docs/src/catalog/EntityPageApi/EntityPageApi.tsx index da2cf71ac4..f26691d58c 100644 --- a/plugins/api-docs/src/catalog/EntityPageApi/EntityPageApi.tsx +++ b/plugins/api-docs/src/catalog/EntityPageApi/EntityPageApi.tsx @@ -39,7 +39,7 @@ export const EntityPageApi: FC<{ entity: Entity }> = ({ entity }) => { {apiNames.map(api => ( - + ))} diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx index c4a366c4d9..5650b0745f 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx @@ -15,31 +15,92 @@ */ import { ApiEntity } from '@backstage/catalog-model'; -import { InfoCard } from '@backstage/core'; +import { TabbedCard, CardTab } from '@backstage/core'; import React from 'react'; -import { ApiDefinitionWidget } from '../ApiDefinitionWidget'; +import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; import { Alert } from '@material-ui/lab'; +import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget'; +import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget'; -type Props = { - title?: string; - apiEntity?: ApiEntity; +type ApiDefinitionWidget = { + type: string; + title: string; + component: (definition: string) => React.ReactElement; + rawLanguage?: string; }; -export const ApiDefinitionCard = ({ title, apiEntity }: Props) => { +export function defaultDefinitionWidgets(): ApiDefinitionWidget[] { + return [ + { + type: 'openapi', + title: 'OpenAPI', + rawLanguage: 'yaml', + component: definition => ( + + ), + }, + { + type: 'asyncapi', + title: 'AsyncAPI', + rawLanguage: 'yaml', + component: definition => ( + + ), + }, + ]; +} + +type Props = { + apiEntity?: ApiEntity; + definitionWidgets?: ApiDefinitionWidget[]; +}; + +const defaultProps = { + definitionWidgets: defaultDefinitionWidgets(), +}; + +export const ApiDefinitionCard = (props: Props) => { + const { apiEntity, definitionWidgets } = { + ...defaultProps, + ...props, + }; + if (!apiEntity) { + return Could not fetch the API; + } + + const definitionWidget = definitionWidgets.find( + d => d.type === apiEntity.spec.type, + ); + + if (definitionWidget) { return ( - - Could not fetch the API - + + + {definitionWidget.component(apiEntity.spec.definition)} + + + + + ); } return ( - - - + + + , + ]} + /> ); }; diff --git a/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx b/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx deleted file mode 100644 index e1283bb525..0000000000 --- a/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget'; -import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget'; -import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; - -type Props = { - type: string; - definition: string; -}; - -export const ApiDefinitionWidget = ({ type, definition }: Props) => { - switch (type) { - case 'openapi': - return ; - - case 'asyncapi': - return ; - - default: - return ( - - ); - } -}; diff --git a/plugins/api-docs/src/components/ApiDefinitionWidget/index.ts b/plugins/api-docs/src/components/ApiDefinitionWidget/index.ts deleted file mode 100644 index 64c5f87b21..0000000000 --- a/plugins/api-docs/src/components/ApiDefinitionWidget/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { ApiDefinitionWidget } from './ApiDefinitionWidget'; diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx index 2f64c4b2ab..ac5dedfd9c 100644 --- a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx @@ -136,7 +136,7 @@ const useStyles = makeStyles(theme => ({ })); type Props = { - definition: any; + definition: string; }; export const AsyncApiDefinitionWidget = ({ definition }: Props) => { diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx index 61f5cb2b75..b96f50166e 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx @@ -66,7 +66,7 @@ const useStyles = makeStyles(theme => ({ })); type Props = { - definition: any; + definition: string; }; export const OpenApiDefinitionWidget = ({ definition }: Props) => { diff --git a/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx b/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx index 46631c5a4b..0b2ebb4ca4 100644 --- a/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx @@ -23,5 +23,7 @@ type Props = { }; export const PlainApiDefinitionWidget = ({ definition, language }: Props) => { - return ; + return ( + + ); }; diff --git a/plugins/api-docs/src/components/index.ts b/plugins/api-docs/src/components/index.ts index d49303c24a..55b9517f9c 100644 --- a/plugins/api-docs/src/components/index.ts +++ b/plugins/api-docs/src/components/index.ts @@ -15,5 +15,8 @@ */ export { ApiDefinitionCard } from './ApiDefinitionCard'; +export { AsyncApiDefinitionWidget } from './AsyncApiDefinitionWidget'; +export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget'; +export { PlainApiDefinitionWidget } from './PlainApiDefinitionWidget'; export { useComponentApiNames } from './useComponentApiNames'; export { useComponentApiEntities } from './useComponentApiEntities'; diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 9f3bc16103..efda451fd5 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -22,6 +22,7 @@ "@backstage/backend-common": "^0.1.1-alpha.21", "@backstage/config": "^0.1.1-alpha.21", "@types/express": "^4.17.6", + "@types/http-proxy-middleware": "^0.19.3", "express": "^4.17.1", "express-promise-router": "^3.0.3", "http-proxy-middleware": "^0.19.1", diff --git a/plugins/proxy-backend/src/service/router.ts b/plugins/proxy-backend/src/service/router.ts index 5c5e17b872..7cd5f37598 100644 --- a/plugins/proxy-backend/src/service/router.ts +++ b/plugins/proxy-backend/src/service/router.ts @@ -18,10 +18,11 @@ import { Config } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; import createProxyMiddleware, { - Config as ProxyConfig, + Config as ProxyMiddlewareConfig, Proxy, } from 'http-proxy-middleware'; import { Logger } from 'winston'; +import http from 'http'; export interface RouterOptions { logger: Logger; @@ -30,6 +31,10 @@ export interface RouterOptions { pathPrefix: string; } +export interface ProxyConfig extends ProxyMiddlewareConfig { + allowedMethods?: string[]; +} + // Creates a proxy middleware, possibly with defaults added on top of the // given config. function buildMiddleware( @@ -58,7 +63,12 @@ function buildMiddleware( // Attach the logger to the proxy config fullConfig.logProvider = () => logger; - return createProxyMiddleware(fullConfig); + // Only permit the allowed HTTP methods if configured + const filter = (_pathname: string, req: http.IncomingMessage): boolean => { + return fullConfig?.allowedMethods?.includes(req.method!) ?? true; + }; + + return createProxyMiddleware(filter, fullConfig); } export async function createRouter( diff --git a/yarn.lock b/yarn.lock index add67f0fcf..11bb8a3fd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4209,7 +4209,7 @@ resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69" integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA== -"@types/http-proxy-middleware@*": +"@types/http-proxy-middleware@*", "@types/http-proxy-middleware@^0.19.3": version "0.19.3" resolved "https://registry.npmjs.org/@types/http-proxy-middleware/-/http-proxy-middleware-0.19.3.tgz#b2eb96fbc0f9ac7250b5d9c4c53aade049497d03" integrity sha512-lnBTx6HCOUeIJMLbI/LaL5EmdKLhczJY5oeXZpX/cXE4rRqb3RmV7VcMpiEfYkmTjipv3h7IAyIINe4plEv7cA== @@ -14876,11 +14876,16 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@2.6.0, node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0: +node-fetch@2.6.0: version "2.6.0" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0: + version "2.6.1" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-forge@0.9.0: version "0.9.0" resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"