Compare commits

..

1 Commits

Author SHA1 Message Date
Uladzimir Havenchyk
f55dc0d3b5 chore: add single dev command to run before push 2025-06-19 16:49:42 +03:00
4248 changed files with 415366 additions and 490395 deletions

View File

@@ -76,13 +76,8 @@
;;
;; TODO -- these should all be made thread safe if possible or renamed so they end in `!`. Then we can remove them
;; from this list because by default anything ending in `!` is considered to be thread-unsafe
;;
;; TODO (Cam 6/19/25) -- move this into the `test-helpers/config.edn` file so they can live with their friends.
:parallel/unsafe
#{java.util.Locale/setDefault
java.lang.System/setProperty
java.lang.System/setProperties
clojure.core/alter-var-root
#{clojure.core/alter-var-root
clojure.core/with-redefs
clojure.core/with-redefs-fn
metabase.actions.test-util/with-actions
@@ -101,6 +96,7 @@
metabase.test.util/with-all-users-permission
metabase.test.util/with-discarded-collections-perms-changes
metabase.test.util/with-env-keys-renamed-by
metabase.test.util/with-locale
metabase.test.util/with-model-cleanup
metabase.test.util/with-non-admin-groups-no-root-collection-for-namespace-perms
metabase.test.util/with-non-admin-groups-no-root-collection-perms
@@ -123,6 +119,7 @@
metabase.test/with-fake-inbox
metabase.test/with-group
metabase.test/with-group-for-user
metabase.test/with-locale
metabase.test/with-log-level
metabase.test/with-model-cleanup
metabase.test/with-non-admin-groups-no-root-collection-for-namespace-perms
@@ -235,8 +232,6 @@
(metabase.driver.druid.query-processor-test/druid-query-returning-rows)
(metabase.lib.util.match/match)
(metabase.lib.util.match/match-one)
(metabase.lib.util.match/match-lite)
(metabase.lib.util.match/match-lite-recursive)
(metabase.lib.util.match/replace)
(metabase.lib.util.match/replace-in)
(metabase.driver-api.core/match)
@@ -292,9 +287,7 @@
medley.core/random-uuid {:message "Use clojure.core/random-uuid instead of medley.core/random-uuid"}
metabase.driver/database-supports? {:message "Use metabase.driver.util/supports? instead of metabase.driver/database-supports?"}
metabase.lib.equality/find-column-indexes-for-refs {:message "Use lib.equality/closest-matches-in-metadata or lib.equality/find-closest-matches-for-refs instead of lib.equality/find-column-indexes-for-refs"}
next.jdbc/active-tx? {:message "Use metabase.app-db.core/in-transaction? to see if we are in a transaction"}
toucan2.core/debug {:message "Don't commit code using t2/debug"}
toucan2.tools.debug/debug {:message "Don't commit code using t2/debug"}}
next.jdbc/active-tx? {:message "Use metabase.app-db.core/in-transaction? to see if we are in a transaction"}}
:discouraged-namespace
{camel-snake-kebab.core {:message "CSK is not Turkish-safe, use the versions in metabase.util instead."}
@@ -525,7 +518,6 @@ metabase-enterprise.content-translation.routes-test/with-new-secret-key!
metabase.dashboards.models.dashboard-tab-test/with-dashtab-in-personal-collection hooks.common/with-one-top-level-binding
metabase.dashboards.models.dashboard-test/with-dash-in-collection! hooks.common/with-three-bindings
metabase.driver.bigquery-cloud-sdk-test/calculate-bird-scarcity hooks.metabase.query-processor-test.expressions-test/calculate-bird-scarcity
metabase.driver.mongo-test/with-describe-table-for-sample hooks.metabase.driver.mongo-test/with-describe-table-for-sample
metabase.driver.oracle-test/with-temp-user hooks.common/let-one-with-optional-value
metabase.driver/register! hooks.metabase.driver/register!
metabase.driver-api/defenterprise hooks.metabase.premium-features.defenterprise/defenterprise
@@ -698,8 +690,6 @@ metabase-enterprise.content-translation.routes-test/with-new-secret-key!
:name printable-namespaces}
{:pattern "^metabase\\.(?:(?:lib)|(?:legacy-mbql))\\..*"
:name metabase-lib}
{:pattern "^metabase\\.lib\\..*"
:name metabase-lib-excluding-legacy-mbql}
;;
;; QP source namespaces: `metabase.query-processor.*`, `metabase-enterprise.sandbox.query-processor.*`, and
;; `metabase.driver.*`, excluding `-test` namespaces.
@@ -780,11 +770,6 @@ metabase-enterprise.content-translation.routes-test/with-new-secret-key!
toucan.util.test {:message "Don't use application database inside MLv2 code"}
toucan2.core {:message "Don't use application database inside MLv2 code"}}}}
metabase-lib-excluding-legacy-mbql
{:linters
{:discouraged-var
{metabase.legacy-mbql.util/unique-name-generator {:message "Use metabase.lib.util/unique-name-generator or non-truncating-unique-name-generator"}}}}
driver-namespaces
{:linters
{:discouraged-var

View File

@@ -324,10 +324,8 @@
audit-app
config
driver
eid-translation
events
legacy-mbql
lib-be
models
notification
permissions
@@ -390,7 +388,6 @@
channel
collections
config
eid-translation
embedding
events
lib
@@ -576,16 +573,15 @@
metabase.lib.core
metabase.lib.equality
metabase.lib.field
metabase.lib.field.resolution
metabase.lib.filter
metabase.lib.ident
metabase.lib.init
metabase.lib.join.util
metabase.lib.metadata
metabase.lib.metadata.cached-provider
metabase.lib.metadata.calculation
metabase.lib.metadata.invocation-tracker
metabase.lib.metadata.protocols
metabase.lib.metadata.result-metadata
metabase.lib.normalize
metabase.lib.options
metabase.lib.query
@@ -598,7 +594,6 @@
metabase.lib.schema.expression.window
metabase.lib.schema.id
metabase.lib.schema.info
metabase.lib.schema.join
metabase.lib.schema.literal
metabase.lib.schema.metadata
metabase.lib.schema.parameter
@@ -760,7 +755,17 @@
{:team "Admin Webapp"
:api #{metabase.permissions.api
metabase.permissions.core
metabase.permissions.init}
metabase.permissions.init
;; TODO -- move these into the API namespace.
metabase.permissions.models.application-permissions-revision
metabase.permissions.models.collection-permission-graph-revision
metabase.permissions.models.collection.graph
metabase.permissions.models.data-permissions
metabase.permissions.models.permissions
metabase.permissions.models.permissions-group
metabase.permissions.path
metabase.permissions.util
metabase.permissions.validation}
:uses #{api
app-db
audit-app
@@ -880,7 +885,6 @@
config
content-verification
dashboards
eid-translation
embedding
events
legacy-mbql
@@ -1351,7 +1355,6 @@
metabase.warehouse-schema.metadata-from-qp
metabase.warehouse-schema.metadata-queries
metabase.warehouse-schema.models.field
metabase.warehouse-schema.models.field-user-settings
metabase.warehouse-schema.models.field-values
metabase.warehouse-schema.models.table
metabase.warehouse-schema.table}
@@ -1360,7 +1363,6 @@
api
app-db
audit-app
database-routing
driver
events
lib
@@ -1585,24 +1587,12 @@
api
util}}
enterprise/database-replication
{:team "Cloud"
:api #{metabase-enterprise.database-replication.api
metabase-enterprise.database-replication.init}
:uses #{analytics
api
premium-features
settings
util
enterprise/harbormaster}}
enterprise/database-routing
{:team "Admin Webapp"
:api #{metabase-enterprise.database-routing.api}
:uses #{api
config
database-routing
driver
events
lib
models
@@ -1613,17 +1603,6 @@
warehouse-schema
warehouses}}
enterprise/email
{:team "Admin Webapp"
:api #{metabase-enterprise.email.api}
:uses #{api
channel
permissions
premium-features
settings
util}}
enterprise/gsheets
{:team "Cloud"
:api #{metabase-enterprise.gsheets.api
@@ -1684,7 +1663,6 @@
app-db
collections
config
driver
legacy-mbql
lib
lib-be
@@ -1694,23 +1672,12 @@
pulse
query-processor
request
server
settings
system
users
util
warehouse-schema}}
enterprise/permission-debug
{:team "Admin Webapp"
:api #{metabase-enterprise.permission-debug.api}
:uses #{api
lib
models
permissions
query-processor
util}}
enterprise/premium-features
{:team "Admin Webapp"
:api #{}

View File

@@ -1,18 +0,0 @@
(ns hooks.metabase.driver.mongo-test
(:require
[clj-kondo.hooks-api :as hooks]
[hooks.common]))
(defn with-describe-table-for-sample
"Forward bindings for results of functions used in mongo's describe-table implementation."
[{{[_ _ & body] :children} :node}]
(let [node* (hooks/list-node
(list*
(hooks/token-node 'let)
(hooks/vector-node
[(hooks/token-node 'dbfields) (hooks/token-node '(delay nil))
(hooks/token-node 'ftree) (hooks/token-node '(delay nil))
(hooks/token-node 'nested-fields) (hooks/token-node '(delay nil))])
body))]
;; Avoid warnings when not all from the dbfields, ftree and nested-fields are used.
{:node (hooks.common/update-ignored-linters node* conj :unused-binding)}))

View File

@@ -139,7 +139,6 @@
saml-keystore-password
saml-keystore-path
saml-user-provisioning-enabled?
sdk-iframe-embed-setup-settings
send-email-on-first-login-from-new-device
send-new-sso-user-admin-email?
session-cookie-samesite

View File

@@ -120,10 +120,6 @@
metabase.collections.models.collection-test/with-personal-and-impersonal-collections [[:block 1]]
metabase.config/build-type-case [[:block 0]]
metabase.dashboards.models.dashboard-test/with-dash-in-collection [[:inner 0]]
metabase.driver-api.core/match [[:inner 0]]
metabase.driver-api.core/match-one [[:inner 0]]
metabase.driver-api.core/replace [[:inner 0]]
metabase.driver-api.core/replace-in [[:inner 0]]
metabase.driver.bigquery-cloud-sdk.query-processor/with-temporal-type [[:default]]
metabase.driver.druid.client/DELETE [[:default]]
metabase.driver.druid.client/GET [[:default]]
@@ -155,8 +151,6 @@
metabase.lib.test-util.macros/mbql-query [[:inner 0]]
metabase.lib.util.match/match [[:inner 0]]
metabase.lib.util.match/match-one [[:inner 0]]
metabase.lib.util.match/match-lite [[:inner 0]]
metabase.lib.util.match/match-lite-recursive [[:inner 0]]
metabase.lib.util.match/replace [[:inner 0]]
metabase.lib.util.match/replace-in [[:inner 0]]
metabase.models.interface/define-batched-hydration-method [[:inner 0]]

View File

@@ -315,12 +315,6 @@ module.exports = {
],
},
},
{
files: ["frontend/src/metabase/query_builder/**/*"],
rules: {
"import/no-cycle": "error",
},
},
{
files: ["docs/**/snippets/**/*.{ts,tsx,js,jsx}"],
rules: {

View File

@@ -1,15 +1,12 @@
name: Cross-branch migration test
inputs:
base-ref: ## Base branch PR came from
required: true
head-ref: ## Source branch of the pull request
base-ref:
required: true
runs:
using: "composite"
steps:
## First we deploy the base branch
- name: Check out base branch
uses: actions/checkout@v4
with:
@@ -42,11 +39,10 @@ runs:
run: kill $(cat metabase_pid)
shell: bash
## Then we deploy the PR branch to ensure it migrates up successfully
- name: Check out pull request branch
uses: actions/checkout@v4
with:
ref: ${{ inputs.head-ref }}
ref: ${{ github.head_ref }}
- name: Run backend on pull request branch
run: |
@@ -69,38 +65,3 @@ runs:
- name: Stop Metabase on pull request branch
run: kill $(cat metabase_pid)
shell: bash
## Testing that originally deploying this PR allows you to roll back to a previous release
## Reset the checksums so when we go back to the base branch, it's as if the PR branch was what was originally deployed
- name: Reset the checksums as if the PR branch was what was originally deployed
run: |
clojure -M:dev:ee:migrate reset-checksums
shell: bash
- name: Rollback the last deployment
run: |
clojure -M:dev:ee:migrate rollback last-deployment
shell: bash
- name: Re-check out base branch
uses: actions/checkout@v4
with:
ref: ${{ inputs.base-ref }}
- name: Re-run backend on base branch
run: |
clojure -M:run:ee > metabase.log 2>&1 & echo $! > metabase_pid
tail -F metabase.log &
shell: bash
- name: Wait for Metabase to start
run: |
while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}' > /dev/null; do
if ! kill -0 $(cat metabase_pid) 2>/dev/null; then
cat metabase.log
echo "Metabase process has exited."
exit 1
fi
sleep 1
done
shell: bash

View File

@@ -8,7 +8,7 @@ inputs:
description: DockerHub password/token
required: true
maildev:
description: Maildev containers
description: Maildev container
required: true
default: false
openldap:
@@ -31,10 +31,6 @@ inputs:
description: Webhook tester container
required: false
default: false
snowplow:
description: Snowplow micro container
required: false
default: false
runs:
using: "composite"
@@ -46,68 +42,56 @@ runs:
password: ${{ inputs.password }}
- name: Start Containers
shell: bash
run: | # bash
run: |
Y='\033[33m'
G='\033[1;32m'
cd e2e/test/scenarios/
docker compose up \
$([ ${{ inputs.postgres }} = true ] && echo "postgres-sample") \
$([ ${{ inputs.mysql }} = true ] && echo "mysql-sample") \
$([ ${{ inputs.mongo }} = true ] && echo "mongo-sample") \
$([ ${{ inputs.maildev }} = true ] && echo "maildev") \
$([ ${{ inputs.maildev }} = true ] && echo "maildev-ssl") \
$([ ${{ inputs.openldap }} = true ] && echo "ldap") \
$([ ${{ inputs.webhook }} = true ] && echo "webhook-tester") \
$([ ${{ inputs.snowplow }} = true ] && echo "snowplow-micro") \
-d
if ${{ inputs.maildev }}; then
echo -e "${Y}checking maildev container..." &&
echo -e "${Y}Starting maildev container..." &&
docker run -d -p 1080:1080 -p 1025:1025 maildev/maildev:2.0.5 &&
while ! nc -z localhost 1080; do sleep 1; done &&
while ! nc -z localhost 1025; do sleep 1; done &&
echo -e "${G}Maildev is up and running!"
echo -e "${Y}checking maildev-ssl container..." &&
while ! nc -z localhost 1081; do sleep 1; done &&
while ! nc -z localhost 465; do sleep 1; done &&
echo -e "${G}Maildev-ssl is up and running!"
fi
if ${{ inputs.openldap }}; then
echo -e "${Y}checking openldap container..." &&
echo -e "${Y}Starting openldap container..." &&
docker run -d -p 389:389 \
--env LDAP_ADMIN_PASSWORD=adminpass \
--env LDAP_USERS=user01@example.org,user02@example.org \
--env LDAP_PASSWORDS=123456,123465 \
--env LDAP_ROOT=dc=example,dc=org \
--env LDAP_PORT_NUMBER=389 \
bitnami/openldap:2.6.4 &&
while ! nc -z localhost 389; do sleep 1; done &&
echo -e "${G}Openldap is up and running!"
fi
if ${{ inputs.postgres }}; then
echo -e "${Y}checking postgres container..." &&
echo -e "${Y}Starting postgres container..." &&
docker run -d -p 5404:5432 -e TZ='US/Pacific' metabase/qa-databases:postgres-sample-12 &&
while ! nc -z localhost 5404; do sleep 1; done &&
echo -e "${G}Postgres is up and running!"
fi
if ${{ inputs.mysql }}; then
echo -e "${Y}checking mysql container..." &&
echo -e "${Y}Starting mysql container..." &&
docker run -d -p 3304:3306 -e TZ='US/Pacific' metabase/qa-databases:mysql-sample-8 &&
while ! nc -z localhost 3304; do sleep 1; done &&
echo -e "${G}MySQL is up and running!"
fi
if ${{ inputs.mongo }}; then
echo -e "${Y}checking mongo container..." &&
echo -e "${Y}Starting mongo container..." &&
docker run -d -p 27004:27017 metabase/qa-databases:mongo-sample-4.4 &&
while ! nc -z localhost 27004; do sleep 1; done &&
echo -e "${G}Mongo is up and running!"
fi
if ${{ inputs.webhook }}; then
echo -e "${Y}checking webhook test container..." &&
echo -e "${Y}Starting webhook test container..." &&
docker run -d -p 9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000 &&
while ! nc -z localhost 9080; do sleep 1; done &&
echo -e "${G}Webhook tester is up and running!"
fi
if ${{ inputs.snowplow }}; then
echo -e "${Y}checking snowplow micro container..." &&
while ! nc -z localhost 9090; do sleep 1; done &&
echo -e "${G}Snowplow micro is up and running!"
fi
shell: bash

View File

@@ -0,0 +1,13 @@
name: Run Snowplow micro
runs:
using: "composite"
steps:
- name: Download Snowplow micro JAR
run: curl -L -o snowplow-micro.jar https://github.com/snowplow-incubator/snowplow-micro/releases/download/micro-1.2.1/snowplow-micro-1.2.1.jar
shell: bash
- name: Launch Snowplow micro
run: java -cp snowplow-micro.jar:snowplow com.snowplowanalytics.snowplow.micro.Main --collector-config snowplow/micro.conf --iglu snowplow/iglu.json &
shell: bash
- name: Wait until Snowplow micro is ready
run: while ! curl -s 'http://localhost:9090' | grep '404'; do sleep 1; done
shell: bash

17
.github/auto_request_review.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
# The reviewers configuration for the auto_request_review workflow
# See https://github.com/necojackarc/auto-request-review/tree/master?tab=readme-ov-file#reviewers-configuration
# for the spec
files:
# migrations related files
'resources/migrations/**':
- team:core-workflows
'src/metabase/app_db/custom_migrations.clj':
- team:core-workflows
options:
ignore_draft: true
ignored_keywords:
- DO NOT REVIEW
- WIP
enable_group_assignment: false

View File

@@ -16,12 +16,10 @@ frontend_ci: &frontend_ci
- ".github/actions/prepare-backend/**"
- ".github/workflows/frontend.yml"
frontend_embedding_sdk_ci: &frontend_embedding_sdk_ci
- ".github/actions/prepare-frontend/**"
- ".github/actions/prepare-backend/**"
- ".github/workflows/*embedding-sdk*.yml"
frontend_configs: &frontend_configs
frontend_sources: &frontend_sources
- *shared_sources
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
- "frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
- "yarn.lock"
- "**/tsconfig*.json"
- "package.json"
@@ -34,15 +32,8 @@ frontend_configs: &frontend_configs
- "webpack.static-viz.config.js"
- ".nvmrc"
frontend_sources: &frontend_sources
- *shared_sources
- *frontend_configs
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
- "frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
frontend_embedding_sdk_sources:
- *frontend_configs
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
- *frontend_sources
frontend_specs: &frontend_specs
- *shared_specs
@@ -114,27 +105,25 @@ e2e_ci: &e2e_ci
- ".github/actions/prepare-uberjar-artifact/**"
- ".github/actions/e2e-prepare-containers/**"
- ".github/actions/prepare-cypress/**"
- ".github/actions/run-snowplow-micro/**"
- ".github/workflows/e2e-*"
e2e_specs: &e2e_specs
- e2e/!(test-host-app)**/*.cy.*.{js,ts}
- "**/*.cy.*.js"
- "**/*.cy.*.ts"
e2e_cross_version: &e2e_cross_version
- ".github/workflows/e2e-cross-version.yml"
- "e2e/test/scenarios/cross-version/**"
e2e_embedding_sdk:
- *frontend_embedding_sdk_ci
- *sources
- "e2e/component/**/*.cy.*.{js,ts}"
e2e_embedding_sdk_compatibility:
- *default
- *frontend_embedding_sdk_ci
- *e2e_ci
- *frontend_sources
- "e2e/embedding-sdk-host-apps/**"
- "e2e/runner/embedding-sdk/**"
- "e2e/test-host-app/**/*.cy.*.{js,ts}"
- "e2e/runner/test-host-app/**/*.cy.*.js"
- "e2e/runner/test-host-app/**/*.cy.*.ts"
e2e_all:
- *default
@@ -148,13 +137,10 @@ snowplow:
- "snowplow/**"
documentation:
- ".typedoc/**"
- "docs/**"
- "**/*.md"
embedding_documentation:
- ".typedoc/**"
- "docs/embedding/**"
yaml:
- "**/*.yml"
- "**/*.yaml"

4
.github/team.json vendored
View File

@@ -106,9 +106,7 @@
{
"name": "Cloud",
"label": "cloud",
"members": [
"filipesilva"
]
"members": []
}
]
}

