Merge pull request #523 from heygen-com/fix/cli-validate-smoke-ci

fix: validate CLI smoke paths
This commit is contained in:
Miguel Ángel
2026-04-28 22:44:54 +02:00
committed by GitHub
3 changed files with 116 additions and 5 deletions
+97
View File
@@ -217,6 +217,103 @@ jobs:
echo "PASS: global install smoke test succeeded" echo "PASS: global install smoke test succeeded"
cli-smoke-required:
name: "CLI smoke (required)"
needs: changes
if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
with:
lfs: true
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Install FFmpeg
run: |
sudo apt-get update
sudo apt-get install -y ffmpeg
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build monorepo
run: bun run build
- name: Create smoke input video
run: |
set -euo pipefail
ffmpeg -hide_banner -loglevel error \
-f lavfi -i testsrc2=size=640x360:rate=30 \
-f lavfi -i sine=frequency=880:sample_rate=48000 \
-t 3 \
-c:v libx264 \
-pix_fmt yuv420p \
-c:a aac \
-shortest \
-y /tmp/hf-cli-input.mp4
test -s /tmp/hf-cli-input.mp4
- name: Smoke-test CLI from monorepo source
run: |
set -euo pipefail
rm -rf /tmp/hf-cli-inside
bun run --filter @hyperframes/cli dev -- init /tmp/hf-cli-inside \
--example warm-grain \
--video /tmp/hf-cli-input.mp4 \
--skip-transcribe \
--non-interactive \
--skip-skills
bun run --filter @hyperframes/cli dev -- lint /tmp/hf-cli-inside
bun run --filter @hyperframes/cli dev -- validate /tmp/hf-cli-inside --timeout 3000
bun run --filter @hyperframes/cli dev -- render /tmp/hf-cli-inside \
--quality standard \
--workers auto \
--strict \
--output /tmp/hf-cli-inside/renders/inside.mp4
test -s /tmp/hf-cli-inside/renders/inside.mp4
- name: Pack CLI tarball
run: |
set -euo pipefail
mkdir -p /tmp/hf-cli-pack
cd packages/cli
PACKED_TARBALL="$(npm pack --pack-destination /tmp/hf-cli-pack | tail -n 1)"
test -n "$PACKED_TARBALL"
test -f "/tmp/hf-cli-pack/$PACKED_TARBALL"
echo "HF_CLI_TARBALL=/tmp/hf-cli-pack/$PACKED_TARBALL" >> "$GITHUB_ENV"
- name: Install packed CLI outside monorepo
run: |
set -euo pipefail
npm install -g --prefix /tmp/hf-cli-global "$HF_CLI_TARBALL"
- name: Smoke-test packed CLI outside monorepo
run: |
set -euo pipefail
export PATH="/tmp/hf-cli-global/bin:$PATH"
rm -rf /tmp/hf-cli-outside
hyperframes init /tmp/hf-cli-outside \
--example warm-grain \
--video /tmp/hf-cli-input.mp4 \
--skip-transcribe \
--non-interactive \
--skip-skills
hyperframes lint /tmp/hf-cli-outside
hyperframes validate /tmp/hf-cli-outside --timeout 3000
hyperframes render /tmp/hf-cli-outside \
--quality standard \
--workers auto \
--strict \
--output /tmp/hf-cli-outside/renders/outside.mp4
test -s /tmp/hf-cli-outside/renders/outside.mp4
semantic-pr-title: semantic-pr-title:
name: Semantic PR title name: Semantic PR title
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
+5
View File
@@ -82,6 +82,11 @@ async function main() {
cpSync(layoutAuditScript, join(DIST, "commands", "layout-audit.browser.js")); cpSync(layoutAuditScript, join(DIST, "commands", "layout-audit.browser.js"));
} }
const contrastAuditScript = join(CLI_ROOT, "src", "commands", "contrast-audit.browser.js");
if (existsSync(contrastAuditScript)) {
cpSync(contrastAuditScript, join(DIST, "commands", "contrast-audit.browser.js"));
}
copyMdFiles(join(CLI_ROOT, "src", "docs"), join(DIST, "docs")); copyMdFiles(join(CLI_ROOT, "src", "docs"), join(DIST, "docs"));
console.log("[build-copy] done"); console.log("[build-copy] done");
+14 -5
View File
@@ -27,10 +27,6 @@ interface ContrastEntry {
bg: string; bg: string;
} }
// esbuild's text loader inlines this at build time — no runtime file read.
// @ts-expect-error — .browser.js files use esbuild text loader, not TS module resolution
import CONTRAST_AUDIT_SCRIPT from "./contrast-audit.browser.js";
const CONTRAST_SAMPLES = 5; const CONTRAST_SAMPLES = 5;
const SEEK_SETTLE_MS = 150; const SEEK_SETTLE_MS = 150;
@@ -64,7 +60,7 @@ async function runContrastAudit(page: import("puppeteer-core").Page): Promise<Co
const duration = await getCompositionDuration(page); const duration = await getCompositionDuration(page);
if (duration <= 0) return []; if (duration <= 0) return [];
await page.addScriptTag({ content: CONTRAST_AUDIT_SCRIPT }); await page.addScriptTag({ content: loadContrastAuditScript() });
const results: ContrastEntry[] = []; const results: ContrastEntry[] = [];
for (let i = 0; i < CONTRAST_SAMPLES; i++) { for (let i = 0; i < CONTRAST_SAMPLES; i++) {
@@ -86,6 +82,19 @@ async function runContrastAudit(page: import("puppeteer-core").Page): Promise<Co
return results; return results;
} }
function loadContrastAuditScript(): string {
const candidates = [
join(__dirname, "contrast-audit.browser.js"),
join(__dirname, "commands", "contrast-audit.browser.js"),
];
for (const candidate of candidates) {
if (existsSync(candidate)) return readFileSync(candidate, "utf-8");
}
throw new Error("Missing contrast audit browser script");
}
async function validateInBrowser( async function validateInBrowser(
projectDir: string, projectDir: string,
opts: { timeout?: number; contrast?: boolean }, opts: { timeout?: number; contrast?: boolean },