.mise/tasks/run-with-frontend
.mise/tasks/run-with-frontendBrowse 1970 files
1,031 tokens
3,918 bytes
Token encoding: o200k_base
Snapshot 21a254f
← Back to SKILL.md
1#!/usr/bin/env bun2 3/**4 * Development script to test building with the Railpack BuildKit frontend.5 *6 * This script validates the production BuildKit frontend flow by:7 * 1. Generating a build plan using `railpack plan`8 * 2. Invoking BuildKit with the frontend container image (ghcr.io/railwayapp/railpack:railpack-frontend)9 * 3. Loading the resulting image into Docker10 *11 * This is useful for testing the frontend integration locally before publishing,12 * as the frontend path is what production platforms use. The `railpack build` command13 * uses a different approach (direct BuildKit client) for simplicity.14 *15 * Example:16 * bun scripts/run-with-frontend.ts examples/node-vite-react17 * bun scripts/run-with-frontend.ts examples/node-vite-react --env NODE_ENV=production18 */19 20import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";21import { join } from "node:path";22import { spawnSync } from "node:child_process";23import crypto from "node:crypto";24 25const PLAN_FILE = "railpack-plan.json";26const PRODUCTION_FRONTEND_IMAGE_NAME = "ghcr.io/railwayapp/railpack:railpack-frontend";27 28// Parse command line arguments29const args = process.argv.slice(2);30if (args.length === 0) {31 console.error("Please provide a directory path");32 process.exit(1);33}34 35const dir = args[0];36const envArgs = args.slice(1).filter((arg) => arg.startsWith("--env"));37 38// Create temp directory to save the build plan to39const randId = Math.random().toString(36).slice(2);40const tmpDir = join("/tmp", "railpack-" + randId);41const planDir = join(tmpDir, "plan");42mkdirSync(planDir, { recursive: true });43 44const cleanup = () => {45 if (existsSync(tmpDir)) {46 rmSync(tmpDir, { recursive: true, force: true });47 }48};49 50process.on("exit", cleanup);51process.on("SIGINT", () => {52 cleanup();53 process.exit();54});55 56// Generate build plan57console.log(`Generating build plan for ${dir}`);58const planResult = spawnSync(59 "go",60 ["run", "cmd/cli/main.go", "plan", dir, ...envArgs],61 {62 stdio: ["inherit", "pipe", "inherit"],63 }64);65 66if (planResult.status !== 0) {67 console.error("Failed to generate build plan");68 process.exit(1);69}70 71const planPath = join(planDir, PLAN_FILE);72writeFileSync(planPath, planResult.stdout);73 74// Parse all env vars so that we can use them as secrets75const envVars: Record<string, string> = {};76const secretArgs: string[] = [];77 78// Find all env args and their values79for (let i = 0; i < args.length; i++) {80 if (args[i] === "--env" && i + 1 < args.length) {81 const nameValue = args[i + 1];82 const [name, value] = nameValue.split("=");83 if (name && value) {84 envVars[name] = value;85 secretArgs.push(`--secret=id=${name},env=${name}`);86 }87 i++; // Skip the next argument since we've processed it88 }89}90 91// Pipe buildctl and docker load together92const buildctlArgs = [93 "build",94 `--local`,95 `context=${dir}`,96 `--local`,97 `dockerfile=${planDir}`,98 "--frontend=gateway.v0",99 "--opt",100 `source=${PRODUCTION_FRONTEND_IMAGE_NAME}`,101 "--output",102 "type=docker,name=test",103 ...secretArgs,104];105 106// Options that are passed to our custom frontend107const cacheKey = dir;108buildctlArgs.push("--opt", `cache-key=${cacheKey}`);109 110if (Object.keys(envVars).length > 0) {111 const secretsHash = crypto112 .createHash("sha256")113 .update(Object.values(envVars).sort().join(""))114 .digest("hex");115 buildctlArgs.push("--opt", `secrets-hash=${secretsHash}`);116}117 118console.log(`Executing buildctl\n ${buildctlArgs.join(" ")}`);119 120const buildctl = spawnSync("buildctl", buildctlArgs, {121 stdio: ["inherit", "pipe", "inherit"],122 env: { ...process.env, ...envVars },123});124 125if (buildctl.status !== 0) {126 console.error("buildctl command failed");127 process.exit(1);128}129 130const dockerLoad = spawnSync("docker", ["load"], {131 input: buildctl.stdout,132 stdio: ["pipe", "inherit", "inherit"],133});134 135if (dockerLoad.status !== 0) {136 console.error("docker load failed");137 process.exit(1);138}139