diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index dd84ea782..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..0a1909fbc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,60 @@ +name: 🐛 Bug +description: Create a report to help us improve +title: "🐛 Bug: " +labels: ["Type: Bug"] +body: +- type: textarea + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is + validations: + required: true +- type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior + placeholder: | + 1. Go to'...' + 2. Click on'...' + 3. Scroll down to'...' + 4. See error + validations: + required: true +- type: textarea + attributes: + label: Expected Behavior + description: A clear and concise description of what you expected to happen + validations: + required: true +- type: textarea + attributes: + label: Screenshots + description: | + If applicable, add screenshots to help explain your problem + + Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in + validations: + required: false +- type: textarea + attributes: + label: Device Information [optional] + description: | + examples: + - **OS**: Ubuntu 20.04 + - **Browser**: chrome + - **version**: 22 + value: | + - OS: + - Browser: + - version: + render: markdown + validations: + required: false +- type: dropdown + attributes: + label: Are you working on this issue? + options: + - 'Yes' + - 'No' + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d6..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..22c44a0c8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,37 @@ +name: ⭐️ Feature request +description: Suggest an idea for this project +title: "✨ Enhancement: " +labels: ["Type: Feature Request"] +body: +- type: textarea + attributes: + label: Is your feature request related to a problem? Please describe + description: A clear and concise description of what the problem is + validations: + required: true +- type: textarea + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen + validations: + required: true +- type: textarea + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered + validations: + required: false +- type: textarea + attributes: + label: Additional context + description: Add any other context about the problem here + validations: + required: false +- type: dropdown + attributes: + label: Are you working on this? + options: + - 'Yes' + - 'No' + validations: + required: true \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..07dca7cd7 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,38 @@ + + + + + +**What kind of change does this PR introduce?** + + + +**Issue Number:** + +- Closes #___ +- Related to #___ +- Others? + + +**Screenshots/videos:** + + + +| Before | After | +| ----- | ----- | +| | | + +**If relevant, did you update the documentation?** + + + +**Summary** + + + + +**Does this PR introduce a breaking change?** + + diff --git a/.github/workflows/typescript_lint.yaml b/.github/workflows/typescript_lint.yaml new file mode 100644 index 000000000..cb81beb1a --- /dev/null +++ b/.github/workflows/typescript_lint.yaml @@ -0,0 +1,52 @@ +name: Typescript Lint, Format and Type check workflow + +on: + pull_request: + types: [opened, reopened, synchronize] + paths: + - "website/**" + +jobs: + linting_and_type-checking: + name: Typescript Linting, Formatting and Type checking + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: yarn install --frozen-lockfile + working-directory: website + + - name: Linting and Formatting checks + run: yarn run lint + working-directory: website + + - name: Type checking + run: yarn run typecheck + + build: + name: Build check + runs-on: ubuntu-latest + needs: linting_and_type-checking + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Build + run: yarn run build diff --git a/README.md b/README.md index b255d8349..34288dcc8 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,10 @@ docker compose up ``` docker compose -f docker-compose.prod.yml build docker compose -f docker-compose.prod.yml up +``` + +### Formatting + +``` +npm run format ``` \ No newline at end of file diff --git a/go/exec/exec.go b/go/exec/exec.go index 90d336ca9..973524fa0 100644 --- a/go/exec/exec.go +++ b/go/exec/exec.go @@ -49,6 +49,7 @@ const ( type Exec struct { UUID uuid.UUID + RawUUID string AnsibleConfig ansible.Config Source string GitRef string @@ -456,32 +457,11 @@ func GetRecentExecutions(client storage.SQLClient) ([]*Exec, error) { } defer result.Close() for result.Next() { - var eUUID string exec := &Exec{} - err = result.Scan(&eUUID, &exec.Status, &exec.GitRef, &exec.StartedAt, &exec.FinishedAt, &exec.Source, &exec.TypeOf, &exec.PullNB, &exec.GolangVersion) + err = result.Scan(&exec.RawUUID, &exec.Status, &exec.GitRef, &exec.StartedAt, &exec.FinishedAt, &exec.Source, &exec.TypeOf, &exec.PullNB, &exec.GolangVersion) if err != nil { return nil, err } - exec.UUID, err = uuid.Parse(eUUID) - if err != nil { - return nil, err - } - if exec.TypeOf != "micro" { - macroResult, err := client.Select("SELECT m.vtgate_planner_version FROM macrobenchmark m, execution e WHERE e.uuid = m.exec_uuid AND e.uuid = ? LIMIT 1", eUUID) - if err != nil { - return nil, err - } - defer macroResult.Close() - - var plannerVersion string - if macroResult.Next() { - err = macroResult.Scan(&plannerVersion) - if err != nil { - return nil, err - } - } - exec.VtgatePlannerVersion = plannerVersion - } res = append(res, exec) } return res, nil diff --git a/go/server/api.go b/go/server/api.go index 22402978d..9c309c5e1 100644 --- a/go/server/api.go +++ b/go/server/api.go @@ -60,7 +60,7 @@ func (s *Server) getRecentExecutions(c *gin.Context) { recentExecs := make([]RecentExecutions, 0, len(execs)) for _, e := range execs { recentExecs = append(recentExecs, RecentExecutions{ - UUID: e.UUID.String(), + UUID: e.RawUUID, Source: e.Source, GitRef: e.GitRef, Status: e.Status, diff --git a/go/server/cron_handlers.go b/go/server/cron_handlers.go index 2f0a5e266..a315a221a 100644 --- a/go/server/cron_handlers.go +++ b/go/server/cron_handlers.go @@ -48,10 +48,26 @@ func (s *Server) branchCronHandler() { execElements := append(mainBranchElements, releaseBranchElements...) for _, elem := range execElements { + s.removeBranchElementFromQueue(elem) s.addToQueue(elem) } } +func (s *Server) removeBranchElementFromQueue(newElem *executionQueueElement) { + mtx.Lock() + defer mtx.Unlock() + + for identifier, element := range queue { + if element.Executing { + continue + } + if identifier.PlannerVersion == newElem.identifier.PlannerVersion && identifier.BenchmarkType == newElem.identifier.BenchmarkType && identifier.Source == newElem.identifier.Source && identifier.GitRef != newElem.identifier.GitRef { + slog.Infof("%+v is removed from the queue", identifier) + delete(queue, identifier) + } + } +} + func (s *Server) mainBranchCronHandler() ([]*executionQueueElement, error) { var elements []*executionQueueElement configs := s.getConfigFiles() diff --git a/website/components.json b/website/components.json index a6fa9968b..14e747050 100644 --- a/website/components.json +++ b/website/components.json @@ -13,4 +13,4 @@ "components": "@/components", "utils": "@/library/utils" } -} \ No newline at end of file +} diff --git a/website/index.html b/website/index.html index 125b66439..810afa259 100644 --- a/website/index.html +++ b/website/index.html @@ -1,4 +1,4 @@ - + diff --git a/website/package.json b/website/package.json index 2b5f504cd..d2e388199 100644 --- a/website/package.json +++ b/website/package.json @@ -8,7 +8,8 @@ "start": "serve -s dist", "build": "vite --mode prod build", "lint": "eslint src --ext js,ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" + "preview": "vite preview", + "format": "prettier --write \"**/*.{ts,tsx,json,scss,css}\"" }, "dependencies": { "@nivo/core": "^0.83.0", diff --git a/website/postcss.config.js b/website/postcss.config.js index 2e7af2b7f..2aa7205d4 100644 --- a/website/postcss.config.js +++ b/website/postcss.config.js @@ -3,4 +3,4 @@ export default { tailwindcss: {}, autoprefixer: {}, }, -} +}; diff --git a/website/src/assets/styles/index.css b/website/src/assets/styles/index.css index 6c79bb901..0faa44ad3 100644 --- a/website/src/assets/styles/index.css +++ b/website/src/assets/styles/index.css @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -@import url('./tailwind.css'); -@import url('./directives.css'); +@import url("./tailwind.css"); +@import url("./directives.css"); /* Raleway font */ @import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,1;0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;0,1000;1,1;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900;1,1000&display=swap"); diff --git a/website/src/assets/styles/tailwind.css b/website/src/assets/styles/tailwind.css index af55a32dc..2ff25f5c1 100644 --- a/website/src/assets/styles/tailwind.css +++ b/website/src/assets/styles/tailwind.css @@ -118,3 +118,18 @@ limitations under the License. @apply after:content-[counter(num)]; } } + +.errorImgAnimation { + animation: translateUpDown 2s infinite alternate; +} + +@keyframes translateUpDown { + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-0.7cm); + } +} diff --git a/website/src/common/DisplayList.tsx b/website/src/common/DisplayList.tsx index b831afc1c..c12be4441 100644 --- a/website/src/common/DisplayList.tsx +++ b/website/src/common/DisplayList.tsx @@ -19,32 +19,54 @@ export default function DisplayList(props) { const { data } = props; return ( - - - - {Object.keys(data[0]).map((item, key) => ( - - ))} - - - - {data.map((val, key) => { - return ( - - {Object.keys(val).map((item, key) => ( - +
+
+ {data.map((val, key) => ( +
+ {Object.keys(val).map((item, itemKey) => ( +
+ {item} + {val[item]} +
+ ))} +
+ ))} +
+
+
- {item} -
- {val[item]} -
+ + + {Object.keys(data[0]).map((item, key) => ( + ))} - ); - })} - -
+ {item} +
+ + + {data.map((val, key) => { + return ( + + {Object.keys(val).map((item, key) => ( + + {val[item]} + + ))} + + ); + })} + + + + ); } diff --git a/website/src/common/Dropdown.tsx b/website/src/common/Dropdown.tsx index 158618c34..2f67cd60e 100644 --- a/website/src/common/Dropdown.tsx +++ b/website/src/common/Dropdown.tsx @@ -17,6 +17,7 @@ import React, { useEffect, useRef, useState } from "react"; import useClickOutside from "../hooks/useClickOutside"; import Icon from "../common/Icon"; import { twMerge } from "tailwind-merge"; +import { Button } from "@/components/ui/button"; function Container(props) { const [open, setOpen] = useState(false); @@ -26,7 +27,7 @@ function Container(props) { let items = React.Children.map( props.children, - (child) => `${child.props.children}` + (child) => `${child.props.children}`, ); useClickOutside(ref, () => setOpen(false)); @@ -45,12 +46,13 @@ function Container(props) { }, [selectedIndex]); return ( -
- + + <>
{props.children} - + ); } diff --git a/website/src/common/Footer.tsx b/website/src/common/Footer.tsx index 349c6b603..c26567568 100644 --- a/website/src/common/Footer.tsx +++ b/website/src/common/Footer.tsx @@ -16,11 +16,8 @@ limitations under the License. import React from "react"; -import { - AiFillGithub, - AiFillSlackCircle, - AiFillTwitterCircle, -} from "react-icons/ai"; +import { AiFillGithub, AiFillSlackCircle } from "react-icons/ai"; +import { FaSquareXTwitter } from "react-icons/fa6"; import { BsStackOverflow } from "react-icons/bs"; import { Link } from "react-router-dom"; @@ -28,7 +25,7 @@ const Footer = () => { const socials = [ { url: "https://github.com/vitessio/arewefastyet", icon: AiFillGithub }, { url: "https://vitess.io/slack", icon: AiFillSlackCircle }, - { url: "https://twitter.com/vitessio", icon: AiFillTwitterCircle }, + { url: "https://twitter.com/vitessio", icon: FaSquareXTwitter }, { url: "https://stackoverflow.com/search?q=vitess", icon: BsStackOverflow }, ]; diff --git a/website/src/common/Macrobench.tsx b/website/src/common/Macrobench.tsx index ec4d39beb..fbe8e0774 100644 --- a/website/src/common/Macrobench.tsx +++ b/website/src/common/Macrobench.tsx @@ -15,10 +15,10 @@ limitations under the License. */ import React from "react"; -import PropTypes from 'prop-types'; +import PropTypes from "prop-types"; import { Link } from "react-router-dom"; import { formatByte, fixed, secondToMicrosecond } from "../utils/Utils"; -import {twMerge} from "tailwind-merge"; +import { twMerge } from "tailwind-merge"; export default function Macrobench({ data, gitRef, commits }) { return ( @@ -166,7 +166,9 @@ export default function Macrobench({ data, gitRef, commits }) { oldVal={data.result.components_cpu_time.vttablet.old} newVal={data.result.components_cpu_time.vttablet.new} delta={data.result.components_cpu_time.vttablet.delta} - insignificant={data.result.components_cpu_time.vttablet.insignificant} + insignificant={ + data.result.components_cpu_time.vttablet.insignificant + } p={fixed(data.result.components_cpu_time.vttablet.p, 3)} fmt={"time"} /> @@ -176,7 +178,9 @@ export default function Macrobench({ data, gitRef, commits }) { oldVal={data.result.total_components_mem_stats_alloc_bytes.old} newVal={data.result.total_components_mem_stats_alloc_bytes.new} delta={data.result.total_components_mem_stats_alloc_bytes.delta} - insignificant={data.result.total_components_mem_stats_alloc_bytes.insignificant} + insignificant={ + data.result.total_components_mem_stats_alloc_bytes.insignificant + } p={fixed(data.result.total_components_mem_stats_alloc_bytes.p, 3)} fmt={"memory"} /> @@ -186,7 +190,9 @@ export default function Macrobench({ data, gitRef, commits }) { oldVal={data.result.components_mem_stats_alloc_bytes.vtgate.old} newVal={data.result.components_mem_stats_alloc_bytes.vtgate.new} delta={data.result.components_mem_stats_alloc_bytes.vtgate.delta} - insignificant={data.result.components_mem_stats_alloc_bytes.vtgate.insignificant} + insignificant={ + data.result.components_mem_stats_alloc_bytes.vtgate.insignificant + } p={fixed(data.result.components_mem_stats_alloc_bytes.vtgate.p, 3)} fmt={"memory"} /> @@ -196,8 +202,14 @@ export default function Macrobench({ data, gitRef, commits }) { oldVal={data.result.components_mem_stats_alloc_bytes.vttablet.old} newVal={data.result.components_mem_stats_alloc_bytes.vttablet.new} delta={data.result.components_mem_stats_alloc_bytes.vttablet.delta} - insignificant={data.result.components_mem_stats_alloc_bytes.vttablet.insignificant} - p={fixed(data.result.components_mem_stats_alloc_bytes.vttablet.p, 3)} + insignificant={ + data.result.components_mem_stats_alloc_bytes.vttablet + .insignificant + } + p={fixed( + data.result.components_mem_stats_alloc_bytes.vttablet.p, + 3, + )} fmt={"memory"} /> @@ -208,32 +220,35 @@ export default function Macrobench({ data, gitRef, commits }) { export function getRange(range) { if (range.infinite == true) { - return "∞" + return "∞"; } if (range.unknown == true) { - return "?" + return "?"; } - return "±"+fixed(range.value, 1)+"%" + return "±" + fixed(range.value, 1) + "%"; } function Row({ title, oldVal, newVal, delta, insignificant, p, fmt }) { - let status = + "text-lg text-white px-4 rounded-full", + insignificant == true && "bg-[#dd1a2a]", + insignificant == false && "bg-[#00aa00]", + )} + > {insignificant == true ? "No" : "Yes"} - + + ); - var oldValFmt = oldVal.center - var newValFmt = newVal.center + var oldValFmt = oldVal.center; + var newValFmt = newVal.center; if (fmt == "time") { - oldValFmt = secondToMicrosecond(oldVal.center) - newValFmt = secondToMicrosecond(newVal.center) + oldValFmt = secondToMicrosecond(oldVal.center); + newValFmt = secondToMicrosecond(newVal.center); } else if (fmt == "memory") { - oldValFmt = formatByte(oldVal.center) - newValFmt = formatByte(newVal.center) + oldValFmt = formatByte(oldVal.center); + newValFmt = formatByte(newVal.center); } return ( @@ -242,10 +257,14 @@ function Row({ title, oldVal, newVal, delta, insignificant, p, fmt }) { {title} - {oldValFmt} ({getRange(oldVal.range)}) + + {oldValFmt} ({getRange(oldVal.range)}) + - {newValFmt} ({getRange(newVal.range)}) + + {newValFmt} ({getRange(newVal.range)}) + {p || "?"} @@ -253,9 +272,7 @@ function Row({ title, oldVal, newVal, delta, insignificant, p, fmt }) { {fixed(delta, 3) || 0}% - - {status} - + {status} ); } @@ -276,10 +293,10 @@ Row.propTypes = { infinite: PropTypes.bool.isRequired, unknown: PropTypes.bool.isRequired, value: PropTypes.number.isRequired, - }) + }), }).isRequired, delta: PropTypes.number.isRequired, insignificant: PropTypes.bool.isRequired, p: PropTypes.string.isRequired, - fmt: PropTypes.oneOf(['none', 'time', 'memory']).isRequired, -}; \ No newline at end of file + fmt: PropTypes.oneOf(["none", "time", "memory"]).isRequired, +}; diff --git a/website/src/common/Modal.tsx b/website/src/common/Modal.tsx index 679c38ba2..2f96ccad6 100644 --- a/website/src/common/Modal.tsx +++ b/website/src/common/Modal.tsx @@ -24,13 +24,13 @@ export default function Modal() {
{modal.element} diff --git a/website/src/common/Navbar.tsx b/website/src/common/Navbar.tsx index fe48a401a..c8361e57a 100644 --- a/website/src/common/Navbar.tsx +++ b/website/src/common/Navbar.tsx @@ -42,7 +42,7 @@ export default function Navbar() {