From 3160c58d8a18ad3fe0c804f56ea9cc7e2f55d899 Mon Sep 17 00:00:00 2001 From: 49fl Date: Wed, 10 Jul 2024 10:08:15 -0400 Subject: [PATCH 1/6] After a sketch keep the extrude button active (#2961) * After a sketch keep the extrude button active * add test * Compare to 0,0 not any x,x or y,y --------- Co-authored-by: Kurt Hutten Irev-Dev --- e2e/playwright/flow-tests.spec.ts | 47 ++++++++++++++++++++++ src/components/ModelingMachineProvider.tsx | 2 + src/lib/selections.ts | 8 ++++ 3 files changed, 57 insertions(+) diff --git a/e2e/playwright/flow-tests.spec.ts b/e2e/playwright/flow-tests.spec.ts index c40924f06..b8ed51e59 100644 --- a/e2e/playwright/flow-tests.spec.ts +++ b/e2e/playwright/flow-tests.spec.ts @@ -4563,6 +4563,53 @@ test.describe('Sketch tests', () => { await doSnapAtDifferentScales(page, [0, 10000, 10000]) }) }) + test('exiting a close extrude, has the extrude button enabled ready to go', async ({ + page, + }) => { + // this was a regression https://github.com/KittyCAD/modeling-app/issues/2832 + await page.addInitScript(async () => { + localStorage.setItem( + 'persistCode', + `const sketch001 = startSketchOn('XZ') + |> startProfileAt([-0.45, 0.87], %) + |> line([1.32, 0.38], %) + |> line([1.02, -1.32], %, $seg01) + |> line([-1.01, -0.77], %) + |> lineTo([profileStartX(%), profileStartY(%)], %) + |> close(%) +` + ) + }) + + const u = await getUtils(page) + await page.setViewportSize({ width: 1200, height: 500 }) + + await u.waitForAuthSkipAppStart() + + // click "line([1.32, 0.38], %)" + await page.getByText(`line([1.32, 0.38], %)`).click() + await page.waitForTimeout(100) + // click edit sketch + await page.getByRole('button', { name: 'Edit Sketch' }).click() + await page.waitForTimeout(600) // wait for animation + + // exit sketch + await page.getByRole('button', { name: 'Exit Sketch' }).click() + + // expect extrude button to be enabled + await expect( + page.getByRole('button', { name: 'Extrude' }) + ).not.toBeDisabled() + + // click extrude + await page.getByRole('button', { name: 'Extrude' }).click() + + // sketch selection should already have been made. "Selection 1 face" only show up when the selection has been made already + // otherwise the cmdbar would be waiting for a selection. + await expect( + page.getByRole('button', { name: 'Selection 1 face' }) + ).toBeVisible() + }) test("Existing sketch with bad code delete user's code", async ({ page }) => { // this was a regression https://github.com/KittyCAD/modeling-app/issues/2832 await page.addInitScript(async () => { diff --git a/src/components/ModelingMachineProvider.tsx b/src/components/ModelingMachineProvider.tsx index 045429518..0640e91da 100644 --- a/src/components/ModelingMachineProvider.tsx +++ b/src/components/ModelingMachineProvider.tsx @@ -35,6 +35,7 @@ import { canExtrudeSelection, handleSelectionBatch, isSelectionLastLine, + isRangeInbetweenCharacters, isSketchPipe, updateSelections, } from 'lib/selections' @@ -425,6 +426,7 @@ export const ModelingMachineProvider = ({ if ( selectionRanges.codeBasedSelections.length === 0 || + isRangeInbetweenCharacters(selectionRanges) || isSelectionLastLine(selectionRanges, codeManager.code) ) { // they have no selection, we should enable the button diff --git a/src/lib/selections.ts b/src/lib/selections.ts index 5ae4031f0..32274967e 100644 --- a/src/lib/selections.ts +++ b/src/lib/selections.ts @@ -360,6 +360,14 @@ export function isSelectionLastLine( return selectionRanges.codeBasedSelections[i].range[1] === code.length } +export function isRangeInbetweenCharacters(selectionRanges: Selections) { + return ( + selectionRanges.codeBasedSelections.length === 1 && + selectionRanges.codeBasedSelections[0].range[0] === 0 && + selectionRanges.codeBasedSelections[0].range[1] === 0 + ) +} + export type CommonASTNode = { selection: Selection ast: Program From 263a4f324dc452494bab421c534c2321bf3b3f60 Mon Sep 17 00:00:00 2001 From: 49fl Date: Wed, 10 Jul 2024 13:13:33 -0400 Subject: [PATCH 2/6] Handle the case of no avatar (#2959) * Handle the case of no avatar * ci go * Scope to the top if... * Account for CI's usage of dev API key causing avatar to show --- e2e/playwright/flow-tests.spec.ts | 38 ++++++++++++++++++++++++++++++ src/machines/authMachine.ts | 13 +++++++++- src/routes/Onboarding/UserMenu.tsx | 7 +++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/e2e/playwright/flow-tests.spec.ts b/e2e/playwright/flow-tests.spec.ts index b8ed51e59..b73563037 100644 --- a/e2e/playwright/flow-tests.spec.ts +++ b/e2e/playwright/flow-tests.spec.ts @@ -2458,6 +2458,44 @@ test.describe('Onboarding tests', () => { await expect(onboardingOverlayLocator).toBeVisible() await expect(onboardingOverlayLocator).toContainText('the menu button') }) + + test("Avatar text doesn't mention avatar when no avatar", async ({ + page, + }) => { + // Override beforeEach test setup + await page.addInitScript( + async ({ settingsKey, settings }) => { + localStorage.setItem(settingsKey, settings) + localStorage.setItem('FORCE_NO_IMAGE', 'FORCE_NO_IMAGE') + }, + { + settingsKey: TEST_SETTINGS_KEY, + settings: TOML.stringify({ + settings: TEST_SETTINGS_ONBOARDING_USER_MENU, + }), + } + ) + + const u = await getUtils(page) + await page.setViewportSize({ width: 1200, height: 500 }) + await u.waitForAuthSkipAppStart() + + await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' }) + + // Test that the text in this step is correct + const avatarLocator = await page + .getByTestId('user-sidebar-toggle') + .locator('img') + const onboardingOverlayLocator = await page + .getByTestId('onboarding-content') + .locator('div') + .nth(1) + + // Expect the avatar to be visible and for the text to reference it + await expect(avatarLocator).not.toBeVisible() + await expect(onboardingOverlayLocator).toBeVisible() + await expect(onboardingOverlayLocator).toContainText('the menu button') + }) }) test.describe('Testing selections', () => { diff --git a/src/machines/authMachine.ts b/src/machines/authMachine.ts index 547a0e4c8..ddeeb87c2 100644 --- a/src/machines/authMachine.ts +++ b/src/machines/authMachine.ts @@ -126,11 +126,17 @@ async function getUser(context: UserContext) { if (!token && isTauri()) return Promise.reject(new Error('No token found')) if (token) headers['Authorization'] = `Bearer ${context.token}` - if (SKIP_AUTH) + if (SKIP_AUTH) { + // For local tests + if (localStorage.getItem('FORCE_NO_IMAGE')) { + LOCAL_USER.image = '' + } + return { user: LOCAL_USER, token, } + } const userPromise = !isTauri() ? fetch(url, { @@ -144,6 +150,11 @@ async function getUser(context: UserContext) { const user = await userPromise + // Necessary here because we use Kurt's API key in CI + if (localStorage.getItem('FORCE_NO_IMAGE')) { + user.image = '' + } + if ('error_code' in user) return Promise.reject(new Error(user.message)) return { diff --git a/src/routes/Onboarding/UserMenu.tsx b/src/routes/Onboarding/UserMenu.tsx index 333ae44e3..b026ca6dd 100644 --- a/src/routes/Onboarding/UserMenu.tsx +++ b/src/routes/Onboarding/UserMenu.tsx @@ -2,13 +2,18 @@ import { OnboardingButtons, useDismiss, useNextClick } from '.' import { onboardingPaths } from 'routes/Onboarding/paths' import { useEffect, useState } from 'react' import { useModelingContext } from 'hooks/useModelingContext' +import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' export default function UserMenu() { const { context } = useModelingContext() + const { auth } = useSettingsAuthContext() const dismiss = useDismiss() const next = useNextClick(onboardingPaths.PROJECT_MENU) const [avatarErrored, setAvatarErrored] = useState(false) - const buttonDescription = !avatarErrored ? 'your avatar' : 'the menu button' + + const user = auth?.context?.user + const errorOrNoImage = !user?.image || avatarErrored + const buttonDescription = errorOrNoImage ? 'the menu button' : 'your avatar' // Set up error handling for the user's avatar image, // so the onboarding text can be updated if it fails to load. From 6c2fa95a323b8284dedb0ff2b5f893f7050837a9 Mon Sep 17 00:00:00 2001 From: Jonathan Tran Date: Wed, 10 Jul 2024 17:50:25 -0400 Subject: [PATCH 3/6] Fix perspective camera toggle in debug pane to update immediately (#2969) --- src/clientSideScene/CameraControls.ts | 4 ++-- src/clientSideScene/ClientSideSceneComp.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/clientSideScene/CameraControls.ts b/src/clientSideScene/CameraControls.ts index 82024896f..4bbec9f68 100644 --- a/src/clientSideScene/CameraControls.ts +++ b/src/clientSideScene/CameraControls.ts @@ -518,9 +518,9 @@ export class CameraControls { direction.normalize() this.camera.position.copy(this.target).addScaledVector(direction, distance) } - usePerspectiveCamera = async () => { + usePerspectiveCamera = async (forceSend = false) => { this._usePerspectiveCamera() - if (this.syncDirection === 'clientToEngine') { + if (forceSend || this.syncDirection === 'clientToEngine') { await this.engineCommandManager.sendSceneCommand({ type: 'modeling_cmd_req', cmd_id: uuidv4(), diff --git a/src/clientSideScene/ClientSideSceneComp.tsx b/src/clientSideScene/ClientSideSceneComp.tsx index aeb261349..8b496abf2 100644 --- a/src/clientSideScene/ClientSideSceneComp.tsx +++ b/src/clientSideScene/ClientSideSceneComp.tsx @@ -717,7 +717,7 @@ export const CamDebugSettings = () => { if (camSettings.type === 'perspective') { sceneInfra.camControls.useOrthographicCamera() } else { - sceneInfra.camControls.usePerspectiveCamera() + sceneInfra.camControls.usePerspectiveCamera(true) } }} /> From c6545821379a8d72f9b381e37abc77aed1ca77e9 Mon Sep 17 00:00:00 2001 From: Pierre Jacquier Date: Wed, 10 Jul 2024 18:41:07 -0400 Subject: [PATCH 4/6] Build tauri updater test bundles on 'Cut release' PRs (#2927) * WIP: Automate tauri updater tests Fixes #2926 * Same product name * Tweak uploads * Add cat * Fix macos universal builds for updater * New artifact name * Revert "New artifact name" This reverts commit 61defcab185a114ceaacc1353010b0501050bdad. * Final check * Clean up --- .github/workflows/ci.yml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 784757f59..8fa771db1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,7 @@ on: # Will checkout the last commit from the default branch (main as of 2023-10-04) env: + CUT_RELEASE_PR: ${{ github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }} BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }} concurrency: @@ -110,8 +111,14 @@ jobs: echo "$(jq --arg name 'Zoo Modeling App (Nightly)' \ '.productName=$name' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json + - name: Set updater test version + if: env.CUT_RELEASE_PR + run: | + echo "$(jq --arg url 'https://dl.zoo.dev/releases/modeling-app/test/last_update.json' \ + '.plugins.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json + - uses: actions/upload-artifact@v3 - if: github.event_name == 'schedule' + if: ${{ github.event_name == 'schedule' || env.CUT_RELEASE_PR }} with: path: | package.json @@ -377,6 +384,30 @@ jobs: E2E_TAURI_ENABLED: true TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}' + - uses: actions/download-artifact@v3 + if: env.CUT_RELEASE_PR + + - name: Copy updated .json file for updater test + if: env.CUT_RELEASE_PR + run: | + ls -l artifact + cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json + cat src-tauri/tauri.release.conf.json + + - name: Build the app (release, updater test) + if: ${{ env.CUT_RELEASE_PR && matrix.os != 'ubuntu-latest' }} + env: + TAURI_CONF_ARGS: "-c ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}" + TAURI_BUNDLE_ARGS: "-b ${{ matrix.os == 'windows-latest' && 'msi' || 'dmg' }}" + run: "yarn tauri build ${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_BUNDLE_ARGS }} ${{ env.TAURI_ARGS_MACOS }}" + + - uses: actions/upload-artifact@v3 + if: ${{ env.CUT_RELEASE_PR && matrix.os != 'ubuntu-latest' }} + with: + path: "${{ matrix.os == 'macos-14' && 'src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg' || 'src-tauri/target/release/bundle/msi/*.msi' }}" + name: updater-test + + publish-apps-release: permissions: contents: write From 08e4c03ca71f04fb1f71bbc0060f93490123c963 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Thu, 11 Jul 2024 14:32:36 +1000 Subject: [PATCH 5/6] send failing test to axiom (#2996) * send failing test to axiom (ubuntu) * forgot always * rename * Update .github/workflows/playwright.yml Co-authored-by: Adam Sunderland * update to indivdual lines of json * another fix * tweak output * log macos too --------- Co-authored-by: Adam Sunderland --- .github/workflows/playwright.yml | 38 +++++++++++++++++++ playwright.config.ts | 5 ++- playwrightProcess.mjs | 65 ++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 playwrightProcess.mjs diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 3490ce17c..5733afa4a 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -83,6 +83,20 @@ jobs: uses: Swatinem/rust-cache@v2 with: workspaces: './src/wasm-lib' + - name: Install vector + run: | + curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh + chmod +x /tmp/vector.sh + /tmp/vector.sh -y -no-modify-path + mkdir -p /tmp/vector + cp .github/workflows/vector.toml /tmp/vector.toml + sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml + sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml + sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml + sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml + sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml + cat /tmp/vector.toml + ${HOME}/.vector/bin/vector --config /tmp/vector.toml & - name: Build Wasm (because rust diff) if: needs.check-rust-changes.outputs.rust-changed == 'true' run: yarn build:wasm @@ -160,6 +174,11 @@ jobs: env: CI: true token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + - name: send to axiom + if: always() + shell: bash + run: | + node playwrightProcess.mjs | tee /tmp/github-actions.log - uses: actions/upload-artifact@v4 if: always() with: @@ -226,6 +245,20 @@ jobs: uses: Swatinem/rust-cache@v2 with: workspaces: './src/wasm-lib' + - name: Install vector + run: | + curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh + chmod +x /tmp/vector.sh + /tmp/vector.sh -y -no-modify-path + mkdir -p /tmp/vector + cp .github/workflows/vector.toml /tmp/vector.toml + sed -i "" "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml + sed -i "" "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml + sed -i "" "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml + sed -i "" "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml + sed -i "" "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml + cat /tmp/vector.toml + ${HOME}/.vector/bin/vector --config /tmp/vector.toml & - name: Build Wasm (because rust diff) if: needs.check-rust-changes.outputs.rust-changed == 'true' run: yarn build:wasm @@ -264,6 +297,11 @@ jobs: env: CI: true token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + - name: send to axiom + if: always() + shell: bash + run: | + node playwrightProcess.mjs | tee /tmp/github-actions.log - uses: actions/upload-artifact@v4 if: ${{ always() }} with: diff --git a/playwright.config.ts b/playwright.config.ts index 4b5c7c43d..95136d8ae 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -20,7 +20,10 @@ export default defineConfig({ /* Different amount of parallelism on CI and local. */ workers: process.env.CI ? 4 : 4, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: [ + [process.env.CI ? 'dot' : 'list'], + ['json', { outputFile: './test-results/report.json' }], + ], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ diff --git a/playwrightProcess.mjs b/playwrightProcess.mjs new file mode 100644 index 000000000..c614e38fd --- /dev/null +++ b/playwrightProcess.mjs @@ -0,0 +1,65 @@ +import { readFileSync } from 'fs' + +const data = readFileSync('./test-results/report.json', 'utf8') + +// types, but was easier to store and run as normal js +// interface FailedTest { +// name: string; +// projectName: string; +// error: string; +// } + +// interface Spec { +// title: string; +// tests: Test[]; +// } + +// interface Test { +// expectedStatus: 'passed' | 'failed' | 'pending'; +// projectName: string; +// title: string; +// results: { +// status: 'passed' | 'failed' | 'pending'; +// error: {stack: string} +// }[] +// } + +// interface Suite { +// title: string +// suites: Suite[]; +// specs: Spec[]; +// } + +// const processReport = (suites: Suite[]): FailedTest[] => { +// const failedTests: FailedTest[] = [] +// const loopSuites = (suites: Suite[], previousName = '') => { +const processReport = (suites) => { + const failedTests = [] + const loopSuites = (suites, previousName = '') => { + if (!suites) return + for (const suite of suites) { + const name = (previousName ? `${previousName} -- ` : '') + suite.title + for (const spec of suite.specs) { + for (const test of spec.tests) { + for (const result of test.results) { + if ((result.status !== 'passed') && test.expectedStatus === 'passed') { + failedTests.push({ + name: (name + ' -- ' + spec.title) + (test.title ? ` -- ${test.title}` : ''), + status: result.status, + projectName: test.projectName, + error: result.error?.stack, + }) + } + } + } + } + loopSuites(suite.suites, name) + } + } + loopSuites(suites) + return failedTests.map(line => JSON.stringify(line)).join('\n') +} +const failedTests = processReport(JSON.parse(data).suites) +// log to stdout to be piped to axiom +console.log(failedTests) + From ff86e41283b389e3efd6ef1ba8f2022e3f67aa1d Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Thu, 11 Jul 2024 17:37:59 +1000 Subject: [PATCH 6/6] Roll your own Playwright retries (#3002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * roll you own playwright retries * tweak * tweak * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * add retries for ubuntu too * Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)" This reverts commit 327cc196cd0ba440012a7d8364070b1c17d7198b. * Revert "add retries for ubuntu too" This reverts commit db877748e274c4cd636b438e02ec0ace09c9bcb9. * add retries for ubuntu too * whoopsie --------- Co-authored-by: github-actions[bot] --- .github/workflows/playwright.yml | 123 +++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 37 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 5733afa4a..bc3203d1e 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -153,24 +153,52 @@ jobs: with: name: test-results-ubuntu-${{ github.sha }} path: test-results/ - - name: Run ubuntu/chrome flow retry failures + - name: Run ubuntu/chrome flow (with retries) id: retry if: always() run: | - if [[ -d "test-results" ]]; - then if [[ $(ls -1 "test-results" | wc -l) != "0" ]]; - then echo "retried=true" >> $GITHUB_OUTPUT; - else echo "retried=false" >> $GITHUB_OUTPUT; exit 0; - fi; - else echo "retried=false" >> $GITHUB_OUTPUT; exit 0; - fi; - yarn playwright test --project="Google Chrome" --last-failed e2e/playwright/flow-tests.spec.ts - env: - CI: true - token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} - - name: Run ubuntu/chrome flow - if: steps.retry.outputs.retried == 'false' - run: yarn playwright test --project="Google Chrome" e2e/playwright/flow-tests.spec.ts + if [[ ! -f "test-results/.last-run.json" ]]; then + # if no last run artifact, than run plawright normally + echo "run playwright normally" + yarn playwright test --project="Google Chrome" e2e/playwright/flow-tests.spec.ts || true + # # send to axiom + node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1 + fi + + retry=1 + max_retrys=4 + + # retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues + while [[ $retry -le $max_retrys ]]; do + if [[ -f "test-results/.last-run.json" ]]; then + failed_tests=$(jq '.failedTests | length' test-results/.last-run.json) + if [[ $failed_tests -gt 0 ]]; then + echo "retried=true" >>$GITHUB_OUTPUT + echo "run playwright with last failed tests and retry $retry" + yarn playwright test --project="Google Chrome" --last-failed e2e/playwright/flow-tests.spec.ts || true + # send to axiom + node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1 + retry=$((retry + 1)) + else + echo "retried=false" >>$GITHUB_OUTPUT + exit 0 + fi + else + echo "retried=false" >>$GITHUB_OUTPUT + exit 0 + fi + done + + echo "retried=false" >>$GITHUB_OUTPUT + + if [[ -f "test-results/.last-run.json" ]]; then + failed_tests=$(jq '.failedTests | length' test-results/.last-run.json) + if [[ $failed_tests -gt 0 ]]; then + # if it still fails after 3 retrys, then fail the job + exit 1 + fi + fi + exit 0 env: CI: true token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} @@ -274,34 +302,55 @@ jobs: with: name: test-results-macos-${{ github.sha }} path: test-results/ - - name: Run macos/safari flow retry failures + - name: Run macos/safari flow (with retries) id: retry if: always() run: | - if [[ -d "test-results" ]]; - then if [[ $(ls -1 "test-results" | wc -l) != "0" ]]; - then echo "retried=true" >> $GITHUB_OUTPUT; - else echo "retried=false" >> $GITHUB_OUTPUT; exit 0; - fi; - else echo "retried=false" >> $GITHUB_OUTPUT; exit 0; - fi; - yarn playwright test --project="webkit" --last-failed e2e/playwright/flow-tests.spec.ts + if [[ ! -f "test-results/.last-run.json" ]]; then + # if no last run artifact, than run plawright normally + echo "run playwright normally" + yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts || true + # # send to axiom + node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1 + fi + + retry=1 + max_retrys=4 + + # retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues + while [[ $retry -le $max_retrys ]]; do + if [[ -f "test-results/.last-run.json" ]]; then + failed_tests=$(jq '.failedTests | length' test-results/.last-run.json) + if [[ $failed_tests -gt 0 ]]; then + echo "retried=true" >>$GITHUB_OUTPUT + echo "run playwright with last failed tests and retry $retry" + yarn playwright test --project="webkit" --last-failed e2e/playwright/flow-tests.spec.ts || true + # send to axiom + node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1 + retry=$((retry + 1)) + else + echo "retried=false" >>$GITHUB_OUTPUT + exit 0 + fi + else + echo "retried=false" >>$GITHUB_OUTPUT + exit 0 + fi + done + + echo "retried=false" >>$GITHUB_OUTPUT + + if [[ -f "test-results/.last-run.json" ]]; then + failed_tests=$(jq '.failedTests | length' test-results/.last-run.json) + if [[ $failed_tests -gt 0 ]]; then + # if it still fails after 3 retrys, then fail the job + exit 1 + fi + fi + exit 0 env: CI: true token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} - - name: Run macos/safari flow - if: steps.retry.outputs.retried == 'false' - # webkit doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues) - # TODO remove this and the matrix and run all tests on ubuntu when this is fixed - run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts - env: - CI: true - token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} - - name: send to axiom - if: always() - shell: bash - run: | - node playwrightProcess.mjs | tee /tmp/github-actions.log - uses: actions/upload-artifact@v4 if: ${{ always() }} with: