#Infinite Pages delete error

6 messages · Page 1 of 1 (latest)

upper herald
#

Hi. Tried this in an open channel, but no dice.

There's no Pages Help forum, so I'll try here, too.

Here's the situation: I can't delete an old Pages project.

The error says "too many deployments." There's a CF link to a project and npm command that deletes the deployments via the terminal. However, that isn't working, either.

https://developers.cloudflare.com/pages/platform/known-issues/#delete-a-project-with-a-high-number-of-deployments

(I don't really know what version of Pages it's on — two or three.)

Error:

Listing next 30 deployments, this may take a while...
Failed to list deployments on page 1... retrying (1/5)
Failed to list deployments on page 1... retrying (2/5)
Failed to list deployments on page 1... retrying (3/5)
Failed to list deployments on page 1... retrying (4/5)
Failed to list deployments on page 1... retrying (5/5)
Failed to list deployments on page 1.
Error: Could not fetch deployments for ...

I believe I passed the script the right API token, account ID, and project name.

Is my only option to try and delete a few hundred deployments by hand?

Lol. I can do it, but it's hilariously tragic. More so, if it fails.

Any thoughts, ideas, opinions, or better CF scripts?

cold jacinth
#

I followed this https://medium.com/@jaredpotter1/connecting-puppeteer-to-existing-chrome-window-8a10828149e0 , signed it to cloudflare on that chrome instance, and then vibe coded this, but the max I could delete was like 30 deployments before some error from the page being rerendered.

async function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

(async () => {
  const browser = await puppeteer.connect({
    browserWSEndpoint:
      "ws://<WEBSOCKET_FROM_THE_ARTICLE>",
  }); // set true for headless
  const page = await browser.newPage();

  await page.goto(
    "https://dash.cloudflare.com/<SOME-NUMBER>/pages/view/<PAGES_PROJECT_NAME>",
    { waitUntil: "networkidle0" }
  );

  while (true) {
    // Re-query all currently visible menu triggers
    const buttons = await page.$$('[data-testid="more-options-menu-trigger"]');

    // Find the first button with an enabled delete button in its menu
    let foundEnabled = false;

    for (let i = 0; i < buttons.length; i++) {
      // REFRESH the handle — don’t use buttons[i] directly
      const currentButtons = await page.$$(
        '[data-testid="more-options-menu-trigger"]'
      );
      const button = currentButtons[i];
      if (!button) continue;

      try {
        await button.click();
        await delay(300);

        const menu = await page.evaluateHandle((btn) => {
          let sibling = btn.nextElementSibling;
          while (sibling) {
            if (sibling.getAttribute("role") === "menu") return sibling;
            sibling = sibling.nextElementSibling;
          }
          return null;
        }, button);
Medium

Be itself Puppeteer (https://github.com/GoogleChrome/puppeteer) is a great tool created by Google to assist with automated UI testing…

#
          await page.keyboard.press("Escape");
          continue;
        }

        const deleteBtnHandle = await menu.evaluateHandle((menuEl) => {
          return (
            Array.from(menuEl.querySelectorAll("button[role='menuitem']")).find(
              (b) =>
                b.innerText.includes("Delete deployment") &&
                !b.disabled &&
                !b.hasAttribute("disabled")
            ) || null
          );
        });

        const deleteBtn = deleteBtnHandle.asElement();
        if (deleteBtn) {
          foundEnabled = true;

          await deleteBtn.click();

          try {
            const confirmBtn = await page.waitForSelector(
              '[data-testid="confirm"]',
              {
                visible: true,
                timeout: 3000,
              }
            );
            await confirmBtn.click();
          } catch {
            console.log("No confirm appeared, skipping");
          }

          await delay(800); // let virtualized list render next items
          await page.keyboard.press("Escape");
          break; // only handle one deletion per while iteration
        }

        await page.keyboard.press("Escape");
      } catch (err) {
        console.log("Button detached or click failed, skipping this one");
      }
    }

    if (!foundEnabled) {
      console.log("No more enabled Delete buttons visible, finished!");
      break;
    }
  }```
upper herald
#

That's a very clever idea.

I'll take a deeper look at it later. Thanks.

arctic sun
upper herald