diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 4b741a917f..bc8e19ccec 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -19,6 +19,8 @@ jobs: steps: - uses: actions/checkout@v2 + - name: fetch branch master + run: git fetch origin master - name: find location of yarn cache id: yarn-cache run: echo "::set-output name=dir::$(yarn cache dir)" diff --git a/.npmrc b/.npmrc index 214c29d139..c3c66347fd 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ registry=https://registry.npmjs.org/ +engine-strict=true diff --git a/docs/FAQ.md b/docs/FAQ.md index 3e0093355e..9b9fff564e 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -20,3 +20,14 @@ Additional open sourced plugins would be added to the `plugins` directory in thi While we encourage using the open soure model, integrators that want to experiment with Backstage internally may also choose to develop closed source plugins in a manner that suits them best, for example in their respective Backstage source repository. + +## Any plans for integrating with other repository managers such as Gitlab or Bitbucket? + +We chose Github by the fact that it is the tool that we are most familiar with and that will naturally +lead to integrations for Github specifically being developed in an early stage. + +Hosting this project on Github does not exclude integrations with other alternatives such as Gitlab or +Bitbucket. We believe that in time there will be plugins that will provide functionality for these tools +as well. Hopefully contributed by the community. + +And note that implementations of Backstage can be hosted wherever you feel suits your needs best. diff --git a/package.json b/package.json index 1370c7eec8..7c6f997efb 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,13 @@ { "name": "root", "private": true, + "engines": { + "node": ">=12.0.0" + }, "scripts": { "start": "yarn build && yarn workspace @spotify-backstage/app start", "build": "lerna run build", - "test": "cross-env CI=true lerna run test -- --coverage", + "test": "cross-env CI=true lerna run test --since origin/master -- --coverage", "create-plugin": "backstage-cli create-plugin", "lint": "lerna run lint", "storybook": "yarn workspace @spotify-backstage/core storybook", diff --git a/packages/cli/templates/default-plugin/package.json.hbs b/packages/cli/templates/default-plugin/package.json.hbs index c6587f326e..20b78a268b 100644 --- a/packages/cli/templates/default-plugin/package.json.hbs +++ b/packages/cli/templates/default-plugin/package.json.hbs @@ -12,7 +12,8 @@ }, "devDependencies": { "@spotify-backstage/cli": "^{{version}}", - "@types/testing-library__jest-dom": "5.0.2" + "@types/testing-library__jest-dom": "5.0.2", + "jest-fetch-mock": "^3.0.3" }, "dependencies": { "@material-ui/lab": "4.0.0-alpha.45" diff --git a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs index 69884c6a44..360055dc3d 100644 --- a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs +++ b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs @@ -16,12 +16,14 @@ import React from 'react'; import { render } from '@testing-library/react'; +import mockFetch from 'jest-fetch-mock'; import ExampleComponent from './ExampleComponent'; import { ThemeProvider } from '@material-ui/core'; import { BackstageTheme } from '@spotify-backstage/core'; describe('ExampleComponent', () => { it('should render', () => { + mockFetch.mockResponse(() => new Promise(() => {})); const rendered = render( diff --git a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs index 7dff1e6ccc..7fecdc6f11 100644 --- a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs +++ b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs @@ -16,11 +16,13 @@ import React from 'react'; import { render } from '@testing-library/react'; +import mockFetch from 'jest-fetch-mock'; import ExampleFetchComponent from './ExampleFetchComponent'; describe('ExampleFetchComponent', () => { - it('should render', () => { + it('should render', async () => { + mockFetch.mockResponse(() => new Promise(() => {})); const rendered = render(); - expect(rendered.getByTestId('progress')).toBeInTheDocument(); + expect(await rendered.findByTestId('progress')).toBeInTheDocument(); }); }); diff --git a/packages/cli/templates/default-plugin/src/setupTests.ts b/packages/cli/templates/default-plugin/src/setupTests.ts index 8925258421..1a907ab8e6 100644 --- a/packages/cli/templates/default-plugin/src/setupTests.ts +++ b/packages/cli/templates/default-plugin/src/setupTests.ts @@ -15,3 +15,4 @@ */ import '@testing-library/jest-dom/extend-expect'; +require('jest-fetch-mock').enableMocks(); diff --git a/packages/core/package.json b/packages/core/package.json index 05ee131bc9..b6ceeb42f2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -8,9 +8,7 @@ "scripts": { "build": "tsc --outDir dist/cjs --noEmit false --module CommonJS", "lint": "backstage-cli lint", - "test": "backstage-cli test", - "storybook": "start-storybook -p 6006", - "build-storybook": "build-storybook" + "test": "backstage-cli test" }, "dependencies": { "@material-ui/core": "^4.9.1", @@ -28,17 +26,10 @@ "recompose": "0.30.0" }, "devDependencies": { - "@babel/core": "^7.9.0", "@spotify-backstage/cli": "^0.1.0", - "@storybook/addon-actions": "^5.3.17", - "@storybook/addon-links": "^5.3.17", - "@storybook/addons": "^5.3.17", - "@storybook/react": "^5.3.17", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", - "babel-loader": "^8.1.0", - "prop-types": "^15.7.2", - "ts-loader": "^6.2.1" + "prop-types": "^15.7.2" } } diff --git a/packages/storybook/.storybook/main.js b/packages/storybook/.storybook/main.js new file mode 100644 index 0000000000..7a51d41e0d --- /dev/null +++ b/packages/storybook/.storybook/main.js @@ -0,0 +1,22 @@ +module.exports = { + stories: [ + '../../core/src/layout/**/*.stories.tsx', + '../../core/src/components/**/*.stories.tsx', + ], + addons: ['@storybook/addon-actions', '@storybook/addon-links'], + webpackFinal: async config => { + config.module.rules.push({ + test: /\.(ts|tsx)$/, + use: [ + { + loader: require.resolve('ts-loader'), + options: { + transpileOnly: true, + }, + }, + ], + }); + config.resolve.extensions.push('.ts', '.tsx'); + return config; + }, +}; diff --git a/packages/storybook/package.json b/packages/storybook/package.json new file mode 100644 index 0000000000..f4e3b9d0ed --- /dev/null +++ b/packages/storybook/package.json @@ -0,0 +1,21 @@ +{ + "name": "storybook", + "version": "0.0.0", + "description": "Storybook build for core package", + "private": true, + "scripts": { + "start": "start-storybook -p 6006", + "build-storybook": "build-storybook --output-dir dist" + }, + "workspaces": { + "nohoist": [ + "@storybook/**" + ] + }, + "devDependencies": { + "@storybook/addon-actions": "^5.3.17", + "@storybook/addon-links": "^5.3.17", + "@storybook/addons": "^5.3.17", + "@storybook/react": "^5.3.17" + } +} diff --git a/scripts/cli-e2e-test.js b/scripts/cli-e2e-test.js index 10be71b1c4..3d4b9c04d1 100644 --- a/scripts/cli-e2e-test.js +++ b/scripts/cli-e2e-test.js @@ -36,8 +36,16 @@ async function main() { print('Backstage loaded correctly, creating plugin'); const createPlugin = spawnPiped(['yarn', 'create-plugin']); + + let stdout = ''; + createPlugin.stdout.on('data', data => { + stdout = stdout + data.toString('utf8'); + }); + + await waitFor(() => stdout.includes('Enter an ID for the plugin')); createPlugin.stdin.write('test-plugin\n'); - await new Promise(resolve => setTimeout(resolve, 2000)); + + await waitFor(() => stdout.includes('Enter the owner(s) of the plugin')); createPlugin.stdin.write('@someuser\n'); print('Waiting for plugin create script to be done'); @@ -59,6 +67,18 @@ async function main() { process.exit(0); } +function waitFor(fn) { + return new Promise(resolve => { + const handle = setInterval(() => { + if (fn()) { + clearInterval(handle); + resolve(); + return; + } + }, 100); + }); +} + function print(msg) { return process.stdout.write(`${msg}\n`); } @@ -117,7 +137,7 @@ async function waitForPageWithText( browser, path, text, - { intervalMs = 1000, maxAttempts = 60 } = {}, + { intervalMs = 1000, maxAttempts = 120 } = {}, ) { let attempts = 0; for (;;) { diff --git a/yarn.lock b/yarn.lock index eaacf83d37..78f006747e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,7 +25,7 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5", "@babel/core@^7.9.0": +"@babel/core@7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": version "7.9.0" resolved "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== @@ -4688,7 +4688,7 @@ babel-jest@^25.1.0: chalk "^3.0.0" slash "^3.0.0" -babel-loader@8.1.0, babel-loader@^8.1.0: +babel-loader@8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== @@ -12713,7 +12713,7 @@ minimist-options@^3.0.1: arrify "^1.0.1" is-plain-obj "^1.1.0" -minimist@1.2.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: +minimist@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=