View File

@@ -1,405 +0,0 @@
name: App DB Tests
on:
workflow_call:
inputs:
skip:
type: boolean
default: false
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-app-db
cancel-in-progress: true
jobs:
be-tests-mariadb:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
version:
- name: MariaDB 10.2
junit-name: be-tests-mariadb-10-2-ee
image: circleci/mariadb:10.2.23
env:
enable-ssl-tests: 'false'
- name: MariaDB Latest
junit-name: be-tests-mariadb-latest-ee
image: circleci/mariadb:latest
env:
enable-ssl-tests: 'false'
job:
- name: Enterprise Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test"'
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 1)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 0
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 2)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 1
exclude-tag: ':mb/driver-tests'
services:
mysql:
image: ${{ matrix.version.image }}
ports:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: circle_test
env:
# Only run old migrations tests on pushes to master or release branches. All other branches should skip tests
# with the tag `mb/old-migrations-test`. `__ADDITIONAL_EXCLUDED_TAG__` is not used anywhere outside of splicing
# it in to the command below.
__ADDITIONAL_EXCLUDED_TAG__: >-
${{
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
) &&
''
) ||
':mb/old-migrations-test'
}}
# actual serious env vars below
CI: 'true'
DRIVERS: mysql
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
#
# SSL config: only for mysql latest tests.
#
# set up env vars for something named "MYSQL_SSL" to run MySQL SSL tests verifying connectivity with PEM cert
# they are deliberately given a different name to prevent them from affecting the regular test run against
# the configured MySQL instance, but there is one particular test (mysql-connect-with-ssl-and-pem-cert-test)
# that overrides the MB_MYSQL_TEST_* values with them
# the MYSQL_RDS_SSL_INSTANCE vars are defined as secrets and can be altered
MB_MYSQL_SSL_TEST_SSL: ${{ matrix.version.env.enable-ssl-tests }}
MB_MYSQL_SSL_TEST_HOST: ${{ secrets.MYSQL_RDS_SSL_INSTANCE_HOST }}
MB_MYSQL_SSL_TEST_ADDITIONAL_OPTIONS: 'verifyServerCertificate=true'
# the contents of the ./resources/certificates/rds-combined-ca-bundle.pem file
MB_MYSQL_SSL_TEST_SSL_CERT: ${{ secrets.MB_MYSQL_SSL_TEST_SSL_CERT }}
MB_MYSQL_SSL_TEST_USER: metabase
MB_MYSQL_SSL_TEST_PASSWORD: ${{ secrets.MYSQL_RDS_SSL_INSTANCE_PASSWORD }}
# for historic reasons (I don't want to mess around with required jobs) the job name should be something like
# "be-tests-mariadb-10-2-ee (0)"
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
steps:
- uses: actions/checkout@v4
- name: Test ${{ matrix.version.name }}
uses: ./.github/actions/test-driver
with:
build-static-viz: ${{ matrix.job.build-static-viz }}
junit-name: ${{ matrix.version.junit-name }}
test-args: >-
${{ matrix.job.test-args }}
:exclude-tags '[ ${{ matrix.job.exclude-tag }} ${{ env.__ADDITIONAL_EXCLUDED_TAG__ }}]'
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit/
output-name: ${{ github.job }}
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-mysql:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
version:
- name: MySQL 8.0
junit-name: be-tests-mysql-8-0-ee
image: cimg/mysql:8.0
env:
enable-ssl-tests: 'false'
- name: MySQL Latest
junit-name: be-tests-mysql-latest-ee
image: mysql:latest
env:
enable-ssl-tests: 'true'
job:
- name: Enterprise Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test"'
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 1)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 0
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 2)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 1
exclude-tag: ':mb/driver-tests'
services:
mysql:
image: ${{ matrix.version.image }}
ports:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: circle_test
env:
# Only run old migrations tests on pushes to master or release branches. All other branches should skip tests
# with the tag `mb/old-migrations-test`. `__ADDITIONAL_EXCLUDED_TAG__` is not used anywhere outside of splicing
# it in to the command below.
__ADDITIONAL_EXCLUDED_TAG__: >-
${{
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
) &&
''
) ||
':mb/old-migrations-test'
}}
# actual serious env vars below
CI: 'true'
DRIVERS: mysql
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
#
# SSL config: only for mysql latest tests.
#
# set up env vars for something named "MYSQL_SSL" to run MySQL SSL tests verifying connectivity with PEM cert
# they are deliberately given a different name to prevent them from affecting the regular test run against
# the configured MySQL instance, but there is one particular test (mysql-connect-with-ssl-and-pem-cert-test)
# that overrides the MB_MYSQL_TEST_* values with them
# the MYSQL_RDS_SSL_INSTANCE vars are defined as secrets and can be altered
MB_MYSQL_SSL_TEST_SSL: ${{ matrix.version.env.enable-ssl-tests }}
MB_MYSQL_SSL_TEST_HOST: ${{ secrets.MYSQL_RDS_SSL_INSTANCE_HOST }}
MB_MYSQL_SSL_TEST_ADDITIONAL_OPTIONS: 'verifyServerCertificate=true'
# the contents of the ./resources/certificates/rds-combined-ca-bundle.pem file
MB_MYSQL_SSL_TEST_SSL_CERT: ${{ secrets.MB_MYSQL_SSL_TEST_SSL_CERT }}
MB_MYSQL_SSL_TEST_USER: metabase
MB_MYSQL_SSL_TEST_PASSWORD: ${{ secrets.MYSQL_RDS_SSL_INSTANCE_PASSWORD }}
# for historic reasons (I don't want to mess around with required jobs) the job name should be something like
# "be-tests-mariadb-10-2-ee (0)"
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
steps:
- uses: actions/checkout@v4
- name: Test ${{ matrix.version.name }}
uses: ./.github/actions/test-driver
with:
build-static-viz: ${{ matrix.job.build-static-viz }}
junit-name: ${{ matrix.version.junit-name }}
test-args: >-
${{ matrix.job.test-args }}
:exclude-tags '[ ${{ matrix.job.exclude-tag }} ${{ env.__ADDITIONAL_EXCLUDED_TAG__ }}]'
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit/
output-name: ${{ github.job }}
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-postgres:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
version:
- name: Postgres 12.x
junit-name: postgres-ee
docker-image: postgres:12-alpine
env:
enable-ssl-tests: 'false'
- name: Postgres Latest
junit-name: postgres-latest-ee
docker-image: postgres:latest
env:
enable-ssl-tests: 'true'
job:
- name: Driver Tests
build-static-viz: false
test-args: >-
:only-tags [:mb/driver-tests]
- name: Enterprise Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test"'
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 1)
build-static-viz: true
test-args: >-
:only '"test"'
:exclude-tags [:mb/driver-tests]
:partition/total 2
:partition/index 0
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 2)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 1
exclude-tag: ':mb/driver-tests'
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
env:
# Only run old migrations tests on pushes to master or release branches. All other branches should skip tests
# with the tag `mb/old-migrations-test`. `__ADDITIONAL_EXCLUDED_TAG__` is not used anywhere outside of splicing
# it in to the command below.
__ADDITIONAL_EXCLUDED_TAG__: >-
${{
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
) &&
''
) ||
':mb/old-migrations-test'
}}
# actual serious env vars below
CI: 'true'
DRIVERS: postgres
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
MB_DB_HOST: localhost
MB_DB_DBNAME: mb_test
MB_DB_USER: mb_test
MB_POSTGRESQL_TEST_USER: mb_test
# SSL tests are only enabled for the postgres-latest job.
MB_POSTGRES_SSL_TEST_SSL: ${{ matrix.version.env.enable-ssl-tests }}
MB_POSTGRES_SSL_TEST_SSL_MODE: verify-full
MB_POSTGRES_SSL_TEST_SSL_ROOT_CERT_PATH: 'test-resources/certificates/us-east-2-bundle.pem'
services:
postgres:
image: ${{ matrix.version.docker-image }}
ports:
- "5432:5432"
env:
POSTGRES_USER: mb_test
POSTGRES_DB: mb_test
POSTGRES_HOST_AUTH_METHOD: trust
steps:
- uses: actions/checkout@v4
- name: Test ${{ matrix.version.name }} (${{ matrix.job.name }})
uses: ./.github/actions/test-driver
with:
build-static-viz: ${{ matrix.job.build-static-viz }}
junit-name: 'be-tests-${{ matrix.version.junit-name }}'
test-args: >-
${{ matrix.job.test-args }}
:exclude-tags '[ ${{ matrix.job.exclude-tag }} ${{ env.__ADDITIONAL_EXCLUDED_TAG__ }}]'
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit/
output-name: ${{ github.job }}
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
app-db-tests-result:
needs:
- be-tests-mariadb
- be-tests-mysql
- be-tests-postgres
runs-on: ubuntu-latest
timeout-minutes: 5
name: app-db-tests-result
if: always() && !cancelled()
steps:
- name: Check job status
uses: actions/github-script@v7
env:
needs: ${{ toJson(needs) }}
with:
script: | # js
const needs = JSON.parse(process.env.needs);
const jobs = Object.entries(needs).map(
([jobName, jobValues]) => ({
name: jobName,
result: jobValues.result
}));
// are all jobs skipped or successful?
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success'))) {
console.log("");
console.log(" _------. ");
console.log(" / , \_ ");
console.log(" / / /{}\ |o\_ ");
console.log(" / \ `--' /-' \ ");
console.log(" | \ \ | ");
console.log(" | |`-, | ");
console.log(" / /__/)/ ");
console.log(" | | ");
console.log("");
console.log("All app db tests have passed (or have been skipped). Cam is very proud of you.");
process.exit(0);
}
// otherwise, something failed
console.log("");
console.log(" .::::::::::. .::::::::::. ");
console.log(" .::::''''''::::. .::::''''''::::. ");
console.log(" .:::' `::::.... ....::::' `:::. ");
console.log(" .::' `:::::::| |:::::::' `::. ");
console.log(" .::| |::::::|_ ___ __|::::::| |::. ");
console.log(" `--' |::::::|_()__()_|::::::| `--' ");
console.log(" ::: |::-o::| |::o-::| ::: ");
console.log(" `::. .|::::::| |::::::|. .::' ");
console.log(" `:::. .::\-----' `-----/::. .:::' ");
console.log(" `::::......::::' `::::......::::' ");
console.log(" `::::::::::' `::::::::::' ");
console.log("");
console.log("App db tests have failed. You have been sentenced to MetaJail.");
jobs.forEach((job) => {
if (job.result !== 'success') {
console.log(`${job.name} - ${job.result}`);
}
});
process.exit(1);

View File

@@ -0,0 +1,21 @@
# Config is in .github/auto_request_review.yml
name: Auto Request Review
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
jobs:
auto-request-review:
# Don't run on forked repos
if: ${{ !github.event.pull_request.head.repo.fork }}
permissions:
contents: read
pull-requests: write
name: Auto Request Review
runs-on: ubuntu-latest
steps:
- name: Request review based on files changes and/or groups the author belongs to
uses: necojackarc/auto-request-review@v0.13.0
with:
token: '${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}'

View File

@@ -5,7 +5,6 @@ on:
types: [auto_merge_enabled, review_requested, labeled, unlabeled, synchronize]
branches:
- "master"
merge_group:
jobs:
backport-reminder:

View File

@@ -3,7 +3,6 @@ name: Prevent backport.sh from being merged
on:
pull_request:
types: [opened, synchronize, reopened]
merge_group:
jobs:
check-backport-script:

View File

@@ -1,21 +0,0 @@
name: Claude Assistant
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned, labeled]
pull_request_review:
types: [submitted]
jobs:
claude-response:
runs-on: ubuntu-latest
steps:
- run: git config --global --add safe.directory /__w/metabase/metabase
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,26 +0,0 @@
name: Test coverage
on:
schedule:
- cron: '40 1 * * *' # every day at 1:40
jobs:
fe-test-coverage:
runs-on: ubuntu-22.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Run frontend unit tests
run: yarn run test-unit --silent --coverage
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
flags: front-end
token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -5,19 +5,6 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- "resources/migrations/**"
workflow_dispatch:
inputs:
base-ref:
description: 'Base reference for the migration test'
required: true
type: string
head-ref:
description: 'Head reference for the migration test'
required: true
type: string
env:
BASE_REF: ${{ inputs.base-ref || github.base_ref }}
HEAD_REF: ${{ inputs.head-ref || github.head_ref }}
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
@@ -26,21 +13,19 @@ concurrency:
jobs:
migrations-h2-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: h2
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}
migrations-postgres-12-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: postgres
@@ -61,12 +46,11 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}
migrations-postgres-latest-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: postgres
@@ -87,12 +71,11 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}
migrations-mysql-8-0-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: mysql
@@ -109,12 +92,11 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}
migrations-mysql-latest-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: mysql
@@ -135,12 +117,11 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}
migrations-mariadb-10-2-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: mysql
@@ -157,12 +138,11 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}
migrations-mariadb-latest-ee:
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 5
env:
CI: 'true'
MB_DB_TYPE: mysql
@@ -179,5 +159,4 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
with:
base-ref: ${{ env.BASE_REF }}
head-ref: ${{ env.HEAD_REF }}
base-ref: ${{ github.base_ref }}

