improve logging, remove act
This commit is contained in:
@@ -1,73 +0,0 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { config } from "dotenv";
|
||||
import { setupTestRepo } from "./setup.ts";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const tempDir = join(__dirname, "..", ".temp");
|
||||
const actionPath = join(__dirname, "..");
|
||||
const envPath = join(__dirname, "..", "..", ".env");
|
||||
|
||||
const ENV_VARS = ["ANTHROPIC_API_KEY", "GITHUB_INSTALLATION_TOKEN"];
|
||||
|
||||
export function runAct(prompt: string): void {
|
||||
setupTestRepo({ tempDir });
|
||||
|
||||
config({ path: envPath });
|
||||
|
||||
const workflowPath = join(tempDir, ".github", "workflows", "pullfrog.yml");
|
||||
|
||||
const distPath = join(actionPath, ".act-dist");
|
||||
console.log("📦 Creating minimal distribution for act...");
|
||||
execSync(`rm -rf "${distPath}" && mkdir -p "${distPath}"`, { shell: "/bin/bash" });
|
||||
|
||||
["action.yml", "entry.cjs", "index.cjs", "package.json"].forEach((file) => {
|
||||
const src = join(actionPath, file);
|
||||
if (existsSync(src)) {
|
||||
execSync(`cp "${src}" "${distPath}"`);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const escapedPrompt = prompt.replace(/'/g, "'\\''");
|
||||
|
||||
const actCommandParts = [
|
||||
"act",
|
||||
"workflow_dispatch",
|
||||
"-W",
|
||||
workflowPath,
|
||||
"--input",
|
||||
`prompt='${escapedPrompt}'`,
|
||||
"--local-repository",
|
||||
`pullfrog/action@v0=${distPath}`, // Use minimal dist without symlinks
|
||||
];
|
||||
|
||||
ENV_VARS.forEach((key) => {
|
||||
if (process.env[key]) {
|
||||
actCommandParts.push("-s", key);
|
||||
}
|
||||
});
|
||||
|
||||
const actCommand = actCommandParts.join(" ");
|
||||
|
||||
console.log("🚀 Running act with prompt:");
|
||||
console.log("─".repeat(50));
|
||||
console.log(prompt);
|
||||
console.log("─".repeat(50));
|
||||
console.log("");
|
||||
|
||||
execSync(actCommand, {
|
||||
stdio: "inherit",
|
||||
cwd: join(__dirname, "..", ".."),
|
||||
});
|
||||
execSync(`rm -rf "${distPath}"`);
|
||||
} catch (error) {
|
||||
execSync(`rm -rf "${distPath}"`);
|
||||
console.error("❌ Act execution failed:", (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* CLI output utilities for GitHub Actions and local development
|
||||
* Uses GitHub Actions Job Summaries API when available for rich formatting
|
||||
*/
|
||||
|
||||
import * as core from "@actions/core";
|
||||
|
||||
const isGitHubActions = !!process.env.GITHUB_ACTIONS;
|
||||
|
||||
/**
|
||||
* Print a formatted box with text (for console output)
|
||||
*/
|
||||
function boxString(
|
||||
text: string,
|
||||
options?: {
|
||||
title?: string;
|
||||
maxWidth?: number;
|
||||
indent?: string;
|
||||
padding?: number;
|
||||
}
|
||||
): string {
|
||||
const { title, maxWidth = 80, indent = "", padding = 1 } = options || {};
|
||||
|
||||
const lines = text.trim().split("\n");
|
||||
const wrappedLines: string[] = [];
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.length <= maxWidth - padding * 2) {
|
||||
wrappedLines.push(line);
|
||||
} else {
|
||||
const words = line.split(" ");
|
||||
let currentLine = "";
|
||||
|
||||
for (const word of words) {
|
||||
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
||||
if (testLine.length <= maxWidth - padding * 2) {
|
||||
currentLine = testLine;
|
||||
} else {
|
||||
if (currentLine) {
|
||||
wrappedLines.push(currentLine);
|
||||
currentLine = word;
|
||||
} else {
|
||||
wrappedLines.push(word.substring(0, maxWidth - padding * 2));
|
||||
currentLine = word.substring(maxWidth - padding * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLine) {
|
||||
wrappedLines.push(currentLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const maxLineLength = Math.max(...wrappedLines.map((line) => line.length));
|
||||
const boxWidth = maxLineLength + padding * 2;
|
||||
|
||||
let result = "";
|
||||
|
||||
if (title) {
|
||||
const titleLine = ` ${title} `;
|
||||
const titlePadding = Math.max(0, boxWidth - titleLine.length);
|
||||
result += `${indent}┌${titleLine}${"─".repeat(titlePadding)}┐\n`;
|
||||
}
|
||||
|
||||
if (!title) {
|
||||
result += `${indent}┌${"─".repeat(boxWidth)}┐\n`;
|
||||
}
|
||||
|
||||
for (const line of wrappedLines) {
|
||||
const paddedLine = line.padEnd(maxLineLength);
|
||||
result += `${indent}│${" ".repeat(padding)}${paddedLine}${" ".repeat(padding)}│\n`;
|
||||
}
|
||||
|
||||
result += `${indent}└${"─".repeat(boxWidth)}┘`;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a formatted box with text
|
||||
* In GitHub Actions, uses markdown code blocks; locally uses box formatting
|
||||
*/
|
||||
function box(
|
||||
text: string,
|
||||
options?: {
|
||||
title?: string;
|
||||
maxWidth?: number;
|
||||
}
|
||||
): void {
|
||||
if (isGitHubActions) {
|
||||
const { title } = options || {};
|
||||
let markdown = "";
|
||||
if (title) {
|
||||
markdown += `### ${title}\n\n`;
|
||||
}
|
||||
markdown += "```\n";
|
||||
markdown += text;
|
||||
markdown += "\n```\n";
|
||||
// Note: summary.write() should be called once at the end, but for immediate visibility we call it here
|
||||
// In practice, you might want to batch multiple calls
|
||||
core.summary.addRaw(markdown);
|
||||
core.info(markdown);
|
||||
} else {
|
||||
log.info(boxString(text, options));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a table using GitHub Actions Job Summaries API
|
||||
* Falls back to formatted console table locally
|
||||
*/
|
||||
async function table(
|
||||
rows: Array<Array<{ data: string; header?: boolean } | string>>,
|
||||
options?: {
|
||||
title?: string;
|
||||
}
|
||||
): Promise<void> {
|
||||
const { title } = options || {};
|
||||
|
||||
if (isGitHubActions) {
|
||||
const summary = core.summary;
|
||||
|
||||
if (title) {
|
||||
summary.addHeading(title);
|
||||
}
|
||||
|
||||
// Convert rows to format expected by Job Summaries API
|
||||
const formattedRows = rows.map((row) =>
|
||||
row.map((cell) => {
|
||||
if (typeof cell === "string") {
|
||||
return { data: cell };
|
||||
}
|
||||
return cell;
|
||||
})
|
||||
);
|
||||
|
||||
summary.addTable(formattedRows);
|
||||
await summary.write();
|
||||
|
||||
// Also log to console for visibility in logs
|
||||
const tableText = formattedRows
|
||||
.map((row) => row.map((cell) => cell.data).join(" | "))
|
||||
.join("\n");
|
||||
log.info(tableText);
|
||||
} else {
|
||||
// Local fallback: simple console table
|
||||
if (title) {
|
||||
log.info(`\n${title}`);
|
||||
}
|
||||
const tableText = rows
|
||||
.map((row) => {
|
||||
const rowData = row.map((cell) => {
|
||||
const text = typeof cell === "string" ? cell : cell.data;
|
||||
const isHeader = typeof cell !== "string" && cell.header;
|
||||
return isHeader ? `**${text}**` : text;
|
||||
});
|
||||
return rowData.join(" | ");
|
||||
})
|
||||
.join("\n");
|
||||
log.info(`\n${tableText}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add raw markdown to job summary (GitHub Actions) or print as info (local)
|
||||
*/
|
||||
async function markdown(content: string): Promise<void> {
|
||||
if (isGitHubActions) {
|
||||
core.summary.addRaw(content);
|
||||
await core.summary.write();
|
||||
// Also log to console
|
||||
core.info(content);
|
||||
} else {
|
||||
log.info(content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a code block to output
|
||||
*/
|
||||
function codeBlock(code: string, language?: string): void {
|
||||
if (isGitHubActions) {
|
||||
core.summary.addCodeBlock(code, language);
|
||||
core.info(`\`\`\`${language || ""}\n${code}\n\`\`\``);
|
||||
} else {
|
||||
log.info(`\`\`\`${language || ""}\n${code}\n\`\`\``);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a link to output
|
||||
*/
|
||||
function link(text: string, url: string): void {
|
||||
if (isGitHubActions) {
|
||||
core.summary.addLink(text, url);
|
||||
log.info(`[${text}](${url})`);
|
||||
} else {
|
||||
log.info(`[${text}](${url})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all pending summary changes to the job summary
|
||||
* Call this at the end of your action to ensure all summary content is written
|
||||
*/
|
||||
async function writeSummary(): Promise<void> {
|
||||
if (isGitHubActions) {
|
||||
await core.summary.write();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a separator line
|
||||
*/
|
||||
function separator(length: number = 50): void {
|
||||
if (isGitHubActions) {
|
||||
core.info("─".repeat(length));
|
||||
} else {
|
||||
console.log("─".repeat(length));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main logging utility object - import this once and access all utilities
|
||||
*/
|
||||
export const log = {
|
||||
/**
|
||||
* Check if running in GitHub Actions environment
|
||||
*/
|
||||
isGitHubActions: (): boolean => isGitHubActions,
|
||||
|
||||
/**
|
||||
* Print info message (GitHub Actions or console)
|
||||
*/
|
||||
info: (message: string): void => {
|
||||
if (isGitHubActions) {
|
||||
core.info(message);
|
||||
} else {
|
||||
console.log(message);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Print warning message
|
||||
*/
|
||||
warning: (message: string): void => {
|
||||
if (isGitHubActions) {
|
||||
core.warning(message);
|
||||
} else {
|
||||
console.warn(`⚠️ ${message}`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Print error message
|
||||
*/
|
||||
error: (message: string): void => {
|
||||
if (isGitHubActions) {
|
||||
core.error(message);
|
||||
} else {
|
||||
console.error(`❌ ${message}`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Print success message
|
||||
*/
|
||||
success: (message: string): void => {
|
||||
const msg = `✅ ${message}`;
|
||||
if (isGitHubActions) {
|
||||
core.info(msg);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Print a formatted box with text
|
||||
* In GitHub Actions, uses markdown code blocks; locally uses box formatting
|
||||
*/
|
||||
box,
|
||||
|
||||
/**
|
||||
* Add a table using GitHub Actions Job Summaries API
|
||||
* Falls back to formatted console table locally
|
||||
*/
|
||||
table,
|
||||
|
||||
/**
|
||||
* Add raw markdown to job summary (GitHub Actions) or print as info (local)
|
||||
*/
|
||||
markdown,
|
||||
|
||||
/**
|
||||
* Add a code block to output
|
||||
*/
|
||||
codeBlock,
|
||||
|
||||
/**
|
||||
* Add a link to output
|
||||
*/
|
||||
link,
|
||||
|
||||
/**
|
||||
* Write all pending summary changes to the job summary
|
||||
* Call this at the end of your action to ensure all summary content is written
|
||||
*/
|
||||
writeSummary,
|
||||
|
||||
/**
|
||||
* Print a separator line
|
||||
*/
|
||||
separator,
|
||||
};
|
||||
Reference in New Issue
Block a user