Compare commits

..

2 Commits

Author SHA1 Message Date
Chris Truter
2076d909d9 Run the tests please 2026-03-16 16:23:48 +02:00
Chris Truter
b2c2816d86 Switch branch of python-runner-container 2026-03-16 16:12:41 +02:00
2048 changed files with 17093 additions and 72204 deletions

View File

@@ -1,173 +0,0 @@
---
name: clojure-eval
description: Evaluate Clojure code via nREPL using clj-nrepl-eval. Use this when you need to test code, check if edited files compile, verify function behavior, or interact with a running REPL session.
---
# Clojure REPL Evaluation
## When to Use This Skill
Use this skill when you need to:
- **Verify that edited Clojure files compile and load correctly**
- Test function behavior interactively
- Check the current state of the REPL
- Debug code by evaluating expressions
- Require or load namespaces for testing
- Validate that code changes work before committing
## How It Works
The `clj-nrepl-eval` command evaluates Clojure code against an nREPL server. **Session state persists between evaluations**, so you can require a namespace in one evaluation and use it in subsequent calls. Each host:port combination maintains its own session file.
## Instructions
### 0. Discover and select nREPL server
First, discover what nREPL servers are running in the current directory:
```bash
clj-nrepl-eval --discover-ports
```
This will show all nREPL servers (Clojure, Babashka, shadow-cljs, etc.) running in the current project directory.
**Then use the AskUserQuestion tool:**
- **If ports are discovered:** Prompt user to select which nREPL port to use:
- **question:** "Which nREPL port would you like to use?"
- **header:** "nREPL Port"
- **options:** Present each discovered port as an option with:
- **label:** The port number
- **description:** The server type and status (e.g., "Clojure nREPL server in current directory")
- Include up to 4 discovered ports as options
- The user can select "Other" to enter a custom port number
- **If no ports are discovered:** Prompt user how to start an nREPL server:
- **question:** "No nREPL servers found. How would you like to start one?"
- **header:** "Start nREPL"
- **options:**
- **label:** "deps.edn alias", **description:** "Find and use an nREPL alias in deps.edn"
- **label:** "Leiningen", **description:** "Start nREPL using 'lein repl'"
- The user can select "Other" for alternative methods or if they already have a server running on a specific port
IMPORTANT: IF you start a REPL do not supply a port let the nREPL start and return the port that it was started on.
### 1. Evaluate Clojure Code
> Evaluation automatically connects to the given port
Use the `-p` flag to specify the port and pass your Clojure code.
**Recommended: Pass code as a command-line argument:**
```bash
clj-nrepl-eval -p <PORT> "(+ 1 2 3)"
```
**For multiple expressions (single line):**
```bash
clj-nrepl-eval -p <PORT> "(def x 10) (+ x 20)"
```
**Alternative: Using heredoc (may require permission approval for multiline commands):**
```bash
clj-nrepl-eval -p <PORT> <<'EOF'
(def x 10)
(+ x 20)
EOF
```
**Alternative: Via stdin pipe:**
```bash
echo "(+ 1 2 3)" | clj-nrepl-eval -p <PORT>
```
### 2. Display nREPL Sessions
**Discover all nREPL servers in current directory:**
```bash
clj-nrepl-eval --discover-ports
```
Shows all running nREPL servers in the current project directory, including their type (clj/bb/basilisp) and whether they match the current working directory.
**Check previously connected sessions:**
```bash
clj-nrepl-eval --connected-ports
```
Shows only connections you have made before (appears after first evaluation on a port).
### 3. Common Patterns
**Require a namespace (always use :reload to pick up changes):**
```bash
clj-nrepl-eval -p <PORT> "(require '[my.namespace :as ns] :reload)"
```
**Test a function after requiring:**
```bash
clj-nrepl-eval -p <PORT> "(ns/my-function arg1 arg2)"
```
**Check if a file compiles:**
```bash
clj-nrepl-eval -p <PORT> "(require 'my.namespace :reload)"
```
**Multiple expressions:**
```bash
clj-nrepl-eval -p <PORT> "(def x 10) (* x 2) (+ x 5)"
```
**Complex multiline code (using heredoc):**
```bash
clj-nrepl-eval -p <PORT> <<'EOF'
(def x 10)
(* x 2)
(+ x 5)
EOF
```
*Note: Heredoc syntax may require permission approval.*
**With custom timeout (in milliseconds):**
```bash
clj-nrepl-eval -p <PORT> --timeout 5000 "(long-running-fn)"
```
**Reset the session (clears all state):**
```bash
clj-nrepl-eval -p <PORT> --reset-session
clj-nrepl-eval -p <PORT> --reset-session "(def x 1)"
```
## Available Options
- `-p, --port PORT` - nREPL port (required)
- `-H, --host HOST` - nREPL host (default: 127.0.0.1)
- `-t, --timeout MILLISECONDS` - Timeout (default: 120000 = 2 minutes)
- `-r, --reset-session` - Reset the persistent nREPL session
- `-c, --connected-ports` - List previously connected nREPL sessions
- `-d, --discover-ports` - Discover nREPL servers in current directory
- `-h, --help` - Show help message
## Important Notes
- **Prefer command-line arguments:** Pass code as quoted strings: `clj-nrepl-eval -p <PORT> "(+ 1 2 3)"` - works with existing permissions
- **Heredoc for complex code:** Use heredoc (`<<'EOF' ... EOF`) for truly multiline code, but note it may require permission approval
- **Sessions persist:** State (vars, namespaces, loaded libraries) persists across invocations until the nREPL server restarts or `--reset-session` is used
- **Automatic delimiter repair:** The tool automatically repairs missing or mismatched parentheses
- **Always use :reload:** When requiring namespaces, use `:reload` to pick up recent changes
- **Default timeout:** 2 minutes (120000ms) - increase for long-running operations
- **Input precedence:** Command-line arguments take precedence over stdin
## Typical Workflow
1. Discover nREPL servers: `clj-nrepl-eval --discover-ports`
2. Use **AskUserQuestion** tool to prompt user to select a port
3. Require namespace:
```bash
clj-nrepl-eval -p <PORT> "(require '[my.ns :as ns] :reload)"
```
4. Test function:
```bash
clj-nrepl-eval -p <PORT> "(ns/my-fn ...)"
```
5. Iterate: Make changes, re-require with `:reload`, test again

View File

@@ -1,834 +0,0 @@
---
name: emotion-migrate
description: Migrate Emotion styled-components to Mantine components with style props and CSS modules. Use when converting .styled.tsx files or removing @emotion imports from components.
---
# Emotion → Mantine + CSS Modules Migration Skill
Migrate Emotion styled-components (`@emotion/styled`, `@emotion/react`) to Mantine layout components with style props and CSS modules. The goal is zero Emotion imports, zero inline styles, and maximum use of design system tokens.
## Priority Order (Strict)
1. **Mantine components + style props** — `Box`, `Flex`, `Stack`, `Group`, `Text`, `Title`, `Card`. This is the DEFAULT. Every CSS property must be checked against style props FIRST.
2. **CSS modules** (`.module.css`) — ONLY for properties that Mantine style props genuinely cannot express: pseudo-selectors (`:hover`, `:focus`, `::before`), `box-shadow`, `border` shorthand, `animation`/`@keyframes`, complex selectors, `cursor`, `pointer-events`, `overflow`, `text-overflow`, `white-space`, `transition`.
3. **Inline styles ONLY for dynamic values** — `style={{ }}` is allowed only for truly dynamic runtime values (e.g., computed widths, positions, data-driven colors). All static styles must use Mantine props or CSS modules.
### Mantine-First Decision Gate (CRITICAL)
For EACH styled component, go through every CSS property and ask: "Can this be a Mantine style prop?" If yes → style prop. If no → CSS module. Do NOT dump an entire component into a CSS module just because one property needs it — split them.
**Properties that ARE style props** (use these, not CSS modules):
- `display` → `display` prop
- `color` → `c` prop (`c="brand"`, `c="text-primary"`)
- `background-color` → `bg` prop (`bg="background-primary"`)
- `font-size` → `fz` prop (`fz="md"`)
- `font-weight` → `fw` prop (`fw="bold"`)
- `line-height` → `lh` prop (`lh="md"`)
- `text-align` → `ta` prop (`ta="center"`)
- `padding` (all variants) → `p`, `px`, `py`, `pt`, `pb`, `pl`, `pr`
- `margin` (all variants) → `m`, `mx`, `my`, `mt`, `mb`, `ml`, `mr`
- `width` → `w`, `min-width` → `miw`, `max-width` → `maw`
- `height` → `h`, `min-height` → `mih`, `max-height` → `mah`
- `flex` → `flex` prop (`flex="0 0 auto"`, `flex={1}`)
- `gap` → `gap` prop (on Flex/Stack/Group)
- `align-items` → `align` prop (on Flex/Stack/Group)
- `justify-content` → `justify` prop (on Flex/Stack/Group)
- `flex-direction` → `direction` prop (on Flex)
- `flex-wrap` → `wrap` prop (on Flex)
- `position` → `pos` prop
- `top/right/bottom/left` → `top`, `right`, `bottom`, `left` props
- `opacity` → `opacity` prop
**Properties that NEED CSS modules** (no style prop equivalent):
- `:hover`, `:focus`, `:active`, `::before`, `::after` (pseudo-selectors)
- `box-shadow`, `border` (shorthand with color), `outline`
- `cursor`, `pointer-events`
- `overflow`, `text-overflow`, `white-space`
- `animation`, `transition`, `transform`
- `@media` queries (UNLESS it's simple responsive spacing/sizing — then use responsive syntax: `p={{ base: "md", lg: "xl" }}`)
**Hybrid approach** — when a component needs BOTH, put style props on the Mantine component AND add a CSS module class for the rest:
```tsx
<Flex
className={S.root} /* for :hover, box-shadow, border */
align="center" /* style prop */
gap="sm" /* style prop */
p="md" /* style prop */
bg="background-primary" /* style prop */
>
```
## CSS Module Conventions (Strict)
### Class Naming: camelCase
All CSS module class names MUST use **camelCase**. This is the dominant convention across the codebase (~830 camelCase vs ~620 PascalCase classes), used consistently in Mantine UI components, and matches standard CSS module conventions.
```css
/* CORRECT */
.root {
}
.settingsSection {
}
.dragHandle {
}
.closeIcon {
}
/* WRONG — do not use PascalCase or kebab-case */
.ItemRoot {
}
.settings-section {
}
```
Modifier/state classes also use camelCase:
```css
.selected {
}
.disabled {
}
.interactive {
}
.draggable {
}
```
### No Cascading — Direct Class Assignment
Cascading selectors are **discouraged**. Instead of styling through parent-child relationships, assign a class directly to the element that needs styling.
```css
/* WRONG — cascading/descendant selectors */
.root > input {
}
.root .label {
}
.container > div > span {
}
/* CORRECT — direct class on the target element */
.input {
}
.label {
}
.title {
}
```
The only acceptable nesting patterns are:
- **Pseudo-selectors on the same element**: `.item { &:hover { } }`
- **Modifier composition**: `.item { &.selected { } }`
- **Hover-reveal patterns** where a parent hover affects a child: `.root:hover .showOnHover { opacity: 1; }` — but only when structurally necessary (the child has no way to know about the parent's hover state)
### Import Alias
Always import the CSS module as `S`:
```tsx
import S from "./ComponentName.module.css";
```
## Step-by-Step Migration Process
### Step 1: Read and Understand
Read the `.styled.tsx` file AND every component that imports from it. Understand:
- Which styled components are used and where
- Which props drive dynamic styles
- Which styles are static vs conditional
- Which styles can map directly to Mantine style props
### Step 2: Classify Each Styled Component
For each styled component, apply the Mantine-First Decision Gate above. Then determine the migration target:
| Emotion Pattern | Migration Target |
| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `styled.div` with only layout/spacing/color | `Box`, `Flex`, `Stack`, or `Group` with style props. **NO CSS module needed.** |
| `styled.div` with flexbox column | `Stack` component with style props |
| `styled.div` with flexbox row | `Flex` or `Group` component with style props |
| `styled.span` / `styled.p` with color/weight/size | **`Text component="span"` with style props** (`c`, `fw`, `fz`). NO CSS module. |
| `styled.div` with hover/focus/pseudo-selectors | **Hybrid**: Mantine component with style props for expressible properties + CSS module class for pseudo-selectors only |
| `styled.div` with media queries (simple spacing/sizing) | **Responsive style props**: `p={{ base: "md", lg: "xl" }}`. NO CSS module. |
| `styled.div` with media queries (complex/non-spacing) | CSS module for the media query parts, style props for the rest |
| `styled.div` with animations/keyframes | CSS module for animation, style props for layout |
| `styled(SomeComponent)` with only color/spacing/flex | **Wrap in Mantine component** with style props: `<Box c="brand" flex="0 0 auto"><Icon /></Box>`, or pass style props if the component accepts them |
| `styled(SomeComponent)` with pseudo-selectors/complex styles | CSS module `className` on the component |
| Dynamic props `styled.div<{ isActive: boolean }>` | Mantine style props for simple toggles (`c={active ? "brand" : "text-primary"}`), `cx()` with CSS module classes for complex state combinations involving pseudo-selectors |
### Step 3: Create CSS Module (if needed)
Create `ComponentName.module.css` alongside the component file:
```css
/* Use design system tokens — NEVER raw color/spacing values */
.root {
border: 1px solid var(--mb-color-border);
border-radius: var(--mantine-radius-md);
background-color: var(--mb-color-background-primary);
}
/* Conditional states as separate classes, combined with cx() */
.active {
background-color: var(--mb-color-brand);
color: var(--mb-color-text-primary-inverse);
}
.disabled {
color: var(--mb-color-text-tertiary);
pointer-events: none;
}
/* Hover/focus/pseudo-selectors — nest with & */
.interactive {
cursor: pointer;
&:hover {
color: var(--mb-color-brand);
background-color: var(--mb-color-background-hover);
}
}
/* Hover-reveal: acceptable parent→child nesting */
.root:hover .showOnHover {
opacity: 1;
}
/* Responsive styles */
@media (--breakpoint-min-md) {
.root {
padding: var(--mantine-spacing-lg);
}
}
```
### Step 4: Update the Component TSX
```tsx
import cx from "classnames";
import CS from "metabase/css/core/index.css";
import { Box, Flex, Group, Stack, Text } from "metabase/ui";
import S from "./ComponentName.module.css";
// Dynamic props → cx() with conditional classes
<Flex
className={cx(S.root, {
[S.active]: isActive,
[S.disabled]: disabled,
})}
align="center"
gap="sm"
p="md"
w="100%"
>
```
### Step 5: Delete the `.styled.tsx` File
Remove the old styled file entirely. Remove all imports of it from other files.
### Step 6: Verify
- Confirm zero `@emotion/styled` or `@emotion/react` imports remain in the migrated files
- Confirm no static inline styles (dynamic runtime values are fine)
- Confirm all colors use tokens, not raw hex/rgb values
## Design System Token Reference
### Mantine Style Props (use directly on components)
**Spacing** (`p`, `px`, `py`, `pt`, `pb`, `pl`, `pr`, `m`, `mx`, `my`, `mt`, `mb`, `ml`, `mr`):
- `"xs"` = 4px, `"sm"` = 8px, `"md"` = 16px, `"lg"` = 24px, `"xl"` = 32px
- Custom: `rem(48)` for non-standard values (import `rem` from `metabase/ui`)
**Dimensions** (`w`, `h`, `maw`, `mah`, `miw`, `mih`):
- `"100%"`, `"100vh"`, `rem(400)`, etc.
**Colors** (`c`, `bg`):
- Text: `"text-primary"`, `"text-secondary"`, `"text-tertiary"`
- Background: `"background-primary"`, `"background-secondary"`, `"background-hover"`
- Brand: `"brand"`, `"error"`, `"success"`, `"warning"`
**Typography** (`fz`, `fw`, `lh`, `ta`, `ff`):
- Font size: `"xs"` = 11px, `"sm"` = 12px, `"md"` = 14px, `"lg"` = 17px, `"xl"` = 21px
- Font weight: `"bold"`, `"normal"`, or numeric `700`
- Line height: `"xs"` = 100%, `"sm"` = 115%, `"md"` = 122%, `"lg"` = 138%, `"xl"` = 150%
- Text align: `"center"`, `"left"`, `"right"`
**Flexbox** (`align`, `justify`, `gap`, `direction`, `wrap`, `flex`):
- `align="center"`, `justify="space-between"`, `gap="sm"`, `direction="column"`, `wrap="nowrap"`
- `flex={1}`, `flex="0 0 auto"`
**Other**: `pos` (position), `display`
**Responsive syntax**: `px={{ base: "md", md: "lg", lg: rem(48) }}`
### CSS Variable Tokens (use in `.module.css` files)
**Colors** — `var(--mb-color-<name>)`:
- `--mb-color-text-primary`, `--mb-color-text-secondary`, `--mb-color-text-tertiary`
- `--mb-color-background-primary`, `--mb-color-background-secondary`, `--mb-color-background-hover`
- `--mb-color-border`, `--mb-color-border-strong`, `--mb-color-border-subtle`
- `--mb-color-brand`, `--mb-color-brand-hover`
- `--mb-color-error`, `--mb-color-success`, `--mb-color-warning`
- `--mb-color-shadow`, `--mb-color-focus`
- `--mb-color-accent0` through `--mb-color-accent7`
**Mantine spacing** — `var(--mantine-spacing-<size>)`:
- `--mantine-spacing-xs` (4px), `--mantine-spacing-sm` (8px), `--mantine-spacing-md` (16px), `--mantine-spacing-lg` (24px), `--mantine-spacing-xl` (32px)
**Mantine radius** — `var(--mantine-radius-<size>)`:
- `--mantine-radius-xs` (4px), `--mantine-radius-sm` (6px), `--mantine-radius-md` (8px), `--mantine-radius-xl` (40px)
**Mantine font sizes** — `var(--mantine-font-size-<size>)`:
- `--mantine-font-size-xs` (11px), `--mantine-font-size-sm` (12px), `--mantine-font-size-md` (14px), `--mantine-font-size-lg` (17px), `--mantine-font-size-xl` (21px)
**Breakpoints** (in `.module.css` files):
- `@media (--breakpoint-min-sm)` (40em / 640px)
- `@media (--breakpoint-min-md)` (60em / 960px)
- `@media (--breakpoint-min-lg)` (80em / 1280px)
- `@media (--breakpoint-min-xl)` (120em / 1920px)
- Also available: `--breakpoint-max-*` variants
### Snap Hardcoded Literals to Nearest Design Token (CRITICAL)
When migrating, **never carry over hardcoded `rem`/`px` values** from the original Emotion code. Instead, snap them to the nearest design system token. The original values were often arbitrary — the migration is an opportunity to align with the design system.
**Spacing** — snap to the nearest Mantine spacing token:
| Hardcoded value | Nearest token | Style prop | CSS variable |
| --------------------------------- | ------------- | ------------ | ------------------------------ |
| `0.125rem` (2px) | `2px` | `2` (number) | `2px` (keep literal, no token) |
| `0.2rem` (3.2px), `0.25rem` (4px) | **xs** (4px) | `"xs"` | `var(--mantine-spacing-xs)` |
| `0.5rem` (8px) | **sm** (8px) | `"sm"` | `var(--mantine-spacing-sm)` |
| `0.75rem` (12px) | between sm/md | `rem(12)` | `0.75rem` (no exact token) |
| `1rem` (16px) | **md** (16px) | `"md"` | `var(--mantine-spacing-md)` |
| `1.5rem` (24px) | **lg** (24px) | `"lg"` | `var(--mantine-spacing-lg)` |
| `2rem` (32px) | **xl** (32px) | `"xl"` | `var(--mantine-spacing-xl)` |
**Border radius** — snap to the nearest Mantine radius token:
| Hardcoded value | Nearest token | CSS variable |
| ---------------- | ----------------------------- | -------------------------- |
| `0.25rem` (4px) | **xs** (4px) | `var(--mantine-radius-xs)` |
| `0.375rem` (6px) | **sm** (6px) | `var(--mantine-radius-sm)` |
| `0.5rem` (8px) | **md** (8px) | `var(--mantine-radius-md)` |
| `1rem`+ (16px+) | **xl** (40px) or keep literal | `var(--mantine-radius-xl)` |
**Font sizes** — snap to the nearest Mantine font size token:
| Hardcoded value | Nearest token | Style prop | CSS variable |
| -------------------------------- | ------------- | ---------- | ----------------------------- |
| `0.6875rem` (11px) | **xs** (11px) | `fz="xs"` | `var(--mantine-font-size-xs)` |
| `0.75rem` (12px) | **sm** (12px) | `fz="sm"` | `var(--mantine-font-size-sm)` |
| `0.875rem` (14px), `1rem` (16px) | **md** (14px) | `fz="md"` | `var(--mantine-font-size-md)` |
| `1.063rem` (17px) | **lg** (17px) | `fz="lg"` | `var(--mantine-font-size-lg)` |
| `1.3rem` (21px) | **xl** (21px) | `fz="xl"` | `var(--mantine-font-size-xl)` |
**Rules:**
- If the hardcoded value is within ~2px of a token, use the token
- If it falls exactly between two tokens, prefer the smaller one (tighter is safer)
- If no token is close (e.g., `48px` spacing), use `rem(48)` for style props or the literal value in CSS modules
- This applies everywhere: style props, CSS module values, Icon `size` props, etc.
## Common Migration Patterns
### Pattern 1: Static Layout Container → Mantine Component
**Before:**
```tsx
// Component.styled.tsx
export const Container = styled.div`
display: flex;
align-items: center;
gap: 0.5rem;
padding: 1rem;
width: 100%;
`;
```
**After:**
```tsx
<Flex align="center" gap="sm" p="md" w="100%">
```
### Pattern 2: Vertical Stack → Stack Component
**Before:**
```tsx
export const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 1.5rem;
padding: 2rem;
`;
```
**After:**
```tsx
<Stack gap="lg" p="xl">
```
### Pattern 3: Dynamic Props → cx() with CSS Module Classes
**Before:**
```tsx
export const Item = styled.div<{ isSelected: boolean; disabled: boolean }>`
color: ${(props) =>
props.disabled ? color("text-tertiary") : color("text-primary")};
background-color: ${(props) =>
props.isSelected ? color("brand") : "transparent"};
cursor: ${(props) => (props.disabled ? "default" : "pointer")};
&:hover {
color: ${(props) => !props.disabled && color("brand")};
}
`;
```
**After (CSS module):**
```css
/* Item.module.css */
.itemRoot {
color: var(--mb-color-text-primary);
cursor: pointer;
&:hover {
color: var(--mb-color-brand);
}
}
.selected {
background-color: var(--mb-color-brand);
}
.disabled {
color: var(--mb-color-text-tertiary);
cursor: default;
&:hover {
color: var(--mb-color-text-tertiary);
}
}
```
**After (TSX):**
```tsx
<Box
className={cx(S.itemRoot, {
[S.selected]: isSelected,
[S.disabled]: disabled,
})}
>
```
### Pattern 4: Extending a Component → Style Props First, CSS Module Only If Needed
When a styled component wraps another component, first check if the styles can be expressed as style props on a Mantine wrapper or on the component itself. Only use a CSS module when properties genuinely need it.
**Before:**
```tsx
export const CardIcon = styled(Icon)`
display: block;
flex: 0 0 auto;
color: var(--mb-color-brand);
`;
export const CardTitle = styled(Ellipsified)`
color: var(--mb-color-text-primary);
font-size: 1rem;
font-weight: bold;
margin-left: 1rem;
`;
```
**After — style props on Mantine wrapper (preferred when ALL properties are expressible):**
```tsx
<Box display="block" flex="0 0 auto" c="brand">
<Icon {...icon} />
</Box>
<Box c="text-primary" fz="md" fw="bold" ml="md">
<Ellipsified>{title}</Ellipsified>
</Box>
```
**After — CSS module (use only when component has pseudo-selectors or non-expressible styles):**
```css
.icon {
color: var(--mb-color-brand);
width: 1.5rem;
height: 1.5rem;
cursor: pointer;
&:hover {
color: var(--mb-color-brand-hover);
}
}
```
```tsx
<Icon className={S.icon} name="warning" />
```
### Pattern 4b: `styled.span` / `styled.p` with Text Styles → `Text` Component
**Before:**
```tsx
export const Label = styled.span`
color: var(--mb-color-text-secondary);
font-weight: bold;
`;
export const Title = styled.span`
color: var(--mb-color-text-primary);
font-size: 1rem;
font-weight: bold;
margin-left: 0.5rem;
`;
```
**After — `Text` component with style props (NO CSS module needed):**
```tsx
<Text component="span" c="text-secondary" fw="bold">
{label}
</Text>
<Text component="span" c="text-primary" fz="md" fw="bold" ml="sm">
{title}
</Text>
```
`Text` renders as `<p>` by default. Use `component="span"` to render inline. All color, typography, and spacing props work directly — no CSS module needed for pure text styling.
### Pattern 5: Keyframes Animation → CSS Module
**Before:**
```tsx
const spin = keyframes`
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
`;
export const Spinner = styled.div`
animation: ${spin} 1s infinite linear;
`;
```
**After (CSS module):**
```css
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.spinner {
animation: spin 1s infinite linear;
}
```
**After (TSX):**
```tsx
<Box className={S.spinner} />
```
### Pattern 6: color() Function → CSS Variables
| Emotion (JS) | CSS Module | Mantine Style Prop |
| ----------------------- | ------------------------------------------------------------ | --------------------------- |
| `color("brand")` | `var(--mb-color-brand)` | `c="brand"` or `bg="brand"` |
| `color("text-primary")` | `var(--mb-color-text-primary)` | `c="text-primary"` |
| `color("border")` | `var(--mb-color-border)` | N/A (use CSS module) |
| `alpha("brand", 0.2)` | `color-mix(in srgb, var(--mb-color-brand), transparent 80%)` | N/A (use CSS module) |
### Pattern 7: Responsive Spacing/Sizing → Responsive Style Props (NOT CSS Media Queries)
When a styled component only changes spacing, sizing, or other style-prop-expressible values at breakpoints, use Mantine's responsive syntax instead of CSS module media queries.
**Before:**
```tsx
export const CaptionRoot = styled.div`
margin-bottom: 1.5rem;
${breakpointMinExtraLarge} {
margin-bottom: 2rem;
}
`;
```
**After — responsive style prop (NO CSS module needed):**
```tsx
<Flex mb={{ base: "lg", xl: "xl" }}>
```
Breakpoint keys: `base` (default), `xs` (40em), `sm` (48em), `md` (60em), `lg` (80em), `xl` (120em).
Only use CSS module `@media` queries when the responsive change involves non-style-prop properties (e.g., `box-shadow`, `border`, `cursor` changes at breakpoints).
### Pattern 8: Dynamic Computed Styles → Inline Styles
Inline styles are allowed **only** for truly dynamic values computed at runtime (e.g., widths, positions, colors from data). Everything else must use Mantine style props or CSS modules.
**Before:**
```tsx
export const Bar = styled.div<{ width: number }>`
width: ${(props) => props.width}%;
`;
```
**After:**
```tsx
<Box style={{ width: `${width}%` }} />
```
### Pattern 9: Core CSS Utility Classes (Discouraged)
**Do NOT introduce new `CS` utility class usage.** Core CSS utilities (`CS` from `metabase/css/core/index.css`) are legacy and discouraged for new code. Prefer Mantine style props or CSS modules instead.
If existing code already uses `CS` classes and you're not migrating that specific code, leave them alone. But when migrating Emotion → Mantine, replace with the proper alternative:
| Instead of `CS.*` | Use |
| ------------------- | ------------------------------------------------------- |
| `CS.overflowHidden` | CSS module: `overflow: hidden` |
| `CS.cursorPointer` | CSS module: `cursor: pointer` |
| `CS.flex1` | Style prop: `flex={1}` |
| `CS.flexNoShrink` | Style prop: `flex="0 0 auto"` |
| `CS.textBrandHover` | CSS module: `&:hover { color: var(--mb-color-brand); }` |
### Pattern 10: Shared Emotion Styles Across Files → Shared CSS Module + cx()
When Emotion exports a shared `css` block (like `animationStyles`) imported by many files, create ONE CSS module with the shared keyframe and a reusable class, then compose via `cx()`.
**Before (Emotion — shared animation used by 13+ skeleton files):**
```tsx
// ChartSkeleton.styled.tsx — defines shared animation
const fadingKeyframes = keyframes`
0% { opacity: 0.0625; }
50% { opacity: 0.125; }
100% { opacity: 0.0625; }
`;
export const animationStyles = css`
opacity: 0.1;
animation: ${fadingKeyframes} 1.5s infinite;
`;
// AreaSkeleton.styled.tsx — consumes it
import { animationStyles } from ".../ChartSkeleton.styled";
export const SkeletonImage = styled.svg`
${animationStyles};
flex: 1 1 0;
margin-top: 1rem;
border-bottom: 1px solid currentColor;
`;
// BarSkeleton.styled.tsx — also consumes it
import { animationStyles } from ".../ChartSkeleton.styled";
export const SkeletonImage = styled.svg`
${animationStyles};
flex: 1 1 0;
margin-top: 1rem;
`;
```
**After — shared CSS module:**
```css
/* ChartSkeleton.module.css */
@keyframes fading {
0% {
opacity: 0.0625;
}
50% {
opacity: 0.125;
}
100% {
opacity: 0.0625;
}
}
.animated {
opacity: 0.1;
animation: fading 1.5s infinite;
}
```
**After — per-component CSS modules with own styles only:**
```css
/* AreaSkeleton.module.css */
.skeletonImage {
flex: 1 1 0;
margin-top: 1rem;
border-bottom: 1px solid currentColor;
}
```
```css
/* BarSkeleton.module.css */
.skeletonImage {
flex: 1 1 0;
margin-top: 1rem;
}
```
**After — component TSX uses cx() to compose:**
```tsx
// AreaSkeleton.tsx
import cx from "classnames";
import ChartSkeletonS from "../ChartSkeleton/ChartSkeleton.module.css";
import S from "./AreaSkeleton.module.css";
const AreaSkeleton = (): JSX.Element => {
return (
<svg
className={cx(ChartSkeletonS.animated, S.skeletonImage)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 371 113"
preserveAspectRatio="none"
>
<path d="..." fill="currentColor" />
</svg>
);
};
```
The shared module owns the `@keyframes` and the `.animated` class. Each consumer composes it with its own module class via `cx()`. No duplication of the keyframe definition.
## Import Template
```tsx
import cx from "classnames"; // only if needed for conditional classes
import { Box, Flex, Group, Stack, Text, rem } from "metabase/ui";
import S from "./ComponentName.module.css"; // only if CSS module is needed
```
## Checklist Before Finishing
- [ ] **MANTINE-FIRST CHECK**: Every CSS property that has a style prop equivalent (`c`, `bg`, `p`, `m`, `fw`, `fz`, `flex`, `gap`, `align`, `w`, `h`, etc.) is expressed as a style prop, NOT in a CSS module
- [ ] `styled.span`/`styled.p` with only color/weight/size are replaced with `Text component="span"` + style props, NOT CSS module classes
- [ ] `styled.div` with only layout props are replaced with `Flex`/`Stack`/`Group`/`Box` + style props, NOT CSS module classes
- [ ] Responsive spacing/sizing uses responsive style props (`mb={{ base: "lg", xl: "xl" }}`), NOT CSS module `@media` queries
- [ ] CSS modules are used ONLY for: pseudo-selectors, box-shadow, border, cursor, overflow, animation, transition, transform, or complex selectors
- [ ] All `@emotion/styled` and `@emotion/react` imports removed from migrated files
- [ ] The `.styled.tsx` file is deleted
- [ ] All imports of the deleted styled file are updated
- [ ] No static inline styles — `style={{ }}` used only for truly dynamic runtime values
- [ ] All colors use design tokens (`c="brand"`, `var(--mb-color-brand)`), not raw hex/rgb
- [ ] All spacing uses design tokens (`p="md"`, `var(--mantine-spacing-md)`), not arbitrary px values — hardcoded `rem`/`px` literals snapped to the nearest token (see mapping table above)
- [ ] All border-radius values use radius tokens (`var(--mantine-radius-md)`), not hardcoded `0.5rem`
- [ ] All font sizes use font-size tokens (`fz="md"`, `var(--mantine-font-size-md)`), not hardcoded `1rem`
- [ ] Layout uses Mantine components (`Flex`, `Stack`, `Group`, `Box`, `Text`) not raw divs/spans with CSS
- [ ] All CSS module class names use camelCase
- [ ] No cascading/descendant selectors targeting raw elements — use direct class assignment instead
- [ ] Component renders identically to the original (visually verify if possible)
## Visual Verification with Screenshots (Optional — Only When Explicitly Asked)
When the user explicitly asks to create before/after screenshots, use the Playwright MCP tools to capture them. This is NOT done by default — only when requested.
Screenshots must be taken in **both light and dark mode** to verify token usage is correct in both themes.
### Switching Color Scheme via API
Toggle between light and dark mode using the Metabase settings API. Use Playwright's `browser_evaluate` or `browser_navigate` with fetch:
```js
// Switch to dark mode
await fetch("/api/setting/color-scheme", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ value: "dark" }),
});
// Switch to light mode
await fetch("/api/setting/color-scheme", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ value: "light" }),
});
```
After switching, reload the page for the theme to take effect.
### Process
For each state (**after** = migrated code, **before** = stashed original), capture screenshots in both themes at both viewport widths. This produces **8 screenshots total**.
1. **Take "after" screenshots first** (migrated code is already in place):
- Navigate to the page that renders the migrated components (`browser_navigate`)
- Wait for content to load (`browser_wait_for` with key text, or `textGone: "Loading..."`)
- Close the sidebar if it overlaps content on narrow viewports (`browser_click` the toggle button)
- **Light mode** (set `color-scheme` to `"light"` via API, reload):
- Desktop (1280x900): `after-light-desktop.png`
- Narrow (640x900), close sidebar: `after-light-narrow.png`
- **Dark mode** (set `color-scheme` to `"dark"` via API, reload):
- Desktop (1280x900): `after-dark-desktop.png`
- Narrow (640x900), close sidebar: `after-dark-narrow.png`
2. **Stash changes to capture "before" screenshots**:
- Run `git stash --include-untracked` to temporarily revert to the Emotion version
- Repeat the same 4 screenshots with `before-` prefix:
- `before-light-desktop.png`, `before-light-narrow.png`
- `before-dark-desktop.png`, `before-dark-narrow.png`
- Run `git stash pop` to restore the migrated code
3. **Restore the user's original color scheme** (set back to `"auto"` or whatever it was before).
4. **Display all 8 screenshots** using the `Read` tool so the user can visually compare before/after in both themes at both viewport sizes.
### Key Details
- Save screenshots in the repo root (they will be untracked — user can delete after review)
- The dev server must be running (typically `http://localhost:3000`)
- Use `browser_snapshot` to find element refs when you need to click buttons (e.g., sidebar toggle)
- The greeting text on the home page changes randomly on each load — this is expected, not a regression
- If the page being tested is not the home page, navigate to the correct URL that exercises the migrated components
- Dark mode screenshots are critical for verifying that CSS variable tokens (`var(--mb-color-*)`) are used correctly — hardcoded colors will look wrong in dark mode

