From 99b5b01aa2f8af1d99fa3a313ed640fa60499b28 Mon Sep 17 00:00:00 2001 From: Nick Clark Date: Tue, 26 May 2026 12:20:47 -0400 Subject: [PATCH 1/6] iPad fixes for the layout --- .../PieceTray.module.responsive.module.css | 30 +++++++++----- .../puzzle/canvas/render/renderTrayPiece.ts | 18 +++++---- src/app/responsive.responsive.e2e.spec.ts | 1 + src/app/screens/Play/PlayScreen.e2e.spec.ts | 1 + .../styles/PlayScreen.board.base.module.css | 36 +++++++++-------- .../PlayScreen.board.responsive.module.css | 39 +++++++++++-------- 6 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/app/components/PieceTray/PieceTray.module.responsive.module.css b/src/app/components/PieceTray/PieceTray.module.responsive.module.css index 137c9858..17ce6705 100644 --- a/src/app/components/PieceTray/PieceTray.module.responsive.module.css +++ b/src/app/components/PieceTray/PieceTray.module.responsive.module.css @@ -280,8 +280,9 @@ @media (min-width: 820px) and (max-width: 1366px) and (min-height: 650px) and (max-height: 860px) and (pointer: coarse) and (orientation: landscape) { .header { - padding: 5px 10px; - gap: 6px; + padding: 3px 8px; + gap: 4px; + min-height: 34px; } .quickFilters, @@ -289,25 +290,36 @@ display: none; } + .randomBtn { + min-width: 34px; + min-height: 34px; + padding: 5px; + } + + .segment button { + min-height: 34px; + padding: 4px 8px; + } + .scrollerWrap { - min-height: 62px; - padding: 4px 8px 6px; + min-height: 46px; + padding: 2px 8px 4px; } .scroller, .trayCompact .scroller, .trayExtraCompact .scroller { - padding: 4px 8px; + padding: 2px 8px; } .trayCompact .thumbWrap { - width: 52px; - height: 52px; + width: 44px; + height: 44px; } .trayCompact .pieceButton, .trayCompact .blankSlot { - min-width: 56px; - min-height: 56px; + min-width: 48px; + min-height: 48px; } } diff --git a/src/app/puzzle/canvas/render/renderTrayPiece.ts b/src/app/puzzle/canvas/render/renderTrayPiece.ts index 3c411988..6a1e6db4 100644 --- a/src/app/puzzle/canvas/render/renderTrayPiece.ts +++ b/src/app/puzzle/canvas/render/renderTrayPiece.ts @@ -27,14 +27,16 @@ export function renderTrayPiece( scale: number = 0.5, options: RenderTrayPieceOptions = {}, ): HTMLCanvasElement { - const CANVAS_PAD = 4; - const maxDim = Math.max(piece.w, piece.h); - const scaledSize = Math.ceil(maxDim * scale); - const canvasSize = scaledSize + CANVAS_PAD * 2; + const OUTLINE_GUTTER = 8; + const rot90 = piece.rotation === 90 || piece.rotation === 270; + const renderW = rot90 ? piece.h : piece.w; + const renderH = rot90 ? piece.w : piece.h; + const canvasW = Math.ceil(renderW * scale) + OUTLINE_GUTTER * 2; + const canvasH = Math.ceil(renderH * scale) + OUTLINE_GUTTER * 2; const canvas = document.createElement("canvas"); - canvas.width = canvasSize; - canvas.height = canvasSize; + canvas.width = canvasW; + canvas.height = canvasH; const ctx = canvas.getContext("2d"); if (!ctx) return canvas; @@ -54,8 +56,8 @@ export function renderTrayPiece( return canvas; } - const canvasCenterX = canvasSize / 2; - const canvasCenterY = canvasSize / 2; + const canvasCenterX = canvasW / 2; + const canvasCenterY = canvasH / 2; ctx.translate(canvasCenterX, canvasCenterY); ctx.scale(scale, scale); ctx.rotate((piece.rotation * Math.PI) / 180); diff --git a/src/app/responsive.responsive.e2e.spec.ts b/src/app/responsive.responsive.e2e.spec.ts index 290e128a..c5683c67 100644 --- a/src/app/responsive.responsive.e2e.spec.ts +++ b/src/app/responsive.responsive.e2e.spec.ts @@ -180,6 +180,7 @@ test.describe("Responsive smoke", () => { expect(boardBox).not.toBeNull(); expect(trayBox).not.toBeNull(); + expect(boardBox?.width ?? 0).toBeGreaterThanOrEqual(560); expect(trayBox?.y ?? 0).toBeGreaterThanOrEqual( (boardBox?.y ?? 0) + (boardBox?.height ?? 0) - 2, ); diff --git a/src/app/screens/Play/PlayScreen.e2e.spec.ts b/src/app/screens/Play/PlayScreen.e2e.spec.ts index e30e7e01..3ee04c7c 100644 --- a/src/app/screens/Play/PlayScreen.e2e.spec.ts +++ b/src/app/screens/Play/PlayScreen.e2e.spec.ts @@ -647,6 +647,7 @@ test.describe("Play screen tablet landscape touch", () => { expect( Math.abs((liveBoardBox?.width ?? 0) - (liveBoardBox?.height ?? 0)), ).toBeLessThanOrEqual(2); + expect(liveBoardBox?.width ?? 0).toBeGreaterThanOrEqual(560); expect( (trayBox?.y ?? Number.POSITIVE_INFINITY) + (trayBox?.height ?? 0), ).toBeLessThanOrEqual(834); diff --git a/src/app/screens/Play/styles/PlayScreen.board.base.module.css b/src/app/screens/Play/styles/PlayScreen.board.base.module.css index 17103c8b..0519425e 100644 --- a/src/app/screens/Play/styles/PlayScreen.board.base.module.css +++ b/src/app/screens/Play/styles/PlayScreen.board.base.module.css @@ -36,7 +36,7 @@ .playBody { --play-board-stage-size: min( var(--play-board-tray-width, min(100%, 760px)), - calc(var(--app-vh-fill, 100dvh) - 338px) + calc(var(--app-vh-fill, 100dvh) - 286px) ); } @@ -56,31 +56,35 @@ --play-board-tray-gap: 14px; --play-board-stage-size: min( var(--play-board-tray-width, min(100%, 820px)), - calc(var(--app-vh-fill, 100dvh) - 384px) + calc(var(--app-vh-fill, 100dvh) - 264px) ); - padding-top: 12px; + padding-top: 8px; } .playBody .main { - height: calc(var(--play-board-stage-size) + 34px); - max-height: calc(var(--play-board-stage-size) + 34px); + height: auto; + max-height: none; padding-top: 0; padding-bottom: 0; } .playBody .trayArea .trayInDock, .playBody .trayArea .trayInDock.trayWrapLarge { - height: clamp(104px, 13vh, 138px); - max-height: min(138px, 18vh); - min-height: 92px; + height: clamp(92px, 11vh, 116px); + max-height: min(116px, 15vh); + min-height: 88px; } } @media (min-width: 601px) and (max-width: 1366px) and (pointer: coarse) and (orientation: landscape) { .playBody { - --play-board-tray-width: min(100%, 760px); - --play-board-tray-gap: 12px; - padding-top: 8px; + --play-board-tray-width: min(100%, 960px); + --play-board-tray-gap: 10px; + --play-board-stage-size: min( + var(--play-board-tray-width, min(100%, 960px)), + calc(var(--app-vh-fill, 100dvh) - 214px) + ); + padding-top: 4px; } .playBody .main { @@ -95,11 +99,11 @@ max-width: min(100%, var(--play-board-tray-width)); } - .playBody .trayArea .tray, - .playBody .trayArea .tray.trayWrapLarge { - height: clamp(88px, 12vh, 112px); - max-height: min(112px, 14vh); - min-height: 82px; + .playBody .trayArea .trayInDock, + .playBody .trayArea .trayInDock.trayWrapLarge { + height: clamp(82px, 10vh, 98px); + max-height: min(98px, 12vh); + min-height: 78px; } } diff --git a/src/app/screens/Play/styles/PlayScreen.board.responsive.module.css b/src/app/screens/Play/styles/PlayScreen.board.responsive.module.css index 53be0f6b..838a397a 100644 --- a/src/app/screens/Play/styles/PlayScreen.board.responsive.module.css +++ b/src/app/screens/Play/styles/PlayScreen.board.responsive.module.css @@ -656,33 +656,38 @@ } .playBody { - --play-board-tray-gap: 14px; + --play-board-tray-gap: 10px; --play-board-stage-size: min( calc( 100dvw - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px) - 32px ), - calc(var(--app-vh-fill, 100dvh) - var(--play-top-bar-outer-h, 60px) - 172px) + calc(var(--app-vh-fill, 100dvh) - var(--play-top-bar-outer-h, 60px) - 148px) ); flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0; - padding: 8px 14px 0; + padding: 4px 14px 0; } .playBody .main { flex: 0 1 auto; width: 100%; - height: calc(var(--play-board-stage-size) + 24px); - max-height: calc(var(--play-board-stage-size) + 24px); - padding-top: 6px; - padding-bottom: 6px; + height: calc(var(--play-board-stage-size) + 20px); + max-height: calc(var(--play-board-stage-size) + 20px); + padding-top: 4px; + padding-bottom: 4px; align-items: center; overflow: hidden; border-bottom-left-radius: calc(var(--radius-board, 20px) + 10px); border-bottom-right-radius: calc(var(--radius-board, 20px) + 10px); } + .boardWrapper { + width: min(100%, var(--play-board-stage-size)); + max-width: min(100%, var(--play-board-stage-size)); + } + .playBody .trayArea { width: 100%; min-width: 0; @@ -694,9 +699,9 @@ .playBody .trayArea .trayInDock, .playBody .trayArea .trayInDock.trayWrapLarge { flex: 0 0 auto; - height: clamp(136px, 16vh, 156px); - max-height: min(156px, 19vh); - min-height: 136px; + height: clamp(88px, 11vh, 104px); + max-height: min(104px, 13vh); + min-height: 84px; } .boardLayoutShell[data-replay-active="true"] .playBody { @@ -721,23 +726,23 @@ calc( 100dvw - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px) - 28px ), - calc(var(--app-vh-fill, 100dvh) - var(--play-top-bar-outer-h, 60px) - 188px) + calc(var(--app-vh-fill, 100dvh) - var(--play-top-bar-outer-h, 60px) - 148px) ); - padding-top: 8px; + padding-top: 4px; } .playBody .main { - height: calc(var(--play-board-stage-size) + 24px); - max-height: calc(var(--play-board-stage-size) + 24px); + height: calc(var(--play-board-stage-size) + 20px); + max-height: calc(var(--play-board-stage-size) + 20px); padding-top: 4px; padding-bottom: 4px; } .playBody .trayArea .trayInDock, .playBody .trayArea .trayInDock.trayWrapLarge { - height: clamp(132px, 16vh, 148px); - max-height: min(148px, 19vh); - min-height: 132px; + height: clamp(84px, 10vh, 98px); + max-height: min(98px, 12vh); + min-height: 80px; } } From 5d719559e1affe83307c3fe7136213936d2dd6f2 Mon Sep 17 00:00:00 2001 From: Nick Clark Date: Tue, 26 May 2026 13:20:32 -0400 Subject: [PATCH 2/6] Fixing this up --- .github/workflows/Phuzzle.yml | 38 +++++++++++------------ .github/workflows/vercel-production.yml | 4 +-- src/app/responsive.responsive.e2e.spec.ts | 23 +++++++++----- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.github/workflows/Phuzzle.yml b/.github/workflows/Phuzzle.yml index aa38f06b..8cabc458 100644 --- a/.github/workflows/Phuzzle.yml +++ b/.github/workflows/Phuzzle.yml @@ -15,7 +15,7 @@ jobs: name: 🧩 Quality + Build runs-on: ubuntu-latest env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" permissions: contents: read @@ -28,12 +28,12 @@ jobs: steps: - name: ⬇️ Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: 🧰 Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6.4.0 with: node-version: "24" cache: npm @@ -67,7 +67,7 @@ jobs: run: npm run test - name: 📤 Upload production build - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: phuzzle-dist path: dist @@ -79,7 +79,7 @@ jobs: runs-on: ubuntu-latest needs: quality env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" PW_USE_EXISTING_BUILD: "1" PW_USE_EDGE: "1" @@ -89,10 +89,10 @@ jobs: steps: - name: ⬇️ Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: 🧰 Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: "24" cache: npm @@ -102,7 +102,7 @@ jobs: run: npm ci - name: 📥 Download production build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: phuzzle-dist path: dist @@ -115,7 +115,7 @@ jobs: - name: 📤 Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: playwright-smoke-artifacts path: | @@ -129,7 +129,7 @@ jobs: runs-on: ubuntu-latest needs: quality env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" PW_USE_EXISTING_BUILD: "1" defaults: @@ -138,10 +138,10 @@ jobs: steps: - name: ⬇️ Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: 🧰 Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: "24" cache: npm @@ -151,7 +151,7 @@ jobs: run: npm ci - name: 📥 Download production build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: phuzzle-dist path: dist @@ -164,7 +164,7 @@ jobs: - name: 📤 Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: playwright-layout-artifacts path: | @@ -178,7 +178,7 @@ jobs: runs-on: ubuntu-latest needs: quality env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" permissions: contents: read @@ -191,10 +191,10 @@ jobs: steps: - name: ⬇️ Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: 🧰 Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: "24" cache: npm @@ -204,7 +204,7 @@ jobs: run: npm ci - name: 📥 Download production build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: phuzzle-dist path: dist @@ -216,7 +216,7 @@ jobs: - name: 📤 Upload Lighthouse reports if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: lhci-reports path: lhci-reports diff --git a/.github/workflows/vercel-production.yml b/.github/workflows/vercel-production.yml index bb652cdf..79979883 100644 --- a/.github/workflows/vercel-production.yml +++ b/.github/workflows/vercel-production.yml @@ -17,10 +17,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6.4.0 with: node-version: "24" cache: npm diff --git a/src/app/responsive.responsive.e2e.spec.ts b/src/app/responsive.responsive.e2e.spec.ts index c5683c67..ccafadb0 100644 --- a/src/app/responsive.responsive.e2e.spec.ts +++ b/src/app/responsive.responsive.e2e.spec.ts @@ -229,6 +229,9 @@ test.describe("Responsive smoke", () => { const tray = page.getByRole("list"); await expect(tray).toBeVisible({ timeout: 15000 }); + await expect(tray.getByRole("button", { name: /place piece/i }).first()).toBeVisible({ + timeout: 15000, + }); const hasCoarsePointer = await page.evaluate( () => window.matchMedia("(pointer: coarse)").matches, @@ -238,16 +241,20 @@ test.describe("Responsive smoke", () => { await expect(page.getByRole("button", { name: /scroll right/i })).toHaveCount(0); } + await expect + .poll( + async () => + tray.evaluate((node) => { + const el = node as HTMLDivElement; + return Math.max(0, el.scrollWidth - el.clientWidth); + }), + { timeout: 15000 }, + ) + .toBeGreaterThan(0); + const right = await tray.evaluate((node) => { const el = node as HTMLDivElement; - const paddingStart = 12; - const paddingEnd = 12; - const row = el.firstElementChild as HTMLElement | null; - const contentWidth = - row && row.offsetWidth > 0 - ? paddingStart + row.offsetWidth + paddingEnd - : el.scrollWidth; - const max = Math.max(0, contentWidth - el.clientWidth); + const max = Math.max(0, el.scrollWidth - el.clientWidth); const before = el.scrollLeft; el.scrollTo({ left: max }); el.scrollBy({ left: 2000 }); From ecb1f994c68c9385e488592603360110c2d013f5 Mon Sep 17 00:00:00 2001 From: Nick Clark Date: Tue, 26 May 2026 14:59:50 -0400 Subject: [PATCH 3/6] Fixing github actions --- .github/workflows/Phuzzle.yml | 20 ++++++++++---------- .github/workflows/renovate-lockfile-pr.yml | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/Phuzzle.yml b/.github/workflows/Phuzzle.yml index 8cabc458..b1f6dac5 100644 --- a/.github/workflows/Phuzzle.yml +++ b/.github/workflows/Phuzzle.yml @@ -67,7 +67,7 @@ jobs: run: npm run test - name: 📤 Upload production build - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: phuzzle-dist path: dist @@ -92,7 +92,7 @@ jobs: uses: actions/checkout@v6 - name: 🧰 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v6.4.0 with: node-version: "24" cache: npm @@ -102,7 +102,7 @@ jobs: run: npm ci - name: 📥 Download production build - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v7 with: name: phuzzle-dist path: dist @@ -115,7 +115,7 @@ jobs: - name: 📤 Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: playwright-smoke-artifacts path: | @@ -141,7 +141,7 @@ jobs: uses: actions/checkout@v6 - name: 🧰 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v6.4.0 with: node-version: "24" cache: npm @@ -151,7 +151,7 @@ jobs: run: npm ci - name: 📥 Download production build - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v7 with: name: phuzzle-dist path: dist @@ -164,7 +164,7 @@ jobs: - name: 📤 Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: playwright-layout-artifacts path: | @@ -194,7 +194,7 @@ jobs: uses: actions/checkout@v6 - name: 🧰 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v6.4.0 with: node-version: "24" cache: npm @@ -204,7 +204,7 @@ jobs: run: npm ci - name: 📥 Download production build - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v7 with: name: phuzzle-dist path: dist @@ -216,7 +216,7 @@ jobs: - name: 📤 Upload Lighthouse reports if: always() - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: lhci-reports path: lhci-reports diff --git a/.github/workflows/renovate-lockfile-pr.yml b/.github/workflows/renovate-lockfile-pr.yml index 5379b3be..e15a670b 100644 --- a/.github/workflows/renovate-lockfile-pr.yml +++ b/.github/workflows/renovate-lockfile-pr.yml @@ -17,7 +17,7 @@ jobs: false runs-on: ubuntu-latest env: - # Opt into Node.js 24 for JavaScript actions (actions/checkout, actions/setup-node) + # Opt into Node.js 24 for JavaScript actions. FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" steps: @@ -27,7 +27,7 @@ jobs: fetch-depth: 0 - name: 🧰 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v6.4.0 with: node-version: "24" cache: "npm" From a49d84245418e7ee548c0ad726d7bbb877cc7f2c Mon Sep 17 00:00:00 2001 From: Nick Clark Date: Wed, 27 May 2026 06:55:59 -0400 Subject: [PATCH 4/6] Trying to see if my key works now --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 167da96f..35669d05 100644 --- a/README.md +++ b/README.md @@ -162,3 +162,4 @@ Different strengths, shared ownership, great teamwork. ## License MIT License. See [LICENSE.md](./LICENSE.md). + From c040e4a70de7e65d2ce2b38a4ca7fc9ab7fbe28f Mon Sep 17 00:00:00 2001 From: Nick Clark Date: Wed, 27 May 2026 06:59:20 -0400 Subject: [PATCH 5/6] style: auto-format with Prettier [skip-precheck] --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 35669d05..167da96f 100644 --- a/README.md +++ b/README.md @@ -162,4 +162,3 @@ Different strengths, shared ownership, great teamwork. ## License MIT License. See [LICENSE.md](./LICENSE.md). - From d8cc04b4b5a4b68b1b03e8a9d1b36f212bf8543c Mon Sep 17 00:00:00 2001 From: Nick Clark Date: Wed, 27 May 2026 07:26:28 -0400 Subject: [PATCH 6/6] couple more changes --- .github/CODEOWNERS | 1 + .github/workflows/Phuzzle.yml | 4 +++- .github/workflows/renovate-patch-automerge.yml | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..697b7310 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @hannahro15 @v-gajjar @NickTheDevOpsGuy diff --git a/.github/workflows/Phuzzle.yml b/.github/workflows/Phuzzle.yml index b1f6dac5..f7c759d1 100644 --- a/.github/workflows/Phuzzle.yml +++ b/.github/workflows/Phuzzle.yml @@ -3,8 +3,10 @@ name: 🧩 Phuzzle on: pull_request: + types: [opened, synchronize, reopened, ready_for_review] branches: - develop + workflow_dispatch: concurrency: group: Phuzzle-${{ github.ref }} @@ -59,7 +61,7 @@ jobs: - name: 📦 Bundle size check env: - BASELINE_REF: origin/${{ github.base_ref }} + BASELINE_REF: origin/${{ github.base_ref || 'develop' }} CHECK_BUNDLE_USE_EXISTING_DIST: "1" run: npm run check:bundle diff --git a/.github/workflows/renovate-patch-automerge.yml b/.github/workflows/renovate-patch-automerge.yml index d902f4e9..828c9e0c 100644 --- a/.github/workflows/renovate-patch-automerge.yml +++ b/.github/workflows/renovate-patch-automerge.yml @@ -6,6 +6,7 @@ on: pull_request_target: types: [opened, synchronize, reopened, ready_for_review, labeled] branches: [develop] + workflow_dispatch: permissions: contents: write