View File

@@ -18,15 +18,10 @@ jobs:
env:
SOURCE_BRANCH: ${{ github.head_ref || github.ref }}
TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
steps:
- name: Report changed docs files exist
run: |
echo "A PR with changes in the docs directory was detected."
echo "Sending workflow trigger to create/update the corresponding PR in docs repo."
echo "source branch: $SOURCE_BRANCH"
echo "target branch: $TARGET_BRANCH"
echo "pr number: $PR_NUMBER"
echo "A change in the docs directory was detected."
- name: Trigger repo dispatch
uses: actions/github-script@v7
@@ -38,7 +33,5 @@ jobs:
repo: "docs.metabase.github.io",
event_type: "docs_update",
client_payload: {
dispatch_type: "docs_update",
source_branch: process.env.SOURCE_BRANCH,
target_branch: process.env.TARGET_BRANCH,
pr_number: process.env.PR_NUMBER}});
target_branch: process.env.TARGET_BRANCH}});

View File

@@ -1,43 +0,0 @@
name: Docs Close Detected
on:
pull_request:
types:
- closed
branches:
- 'master'
- 'release-x.[0-9]+.x'
paths:
- 'docs/**'
jobs:
push_and_merge_workflow_to_docs_metabase_github_io_job:
if: github.event.pull_request.merged == false
runs-on: ubuntu-latest
env:
SOURCE_BRANCH: ${{ github.head_ref || github.ref }}
TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
steps:
- name: Report changed docs files exist
run: |
echo "A PR with changes to the docs directory was closed."
echo "Sending workflow trigger to close corresponding PR in docs repo."
echo "source branch: $SOURCE_BRANCH"
echo "target branch: $TARGET_BRANCH"
echo "pr number: $PR_NUMBER"
- name: Trigger repo dispatch
uses: actions/github-script@v7
with:
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
script: | #js
github.rest.repos.createDispatchEvent({
owner: "${{ github.repository_owner }}",
repo: "docs.metabase.github.io",
event_type: "docs_close",
client_payload: {
dispatch_type: "docs_close",
source_branch: process.env.SOURCE_BRANCH,
target_branch: process.env.TARGET_BRANCH,
pr_number: process.env.PR_NUMBER}});

View File

@@ -17,15 +17,10 @@ jobs:
env:
SOURCE_BRANCH: ${{ github.head_ref || github.ref }}
TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
steps:
- name: Report changed docs files exist
run: |
echo "A PR with changes to the docs directory was merged."
echo "Sending workflow trigger to merge corresponding PR in docs repo."
echo "source branch: $SOURCE_BRANCH"
echo "target branch: $TARGET_BRANCH"
echo "pr number: $PR_NUMBER"
- name: Trigger repo dispatch
uses: actions/github-script@v7
@@ -37,7 +32,5 @@ jobs:
repo: "docs.metabase.github.io",
event_type: "docs_merge",
client_payload: {
dispatch_type: "docs_merge",
source_branch: process.env.SOURCE_BRANCH,
target_branch: process.env.TARGET_BRANCH,
pr_number: process.env.PR_NUMBER}});
target_branch: process.env.TARGET_BRANCH}});

View File

@@ -12,38 +12,8 @@ concurrency:
cancel-in-progress: true
jobs:
# This job will determine if the tier 3 driver tests should be skipped.
# It will always run first.
determine-driver-skips:
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check_team_and_branch.outputs.skip }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check if tier3 drivers should run
id: check_team_and_branch
run: |
IS_MASTER_OR_RELEASE="${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-') }}"
HAS_TEAM_LABEL="${{ contains(github.event.pull_request.labels.*.name, '.Team/Drivers') || contains(github.event.pull_request.labels.*.name, '.Team/Querying') || contains(github.event.pull_request.labels.*.name, '.Team/SemanticLayer') }}"
echo "Is master or release: ${IS_MASTER_OR_RELEASE}"
echo "Has '.Team/Drivers' or '.Team/Querying' or '.Team/SemanticLayer' label: ${HAS_TEAM_LABEL}"
if [[ "${IS_MASTER_OR_RELEASE}" == "true" ]]; then
echo "skip=false" >> $GITHUB_OUTPUT
echo "Merging into master or a release branch. Tier 3 driver tests will run."
elif [[ "${HAS_TEAM_LABEL}" == "true" ]]; then
echo "skip=false" >> $GITHUB_OUTPUT
echo "A relevant team label is present. Tier 3 driver tests will run."
else
echo "skip=true" >> $GITHUB_OUTPUT
echo "Not labeled with required team and not merging into master/release. Tier 3 driver tests will be skipped."
fi
shell: bash
be-tests-athena-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -90,7 +60,6 @@ jobs:
MB_BIGQUERY_TEST_ACCESS_TOKEN: ${{ secrets.MB_BIGQUERY_TEST_ACCESS_TOKEN }}
MB_BIGQUERY_TEST_REFRESH_TOKEN: ${{ secrets.MB_BIGQUERY_TEST_REFRESH_TOKEN }}
MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON: ${{ secrets.MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON }}
MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON_ROUTING: ${{ secrets.MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON_ROUTING }}
name: BigQuery
steps:
- uses: actions/checkout@v4
@@ -160,8 +129,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-druid-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -196,8 +164,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-druid-jdbc-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -232,8 +199,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-databricks-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -267,8 +233,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-databricks-multi-catalog-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -349,7 +314,7 @@ jobs:
enable-ssl-tests: 'false'
- name: MySQL 8.0
junit-name: be-tests-mysql-8-0-ee
image: mysql:8.0
image: cimg/mysql:8.0
env:
enable-ssl-tests: 'false'
- name: MySQL Latest
@@ -359,8 +324,28 @@ jobs:
enable-ssl-tests: 'true'
job:
- name: Driver Tests
build-static-viz: false
test-args: >-
:only-tags [:mb/driver-tests]
- name: Enterprise Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test"'
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 1)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 0
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 2)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 1
exclude-tag: ':mb/driver-tests'
services:
mysql:
@@ -418,6 +403,7 @@ jobs:
- name: Test ${{ matrix.version.name }}
uses: ./.github/actions/test-driver
with:
build-static-viz: ${{ matrix.job.build-static-viz }}
junit-name: ${{ matrix.version.junit-name }}
test-args: >-
${{ matrix.job.test-args }}
@@ -435,8 +421,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-mongo:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
@@ -485,8 +470,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-mongo-ssl:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
@@ -550,8 +534,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-mongo-sharded-cluster-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -584,8 +567,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-oracle:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
@@ -675,8 +657,29 @@ jobs:
enable-ssl-tests: 'true'
job:
- name: Driver Tests
build-static-viz: false
test-args: >-
:only-tags [:mb/driver-tests]
- name: Enterprise Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test"'
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 1)
build-static-viz: true
test-args: >-
:only '"test"'
:exclude-tags [:mb/driver-tests]
:partition/total 2
:partition/index 0
exclude-tag: ':mb/driver-tests'
- name: EE App DB Tests (Part 2)
build-static-viz: true
test-args: >-
:only '"test"'
:partition/total 2
:partition/index 1
exclude-tag: ':mb/driver-tests'
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
env:
# Only run old migrations tests on pushes to master or release branches. All other branches should skip tests
@@ -721,6 +724,7 @@ jobs:
- name: Test ${{ matrix.version.name }} (${{ matrix.job.name }})
uses: ./.github/actions/test-driver
with:
build-static-viz: ${{ matrix.job.build-static-viz }}
junit-name: 'be-tests-${{ matrix.version.junit-name }}'
test-args: >-
${{ matrix.job.test-args }}
@@ -738,8 +742,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-presto-jdbc-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -868,10 +871,6 @@ jobs:
MB_SNOWFLAKE_TEST_WAREHOUSE: ${{ secrets.MB_SNOWFLAKE_TEST_WAREHOUSE }}
MB_SNOWFLAKE_TEST_PK_USER: METABASE PK
MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY }}
MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY_2: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY_2 }}
MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY }}
MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY_2: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY_2 }}
# RSA Role testing:
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_DEFAULT_USER: RSA_ROLE_TEST_DEFAULT_USER
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_CUSTOM_USER: RSA_ROLE_TEST_CUSTOM_USER
@@ -899,8 +898,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-sparksql-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -933,8 +931,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-sqlite-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -962,8 +959,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-sqlserver:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
@@ -1013,8 +1009,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-starburst-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
@@ -1051,8 +1046,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-vertica-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
env:

View File

@@ -5,7 +5,7 @@ on:
jobs:
files-changed:
name: "SDK cross-version E2E > Check which files changed"
name: Check which files changed
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
@@ -21,7 +21,6 @@ jobs:
# if this is a test on a release branch, we need to check the build requirements
get-build-requirements:
name: "SDK cross-version E2E > [Backport only] Get build requirements"
if: |
!cancelled()
runs-on: ubuntu-22.04
@@ -55,7 +54,6 @@ jobs:
};
build:
name: "SDK cross-version E2E > Build uberjar"
needs: [files-changed, get-build-requirements]
if: |
!cancelled()
@@ -87,7 +85,6 @@ jobs:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-cross-version
resolve-sdk-version:
name: "SDK cross-version E2E > Resolve SDK version"
if: |
!cancelled()
runs-on: ubuntu-22.04
@@ -120,21 +117,19 @@ jobs:
};
e2e-tests:
name: "SDK cross-version E2E > Run e2e tests"
needs: [get-build-requirements, build, resolve-sdk-version]
if: |
!cancelled() && needs.build.result == 'success'
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-tests-embedding-sdk
env:
MB_EDITION: ee
DISPLAY: ""
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
TZ: US/Pacific # to make node match the instance tz
@@ -143,6 +138,12 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Prepare Docker containers
uses: ./.github/actions/e2e-prepare-containers
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Needed to omit newly added tests for functionality that is not yet released
- name: Sparse checkout tests from SDK release commit
uses: actions/checkout@v4
@@ -228,3 +229,15 @@ jobs:
const summary = formatSummary(results);
await core.summary.addRaw(summary).write();
e2e-tests-skipped-stub:
needs: [e2e-tests]
if: |
!cancelled() &&
needs.e2e-tests.result == 'skipped'
runs-on: ubuntu-22.04
timeout-minutes: 5
name: e2e-component-tests-embedding-sdk-cross-version
steps:
- run: |
echo "Didn't run due to conditional filtering"

View File

@@ -9,11 +9,11 @@ on:
jobs:
files-changed:
name: "SDK e2e > Check which files changed"
name: Check which files changed
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
e2e_all: ${{ steps.changes.outputs.e2e_all }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
@@ -25,7 +25,6 @@ jobs:
# if this is a test on a release branch, we need to check the build requirements
get-build-requirements:
name: "SDK e2e > [Backport only] Get build requirements"
if: |
!cancelled() &&
contains(github.base_ref || github.ref, 'release-x')
@@ -60,11 +59,10 @@ jobs:
};
build-uberjar:
name: "SDK e2e > Build uberjar"
needs: [files-changed, get-build-requirements]
if: |
!cancelled() &&
needs.files-changed.outputs.e2e_embedding_sdk == 'true'
needs.files-changed.outputs.e2e_all == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 25
env:
@@ -92,10 +90,9 @@ jobs:
- name: Prepare uberjar artifact
uses: ./.github/actions/prepare-uberjar-artifact
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-sdk-tests
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
e2e-tests:
name: "SDK e2e > Run e2e tests (React ${{ matrix.react-version }})"
needs: [get-build-requirements, build-uberjar]
if: |
!cancelled() &&
@@ -106,17 +103,16 @@ jobs:
matrix:
react-version: [18, 19]
fail-fast: false
name: React ${{ matrix.react-version }}
env:
MB_EDITION: ee
DISPLAY: ""
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
CYPRESS_IS_EMBEDDING_SDK: "true"
CYPRESS_IS_EMBEDDING_SDK: true
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
@@ -124,10 +120,16 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Prepare Docker containers
uses: ./.github/actions/e2e-prepare-containers
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Retrieve uberjar artifact for ee
uses: actions/download-artifact@v4
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-sdk-tests
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
@@ -178,7 +180,7 @@ jobs:
aws-region: ${{ vars.AWS_REGION }}
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
- name: "SDK e2e > Upload Cypress Artifacts upon failure"
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4
if: failure()
with:
@@ -188,7 +190,7 @@ jobs:
./logs/test.log
if-no-files-found: ignore
- name: "SDK e2e > Publish Summary"
- name: Publish Summary
if: failure()
uses: actions/github-script@v7
with:

View File

@@ -1,6 +1,4 @@
name: E2E cross-version for breaking changes
# See `bin/backward-compatibility-test.js` for the documentation of this workflow.
name: E2E Cross-version Tests
on:
workflow_dispatch:
@@ -38,7 +36,6 @@ on:
jobs:
generate-matrix:
name: "Breaking changes E2E > Generate matrix"
runs-on: ubuntu-latest
outputs:
matrix_json: ${{ steps.set_matrix.outputs.matrix_json }}
@@ -63,7 +60,6 @@ jobs:
TOTAL_SHARDS_INPUT: ${{ inputs.total-shards }}
build-jar:
name: "Breaking changes E2E > Build jar"
runs-on: ubuntu-22.04
timeout-minutes: 45
@@ -100,7 +96,6 @@ jobs:
if-no-files-found: error
run-breaking-changes-tests:
name: "Breaking changes E2E > Run breaking changes tests"
needs: [build-jar, generate-matrix]
runs-on: ubuntu-22.04
timeout-minutes: 45
@@ -148,10 +143,8 @@ jobs:
- name: Run the tests
env:
MB_EDITION: ee
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
CYPRESS_CI: true
run: |
node bin/backward-compatibility-test.js \

View File

