From a3413197de451741904b9667747527cb46b0353c Mon Sep 17 00:00:00 2001 From: Ville Brofeldt <33317356+villebro@users.noreply.github.com> Date: Sat, 25 Sep 2021 07:26:35 +0200 Subject: [PATCH] chore: upgrade to Node 16 (#16809) * chore: upgrade to Node 16 * add docs * fix test --- .github/workflows/bashlib.sh | 2 -- .github/workflows/superset-e2e.yml | 22 ++++++------ .github/workflows/superset-frontend.yml | 4 +++ .github/workflows/superset-translations.yml | 4 +++ CONTRIBUTING.md | 12 +++---- Dockerfile | 2 +- UPDATING.md | 2 ++ docker-compose.yml | 2 +- superset-frontend/package.json | 2 +- .../components/PropertiesModal_spec.jsx | 5 +-- .../javascripts/sqllab/ResultSet_spec.jsx | 2 ++ .../sqllab/SqlEditorLeftBar_spec.jsx | 3 +- .../AlteredSliceTag/AlteredSliceTag.test.jsx | 2 +- .../components/Header/Header.test.tsx | 36 ++++++++++--------- .../database/DatabaseModal/index.test.jsx | 5 +++ superset-websocket/Dockerfile | 2 +- 16 files changed, 60 insertions(+), 47 deletions(-) diff --git a/.github/workflows/bashlib.sh b/.github/workflows/bashlib.sh index 44e97d253a040..0f9a8fd10e01b 100644 --- a/.github/workflows/bashlib.sh +++ b/.github/workflows/bashlib.sh @@ -55,8 +55,6 @@ npm-install() { cd "$GITHUB_WORKSPACE/superset-frontend" # cache-restore npm - say "::group::Install npm@7" - sudo npm i -g npm@7 --registry=https://registry.npmjs.org say "::group::Install npm packages" echo "npm: $(npm --version)" echo "node: $(node --version)" diff --git a/.github/workflows/superset-e2e.yml b/.github/workflows/superset-e2e.yml index 3b3898b52091a..ab0d61bf3469a 100644 --- a/.github/workflows/superset-e2e.yml +++ b/.github/workflows/superset-e2e.yml @@ -72,8 +72,7 @@ jobs: if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies with: - run: | - apt-get-install + run: apt-get-install - name: Install python dependencies if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies @@ -85,32 +84,31 @@ jobs: if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies with: - run: | - setup-postgres + run: setup-postgres - name: Import test data if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies with: - run: | - testdata + run: testdata + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' - name: Install npm dependencies if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies with: - run: | - npm-install + run: npm-install - name: Build javascript packages if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies with: - run: | - build-instrumented-assets + run: build-instrumented-assets - name: Install cypress if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies with: - run: | - cypress-install + run: cypress-install - name: Run Cypress if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies diff --git a/.github/workflows/superset-frontend.yml b/.github/workflows/superset-frontend.yml index 670c8155899a4..c4b4e4ef152ee 100644 --- a/.github/workflows/superset-frontend.yml +++ b/.github/workflows/superset-frontend.yml @@ -25,6 +25,10 @@ jobs: PR_NUMBER: ${{ github.event.pull_request.number }} continue-on-error: true run: ./scripts/ci_check_no_file_changes.sh frontend + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' - name: Install dependencies if: steps.check.outcome == 'failure' uses: ./.github/actions/cached-dependencies diff --git a/.github/workflows/superset-translations.yml b/.github/workflows/superset-translations.yml index 66160fa631261..029c914cf1fc4 100644 --- a/.github/workflows/superset-translations.yml +++ b/.github/workflows/superset-translations.yml @@ -17,6 +17,10 @@ jobs: with: persist-credentials: false submodules: recursive + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' - name: Install dependencies uses: ./.github/actions/cached-dependencies with: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 93a162e218e2c..767c25de7b028 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -522,7 +522,11 @@ Frontend assets (TypeScript, JavaScript, CSS, and images) must be compiled in or ##### nvm and node -First, be sure you are using recent versions of Node.js and npm. We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage your node environment: +First, be sure you are using the following versions of Node.js and npm: +- `Node.js`: Version 16 +- `npm`: Version 7 + +We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage your node environment: ```bash curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash @@ -540,12 +544,6 @@ sh -c "$(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install For those interested, you may also try out [avn](https://github.com/nvm-sh/nvm#deeper-shell-integration) to automatically switch to the node version that is required to run Superset frontend. -We have upgraded our `package-lock.json` to use `lockfileversion: 2` from npm 7, so please make sure you have installed npm 7, too: - -```bash -npm install -g npm@7 -``` - #### Install dependencies Install third-party dependencies listed in `package.json` via: diff --git a/Dockerfile b/Dockerfile index c73e6cad61988..8244f16a11543 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,7 +45,7 @@ RUN cd /app \ ###################################################################### # Node stage to deal with static asset construction ###################################################################### -FROM node:14 AS superset-node +FROM node:16 AS superset-node ARG NPM_VER=7 RUN npm install -g npm@${NPM_VER} diff --git a/UPDATING.md b/UPDATING.md index b967b829e9c5d..3e2d5da22604e 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -35,6 +35,8 @@ assists people when migrating to a new version. ### Other +- [16809](https://github.com/apache/incubator-superset/pull/16809): When building the superset frontend assets manually, you should now use Node 16 (previously Node 14 was required/recommended). Node 14 will most likely still work for at least some time, but is no longer actively tested for on CI. + ## 1.3.0 ### Breaking Changes diff --git a/docker-compose.yml b/docker-compose.yml index 93a79809178e5..3131d2384a761 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -102,7 +102,7 @@ services: CYPRESS_CONFIG: "${CYPRESS_CONFIG}" superset-node: - image: node:14 + image: node:16 container_name: superset_node command: ["/app/docker/docker-frontend.sh"] env_file: docker/.env diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 05aa0d6004bfb..10cd5a499ca38 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -56,7 +56,7 @@ "last 3 edge versions" ], "engines": { - "node": "^14.15.5", + "node": "^16.9.1", "npm": "^7.5.4" }, "homepage": "https://superset.apache.org/", diff --git a/superset-frontend/spec/javascripts/dashboard/components/PropertiesModal_spec.jsx b/superset-frontend/spec/javascripts/dashboard/components/PropertiesModal_spec.jsx index 81bd0d0670d12..df2a03637fa5b 100644 --- a/superset-frontend/spec/javascripts/dashboard/components/PropertiesModal_spec.jsx +++ b/superset-frontend/spec/javascripts/dashboard/components/PropertiesModal_spec.jsx @@ -150,8 +150,9 @@ describe('PropertiesModal', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); const spy = jest.spyOn(modalInstance, 'updateFormState'); - modalInstance.onOwnersChange('foo'); - expect(spy).toHaveBeenCalledWith('owners', 'foo'); + const newOwners = [{ value: 1, label: 'foo' }]; + modalInstance.onOwnersChange(newOwners); + expect(spy).toHaveBeenCalledWith('owners', newOwners); }); }); describe('onMetadataChange', () => { diff --git a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx index 0c8d0f74e13c7..2b37332d88899 100644 --- a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx +++ b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx @@ -26,6 +26,7 @@ import Alert from 'src/components/Alert'; import ProgressBar from 'src/components/ProgressBar'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +import fetchMock from 'fetch-mock'; import FilterableTable from 'src/components/FilterableTable/FilterableTable'; import ExploreResultsButton from 'src/SqlLab/components/ExploreResultsButton'; import ResultSet from 'src/SqlLab/components/ResultSet'; @@ -80,6 +81,7 @@ const newProps = { }, }, }; +fetchMock.get('glob:*/api/v1/dataset?*', { result: [] }); test('is valid', () => { expect(React.isValidElement()).toBe(true); diff --git a/superset-frontend/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx b/superset-frontend/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx index 4271b59118572..b99d6cd7801ca 100644 --- a/superset-frontend/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx +++ b/superset-frontend/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx @@ -46,8 +46,7 @@ const mockedProps = { const middlewares = [thunk]; const mockStore = configureStore(middlewares); const store = mockStore(initialState); -const DATABASE_ENDPOINT = 'glob:*/api/v1/database/?*'; -fetchMock.get(DATABASE_ENDPOINT, []); +fetchMock.get('glob:*/api/v1/database/*/schemas/?*', { result: [] }); describe('SqlEditorLeftBar', () => { let wrapper; diff --git a/superset-frontend/src/components/AlteredSliceTag/AlteredSliceTag.test.jsx b/superset-frontend/src/components/AlteredSliceTag/AlteredSliceTag.test.jsx index 6f3d5e33ab2a2..1b7357c39d68f 100644 --- a/superset-frontend/src/components/AlteredSliceTag/AlteredSliceTag.test.jsx +++ b/superset-frontend/src/components/AlteredSliceTag/AlteredSliceTag.test.jsx @@ -129,7 +129,7 @@ describe('AlteredSliceTag', () => { const th = getTableWrapperFromModalBody(modalBody).find('th'); expect(th).toHaveLength(3); ['Control', 'Before', 'After'].forEach(async (v, i) => { - await expect(th.find('span').get(i).props.children[0]).toBe(v); + await expect(th.at(i).find('span').get(0).props.children[0]).toBe(v); }); }); diff --git a/superset-frontend/src/dashboard/components/Header/Header.test.tsx b/superset-frontend/src/dashboard/components/Header/Header.test.tsx index 8a9ecdb5be46f..9e285f1c66af1 100644 --- a/superset-frontend/src/dashboard/components/Header/Header.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/Header.test.tsx @@ -23,7 +23,6 @@ import sinon from 'sinon'; import fetchMock from 'fetch-mock'; import * as actions from 'src/reports/actions/reports'; import * as featureFlags from 'src/featureFlags'; -import { ReportObject } from 'src/components/ReportModal'; import mockState from 'spec/fixtures/mockStateWithoutUser'; import { HeaderProps } from './types'; import Header from '.'; @@ -345,24 +344,27 @@ describe('Email Report Modal', () => { render(setup(mockedProps), { useRedux: true }); const reportValues = { - active: true, - creation_method: 'dashboards', - crontab: '0 12 * * 1', - dashboard: mockedProps.dashboardInfo.id, - name: 'Weekly Report', - owners: [mockedProps.user.userId], - recipients: [ - { - recipient_config_json: { - target: mockedProps.user.email, + id: 1, + result: { + active: true, + creation_method: 'dashboards', + crontab: '0 12 * * 1', + dashboard: mockedProps.dashboardInfo.id, + name: 'Weekly Report', + owners: [mockedProps.user.userId], + recipients: [ + { + recipient_config_json: { + target: mockedProps.user.email, + }, + type: 'Email', }, - type: 'Email', - }, - ], - type: 'Report', + ], + type: 'Report', + }, }; // This is needed to structure the reportValues to match the fetchMock return - const stringyReportValues = `{"active":true,"creation_method":"dashboards","crontab":"0 12 * * 1","dashboard":${mockedProps.dashboardInfo.id},"name":"Weekly Report","owners":[${mockedProps.user.userId}],"recipients":[{"recipient_config_json":{"target":"${mockedProps.user.email}"},"type":"Email"}],"type":"Report"}`; + const stringyReportValues = `{"id":1,"result":{"active":true,"creation_method":"dashboards","crontab":"0 12 * * 1","dashboard":${mockedProps.dashboardInfo.id},"name":"Weekly Report","owners":[${mockedProps.user.userId}],"recipients":[{"recipient_config_json":{"target":"${mockedProps.user.email}"},"type":"Email"}],"type":"Report"}}`; // Watch for report POST fetchMock.post(REPORT_ENDPOINT, reportValues); @@ -380,7 +382,7 @@ describe('Email Report Modal', () => { // Mock addReport from Redux const makeRequest = () => { - const request = actions.addReport(reportValues as ReportObject); + const request = actions.addReport(reportValues); return request(dispatch); }; diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx index 6214e997bff6a..088fd79906a70 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.test.jsx @@ -42,6 +42,8 @@ const dbProps = { const DATABASE_FETCH_ENDPOINT = 'glob:*/api/v1/database/10'; // const DATABASE_POST_ENDPOINT = 'glob:*/api/v1/database/'; const AVAILABLE_DB_ENDPOINT = 'glob:*/api/v1/database/available*'; +const VALIDATE_PARAMS_ENDPOINT = 'glob:*/api/v1/database/validate_parameters*'; + fetchMock.config.overwriteRoutes = true; fetchMock.get(DATABASE_FETCH_ENDPOINT, { result: { @@ -194,6 +196,9 @@ fetchMock.mock(AVAILABLE_DB_ENDPOINT, { }, ], }); +fetchMock.post(VALIDATE_PARAMS_ENDPOINT, { + message: 'OK', +}); describe('DatabaseModal', () => { const renderAndWait = async () => { diff --git a/superset-websocket/Dockerfile b/superset-websocket/Dockerfile index 84c6d28d7df18..85ff66520dd29 100644 --- a/superset-websocket/Dockerfile +++ b/superset-websocket/Dockerfile @@ -12,7 +12,7 @@ # 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. -FROM node:14.16.1 +FROM node:16 WORKDIR /home/superset-websocket