View File

@@ -178,7 +178,6 @@
metabase.channel.core/send!
metabase.driver.sql-jdbc.execute/execute-prepared-statement!
metabase.notification.models/create-notification!
metabase.oauth-server.core/reset-provider!
metabase.pulse.send/send-pulse!
metabase-enterprise.transforms-python.python-runner-test/execute!
;; Workspace isolation functions are safe in parallel tests because they operate on
@@ -553,7 +552,6 @@
metabase-enterprise.cache.config-test/with-temp-persist-models hooks.common/with-seven-bindings
metabase-enterprise.dependencies.api-test/with-dependents-test! hooks.common/with-two-bindings
metabase-enterprise.metabot-v3.tools.dependencies-test/with-dependent-transforms! hooks.common/with-two-bindings
metabase-enterprise.metabot.tools.dependencies-test/with-dependent-transforms! hooks.common/with-two-bindings
metabase-enterprise.semantic-search.db.connection/with-migrate-tx hooks.common/let-one-with-optional-value
metabase-enterprise.serialization.api-test/with-serialization-test-data! hooks.common/with-three-bindings
metabase-enterprise.serialization.test-util/with-temp-dpc hooks.toucan2.tools.with-temp/with-temp
@@ -795,7 +793,7 @@
:private-call {:level :off}
:metabase/defsetting-must-specify-export {:level :off}
:metabase/defsetting-namespace {:level :off}
:metabase/test-helpers-use-non-thread-safe-functions {:level :warning} ; more config in `.clj-kondo/config/test-helpers/config.edn`
:metabase/test-helpers-use-non-thread-safe-functions {:level :warning} ; more config in `.clj-kondo/config/test-helpers/config.edn
:discouraged-var
{metabase.driver/database-supports? {:level :off}

File diff suppressed because it is too large Load Diff

View File

@@ -110,7 +110,6 @@
metabase.settings.models.setting-test/test-user-local-allowed-setting!
metabase.settings.models.setting-test/test-user-local-only-setting!
metabase.settings.models.setting.cache/restore-cache!
metabase.settings.models.setting/log-deprecated-env-var-usage!
metabase.settings.models.setting/set!
metabase.settings.models.setting/validate-settings-formatting!
metabase.setup.core/create-token!

View File

@@ -3,7 +3,7 @@ const { buildMatrix } = require("./build-e2e-matrix");
describe("buildMatrix", () => {
const options = {
java: "11",
defaultRunner: "${{ vars.DEFAULT_RUNNER_KEY }}",
defaultRunner: "ubuntu-22.04",
};
const testBuildMatrix = (entry, chunks) =>
buildMatrix(options, entry, chunks);

View File

@@ -19,7 +19,7 @@ while [[ $# -gt 0 ]]; do
done
echo "Cloning python-runner repository..."
git clone --depth 1 https://${METABASE_AUTOMATION_USER_TOKEN}@github.com/metabase/python-runner-container.git python-runner
git clone --depth 1 -b extensible-resource-schema https://${METABASE_AUTOMATION_USER_TOKEN}@github.com/metabase/python-runner-container.git python-runner
if [ "$SKIP_START" = false ]; then
echo "Starting python-runner..."

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
be-tests-mariadb:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -22,12 +22,12 @@ jobs:
version:
- name: MariaDB 10.6
junit-name: be-tests-mariadb-10-6-ee
image: metabase/mariadb:10.6 # https://github.com/metabase/metabase-mariadb-docker-image
image: circleci/mariadb:10.6
env:
enable-ssl-tests: 'false'
- name: MariaDB Latest
junit-name: be-tests-mariadb-latest-ee
image: mariadb:latest
image: circleci/mariadb:latest
env:
enable-ssl-tests: 'false'
job:
@@ -57,8 +57,8 @@ jobs:
ports:
- "3306:3306"
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: mb_test
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
@@ -81,7 +81,7 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
#
@@ -128,7 +128,7 @@ jobs:
be-tests-mysql:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -136,7 +136,7 @@ jobs:
version:
- name: MySQL 8.4
junit-name: be-tests-mysql-8-4-ee
image: mysql:8.4
image: cimg/mysql:8.4
env:
enable-ssl-tests: 'false'
enable-aws-iam-tests: 'false'
@@ -174,7 +174,7 @@ jobs:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: mb_test
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
@@ -197,7 +197,7 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
#
@@ -252,7 +252,7 @@ jobs:
be-tests-postgres:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -366,7 +366,7 @@ jobs:
- be-tests-mariadb
- be-tests-mysql
- be-tests-postgres
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
name: app-db-tests-result
if: always() && !cancelled()

View File

@@ -11,7 +11,7 @@ on:
jobs:
deploy:
name: Publish Athena JDBC Driver
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out the code

View File

@@ -7,7 +7,7 @@ on:
jobs:
update_pr:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
steps:
- uses: tibdex/github-app-token@v2.1.0

View File

@@ -20,7 +20,7 @@ jobs:
github.event.label.name == 'triple-backport'
)
)
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:

View File

@@ -17,7 +17,7 @@ on:
jobs:
setup-oss:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
outputs:
modules: ${{ steps.get-modules.outputs.modules }}
steps:
@@ -31,7 +31,7 @@ jobs:
needs: setup-oss
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
fail-fast: false
@@ -64,7 +64,7 @@ jobs:
flags: back-end
setup-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
outputs:
modules: ${{ steps.get-modules.outputs.modules }}
steps:
@@ -78,7 +78,7 @@ jobs:
needs: setup-ee
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
fail-fast: false

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
be-linter-clj-kondo:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
name: Clj-Kondo
steps:
@@ -26,7 +26,7 @@ jobs:
be-linter-eastwood:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
name: Eastwood
steps:
@@ -37,20 +37,20 @@ jobs:
name: Run Eastwood linter
be-linter-eastwood-test:
if: ${{ !inputs.skip && github.ref_name == 'master' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 30
name: Eastwood (tests only)
name: Eastwood (test)
steps:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:eastwood/test
name: Run Eastwood linter on our backend tests
name: Run Eastwood linter on tests
be-tests:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -167,7 +167,7 @@ jobs:
# as `:dev` dependencies). See #27009 for more context.
be-check:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
strategy:
matrix:
@@ -183,7 +183,7 @@ jobs:
be-cljfmt:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
name: Cljfmt
steps:
@@ -202,7 +202,7 @@ jobs:
- be-check
- be-tests
if: always() && !cancelled()
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
env:
needs: ${{ toJson(needs) }}

View File

@@ -10,7 +10,7 @@ on:
jobs:
backport-reminder:
name: Decide whether to backport or not
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: jesusvasquez333/verify-pr-label-action@v1.4.0

View File

@@ -5,7 +5,7 @@ on:
jobs:
check-source-branch:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
steps:
- name: Block master branch PRs
if: github.head_ref == 'master'

View File

@@ -14,7 +14,7 @@ on:
jobs:
start-message:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
@@ -45,7 +45,7 @@ jobs:
}).catch(console.error);
trigger-milestone-check:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
needs: start-message
steps:
@@ -66,7 +66,7 @@ jobs:
check-version:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
ee: ${{ fromJson(steps.canonical_version.outputs.result).ee }}
@@ -118,7 +118,7 @@ jobs:
return versions;
check-commit:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- name: Check out the code to verify the release branch
@@ -150,7 +150,7 @@ jobs:
git checkout -
get-build-requirements:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
@@ -185,7 +185,7 @@ jobs:
build-uberjar-for-release:
needs: [check-version, check-commit, get-build-requirements]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 50
strategy:
matrix:

View File

@@ -10,7 +10,7 @@ on:
jobs:
test-build-scripts:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Prepare back-end environment

View File

@@ -39,7 +39,7 @@ concurrency:
jobs:
get-cache-keys:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Get cache keys
@@ -52,7 +52,7 @@ jobs:
cypress-cache-key: ${{ steps.get-cache-keys.outputs.cypress-cache-key }}
generate-caches:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
needs: get-cache-keys
env:

View File

@@ -7,7 +7,7 @@ on:
jobs:
check-backport-script:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

View File

@@ -15,7 +15,7 @@ on:
jobs:
set-milestone:
name: Automatically set milestone
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
env:
isNewReleaseBranch: ${{ github.event_name == 'workflow_dispatch' }}

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
frontend_all: ${{ steps.changes.outputs.frontend_all }}
@@ -30,7 +30,7 @@ jobs:
fe-chromatic:
needs: files-changed
if: contains(github.event.pull_request.labels.*.name, 'chromatic') || (github.ref_name == 'master' && needs.files-changed.outputs.frontend_all == 'true')
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4

View File

@@ -21,7 +21,7 @@ on:
jobs:
auto-fix-bug:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
cljs: ${{ steps.changes.outputs.cljs }}
@@ -30,7 +30,7 @@ jobs:
shared-tests-cljs:
needs: files-changed
if: needs.files-changed.outputs.cljs == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

View File

@@ -10,7 +10,7 @@ on:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
codeql: ${{ steps.changes.outputs.codeql }}
@@ -25,7 +25,7 @@ jobs:
analyze:
needs: files-changed
if: needs.files-changed.outputs.codeql == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4

View File

@@ -8,7 +8,7 @@ on:
jobs:
codespell:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write

View File

@@ -48,7 +48,7 @@ on:
jobs:
containerize:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
platforms: ${{ steps.platforms.outputs.result }}
@@ -117,7 +117,7 @@ jobs:
bin/docker/.
verify-docker-pull:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
needs: containerize
timeout-minutes: 15
steps:

View File

@@ -6,7 +6,7 @@ on:
jobs:
get-container-info:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
name: Get container info
outputs:
@@ -68,7 +68,7 @@ jobs:
strategy:
matrix:
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
name: Run Trivy vulnerability scanner
steps:
- name: Check out the code
@@ -76,7 +76,7 @@ jobs:
with:
ref: ${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1
uses: aquasecurity/trivy-action@0.29.0
env:
TRIVY_OFFLINE_SCAN: true
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
@@ -85,6 +85,7 @@ jobs:
image-ref: docker.io/${{ env.repo }}:${{ env.tag }}
format: sarif
output: trivy-results.sarif
version: "v0.57.1"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
@@ -93,7 +94,7 @@ jobs:
post-comment:
needs: [get-container-info, containerize]
if: github.event_name == 'pull_request'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
name: Post PR comment
steps:
- name: Check out the code

View File

@@ -8,7 +8,7 @@ on:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
frontend_embedding_sources: ${{ steps.changes.outputs.frontend_embedding_sources }}
@@ -22,7 +22,7 @@ jobs:
filters: .github/file-paths.yaml
pr-title-reminder:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
permissions:
pull-requests: write

View File

@@ -7,7 +7,7 @@ on:
jobs:
fe-test-coverage:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v4

View File

@@ -25,7 +25,7 @@ concurrency:
jobs:
migrations-h2-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
@@ -39,23 +39,23 @@ jobs:
head-ref: ${{ env.HEAD_REF }}
migrations-postgres-14-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
MB_DB_HOST: localhost
MB_DB_DBNAME: mb_test
MB_DB_USER: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: circle_test
services:
postgres:
image: postgres:14-alpine
ports:
- "5432:5432"
env:
POSTGRES_USER: mb_test
POSTGRES_DB: mb_test
POSTGRES_USER: circle_test
POSTGRES_DB: circle_test
POSTGRES_HOST_AUTH_METHOD: trust
steps:
- uses: actions/checkout@v4
@@ -65,23 +65,23 @@ jobs:
head-ref: ${{ env.HEAD_REF }}
migrations-postgres-latest-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
MB_DB_HOST: localhost
MB_DB_DBNAME: mb_test
MB_DB_USER: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: circle_test
services:
postgres:
image: postgres:latest
image: circleci/postgres:latest
ports:
- "5432:5432"
env:
POSTGRES_USER: mb_test
POSTGRES_DB: mb_test
POSTGRES_USER: circle_test
POSTGRES_DB: circle_test
POSTGRES_HOST_AUTH_METHOD: trust
steps:
- uses: actions/checkout@v4
@@ -91,23 +91,20 @@ jobs:
head-ref: ${{ env.HEAD_REF }}
migrations-mysql-8-4-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
services:
mysql:
image: mysql:8.4
image: cimg/mysql:8.4
ports:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: mb_test
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
@@ -116,14 +113,14 @@ jobs:
head-ref: ${{ env.HEAD_REF }}
migrations-mysql-latest-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
services:
@@ -131,7 +128,7 @@ jobs:
image: mysql:latest
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: mb_test
MYSQL_DATABASE: circle_test
ports:
- "3306:3306"
steps:
@@ -142,24 +139,20 @@ jobs:
head-ref: ${{ env.HEAD_REF }}
migrations-mariadb-10-6-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
services:
mariadb:
image: metabase/mariadb:10.6 # https://github.com/metabase/metabase-mariadb-docker-image
image: ${{ matrix.version.image }}
image: circleci/mariadb:10.6
ports:
- "3306:3306"
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: mb_test
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test
@@ -168,23 +161,20 @@ jobs:
head-ref: ${{ env.HEAD_REF }}
migrations-mariadb-latest-ee:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
CI: 'true'
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
services:
mariadb:
image: mariadb:latest
image: circleci/mariadb:latest
ports:
- "3306:3306"
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: mb_test
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/cross-branch-migration-test

View File

@@ -26,7 +26,7 @@ jobs:
# Generate matrix for scheduled/PR runs
generate-matrix:
if: github.event_name != 'workflow_dispatch'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
@@ -49,7 +49,7 @@ jobs:
test-matrix:
if: github.event_name != 'workflow_dispatch'
needs: generate-matrix
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
@@ -78,7 +78,7 @@ jobs:
# Manual test for workflow_dispatch
test-manual:
if: github.event_name == 'workflow_dispatch'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:

View File

@@ -7,7 +7,7 @@ on:
jobs:
notify-disabled-drivers:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/setup-node@v4

View File

@@ -21,7 +21,7 @@ permissions:
jobs:
update-docs:
name: Update documentation for ${{ inputs.target_branch }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
steps:
- name: Checkout code

View File

@@ -7,7 +7,7 @@ on:
jobs:
link-checker:
name: Check documentation links
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read

View File

@@ -2,7 +2,7 @@ name: Auto-update documentation (master)
on:
schedule:
- cron: "0 21 * * 1-5" # Every Monday through Friday at 9 PM UTC
- cron: "0 1 * * 1-5" # Every Monday through Friday at 1 AM UTC
workflow_dispatch:
jobs:

View File

@@ -2,7 +2,7 @@ name: Auto-update documentation (release)
on:
schedule:
- cron: "0 22 * * 1-5" # Every Monday through Friday at 10 PM UTC
- cron: "0 2 * * 1-5" # Every Monday through Friday at 2 AM UTC
workflow_dispatch:
inputs:
target_branch:

View File

@@ -49,7 +49,7 @@ jobs:
be-tests-athena-ee:
if: inputs.driver == 'Athena'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -68,7 +68,7 @@ jobs:
be-tests-bigquery-cloud-sdk-ee:
if: inputs.driver == 'BigQuery'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -89,7 +89,7 @@ jobs:
be-tests-druid-ee:
if: inputs.driver == 'Druid'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -111,7 +111,7 @@ jobs:
be-tests-mariadb-10-6-ee:
if: inputs.driver == 'Maria DB'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -119,17 +119,14 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
services:
mariadb:
image: metabase/mariadb:10.6 # https://github.com/metabase/metabase-mariadb-docker-image
image: circleci/mariadb:10.6
ports:
- "3306:3306"
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: mb_test
steps:
- uses: actions/checkout@v4
- name: Test MariaDB driver (10.6)
@@ -140,7 +137,7 @@ jobs:
be-tests-mariadb-latest-ee:
if: inputs.driver == 'Maria DB (latest)'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -148,17 +145,14 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
services:
mariadb:
image: mariadb:latest
image: circleci/mariadb:latest
ports:
- "3306:3306"
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: mb_test
steps:
- uses: actions/checkout@v4
- name: Test MariaDB driver (latest)
@@ -169,7 +163,7 @@ jobs:
be-tests-mongo-4-4-ee:
if: inputs.driver == 'Mongo 4'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -191,7 +185,7 @@ jobs:
be-tests-mongo-4-4-ssl-ee:
if: inputs.driver == 'Mongo 4 (SSL)'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -225,7 +219,7 @@ jobs:
be-tests-mongo-5-0-ee:
if: inputs.driver == 'Mongo 5'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -247,7 +241,7 @@ jobs:
be-tests-mongo-5-0-ssl-ee:
if: inputs.driver == 'Mongo 5 (SSL)'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -281,7 +275,7 @@ jobs:
be-tests-mongo-latest-ee:
if: inputs.driver == 'Mongo (latest)'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -290,7 +284,7 @@ jobs:
MB_MONGO_TEST_PASSWORD: metasample123
services:
mongodb:
image: mongo:latest
image: circleci/mongo:latest
ports:
- "27017:27017"
env:
@@ -306,7 +300,7 @@ jobs:
be-tests-mysql-8-4-ee:
if: inputs.driver == 'MySQL'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -314,17 +308,14 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
services:
mysql:
image: mysql:8.4
image: cimg/mysql:8.4
ports:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: mb_test
steps:
- uses: actions/checkout@v4
- name: Test MySQL driver (8.4)
@@ -335,7 +326,7 @@ jobs:
be-tests-mysql-latest-ee:
if: inputs.driver == 'MySQL (latest)'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -343,7 +334,7 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
# set up env vars for something named "MYSQL_SSL" to run MySQL SSL tests verifying connectivity with PEM cert
@@ -373,7 +364,7 @@ jobs:
be-tests-oracle-18-4-ee:
if: inputs.driver == 'Oracle 18'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -399,7 +390,7 @@ jobs:
be-tests-oracle-21-3-ee:
if: inputs.driver == 'Oracle 21'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -434,7 +425,7 @@ jobs:
be-tests-postgres-ee:
if: inputs.driver == 'Postgres'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -464,7 +455,7 @@ jobs:
be-tests-postgres-latest-ee:
if: inputs.driver == 'Postgres (latest)'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -472,20 +463,20 @@ jobs:
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
MB_DB_DBNAME: circle_test
MB_DB_USER: circle_test
MB_POSTGRESQL_TEST_USER: circle_test
MB_POSTGRES_SSL_TEST_SSL: true
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: postgres:latest
image: circleci/postgres:latest
ports:
- "5432:5432"
env:
POSTGRES_USER: mb_test
POSTGRES_DB: mb_test
POSTGRES_USER: circle_test
POSTGRES_DB: circle_test
POSTGRES_HOST_AUTH_METHOD: trust
steps:
- uses: actions/checkout@v4
@@ -497,7 +488,7 @@ jobs:
be-tests-presto-jdbc-ee:
if: inputs.driver == 'Presto JDBC'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -546,7 +537,7 @@ jobs:
be-tests-redshift-ee:
if: inputs.driver == 'Redshift'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -565,7 +556,7 @@ jobs:
be-tests-snowflake-ee:
if: inputs.driver == 'Snowflake'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -586,7 +577,7 @@ jobs:
be-tests-sparksql-ee:
if: inputs.driver == 'SparkSQL'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -606,7 +597,7 @@ jobs:
be-tests-sqlite-ee:
if: inputs.driver == 'SQLite'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -621,7 +612,7 @@ jobs:
be-tests-sqlserver-2017-ee:
if: inputs.driver == 'SQL Server 2017'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -648,7 +639,7 @@ jobs:
be-tests-sqlserver-2022-ee:
if: inputs.driver == 'SQL Server 2022'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -675,7 +666,7 @@ jobs:
be-tests-starburst-ee:
if: inputs.driver == 'Starburst'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
env:
CI: 'true'
@@ -700,7 +691,7 @@ jobs:
login-to-ecr:
if: inputs.driver == 'Vertica'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
permissions:
id-token: write
@@ -729,7 +720,7 @@ jobs:
be-tests-vertica-ee:
if: inputs.driver == 'Vertica'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: login-to-ecr
timeout-minutes: 90
env:

View File

@@ -15,7 +15,7 @@ jobs:
# This job determines which driver tests should run based on PR context.
# All decision logic is consolidated in mage driver-decisions.
determine-driver-skips:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
outputs:
# All driver run decisions (from mage driver-decisions)
h2-should-run: ${{ steps.driver-decisions.outputs.h2-should-run }}
@@ -82,9 +82,6 @@ jobs:
echo ""
# First call: show human-readable output for debugging
./bin/mage -driver-decisions "${MAGE_ARGS[@]}"
echo ""
echo "Want to force-run a specific driver? Add a ci:run-<driver> or ci:run-all-drivers label to your PR."
echo "Run './bin/mage -driver-decisions -h' locally for the full list of drivers and labels."
# Second call: output only key=value lines for GITHUB_OUTPUT
./bin/mage -driver-decisions "${MAGE_ARGS[@]}" --github-output-only >> $GITHUB_OUTPUT
shell: bash
@@ -92,7 +89,7 @@ jobs:
be-tests-athena-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.athena-should-run == 'true' || needs.determine-driver-skips.outputs.athena-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -143,7 +140,7 @@ jobs:
be-tests-bigquery-cloud-sdk-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.bigquery-should-run == 'true' || needs.determine-driver-skips.outputs.bigquery-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
@@ -215,7 +212,7 @@ jobs:
be-tests-clickhouse-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.clickhouse-should-run == 'true' || needs.determine-driver-skips.outputs.clickhouse-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -298,7 +295,7 @@ jobs:
be-tests-druid-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.druid-should-run == 'true' || needs.determine-driver-skips.outputs.druid-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -347,7 +344,7 @@ jobs:
be-tests-druid-jdbc-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.druid-jdbc-should-run == 'true' || needs.determine-driver-skips.outputs.druid-jdbc-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -396,7 +393,7 @@ jobs:
be-tests-databricks-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.databricks-should-run == 'true' || needs.determine-driver-skips.outputs.databricks-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -445,7 +442,7 @@ jobs:
be-tests-databricks-multi-catalog-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.databricks-should-run == 'true' || needs.determine-driver-skips.outputs.databricks-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -495,7 +492,7 @@ jobs:
be-tests-h2:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.h2-should-run == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -526,7 +523,7 @@ jobs:
be-tests-h2-oss:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.h2-should-run == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -558,7 +555,7 @@ jobs:
be-tests-mysql-mariadb:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.mysql-mariadb-should-run == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -566,13 +563,13 @@ jobs:
version:
- name: MariaDB 10.6
junit-name: be-tests-mariadb-10-6-ee
image: metabase/mariadb:10.6 # https://github.com/metabase/metabase-mariadb-docker-image
image: circleci/mariadb:10.6
env:
enable-ssl-tests: 'false'
enable-aws-iam-tests: 'false'
- name: MariaDB Latest
junit-name: be-tests-mariadb-latest-ee
image: mariadb:latest
image: circleci/mariadb:latest
env:
enable-ssl-tests: 'false'
enable-aws-iam-tests: 'false'
@@ -605,7 +602,7 @@ jobs:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: mb_test
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
@@ -628,7 +625,7 @@ jobs:
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
#
@@ -695,7 +692,7 @@ jobs:
be-tests-mongo:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.mongo-should-run == 'true' || needs.determine-driver-skips.outputs.mongo-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -776,7 +773,7 @@ jobs:
be-tests-mongo-ssl:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.mongo-ssl-should-run == 'true' || needs.determine-driver-skips.outputs.mongo-ssl-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -853,7 +850,7 @@ jobs:
be-tests-mongo-sharded-cluster-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.mongo-sharded-cluster-should-run == 'true' || needs.determine-driver-skips.outputs.mongo-sharded-cluster-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -899,7 +896,7 @@ jobs:
be-tests-oracle:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.oracle-should-run == 'true' || needs.determine-driver-skips.outputs.oracle-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -985,7 +982,7 @@ jobs:
be-tests-postgres:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.postgres-should-run == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -1096,7 +1093,7 @@ jobs:
be-tests-presto-jdbc-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.presto-jdbc-should-run == 'true' || needs.determine-driver-skips.outputs.presto-jdbc-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -1178,7 +1175,7 @@ jobs:
be-tests-redshift-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.redshift-should-run == 'true' || needs.determine-driver-skips.outputs.redshift-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
strategy:
fail-fast: false
@@ -1269,7 +1266,7 @@ jobs:
be-tests-snowflake-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.snowflake-should-run == 'true' || needs.determine-driver-skips.outputs.snowflake-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
@@ -1350,7 +1347,7 @@ jobs:
be-tests-sparksql-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.sparksql-should-run == 'true' || needs.determine-driver-skips.outputs.sparksql-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -1397,7 +1394,7 @@ jobs:
be-tests-sqlite-ee:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.sqlite-should-run == 'true' || needs.determine-driver-skips.outputs.sqlite-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -1439,7 +1436,7 @@ jobs:
be-tests-sqlserver:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.sqlserver-should-run == 'true' || needs.determine-driver-skips.outputs.sqlserver-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
@@ -1523,7 +1520,7 @@ jobs:
# be-tests-starburst-ee:
# needs: determine-driver-skips
# if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
# runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
# runs-on: ubuntu-latest
# timeout-minutes: 40
# env:
# CI: 'true'
@@ -1561,7 +1558,7 @@ jobs:
login-to-ecr:
needs: determine-driver-skips
if: ${{ needs.determine-driver-skips.outputs.vertica-should-run == 'true' || needs.determine-driver-skips.outputs.vertica-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
id-token: write
@@ -1591,7 +1588,7 @@ jobs:
be-tests-vertica-ee:
needs: [determine-driver-skips, login-to-ecr]
if: ${{ needs.determine-driver-skips.outputs.vertica-should-run == 'true' || needs.determine-driver-skips.outputs.vertica-quarantine-conflict == 'true' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: 'true'
@@ -1665,7 +1662,7 @@ jobs:
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
# - be-tests-vertica-ee
- be-tests-clickhouse-ee
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
name: drivers-tests-result
if: always() && !cancelled()

View File

@@ -21,7 +21,7 @@ on:
jobs:
build-matrix:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
matrix: ${{ steps.matrix.outputs.config }}
@@ -47,7 +47,7 @@ jobs:
const inputSpecs = "${{ inputs.specs }}";
const inputChunks = Number(process.env.chunks);
const java = 21;
const defaultRunner = "${{ vars.DEFAULT_RUNNER_KEY }}";
const defaultRunner = "ubuntu-22.04";
const options = {
java,
defaultRunner,

View File

@@ -35,7 +35,7 @@ on:
jobs:
determine-test-type:
name: Determine test type
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
type: ${{ steps.detect.outputs.type }}
@@ -53,7 +53,7 @@ jobs:
workflow-summary:
name: Stress test inputs
needs: [determine-test-type]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Generate workflow summary
@@ -72,7 +72,7 @@ jobs:
stress-test-flake-fix:
needs: [determine-test-type]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 60
name: Stress test E2E flake fix
env:

View File

@@ -21,7 +21,7 @@ on:
runner:
required: false
type: string
default: ${{ vars.DEFAULT_RUNNER_KEY }}
default: ubuntu-22.04
total_chunks: # number of chunks
required: false
type: number

View File

@@ -24,7 +24,7 @@ jobs:
reset-e2e-test-comment:
if: ${{ github.event_name == 'pull_request' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Remove test results comment
@@ -75,7 +75,7 @@ jobs:
collect-timings:
name: Collect E2E Timings
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
needs: e2e-tests
if: always() && !cancelled() && github.ref == 'refs/heads/master'
@@ -138,7 +138,7 @@ jobs:
e2e-tests-result:
needs:
- e2e-tests
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
name: e2e-tests-result
if: always() && !cancelled()

View File

@@ -12,7 +12,7 @@ env:
jobs:
sdk-component-tests:
name: "SDK component tests (React ${{ matrix.react-version }})"
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 45
strategy:
matrix:
@@ -128,7 +128,7 @@ jobs:
await core.summary.addRaw(summary).write();
decide-target-ref:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
outputs:
target-ref: ${{ steps.get-target-ref.outputs.value }}
steps:
@@ -151,7 +151,7 @@ jobs:
sdk-component-tests-backward-compatibility:
name: "SDK component tests (Backward compatibility)"
needs: [decide-target-ref]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 45
env:
MB_RUN_MODE: "e2e"

View File

@@ -12,7 +12,7 @@ env:
MB_EDITION: ee
jobs:
get-sample-apps-data:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
# we must support the last two stable releases
@@ -94,7 +94,7 @@ jobs:
environment: ["production", "development"]
if: |
!cancelled() && needs.get-sample-apps-data.result == 'success'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-sample-app-${{ matrix.test_suite }}-tests-${{ matrix.environment }}-bundle
env:
@@ -201,7 +201,7 @@ jobs:
if: |
!cancelled() && needs.get-sample-apps-data.result == 'success' &&
(github.ref == 'refs/heads/master' || github.base_ref == 'master')
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-sample-app-shoppy-e2e-tests-${{ matrix.environment }}-bundle
env:
@@ -264,7 +264,7 @@ jobs:
!cancelled() && needs.get-sample-apps-data.result == 'success' &&
github.event_name == 'push' &&
github.ref == 'refs/heads/master'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-shoppy-synthetic-monitoring-tests
env:
@@ -354,7 +354,7 @@ jobs:
"angular-20-host-app-e2e",
]
environment: ["production", "development"]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-host-app-${{ matrix.test_suite }}-tests-${{ matrix.environment }}-bundle
env:

View File

@@ -10,7 +10,7 @@ on:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
frontend_embedding_sdk_package_sources: ${{ steps.changes.outputs.frontend_embedding_sdk_package_sources }}
@@ -29,7 +29,7 @@ jobs:
!cancelled() &&
(needs.files-changed.outputs.frontend_embedding_sdk_package_sources == 'true')
name: Embedding SDK package release-notes/no-release-notes label reminder
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

View File

@@ -10,7 +10,7 @@ concurrency:
jobs:
build-sdk-package:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 25
steps:
- uses: actions/checkout@v4

View File

@@ -39,7 +39,7 @@ concurrency:
jobs:
embedding-sdk-cli-snippets-type-check:
if: inputs.cli-snippets-type-check && !inputs.skip
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
@@ -55,7 +55,7 @@ jobs:
embedding-sdk-docs-snippets-type-check:
if: inputs.docs-snippets-type-check && !inputs.skip
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
@@ -71,7 +71,7 @@ jobs:
embedding-sdk-api-documentation-generation-validation:
if: inputs.documentation-validation && !inputs.skip
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
@@ -131,7 +131,7 @@ jobs:
embedding-sdk-bundle-size-check:
if: inputs.bundle-size-check
continue-on-error: true
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
BUNDLE_SIZE_THRESHOLD_PERCENT: 2
@@ -186,7 +186,7 @@ jobs:
- embedding-sdk-api-documentation-generation-validation
- embedding-sdk-component-tests
if: always() && !cancelled()
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
env:
needs: ${{ toJson(needs) }}

View File

@@ -7,7 +7,7 @@ on:
jobs:
on-escalation-label:
if: github.event.label.name == '.Escalation'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- name: Format issue title (escape quotes)

View File

@@ -19,7 +19,7 @@ on:
jobs:
workflow-summary:
name: Stress test inputs
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Generate workflow summary
@@ -34,7 +34,7 @@ jobs:
echo 'triggered by: @${{ github.event.sender.login }}' >> $GITHUB_STEP_SUMMARY
frontend-unit-test-stress-test-flake-fix:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 60
name: Stress test frontend unit test flake fix
steps:

View File

@@ -27,7 +27,7 @@ concurrency:
jobs:
fe-lint:
if: ${{ !inputs.skip-lint }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
@@ -58,7 +58,7 @@ jobs:
fe-type-check:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -73,7 +73,7 @@ jobs:
fe-tests-unit:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
fail-fast: false
@@ -111,7 +111,7 @@ jobs:
fe-tests-timezones:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
@@ -129,7 +129,7 @@ jobs:
- fe-tests-unit
- fe-tests-timezones
if: always() && !cancelled()
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
env:
needs: ${{ toJson(needs) }}

View File

@@ -24,7 +24,7 @@ on:
# TODO: Consider renaming the job in next milestones
jobs:
generative-query-test:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 90
name: Generative Query Test
env:

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
i18n: ${{ steps.changes.outputs.i18n }}
@@ -30,7 +30,7 @@ jobs:
verify-i18n-files:
needs: files-changed
if: needs.files-changed.outputs.i18n == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

View File

@@ -7,7 +7,7 @@ on:
jobs:
js-stats:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

View File

@@ -6,7 +6,7 @@ on:
jobs:
add-issue-references:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

View File

@@ -21,7 +21,7 @@ on:
jobs:
detect-changed-stories:
name: Detect changed stories
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
story_files: ${{ steps.detect.outputs.story_files }}
@@ -84,7 +84,7 @@ jobs:
name: Summary
needs: detect-changed-stories
if: needs.detect-changed-stories.outputs.should_run == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Generate workflow summary
@@ -109,7 +109,7 @@ jobs:
stress-test-loki:
needs: detect-changed-stories
if: needs.detect-changed-stories.outputs.should_run == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
name: Stress test Loki visual tests
services:

View File

@@ -7,7 +7,7 @@ on:
jobs:
check-label-and-update-snapshot:
if: contains(github.event.pull_request.labels.*.name, 'loki-update')
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

View File

@@ -7,7 +7,7 @@ on:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
frontend_ci: ${{ steps.changes.outputs.frontend_ci }}
@@ -25,7 +25,7 @@ jobs:
visual-test:
needs: files-changed
if: needs.files-changed.outputs.frontend_ci == 'true' || needs.files-changed.outputs.frontend_sources == 'true' || needs.files-changed.outputs.frontend_loki_ci == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
services:
docker:
image: docker:19.03.12

View File

@@ -6,7 +6,7 @@ on:
jobs:
# run mage tests even if the rest of be isnt needed
mage-tests:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
name: Mage
steps:
- uses: actions/checkout@v4

View File

@@ -6,7 +6,7 @@ on:
- labeled
jobs:
on-issue-labeled:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
if: |
contains(github.event.issue.labels.*.name, 'Type:New Feature')

View File

@@ -11,7 +11,7 @@ on:
- src/metabase/lib/js.cljs
jobs:
mbql-library-changelog-check:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
if: ${{ !contains( github.event.pull_request.labels.*.name, '.metabase-lib/no-change' ) }}
steps:
# - uses: jesusvasquez333/verify-pr-label-action@v1.4.0

View File

@@ -10,7 +10,7 @@ on:
jobs:
lint-migrations:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

View File

@@ -11,7 +11,7 @@ concurrency:
jobs:
# Only run if the PR has the minimal-tests label
check-label:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 1
outputs:
should-run: ${{ steps.check.outputs.result }}
@@ -29,7 +29,7 @@ jobs:
postgres-app-db-test:
needs: check-label
if: needs.check-label.outputs.should-run == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
env:
CI: "true"
@@ -80,7 +80,7 @@ jobs:
postgres-driver-test:
needs: check-label
if: needs.check-label.outputs.should-run == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 40
env:
CI: "true"
@@ -128,7 +128,7 @@ jobs:
frontend-unit-tests:
needs: check-label
if: needs.check-label.outputs.should-run == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
env:
JEST_JUNIT_OUTPUT_DIR: ./target/junit
@@ -163,7 +163,7 @@ jobs:
- postgres-app-db-test
- postgres-driver-test
- frontend-unit-tests
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
name: minimal-tests-result
if: always() && !cancelled()

View File

@@ -7,7 +7,7 @@ on:
jobs:
module-boundaries-stats:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

View File

@@ -10,7 +10,7 @@ concurrency:
jobs:
check-openapi-specs:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
if: contains(github.event.pull_request.labels.*.name, 'openapi-self-healing')
steps:

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
openapi: ${{ steps.changes.outputs.openapi }}
@@ -30,7 +30,7 @@ jobs:
validate-openapi:
needs: files-changed
if: needs.files-changed.outputs.openapi == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

View File

@@ -7,7 +7,7 @@ on:
jobs:
optimize-images:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
if: ${{ contains(github.event.pull_request.labels.*.name,'Type:Documentation') }}
steps:
- name: Checkout repository

View File

@@ -5,7 +5,7 @@ on:
workflow_call:
jobs:
build:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository
name: Build Metabase Docker image
timeout-minutes: 60
@@ -47,7 +47,7 @@ jobs:
push: true
launch_perf_test:
needs: [ build ]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
name: Launch Perf Test
permissions:
id-token: write

View File

@@ -14,7 +14,7 @@ on:
jobs:
approve:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
environment: pr-env-admin
steps:
- name: Approved

View File

@@ -19,7 +19,7 @@ env:
jobs:
destroy_pr:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
name: PR Review ENV Destroy
permissions:
id-token: write

View File

@@ -16,7 +16,7 @@ on:
default: false
jobs:
build:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository
name: Build Metabase Docker image
timeout-minutes: 60
@@ -58,7 +58,7 @@ jobs:
push: true
deploy_pr:
needs: [build]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
name: PR Review ENV
permissions:
id-token: write
@@ -188,7 +188,7 @@ jobs:
--atomic \
--timeout 10m
preview_links:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
needs: [deploy_pr]
steps:
- uses: marocchino/sticky-pull-request-comment@v2

View File

@@ -25,7 +25,7 @@ on:
jobs:
test-mode-config:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
run_mode: ${{ fromJson(steps.config.outputs.result).runMode }}
@@ -65,7 +65,7 @@ jobs:
});
release-artifact:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
strategy:
matrix:
@@ -110,7 +110,7 @@ jobs:
check-uberjar-health:
needs: [release-artifact]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
timeout-minutes: 10
strategy:
@@ -136,7 +136,7 @@ jobs:
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
run-sanity-check:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 30
needs: [test-mode-config, release-artifact]
strategy:
@@ -258,8 +258,14 @@ jobs:
tests-complete-message:
if: always()
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
needs: [run-sanity-check, check-uberjar-health, containerize-ee, containerize-oss]
runs-on: ubuntu-22.04
needs:
[
run-sanity-check,
check-uberjar-health,
containerize-ee,
containerize-oss,
]
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

View File

@@ -18,7 +18,7 @@ on:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
backend_presto_kerberos: ${{ steps.changes.outputs.backend_presto_kerberos }}
@@ -34,7 +34,7 @@ jobs:
run-presto-kerberos-test:
needs: files-changed
if: needs.files-changed.outputs.backend_presto_kerberos == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
steps:
- name: Install babashka

View File

@@ -10,7 +10,7 @@ jobs:
external-reminder:
name: External PR Helper
if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
permissions:
pull-requests: write

View File

@@ -7,7 +7,7 @@ on:
jobs:
notify-querying-on-call:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
if: |
(github.event.label.name == 'Priority:P0' || github.event.label.name == 'Priority:P1' || github.event.label.name == '.Escalation') &&

View File

@@ -1,68 +0,0 @@
name: Release Custom Viz Package
run-name: Release @metabase/custom-viz v${{ inputs.version }} from ${{ inputs.branch }}
on:
workflow_dispatch:
inputs:
branch:
description: "Branch to release from"
type: string
required: true
default: "custom-viz"
version:
description: "Version to publish (e.g. 0.1.0)"
type: string
required: true
npm_tag:
description: "NPM dist-tag"
type: choice
required: true
default: "latest"
options:
- latest
- next
- canary
jobs:
build-and-publish:
runs-on: ubuntu-22.04
timeout-minutes: 20
defaults:
run:
working-directory: frontend/src/custom-viz
steps:
- name: Check out the code
uses: actions/checkout@v4
with:
ref: ${{ inputs.branch }}
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Setup npm registry auth
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
registry-url: "https://registry.npmjs.org"
- name: Set package version
run: npm version ${{ inputs.version }} --no-git-tag-version
- name: Build package
run: bun run build
- name: Publish to NPM
run: npm publish --tag ${{ inputs.npm_tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_RELEASE_TOKEN }}
- name: Generate workflow summary
run: |
tee -a $GITHUB_STEP_SUMMARY << EOF
## Published @metabase/custom-viz
- **Version**: ${{ inputs.version }}
- **Tag**: ${{ inputs.npm_tag }}
- **Branch**: ${{ inputs.branch }}
- **Triggered by**: @${{ github.event.sender.login }}
EOF

View File

@@ -21,7 +21,7 @@ concurrency:
jobs:
workflow-summary:
name: Log inputs
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Generate workflow summary
@@ -37,7 +37,7 @@ jobs:
send-slack-notification-start:
name: "Send Slack notification: SDK release started"
needs: determine-sdk-version
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
slackMessageId: ${{ steps.send-slack-message-start.outputs.result }}
@@ -96,7 +96,7 @@ jobs:
"publish-npm",
"git-tag",
]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
env:
slackMessageId: ${{ needs.send-slack-notification-start.outputs.slackMessageId }}
@@ -134,7 +134,7 @@ jobs:
name: "Send Slack notification: SDK release successful"
needs:
["determine-sdk-version", "send-slack-notification-start", "publish-npm"]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
env:
slackMessageId: ${{ needs.send-slack-notification-start.outputs.slackMessageId }}
@@ -168,7 +168,7 @@ jobs:
});
determine-sdk-version:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
outputs:
sdk_version: ${{ fromJson(steps.new-sdk-version.outputs.result).version }}
@@ -219,7 +219,7 @@ jobs:
check-git-tag:
needs: determine-sdk-version
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
tag: embedding-sdk-${{ needs.determine-sdk-version.outputs.sdk_version }}
@@ -243,7 +243,7 @@ jobs:
test:
needs: check-git-tag
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Check out the code using the provided branch
@@ -262,7 +262,7 @@ jobs:
build-sdk:
needs: [test, determine-sdk-version]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Check out the code using the provided branch
@@ -297,7 +297,7 @@ jobs:
publish-npm:
needs: [build-sdk, determine-sdk-version]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
sdk_version: ${{ needs.determine-sdk-version.outputs.sdk_version }}
@@ -398,7 +398,7 @@ jobs:
git-tag:
needs: [publish-npm, determine-sdk-version]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
tag: embedding-sdk-${{ needs.determine-sdk-version.outputs.sdk_version }}

View File

@@ -23,7 +23,7 @@ on:
jobs:
update-release-log:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
# don't run this workflow for forks
if: ${{ github.event_name != 'push' || github.repository == 'metabase/metabase' }}

View File

@@ -15,7 +15,7 @@ on:
jobs:
check-milestone:
permissions: write-all
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

View File

@@ -11,7 +11,7 @@ on:
jobs:
preview-release-notes:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Fail early on the incorrect version format

View File

@@ -5,22 +5,22 @@ on:
workflow_dispatch:
inputs:
version:
description: "Major Metabase version (e.g. 45, 52, 68)"
description: 'Major Metabase version (e.g. 45, 52, 68)'
type: number
required: true
override_sha:
description: DANGEROUSLY allow releasing from this commit sha, regardless of the state of CI (can be empty)
type: string
required: false
default: ""
# schedule:
# - cron: "0 21 * * 1-5" # every weekday at 4 pm EST/5 pm EDT
default: ''
schedule:
- cron: '0 21 * * 1-5' # every weekday at 4 pm EST/5 pm EDT
jobs:
auto-patch-trigger:
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

View File

@@ -9,7 +9,7 @@ jobs:
check-release-status:
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -44,7 +44,7 @@ jobs:
});
open-backport-reminder:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

View File

@@ -55,7 +55,7 @@ on:
jobs:
green-check-stub:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 2
steps:
- name: Stub
@@ -63,7 +63,7 @@ jobs:
check-version:
# skips everything if the tag_name is 'none' because all later jobs depend on this job
if: ${{ inputs.tag_name != 'none' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
ee: ${{ fromJson(steps.canonical_version.outputs.result).ee }}
@@ -138,7 +138,7 @@ jobs:
throw new Error("No edition selected to tag");
copy-to-s3:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: check-version
timeout-minutes: 5
strategy:
@@ -221,7 +221,7 @@ jobs:
fi
tag-docker-image:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: check-version
timeout-minutes: 5
strategy:
@@ -257,7 +257,7 @@ jobs:
push-git-tags:
permissions: write-all
needs: check-version
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
env:
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
@@ -288,7 +288,7 @@ jobs:
update-version-info:
if: ${{ !inputs.dot-x-tag }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: check-version
timeout-minutes: 5
strategy:

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
release_source: ${{ steps.changes.outputs.release_source }}
@@ -30,7 +30,7 @@ jobs:
release-type-check:
needs: files-changed
if: needs.files-changed.outputs.release_source == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
@@ -49,7 +49,7 @@ jobs:
release-tests-unit:
needs: files-changed
if: needs.files-changed.outputs.release_source == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -68,7 +68,7 @@ jobs:
release-test-build:
needs: files-changed
if: needs.files-changed.outputs.release_source == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

View File

@@ -48,7 +48,7 @@ on:
jobs:
check-version:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
ee: ${{ fromJson(steps.canonical_version.outputs.result).ee }}
@@ -104,7 +104,7 @@ jobs:
return versions
publish-start-message:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: [check-version]
timeout-minutes: 5
steps:
@@ -135,7 +135,7 @@ jobs:
download-uberjar:
needs: check-version
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
strategy:
matrix:
@@ -178,7 +178,7 @@ jobs:
./version.properties
upload-to-s3:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: download-uberjar
timeout-minutes: 15
strategy:
@@ -230,7 +230,7 @@ jobs:
--paths "/${{ steps.version_path.outputs.result }}/*"
verify-s3-download:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: upload-to-s3
timeout-minutes: 15
strategy:
@@ -287,7 +287,7 @@ jobs:
push-tags:
permissions: write-all
needs: [verify-s3-download, containerize-oss, containerize-ee, check-version]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -320,7 +320,7 @@ jobs:
get-extra-tags:
needs: [ check-version ]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
outputs:
extra_tags: ${{ steps.taglist.outputs.extra_tags }}
steps:
@@ -371,7 +371,7 @@ jobs:
trigger-cloud-issues:
if: ${{ !inputs.auto }}
needs: push-tags
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -423,7 +423,7 @@ jobs:
needs:
- containerize-ee
- verify-s3-download
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/github-script@v7
@@ -446,7 +446,7 @@ jobs:
draft-release-notes:
if: ${{ !inputs.auto }}
needs: add-extra-tags
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
permissions: write-all
env:
@@ -514,7 +514,7 @@ jobs:
}).catch(console.warn);
publish-version-info:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: [push-tags, check-version]
timeout-minutes: 15
strategy:
@@ -590,7 +590,7 @@ jobs:
tag_oss: true
publish-complete-message:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: [set-release-channel, add-extra-tags]
timeout-minutes: 5
steps:
@@ -623,7 +623,7 @@ jobs:
manage-milestones:
if: ${{ !inputs.auto }}
permissions: write-all
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
needs: [draft-release-notes, publish-version-info] # this will ensure that the milestone stays open until the release notes are published
timeout-minutes: 15
steps:

View File

@@ -18,13 +18,14 @@ on:
jobs:
repro-bot:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
issues: read
id-token: write
if: |
(github.event_name == 'push') ||
(github.event_name == 'issues' && github.event.label.name == '.Run Repro Bot' && github.event.issue.state == 'open') ||
(github.event_name == 'workflow_dispatch')
@@ -33,12 +34,12 @@ jobs:
id: issue
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
ISSUE_NUMBER="${{ github.event.inputs.issue_number }}"
echo "number=${{ github.event.inputs.issue_number }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "push" ]; then
echo "number=70292" >> $GITHUB_OUTPUT
else
ISSUE_NUMBER="${{ github.event.issue.number }}"
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
fi
echo "number=$ISSUE_NUMBER" >> $GITHUB_OUTPUT
echo "Issue: https://github.com/${{ github.repository }}/issues/$ISSUE_NUMBER"
- uses: actions/checkout@v4
- uses: ./.github/actions/prepare-backend
@@ -53,14 +54,11 @@ jobs:
path: repro-bot
- name: Pre-clone metabase bare git repo
run: git clone --bare "https://github.com/${{ github.repository }}.git" repro-bot/git/metabase
run: git clone --bare .git repro-bot/git/metabase
- name: Capture Node.js path for MCP subprocesses
run: echo "NODE_BIN_DIR=$(dirname $(which node))" >> $GITHUB_ENV
- name: Pre-install MCP server dependencies
run: uv sync --directory repro-bot/mcp
- name: Install playwright-cli
run: |
npm install -g @playwright/cli@latest
@@ -101,12 +99,11 @@ jobs:
jq -n \
--arg uv "$UV_PATH" \
--arg key "$LINEAR_API_KEY" \
--arg workspace "${{ github.workspace }}" \
'{
mcpServers: {
"metabase-repro": {
command: $uv,
args: ["run", "--directory", ($workspace + "/repro-bot/mcp"), "--with", "fastmcp", "python", "-m", "metabase_repro"]
args: ["run", "--directory", "mcp", "--with", "fastmcp", "python", "-m", "metabase_repro"]
},
"linear-server": {
url: "https://mcp.linear.app/mcp",
@@ -134,17 +131,12 @@ jobs:
CLAUDE_WORKING_DIR: ${{ github.workspace }}/repro-bot
MB_PREMIUM_EMBEDDING_TOKEN: ${{ secrets.PR_ENV_MB_PREMIUM_EMBEDDING_TOKEN }}
GITHUB_ACTIONS_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
REPRO_NODE_MODULES_DIR: ${{ github.workspace }}/node_modules
timeout-minutes: 30
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY_REPRO_BOT }}
github_token: ${{ steps.claude-app-token.outputs.token }}
allowed_bots: linear
prompt: |
IMPORTANT: Your working directory is the repo root, but repro-bot lives in the `repro-bot/` subdirectory.
First, run `cd ${{ github.workspace }}/repro-bot` to change into the repro-bot directory before doing anything else.
Then read and follow the instructions in .claude/commands/repro.md to investigate this GitHub issue:
Read and follow the instructions in .claude/commands/repro.md to investigate this GitHub issue:
https://github.com/${{ github.repository }}/issues/${{ steps.issue.outputs.number }}
## CI Environment Notes
@@ -235,7 +227,9 @@ jobs:
mcp__linear-server__get_issue,
mcp__linear-server__list_comments,
mcp__linear-server__list_issues,
mcp__linear-server__save_comment"
mcp__linear-server__list_issue_labels,
mcp__linear-server__save_comment,
mcp__linear-server__save_issue"
--disallowedTools "Bash(git push*),Bash(rm -rf /*)"
- name: Verify repro-bot completed successfully
@@ -265,8 +259,8 @@ jobs:
name: repro-bot-${{ steps.issue.outputs.number }}
if-no-files-found: ignore
path: |
repro-bot/repro/*/SUGGESTIONS.md
repro-bot/repro/*/*.log
repro-bot/repro/*/*.patch
repro-bot/repro/*/playwright/**
repro/*/SUGGESTIONS.md
repro/*/*.log
repro/*/*.patch
repro/*/playwright/**
${{ steps.claude.outputs.execution_file }}

View File

@@ -9,7 +9,7 @@ on:
jobs:
rerun-on-failure:
name: 'Re-run ''${{ github.event.workflow_run.name }}'' workflow'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
# Do not re-run scheduled workflow runs
if: github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event != 'schedule'
env:

View File

@@ -21,7 +21,7 @@ on:
jobs:
reset-dataset:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 10
env:
CI: 'true'

View File

@@ -14,7 +14,7 @@ jobs:
files-changed:
if: ${{ !contains(github.event.pull_request.labels.*.name,'ci skip') && !contains(github.event.pull_request.labels.*.name,'minimal-tests') }}
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
e2e_all: ${{ steps.changes.outputs.e2e_all }}

View File

@@ -7,7 +7,7 @@ on:
jobs:
on-issue-opened:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
if: github.event.label.name == 'SECURITY'
steps:

View File

@@ -14,7 +14,7 @@ concurrency:
jobs:
semantic-search-tests-h2:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -69,7 +69,7 @@ jobs:
semantic-search-tests-mariadb:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -77,11 +77,11 @@ jobs:
version:
- name: MariaDB 10.6 with pgvector pg17
junit-name: semantic-search-tests-mariadb-10-6
mariadb-image: metabase/mariadb:10.6 # https://github.com/metabase/metabase-mariadb-docker-image
mariadb-image: circleci/mariadb:10.6
pgvector-image: pgvector/pgvector:pg17
- name: MariaDB Latest with pgvector pg17
junit-name: semantic-search-tests-mariadb-latest
mariadb-image: mariadb:latest
mariadb-image: circleci/mariadb:latest
pgvector-image: pgvector/pgvector:pg17
job:
- name: Semantic Search Tests
@@ -104,15 +104,15 @@ jobs:
ports:
- "3306:3306"
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: mb_test
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: circle_test
env:
CI: 'true'
DRIVERS: mysql
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
@@ -143,7 +143,7 @@ jobs:
semantic-search-tests-mysql:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -151,7 +151,7 @@ jobs:
version:
- name: MySQL 8.4 with pgvector pg17
junit-name: semantic-search-tests-mysql-8-4
mysql-image: mysql:8.4
mysql-image: cimg/mysql:8.4
pgvector-image: pgvector/pgvector:pg17
- name: MySQL Latest with pgvector pg17
junit-name: semantic-search-tests-mysql-latest
@@ -179,14 +179,14 @@ jobs:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: mb_test
MYSQL_DATABASE: circle_test
env:
CI: 'true'
DRIVERS: mysql
MB_DB_TYPE: mysql
MB_DB_HOST: localhost
MB_DB_PORT: 3306
MB_DB_DBNAME: mb_test
MB_DB_DBNAME: circle_test
MB_DB_USER: root
MB_MYSQL_TEST_USER: root
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
@@ -217,7 +217,7 @@ jobs:
semantic-search-tests-postgres:
if: ${{ !inputs.skip }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
fail-fast: false
@@ -296,7 +296,7 @@ jobs:
- semantic-search-tests-mariadb
- semantic-search-tests-mysql
- semantic-search-tests-postgres
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
name: semantic-search-tests-result
if: always() && !cancelled()

View File

@@ -11,7 +11,7 @@ on:
jobs:
set-announce-url:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
steps:
- name: Validate input

View File

@@ -8,7 +8,7 @@ on:
jobs:
files-changed:
name: Check which files changed
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
snowplow: ${{ steps.changes.outputs.snowplow }}
@@ -24,7 +24,7 @@ jobs:
lint:
needs: files-changed
if: needs.files-changed.outputs.snowplow == 'true'
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -18,7 +18,7 @@ jobs:
generate-poms:
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
name: Generate pom.xml files
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Prepare back-end environment
@@ -37,7 +37,7 @@ jobs:
frontend-projects:
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
name: ${{ matrix.project.name }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
strategy:
matrix:
project:
@@ -88,7 +88,7 @@ jobs:
needs: generate-poms
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
name: ${{ matrix.project.name }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
strategy:
matrix:
project:

View File

@@ -12,7 +12,7 @@ jobs:
close-stale-prs:
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/stale@v9

View File

@@ -18,7 +18,7 @@ on:
jobs:
start-message:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
@@ -49,7 +49,7 @@ jobs:
}).catch(console.error);
check-version:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
ee: ${{ fromJson(steps.canonical_version.outputs.result).ee }}
@@ -101,7 +101,7 @@ jobs:
return versions;
check-commit:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- name: Check out the code to verify the release branch
@@ -134,7 +134,7 @@ jobs:
tag-uberjar-for-release:
needs: [check-version, check-commit]
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
strategy:
matrix:

View File

@@ -7,7 +7,7 @@ on:
jobs:
on-team-label-added:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
if: |
contains(github.event.label.name, '.Team/') &&
@@ -19,7 +19,7 @@ jobs:
id: vars
with:
script: |
core.setOutput('issue_title', JSON.stringify(${{ toJson(github.event.issue.title) }} + '\n' + ${{ toJson(github.event.issue.html_url) }}));
core.setOutput('issue_title', ${{ toJson(github.event.issue.title) }}.replaceAll(/"/g, '\\"'));
- name: Extracting team name
id: team_name
run: |
@@ -39,7 +39,7 @@ jobs:
"type": "section",
"text": {
"type": "mrkdwn",
"text": ${{ steps.vars.outputs.issue_title }}
"text": "${{ steps.vars.outputs.issue_title }}\n${{ github.event.issue.html_url }}"
}
}
]

View File

@@ -29,7 +29,7 @@ jobs:
be-tests-bigquery-transforms:
# inputs.driver is empty on push triggers, so treat '' as 'all'
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'bigquery' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -77,7 +77,7 @@ jobs:
be-tests-clickhouse-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'clickhouse' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -137,7 +137,7 @@ jobs:
be-tests-mongo-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'mongo' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -188,7 +188,7 @@ jobs:
be-tests-mysql-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'mysql' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
services:
mysql:
@@ -243,7 +243,7 @@ jobs:
be-tests-postgres-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'postgres' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -299,7 +299,7 @@ jobs:
be-tests-redshift-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'redshift' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -345,7 +345,7 @@ jobs:
be-tests-snowflake-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'snowflake' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -400,7 +400,7 @@ jobs:
be-tests-sqlserver-transforms:
if: ${{ inputs.driver == 'all' || inputs.driver == '' || inputs.driver == 'sqlserver' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
@@ -461,7 +461,7 @@ jobs:
- be-tests-redshift-transforms
- be-tests-snowflake-transforms
- be-tests-sqlserver-transforms
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
timeout-minutes: 5
name: transforms-stress-test-result
if: always() && !cancelled()

View File

@@ -7,7 +7,7 @@ on:
jobs:
harvest:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:

View File

@@ -17,7 +17,7 @@ jobs:
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Checkout code

View File

@@ -12,7 +12,6 @@ on:
branches:
- master
- internal-tools
- ai-service-port
paths-ignore:
# config files
- ".**"
@@ -31,7 +30,7 @@ on:
jobs:
check-existing-artifacts:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
ee_exists: ${{ steps.check-ee.outcome == 'success' }}
@@ -84,7 +83,7 @@ jobs:
if: |
!cancelled() &&
contains(github.ref, 'release-x')
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
@@ -118,7 +117,7 @@ jobs:
[check-existing-artifacts, get-build-requirements]
if: always() && !cancelled() && needs.check-existing-artifacts.outputs.should_build == 'true' && (needs.get-build-requirements.result == 'success' || needs.get-build-requirements.result == 'skipped')
name: Build MB ${{ matrix.edition }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
timeout-minutes: 15
strategy:
matrix:
@@ -148,7 +147,7 @@ jobs:
edition: ${{ matrix.edition }}
check-jar-health:
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
runs-on: ubuntu-22.04
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
needs: [build, check-existing-artifacts]
# We only care about the explicit JAR health check on push to `master` and the `release-` branches.

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