@@ -66,10 +66,8 @@ jobs:
docker run -d \
-v $PWD/my-metabase:/metabase.db \
-p 3000:3000 \
-e CYPRESS_MB_ALL_FEATURES_TOKEN=${{ secrets.MB_ALL_FEATURES_TOKEN }} \
-e CYPRESS_MB_STARTER_CLOUD_TOKEN=${{ secrets.MB_STARTER_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_CLOUD_TOKEN=${{ secrets.MB_PRO_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_SELF_HOSTED_TOKEN=${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }} \
-e CYPRESS_ALL_FEATURES_TOKEN=${{ secrets.ENTERPRISE_TOKEN }} \
-e CYPRESS_NO_FEATURES_TOKEN=${{ secrets.E2E_STARTER_TOKEN }} \
--name metabase-${{ matrix.version.source }} \
${{ env.DOCKER_SOURCE_IMAGE }}
- name: Wait for Metabase to start on port 3000
@@ -99,10 +97,8 @@ jobs:
docker run -d \
-v $PWD/my-metabase:/metabase.db \
-p 3001:3000 \
-e CYPRESS_MB_ALL_FEATURES_TOKEN=${{ secrets.MB_ALL_FEATURES_TOKEN }} \
-e CYPRESS_MB_STARTER_CLOUD_TOKEN=${{ secrets.MB_STARTER_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_CLOUD_TOKEN=${{ secrets.MB_PRO_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_SELF_HOSTED_TOKEN=${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }} \
-e CYPRESS_ALL_FEATURES_TOKEN=${{ secrets.ENTERPRISE_TOKEN }} \
-e CYPRESS_NO_FEATURES_TOKEN=${{ secrets.E2E_STARTER_TOKEN }} \
--name metabase-${{ matrix.version.target }} \
${{ env.DOCKER_TARGET_IMAGE }}
- name: Wait for Metabase to start on port 3001

View File

@@ -1,4 +1,4 @@
name: "[NOT REQUIRED] SDK Compatibility tests"
name: E2E Embedding SDK Compatibility tests
on:
push:
@@ -191,12 +191,6 @@ jobs:
name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
path: resources/embedding-sdk
# In order to check compatibility between Sample Apps and Embedding SDK, the job for each sample app:
# - pulls a Sample App
# - starts it
# - runs its Cypress tests against the local metabase.jar and local @metabase/embedding-sdk-react package.
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
# For more details see `Sample Apps compatibility with Embedding SDK tests` in `enterprise/frontend/src/embedding-sdk/dev.md`
e2e-sample-apps-tests:
needs: [get-build-requirements, get-sample-apps-data, build]
strategy:
@@ -214,8 +208,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_IS_EMBEDDING_SDK: "true"
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_IS_EMBEDDING_SDK: true
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
SAMPLE_APP_BRANCH_NAME: ${{ needs.get-sample-apps-data.outputs.branch_name }}
@@ -314,25 +308,17 @@ jobs:
run: |
exit 1
# The job checks integration of the Embedding SDK with consumer's apps that use different frameworks/bundlers,
# or when we want to test some tricky integration cases like conflicting types.
# The job
# - starts an app
# - runs its Cypress tests against the e2e test metabase instance and local @metabase/embedding-sdk-react package.
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk/dev.md`
e2e-host-apps-tests:
needs: [get-build-requirements, build]
needs: [ get-build-requirements, build ]
strategy:
matrix:
test_suite:
[
"vite-6-host-app-e2e",
"next-15-app-router-host-app-e2e",
"next-15-pages-router-host-app-e2e",
"angular-20-host-app-e2e",
]
environment: ["production", "development"]
test_suite: [
"vite-6-host-app-e2e",
"next-15-app-router-host-app-e2e",
"next-15-pages-router-host-app-e2e",
"angular-20-host-app-e2e",
]
environment: [ "production", "development" ]
if: |
!cancelled() && needs.build.result == 'success'
runs-on: ubuntu-22.04
@@ -344,8 +330,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_IS_EMBEDDING_SDK: "true"
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_IS_EMBEDDING_SDK: true
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
HOST_APP_ENVIRONMENT: ${{ matrix.environment }}

View File

@@ -63,10 +63,8 @@ jobs:
DISPLAY: ""
QA_DB_ENABLED: ${{ contains(fromJSON('["sql", "mongo"]'), inputs.qa_db) }}
CYPRESS_QA_DB_MONGO: ${{ inputs.qa_db == 'mongo' }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
MB_SNOWPLOW_AVAILABLE: true
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
MB_EDITION: ${{ inputs.mb_edition }}
@@ -86,7 +84,6 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
maildev: true
openldap: true
snowplow: true
postgres: ${{ inputs.qa_db == 'sql' }}
mysql: ${{ inputs.qa_db == 'sql' }}
mongo: ${{ inputs.qa_db == 'mongo' }}
@@ -106,6 +103,8 @@ jobs:
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Run Snowplow micro
uses: ./.github/actions/run-snowplow-micro
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Generate database snapshots

View File

@@ -44,10 +44,8 @@ jobs:
JOB_NAME: ${{ inputs.name }}
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
MB_EXPERIMENTAL_SEARCH_BLOCK_ON_QUEUE: true
@@ -57,7 +55,13 @@ jobs:
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
CYPRESS_QA_DB_MONGO: ${{ inputs.name == 'mongo' }}
CYPRESS_IS_EMBEDDING_SDK: "${{ inputs.name == 'embedding-sdk' }}"
CYPRESS_IS_EMBEDDING_SDK: ${{ inputs.name == 'embedding-sdk' }}
mongo: ${{ inputs.name == 'mongo' }}
postgres: ${{ inputs.name != 'mongo' }}
mysql: ${{ inputs.name != 'mongo' }}
openldap: true
maildev: true
webhook: true
steps:
- uses: actions/checkout@v4
@@ -67,12 +71,11 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
maildev: true
openldap: true
webhook: true
snowplow: true
postgres: ${{ inputs.name != 'mongo' }}
mysql: ${{ inputs.name != 'mongo' }}
mongo: ${{ inputs.name == 'mongo' }}
openldap: ${{ env.openldap }}
postgres: ${{ env.postgres }}
mysql: ${{ env.mysql }}
mongo: ${{ env.mongo }}
webhook: ${{ env.webhook }}
- name: Run Embedding SDK Storybook
if: inputs.name == 'embedding-sdk'
@@ -108,6 +111,9 @@ jobs:
if: github.run_attempt != '1'
run: echo "specs=$(cat failed-specs)" >> $GITHUB_ENV
- name: Run Snowplow micro
uses: ./.github/actions/run-snowplow-micro
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start

View File

@@ -1,7 +1,12 @@
name: SDK
name: Embedding SDK
on:
workflow_call:
push:
branches:
- "master"
- "release-**"
pull_request:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
@@ -13,9 +18,8 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
documentation: ${{ steps.changes.outputs.documentation }}
frontend_embedding_sdk_sources: ${{ steps.changes.outputs.frontend_embedding_sdk_sources }}
embedding_documentation: ${{ steps.changes.outputs.embedding_documentation }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
@@ -29,9 +33,8 @@ jobs:
needs: [files-changed]
if: |
!cancelled() &&
(needs.files-changed.outputs.e2e_embedding_sdk == 'true' ||
needs.files-changed.outputs.frontend_embedding_sdk_sources == 'true' ||
needs.files-changed.outputs.embedding_documentation == 'true')
(needs.files-changed.outputs.frontend_embedding_sdk_sources == 'true' ||
needs.files-changed.outputs.documentation == 'true')
runs-on: ubuntu-22.04
timeout-minutes: 25
steps:
@@ -72,7 +75,7 @@ jobs:
embedding-sdk-docs-snippets-type-check:
needs: [files-changed, build]
if: |
needs.files-changed.outputs.embedding_documentation == 'true' &&
needs.files-changed.outputs.documentation == 'true' &&
needs.build.result == 'success'
runs-on: ubuntu-22.04
timeout-minutes: 20
@@ -124,7 +127,7 @@ jobs:
with:
remove-previous-comment: true
add-new-comment: ${{ steps.docs-generation.outcome == 'failure' && contains(steps.docs-generation.outputs.output, 'not included in the documentation') }}
message: "📝 Some exported types from `@metabase/embedding-sdk-react` reference other types that are not exported, i.e. internal types.<br><br>The internal type reference breaks API documentation generation for the SDK and also may unexpectedly increase the output size of the type declaration file.<br><br>Please check the CI logs to find the name of such type.<br><br>- If a type should be publicly available in the SDK, add a description to it or a TypeDoc annotation and export it from SDK.<br>- If a type is internal and should _not_ be publicly exposed, refactor types to prevent referencing other types that are not exported from SDK.<br><br>You can run `yarn embedding-sdk:docs:generate` locally to verify that the issue has been resolved."
message: "📝 Some exported from `@metabase/embedding-sdk-react` types reference other types that are not exported, i.e. internal types.<br><br>The internal type reference breaks API documentation generation for the SDK and also may unexpectedly increase the output size of the type declaration file.<br><br>Please check the CI logs to find the name of such type.<br><br>- If a type should be publicly available in the SDK, add a description to it or a TypeDoc annotation and export it from SDK.<br>- If a type is internal and should _not_ be publicly exposed, refactor types to prevent referencing other types that are not exported from SDK.<br><br>You can run `yarn embedding-sdk:docs:generate` locally to verify that the issue has been resolved."
include-log: true
- name: Comment on PR if 'Failed to resolve link' error happens
uses: ./.github/actions/notify-pull-request
@@ -137,9 +140,7 @@ jobs:
if: ${{ steps.docs-generation.outcome == 'failure' }}
run: exit 1
# See `Component e2e tests` in `enterprise/frontend/src/embedding-sdk/dev.md`
sdk-e2e-tests:
name: "SDK e2e tests"
uses: ./.github/workflows/e2e-component-tests-embedding-sdk.yml
needs: [build]
secrets: inherit
@@ -147,23 +148,19 @@ jobs:
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
e2e-component-tests-embedding-sdk-cross-version:
name: "[Backport only] SDK e2e cross version tests"
# run on: every push on release branches, and every pr that targets a release branch
if: ${{ startsWith(github.ref, 'refs/heads/release-x.') || (github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.')) }}
uses: ./.github/workflows/e2e-component-tests-embedding-sdk-cross-version.yml
secrets: inherit
# Temporarily skipped because the cypress runner crashes
# See `bin/backward-compatibility-test.js` for the documentation of this workflow.
# cross-version-for-breaking-changes:
# name: "[NOT REQUIRED - Experimental - Backport only] detect breaking changes with cross versions tests"
# # run on: every pr that targets a release branch, it does NOT run for pr targeting master
# if: ${{ github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.') }}
# uses: ./.github/workflows/e2e-cross-version-for-breaking-changes.yml
# secrets: inherit
# with:
# fe-ref: ${{ github.base_ref }}
# be-ref: ${{ github.head_ref }}
cross-version-for-breaking-changes:
# run on: every pr that targets a release branch
if: ${{ github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.') }}
uses: ./.github/workflows/e2e-cross-version-for-breaking-changes.yml
secrets: inherit
with:
fe-ref: ${{ github.base_ref }}
be-ref: ${{ github.head_ref }}
embedding-sdk-tests-result:
needs:

View File

@@ -63,13 +63,8 @@ jobs:
fe-tests-unit:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
shard: [1, 2]
timeout-minutes: 60
env:
SHARDS: 2 # should match matrix above
JEST_JUNIT_OUTPUT_DIR: ./target/junit
JEST_JUNIT_OUTPUT_NAME: test-report-frontend-unit.xml
steps:
@@ -80,8 +75,19 @@ jobs:
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Run frontend unit tests and collect the code coverage information
if: github.ref_name == 'master'
run: yarn run test-unit --coverage --silent
- name: Run frontend unit tests
run: yarn run test-unit --silent --shard=${{ matrix.shard }}/${{ env.SHARDS }}
if: github.ref_name != 'master'
run: yarn run test-unit --silent
- name: Upload coverage to codecov.io
if: github.ref_name == 'master'
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
flags: front-end
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()

View File

@@ -1,8 +1,6 @@
name: Loki Visual Regression Testing
on:
pull_request:
merge_group:
on: [pull_request]
jobs:
files-changed:

View File

@@ -1,132 +0,0 @@
name: Auto-Optimize Docs PNG Images
on:
push:
paths:
- 'docs/**/*.png'
jobs:
optimize-images:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install pngcrush and bc
run: |
sudo apt-get update
sudo apt-get install -y pngcrush bc
- name: Get changed PNG files
id: changed-files
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46
with:
files: |
docs/**/*.png
- name: Optimize changed PNG files
if: steps.changed-files.outputs.any_changed == 'true'
id: optimize
run: |
echo "Optimizing PNG files with pngcrush..."
echo "Branch:" $(git_current_branch)
# Initialize tracking variables
total_files=0
total_before=0
total_after=0
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
echo "Processing: $file"
before_size=$(stat -c%s "$file")
# Use pngcrush with maximum lossless compression settings
# -rem alla removes all ancillary chunks (metadata)
# -brute tries all filter types and compression levels
# -ow overwrites the original file
pngcrush -rem alla -brute -ow "$file"
after_size=$(stat -c%s "$file")
echo " > Before: ${before_size} bytes, After: ${after_size} bytes"
# Track totals
total_files=$((total_files + 1))
total_before=$((total_before + before_size))
total_after=$((total_after + after_size))
done
# Calculate savings
total_saved=$((total_before - total_after))
# Output results for use in commit message
echo "files_optimized=${total_files}" >> "$GITHUB_OUTPUT"
echo "bytes_saved=${total_saved}" >> "$GITHUB_OUTPUT"
echo "total_before=${total_before}" >> "$GITHUB_OUTPUT"
echo "total_after=${total_after}" >> "$GITHUB_OUTPUT"
echo "Optimization complete"
echo "Files processed: ${total_files}"
echo "Total bytes saved: ${total_saved} (${total_before} -> ${total_after})"
- name: Check for changes after optimization
if: steps.changed-files.outputs.any_changed == 'true'
id: check_changes
run: |
git add ${{ steps.changed-files.outputs.all_changed_files }}
if git diff --quiet --cached; then
echo "has_changes=false" >> "$GITHUB_OUTPUT"
echo "No changes detected after optimization"
else
echo "has_changes=true" >> "$GITHUB_OUTPUT"
echo "Changes detected after optimization"
git diff --cached --stat
fi
- name: Commit optimized images
if: steps.changed-files.outputs.any_changed == 'true' && steps.check_changes.outputs.has_changes == 'true'
env:
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
run: |
git config --global user.email "github-automation@metabase.com"
git config --global user.name "Metabase Automation"
git add docs/**/*.png
# Format bytes saved for human readability
bytes_saved="${{ steps.optimize.outputs.bytes_saved }}"
bytes_before="${{ steps.optimize.outputs.total_before }}"
if [ "$bytes_saved" -gt 1048576 ]; then
# Convert to MB
size_saved=$(echo "scale=1; $bytes_saved / 1048576" | bc)
size_unit="MB"
elif [ "$bytes_saved" -gt 1024 ]; then
# Convert to KB
size_saved=$(echo "scale=1; $bytes_saved / 1024" | bc)
size_unit="KB"
else
size_saved="$bytes_saved"
size_unit="bytes"
fi
# Calculate percentage reduction
if [ "$bytes_before" -gt 0 ]; then
percentage=$(echo "scale=1; $bytes_saved * 100 / $bytes_before" | bc)
git commit -m "Optimized ${{ steps.optimize.outputs.files_optimized }} images, saved ${size_saved} ${size_unit} (${percentage}% smaller)"
else
git commit -m "Optimized ${{ steps.optimize.outputs.files_optimized }} images, saved ${size_saved} ${size_unit}"
fi
git push
echo 'Files optimized:'
echo ${{ steps.changed-files.outputs.all_changed_files }}
echo 'Applied: pngcrush -rem alla -brute -ow'
- name: Output summary
if: steps.changed-files.outputs.any_changed == 'true'
run: |
if [ "${{ steps.check_changes.outputs.has_changes }}" = "false" ]; then
echo "PNG files were already optimized - no changes needed"
else
echo "PNG files optimized and committed successfully"
fi

View File

@@ -103,14 +103,8 @@ jobs:
env:
MB_EDITION: ${{ matrix.edition }}
DISPLAY: ""
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
# these are needed for backwards compatibility with release branches earlier than v55, since
# this workflow always runs from master, but we run tests from the release branch
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
# disabled because of out of memory issues
# probably related to https://github.com/cypress-io/cypress/issues/27415
CYPRESS_NO_COMMAND_LOG: 1
@@ -128,7 +122,6 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
maildev: true
snowplow: true
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare JDK 21
@@ -139,6 +132,8 @@ jobs:
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Run Snowplow micro
uses: ./.github/actions/run-snowplow-micro
- uses: actions/download-artifact@v4
name: Retrieve uberjar artifact for ${{ matrix.edition }}
with:

View File

@@ -250,9 +250,19 @@ jobs:
- name: Tag the docker image
run: | # sh
docker buildx imagetools create --tag \
$DOCKERHUB_REPO\:$TAG_NAME \
$DOCKERHUB_REPO\:$DOCKERHUB_VERSION
docker pull $DOCKERHUB_REPO\:$DOCKERHUB_VERSION
docker tag $DOCKERHUB_REPO\:$DOCKERHUB_VERSION $DOCKERHUB_REPO\:$TAG_NAME
docker image ls $DOCKERHUB_REPO
SOURCE_ID=$(docker image ls $DOCKERHUB_REPO\:$DOCKERHUB_VERSION -q)
TAGGED_ID=$(docker image ls $DOCKERHUB_REPO\:$TAG_NAME -q)
if [[ $SOURCE_ID != $TAGGED_ID ]]; then
echo "Error tagging docker image"
exit 1
fi
docker push $DOCKERHUB_REPO\:$TAG_NAME
push-git-tags:
permissions: write-all

View File

@@ -7,7 +7,6 @@ on:
- "release-**"
pull_request:
types: [opened, synchronize, reopened]
merge_group:
jobs:
files-changed:
@@ -72,13 +71,6 @@ jobs:
with:
skip: ${{ needs.files-changed.outputs.backend_all != 'true' && needs.static-viz-files-changed.outputs.static_viz != 'true' }}
app-db-tests:
needs: files-changed
uses: ./.github/workflows/app-db.yml
secrets: inherit
with:
skip: ${{ needs.files-changed.outputs.backend_all != 'true' }}
driver-tests:
needs: files-changed
uses: ./.github/workflows/drivers.yml
@@ -105,8 +97,3 @@ jobs:
# e2e_all_files includes all changes which trigger all e2e tests, if the list of changes files is included in the
# list of changed specs files, then only specs are changed and we can run only those specs
specs: ${{ needs.files-changed.outputs.e2e_all_files == needs.files-changed.outputs.e2e_specs_files && needs.files-changed.outputs.e2e_specs_files || '' }}
sdk-tests:
needs: files-changed
uses: ./.github/workflows/embedding-sdk.yml
secrets: inherit

View File

@@ -43,7 +43,6 @@ jobs:
command_args: |
--config locales/crowdin.yml
-e=el
-e=et
-e=es-MX
-e=gu-IN
-e=hr

View File

@@ -10,7 +10,6 @@ on:
- metabot-v3-main
- feature-visualizer
- internal-tools
- viz-1048-only-visualizer-compatible
paths-ignore:
# config files
- ".**"
@@ -21,8 +20,6 @@ on:
- "**test/**"
- "**_test.clj"
- "**/frontend/**.unit.*"
pull_request:
types: [labeled, opened, synchronize, reopened]
workflow_dispatch:
inputs:
commit:
@@ -33,8 +30,6 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 5
name: Get container info
# Skip if this is a PR without the build-docker-uberjar label
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar')
outputs:
editions: ${{ toJson(fromJson(steps.info.outputs.result).editions) }}
ee: ${{ toJson(fromJson(steps.info.outputs.result).ee) }}

View File

@@ -6,7 +6,6 @@ on:
- 'master'
- 'release-**'
pull_request:
merge_group:
jobs:
whitespace-linter:

2
.gitignore vendored
View File

@@ -36,7 +36,6 @@
/coverage
/crate-*
/cypress
cypress.env.json
/deploy/artifacts/*
/docs/**/node_modules
/docs/**/package.json
@@ -147,7 +146,6 @@ llm-payloads
.aider*
/config.yml
CLAUDE.local.md
.claude/settings.local.json
.eslintcache

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Some files were not shown because too many files have changed in this diff Show More