feat: use docker in frontend GHA to parallelize work (#31490)
This commit is contained in:
parent
550d893c38
commit
0eca79cb6c
|
|
@ -34,7 +34,6 @@
|
||||||
**/*.sqllite
|
**/*.sqllite
|
||||||
**/*.swp
|
**/*.swp
|
||||||
**/.terser-plugin-cache/
|
**/.terser-plugin-cache/
|
||||||
**/.storybook/
|
|
||||||
**/node_modules/
|
**/node_modules/
|
||||||
|
|
||||||
tests/
|
tests/
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ jobs:
|
||||||
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
||||||
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
||||||
with:
|
with:
|
||||||
paths: "**/*.md, **/*.mdx"
|
paths: "**/*.md, **/*.mdx, !superset-frontend/CHANGELOG.md"
|
||||||
linksToSkip: >-
|
linksToSkip: >-
|
||||||
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
||||||
http://localhost:8088/,
|
http://localhost:8088/,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
name: Frontend
|
name: "Frontend Build CI (unit tests, linting & sanity checks)"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|
@ -13,68 +13,166 @@ concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
TAG: apache/superset:GHA-${{ github.run_id }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
frontend-build:
|
frontend-build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: recursive
|
|
||||||
- name: Check npm lock file version
|
- name: Check for File Changes
|
||||||
run: ./scripts/ci_check_npm_lock_version.sh ./superset-frontend/package-lock.json
|
|
||||||
- name: Check for file changes
|
|
||||||
id: check
|
id: check
|
||||||
uses: ./.github/actions/change-detector/
|
uses: ./.github/actions/change-detector/
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Setup Node.js
|
|
||||||
|
- name: Build Docker Image
|
||||||
if: steps.check.outputs.frontend
|
if: steps.check.outputs.frontend
|
||||||
uses: actions/setup-node@v4
|
shell: bash
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
docker buildx build \
|
||||||
|
-t $TAG \
|
||||||
|
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-bookworm \
|
||||||
|
--target superset-node-ci \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Save Docker Image as Artifact
|
||||||
|
if: steps.check.outputs.frontend
|
||||||
|
run: |
|
||||||
|
docker save $TAG | gzip > docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: Upload Docker Image Artifact
|
||||||
|
if: steps.check.outputs.frontend
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
node-version: "20"
|
name: docker-image
|
||||||
- name: Install dependencies
|
path: docker-image.tar.gz
|
||||||
if: steps.check.outputs.frontend
|
|
||||||
uses: ./.github/actions/cached-dependencies
|
sharded-jest-tests:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.result == 'success'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
shard: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
run: npm-install
|
name: docker-image
|
||||||
- name: eslint
|
|
||||||
if: steps.check.outputs.frontend
|
- name: Load Docker Image
|
||||||
working-directory: ./superset-frontend
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: npm run test with coverage
|
||||||
run: |
|
run: |
|
||||||
npm run eslint -- . --quiet
|
mkdir -p ${{ github.workspace }}/superset-frontend/coverage
|
||||||
- name: tsc
|
docker run \
|
||||||
if: steps.check.outputs.frontend
|
-v ${{ github.workspace }}/superset-frontend/coverage:/app/superset-frontend/coverage \
|
||||||
working-directory: ./superset-frontend
|
--rm $TAG \
|
||||||
run: |
|
bash -c \
|
||||||
npm run type
|
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json-summary"
|
||||||
- name: Build plugins packages
|
|
||||||
if: steps.check.outputs.frontend
|
- name: Upload Coverage Artifact
|
||||||
working-directory: ./superset-frontend
|
uses: actions/upload-artifact@v4
|
||||||
run: npm run plugins:build
|
with:
|
||||||
- name: Build plugins Storybook
|
name: coverage-artifacts-${{ matrix.shard }}
|
||||||
if: steps.check.outputs.frontend
|
path: superset-frontend/coverage
|
||||||
working-directory: ./superset-frontend
|
|
||||||
run: npm run plugins:build-storybook
|
report-coverage:
|
||||||
- name: superset-ui/core coverage
|
needs: [sharded-jest-tests]
|
||||||
if: steps.check.outputs.frontend
|
if: needs.frontend-build.result == 'success'
|
||||||
working-directory: ./superset-frontend
|
runs-on: ubuntu-24.04
|
||||||
run: |
|
steps:
|
||||||
npm run core:cover
|
- name: Download Coverage Artifacts
|
||||||
- name: unit tests
|
uses: actions/download-artifact@v4
|
||||||
if: steps.check.outputs.frontend
|
with:
|
||||||
working-directory: ./superset-frontend
|
pattern: coverage-artifacts-*
|
||||||
run: |
|
path: coverage/
|
||||||
npm run test -- --coverage --silent
|
|
||||||
# todo: remove this step when fix generator as a project in root jest.config.js
|
- name: Show Files
|
||||||
- name: generator-superset unit tests
|
run: find coverage/
|
||||||
if: steps.check.outputs.frontend
|
|
||||||
working-directory: ./superset-frontend/packages/generator-superset
|
- name: Merge Code Coverage
|
||||||
run: npm run test
|
run: npx nyc merge coverage/ merged-output/coverage-summary.json
|
||||||
- name: Upload code coverage
|
|
||||||
|
- name: Upload Code Coverage
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
flags: javascript
|
flags: javascript
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
verbose: true
|
verbose: true
|
||||||
|
files: merged-output/coverage-summary.json
|
||||||
|
slug: apache/superset
|
||||||
|
|
||||||
|
core-cover:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.result == 'success'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-image
|
||||||
|
|
||||||
|
- name: Load Docker Image
|
||||||
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: superset-ui/core coverage
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run core:cover"
|
||||||
|
|
||||||
|
lint-frontend:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.result == 'success'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-image
|
||||||
|
|
||||||
|
- name: Load Docker Image
|
||||||
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: eslint
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm i && npm run eslint -- . --quiet"
|
||||||
|
|
||||||
|
- name: tsc
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run type"
|
||||||
|
|
||||||
|
validate-frontend:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.result == 'success'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-image
|
||||||
|
|
||||||
|
- name: Load Docker Image
|
||||||
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: Build Plugins Packages
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run plugins:build"
|
||||||
|
|
||||||
|
- name: Build Plugins Storybook
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run plugins:build-storybook"
|
||||||
|
|
|
||||||
13
Dockerfile
13
Dockerfile
|
|
@ -24,9 +24,9 @@ ARG PY_VER=3.10-slim-bookworm
|
||||||
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# superset-node used for building frontend assets
|
# superset-node-ci used as a base for building frontend assets and CI
|
||||||
######################################################################
|
######################################################################
|
||||||
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node
|
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node-ci
|
||||||
ARG BUILD_TRANSLATIONS="false" # Include translations in the final build
|
ARG BUILD_TRANSLATIONS="false" # Include translations in the final build
|
||||||
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
||||||
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
||||||
|
|
@ -53,6 +53,10 @@ RUN mkdir -p /app/superset/static/assets \
|
||||||
/app/superset/translations
|
/app/superset/translations
|
||||||
|
|
||||||
# Mount package files and install dependencies if not in dev mode
|
# Mount package files and install dependencies if not in dev mode
|
||||||
|
# NOTE: we mount packages and plugins as they are referenced in package.json as workspaces
|
||||||
|
# ideally we'd COPY only their package.json. Here npm ci will be cached as long
|
||||||
|
# as the full content of these folders don't change, yielding a decent cache reuse rate.
|
||||||
|
# Note that's it's not possible selectively COPY of mount using blobs.
|
||||||
RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.json \
|
RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.json \
|
||||||
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
|
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
|
||||||
--mount=type=cache,target=/root/.cache \
|
--mount=type=cache,target=/root/.cache \
|
||||||
|
|
@ -66,6 +70,11 @@ RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.j
|
||||||
# Runs the webpack build process
|
# Runs the webpack build process
|
||||||
COPY superset-frontend /app/superset-frontend
|
COPY superset-frontend /app/superset-frontend
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# superset-node used for compile frontend assets
|
||||||
|
######################################################################
|
||||||
|
FROM superset-node-ci AS superset-node
|
||||||
|
|
||||||
# Build the frontend if not in dev mode
|
# Build the frontend if not in dev mode
|
||||||
RUN --mount=type=cache,target=/app/superset-frontend/.temp_cache \
|
RUN --mount=type=cache,target=/app/superset-frontend/.temp_cache \
|
||||||
--mount=type=cache,target=/root/.npm \
|
--mount=type=cache,target=/root/.npm \
|
||||||
|
|
|
||||||
|
|
@ -57127,7 +57127,7 @@
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@data-ui/event-flow": "^0.0.84",
|
"@data-ui/event-flow": "^0.0.84",
|
||||||
"@emotion/cache": "^11.4.0",
|
"@emotion/cache": "^11.14.0",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||||
|
|
@ -67792,7 +67792,7 @@
|
||||||
"@babel/preset-react": "^7.26.3",
|
"@babel/preset-react": "^7.26.3",
|
||||||
"@babel/preset-typescript": "^7.23.3",
|
"@babel/preset-typescript": "^7.23.3",
|
||||||
"@data-ui/event-flow": "^0.0.84",
|
"@data-ui/event-flow": "^0.0.84",
|
||||||
"@emotion/cache": "^11.4.0",
|
"@emotion/cache": "^11.14.0",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ ALEMBIC_SKIP_LOG_CONFIG = False
|
||||||
# generated on install via setup.py. In the event that we're
|
# generated on install via setup.py. In the event that we're
|
||||||
# actually running Superset, we will have already installed,
|
# actually running Superset, we will have already installed,
|
||||||
# therefore it WILL exist. When unit tests are running, however,
|
# therefore it WILL exist. When unit tests are running, however,
|
||||||
# it WILL NOT exist, so we fall back to reading package.json
|
# it WILL NOT exist, so we fall back on reading package.json
|
||||||
VERSION_STRING = _try_json_readversion(VERSION_INFO_FILE) or _try_json_readversion(
|
VERSION_STRING = _try_json_readversion(VERSION_INFO_FILE) or _try_json_readversion(
|
||||||
PACKAGE_JSON_FILE
|
PACKAGE_JSON_FILE
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you 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.
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: eb1c288c71c4
|
||||||
|
Revises: ('df3d7e2eb9a4', '7b17aa722e30')
|
||||||
|
Create Date: 2025-01-07 16:03:44.936921
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "eb1c288c71c4"
|
||||||
|
down_revision = ("df3d7e2eb9a4", "7b17aa722e30")
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
pass
|
||||||
Loading…
Reference in New Issue