Skip to content

feat: bundle action with ncc and add E2E workflow#1

Merged
DeDuckProject merged 20 commits intomainfrom
feat/e2e-action-workflow
Mar 11, 2026
Merged

feat: bundle action with ncc and add E2E workflow#1
DeDuckProject merged 20 commits intomainfrom
feat/e2e-action-workflow

Conversation

@DeDuckProject
Copy link
Copy Markdown
Owner

Summary

  • Bundles packages/action with @vercel/ncc into a self-contained dist/index.js — no pnpm install needed in CI
  • Adds examples/simple-app (plain-JS server, zero build step) as the E2E test target
  • Replaces the old broken demo.yml with a real E2E workflow that starts the example app, installs Playwright Chromium, and invokes ./packages/action locally

Test plan

  • Workflow triggers on this PR (pull_request event)
  • Example app starts on port 3000 and passes the readiness check
  • Action runs the full pipeline (diff → LLM → Playwright → GIF)
  • PR receives a bot comment with <!-- git-glimpse-demo --> marker containing a GIF or screenshot fallback
  • Action outputs (recording-url, comment-url, success) are populated in the workflow logs

🤖 Generated with Claude Code

DeDuckProject and others added 14 commits March 11, 2026 14:03
- Switch packages/action build from tsc to @vercel/ncc, producing a
  self-contained dist/index.js that CI can run without pnpm install
- Commit packages/action/dist/ (standard practice for GitHub Actions)
- Add @actions/artifact as devDep to packages/core to fix tsc types
- Create examples/simple-app (plain-JS server, no build step) for E2E
- Replace demo.yml with a real E2E workflow: starts the example app,
  installs Playwright Chromium, then invokes ./packages/action locally

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ore)

Add !examples/**/*.js exception so the plain-JS example server is committed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
!packages/action/dist/ only un-ignores the directory itself.
Change to !packages/action/dist/** to un-ignore all files within it,
including the critical index.js bundle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
esbuild was --external so wasn't bundled, but also not installed on
the CI runner. ncc handles esbuild's native binaries fine (same as
fsevents.node), so just include it in the bundle.

Also fix .gitignore: need both !packages/action/dist/ (directory) and
!packages/action/dist/** (contents) to fully un-ignore the dist folder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ncc was generating ESM (due to "type": "module"), but bundled Playwright
code uses CJS constructs like __dirname. Add a post-build step that
resets dist/package.json to {} so Node treats the bundle as CJS, which
is the GitHub Actions standard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Playwright can't be bundled by ncc (native deps + ESM/CJS conflicts).
Mark it external and restore pnpm install so it's available at runtime.
Bundle size drops from 8.7MB → 2.3MB as a bonus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… field)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ncc always outputs ESM when source has "type": "module", causing
__dirname errors in bundled Playwright and module-not-found errors
for external packages. esbuild with --format=cjs produces proper CJS
regardless of source module type, solving both issues definitively.

- Remove @vercel/ncc, patch-dist.cjs hack, and all ncc artifacts
- Bundle is now a single dist/index.js (CJS, "use strict")
- @playwright/test, playwright-core, esbuild remain external (from pnpm install)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Node treats .js as ESM when package.json has "type": "module", causing
require() to fail even though esbuild outputs valid CJS. Removing the
field lets Node default to CJS for dist/index.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pnpm's strict isolation only symlinks packages for direct dependencies.
Since @playwright/test was only a dep of @git-glimpse/core, it wasn't
accessible from packages/action/dist/ at runtime. Adding it as a direct
dep ensures pnpm creates the symlink in packages/action/node_modules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Node can't natively import .ts files. When the config path ends in .ts,
use esbuild to bundle-transpile it to a temp .mjs file, import that,
then clean up. .js/.mjs configs use the original dynamic import path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The default 1 MB buffer was too small for the diff between commits in CI,
causing spawnSync to throw ENOBUFS. Raise the limit to 10 MB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
execFileSync has a maxBuffer cap; large PRs with committed dist bundles
easily exceed it. Switch to a spawn-based streaming helper that has no
buffer limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 11, 2026

🎬 UI Demo Preview

Changes detected in: .github/workflows/demo.yml, .gitignore, examples/simple-app/git-glimpse.config.ts, examples/simple-app/package.json, examples/simple-app/server.js (+11 more)

What changed: A new example 'Product Page' web app has been added, featuring a wireless headphones listing with an Add to Cart counter and a Virtual Try-On modal. This serves as the live demo target for the GitGlimpse end-to-end workflow.

Screenshot 1

Demo script (auto-generated)
import type { Page } from '@playwright/test';

export async function demo(page: Page): Promise<void> {
  await page.setViewportSize({ width: 1280, height: 720 });

  // Navigate to the home page
  await page.goto('http://localhost:3000');
  await page.waitForLoadState('networkidle');
  await page.waitForTimeout(1500);

  // Show the product page with the Wireless Headphones card
  await page.waitForSelector('text=Wireless Headphones');
  await page.waitForTimeout(1000);

  // Click 'Add to Cart' several times to show the counter incrementing
  const addToCartButton = page.locator('button', { hasText: 'Add to Cart' });

  await addToCartButton.click();
  await page.waitForTimeout(700);

  await addToCartButton.click();
  await page.waitForTimeout(700);

  await addToCartButton.click();
  await page.waitForTimeout(1000);

  // Pause to show the counter at 3
  await page.waitForTimeout(1500);

  // Click the green 'Virtual Try-On' button to open the modal overlay
  const tryOnButton = page.locator('button', { hasText: 'Virtual Try-On' });
  await tryOnButton.click();
  await page.waitForTimeout(1500);

  // Modal should now be visible
  await page.waitForSelector('text=See how these headphones look on you');
  await page.waitForTimeout(1500);

  // Close the modal using the X button
  const closeButton = page.locator('button[aria-label="Close"]');
  await closeButton.click();
  await page.waitForTimeout(1500);

  // Final pause on the product page
  await page.waitForTimeout(1000);
}

Generated by git-glimpse

DeDuckProject and others added 6 commits March 11, 2026 16:44
Local file paths were being passed directly as URLs to postPRComment,
causing 404s when GitHub rendered them relative to the compare page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The /artifacts path doesn't exist on GitHub — the correct URL
is the run page itself (/actions/runs/{runId}).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The uploadArtifact response includes an id field that can be used
to build the direct URL: /actions/runs/{runId}/artifacts/{artifactId}.
Falls back to the run page URL if no id is returned.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also update action build script to always build @git-glimpse/core first,
preventing stale dist from being bundled when building action in isolation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Upload screenshots via GitHub release assets (browser_download_url)
instead of Actions artifacts, so the URL is publicly accessible and
can be embedded as an image in the comment with ![...](url).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@DeDuckProject DeDuckProject merged commit b802da9 into main Mar 11, 2026
1 check passed
@DeDuckProject DeDuckProject deleted the feat/e2e-action-workflow branch March 11, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant