refactor action to use INPUTS_JSON object

This commit is contained in:
David Blass
2025-10-13 16:57:02 -04:00
parent cd20491d22
commit a93c34e61b
10 changed files with 56 additions and 26599 deletions
+1 -5
View File
@@ -2,9 +2,5 @@
echo "🔒 Updating lockfile..." echo "🔒 Updating lockfile..."
pnpm install --lockfile-only pnpm install --lockfile-only
# Build the action before committing
echo "🔨 Building action..."
npm run build
# Add the built files and lockfile to the commit # Add the built files and lockfile to the commit
git add entry.cjs pnpm-lock.yaml git add pnpm-lock.yaml
+3 -4
View File
@@ -10,9 +10,6 @@ inputs:
anthropic_api_key: anthropic_api_key:
description: "Anthropic API key for Claude Code authentication" description: "Anthropic API key for Claude Code authentication"
required: false required: false
github_token:
description: "GitHub token for repository access"
required: false
github_installation_token: github_installation_token:
description: "GitHub App installation token" description: "GitHub App installation token"
required: false required: false
@@ -41,7 +38,9 @@ runs:
run: node entry.ts run: node entry.ts
shell: bash shell: bash
working-directory: ${{ github.action_path }} working-directory: ${{ github.action_path }}
env:
INPUTS_JSON: ${{ toJSON(inputs) }}
branding: branding:
icon: "code" icon: "code"
color: "orange" color: "green"
-26451
View File
File diff suppressed because one or more lines are too long
+9 -35
View File
@@ -2,49 +2,26 @@
/** /**
* Entry point for GitHub Action * Entry point for GitHub Action
* This file is bundled to entry.cjs and called directly by GitHub Actions
*/ */
import * as core from "@actions/core"; import * as core from "@actions/core";
import { type ExecutionInputs, type MainParams, main } from "./main.ts"; import { type } from "arktype";
import { main, Inputs } from "./main.ts";
import packageJson from "./package.json" with { type: "json" }; import packageJson from "./package.json" with { type: "json" };
import { setupGitHubInstallationToken } from "./utils/github.ts";
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
console.log(`🐸 Running pullfrog/action@${packageJson.version}...`); console.log(`🐸 Running pullfrog/action@${packageJson.version}...`);
const prompt = core.getInput("prompt", { required: true });
const anthropic_api_key = core.getInput("anthropic_api_key");
if (!prompt) { const inputsJson = process.env.INPUTS_JSON;
throw new Error("prompt is required"); if (!inputsJson) {
throw new Error("INPUTS_JSON environment variable not found");
} }
const inputs: ExecutionInputs = { const parsed = type("string.json.parse").assert(inputsJson);
prompt, const inputs = Inputs.assert(parsed);
anthropic_api_key,
};
const githubToken = core.getInput("github_token") || process.env.GITHUB_TOKEN; const result = await main(inputs);
if (githubToken) {
inputs.github_token = githubToken;
}
const githubInstallationToken =
core.getInput("github_installation_token") || process.env.GITHUB_INSTALLATION_TOKEN;
if (githubInstallationToken) {
inputs.github_installation_token = githubInstallationToken;
} else {
await setupGitHubInstallationToken();
}
const params: MainParams = {
inputs,
env: {},
cwd: process.cwd(),
};
const result = await main(params);
if (!result.success) { if (!result.success) {
throw new Error(result.error || "Agent execution failed"); throw new Error(result.error || "Agent execution failed");
@@ -55,7 +32,4 @@ async function run(): Promise<void> {
} }
} }
run().catch((error) => { await run();
console.error("Action failed:", error);
process.exit(1);
});
-16
View File
@@ -1,16 +0,0 @@
import { build } from "esbuild";
// Build the GitHub Action bundle only
// For npm package builds, use zshy (pnpm build:npm)
await build({
entryPoints: ["./entry.ts"],
bundle: true,
outfile: "./entry.cjs",
format: "cjs",
platform: "node",
target: "node20",
minify: false,
sourcemap: false,
});
console.log("✅ Build completed successfully!");
+1 -2
View File
@@ -6,8 +6,7 @@
export { ClaudeAgent } from "./agents/claude.ts"; export { ClaudeAgent } from "./agents/claude.ts";
export type { Agent, AgentConfig, AgentResult } from "./agents/types.ts"; export type { Agent, AgentConfig, AgentResult } from "./agents/types.ts";
export { export {
type ExecutionInputs, type ActionInputs as ExecutionInputs,
type MainParams,
type MainResult, type MainResult,
main, main,
} from "./main.ts"; } from "./main.ts";
+9 -27
View File
@@ -1,24 +1,14 @@
import * as core from "@actions/core"; import * as core from "@actions/core";
import { type } from "arktype";
import { ClaudeAgent } from "./agents/claude.ts"; import { ClaudeAgent } from "./agents/claude.ts";
export const EXPECTED_INPUTS: string[] = [ export const Inputs = type({
"ANTHROPIC_API_KEY", prompt: "string",
"GITHUB_TOKEN", "anthropic_api_key?": "string | undefined",
"GITHUB_INSTALLATION_TOKEN", "github_installation_token?": "string | undefined",
]; });
export interface ExecutionInputs { export type ActionInputs = typeof Inputs.infer;
prompt: string;
anthropic_api_key: string;
github_token?: string;
github_installation_token?: string;
}
export interface MainParams {
inputs: ExecutionInputs;
env: Record<string, string>;
cwd: string;
}
export interface MainResult { export interface MainResult {
success: boolean; success: boolean;
@@ -26,19 +16,11 @@ export interface MainResult {
error?: string | undefined; error?: string | undefined;
} }
export async function main(params: MainParams): Promise<MainResult> { export async function main(inputs: ActionInputs): Promise<MainResult> {
try { try {
const { inputs, env, cwd } = params;
if (cwd !== process.cwd()) {
process.chdir(cwd);
}
Object.assign(process.env, env);
core.info(`→ Starting agent run with Claude Code`); core.info(`→ Starting agent run with Claude Code`);
const agent = new ClaudeAgent({ apiKey: inputs.anthropic_api_key }); const agent = new ClaudeAgent({ apiKey: inputs.anthropic_api_key! });
await agent.install(); await agent.install();
const result = await agent.execute(inputs.prompt); const result = await agent.execute(inputs.prompt);
+8 -16
View File
@@ -1,6 +1,6 @@
{ {
"name": "@pullfrog/action", "name": "@pullfrog/action",
"version": "0.0.40", "version": "0.0.42",
"type": "module", "type": "module",
"files": [ "files": [
"index.js", "index.js",
@@ -12,39 +12,31 @@
"main.js", "main.js",
"main.d.ts" "main.d.ts"
], ],
"directories": {
"example": "examples"
},
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "node esbuild.config.js",
"build:npm": "zshy",
"build:dev": "node esbuild.config.js",
"prepare": "husky", "prepare": "husky",
"play": "node play.ts", "play": "node play.ts",
"upDeps": "pnpm up --latest", "upDeps": "pnpm up --latest",
"createLockfile": "pnpm --ignore-workspace install" "createLockfile": "pnpm --ignore-workspace install"
}, },
"dependencies": { "dependencies": {
"@ark/fs": "0.49.0",
"@actions/core": "^1.11.1", "@actions/core": "^1.11.1",
"@modelcontextprotocol/sdk": "^1.17.5", "@ark/fs": "0.49.0",
"@modelcontextprotocol/sdk": "^1.20.0",
"@octokit/rest": "^22.0.0", "@octokit/rest": "^22.0.0",
"@octokit/webhooks-types": "^7.6.1", "@octokit/webhooks-types": "^7.6.1",
"arktype": "^2.1.22", "arktype": "^2.1.22",
"dotenv": "^17.2.2", "dotenv": "^17.2.3",
"execa": "^9.6.0", "execa": "^9.6.0",
"table": "^6.9.0", "table": "^6.9.0",
"zod": "^3.24.4" "zod": "^3.24.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.10.0", "@types/node": "^24.7.2",
"arg": "^5.0.2", "arg": "^5.0.2",
"esbuild": "^0.25.9", "husky": "^9.1.7",
"husky": "^9.0.0", "typescript": "^5.9.3"
"typescript": "^5.3.0",
"zshy": "^0.4.1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -52,7 +44,7 @@
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/pullfrog/action/issues" "url": "https://github.com/pullfrog/action/issues"
}, },
+9 -28
View File
@@ -4,7 +4,7 @@ import { pathToFileURL } from "node:url";
import { fromHere } from "@ark/fs"; import { fromHere } from "@ark/fs";
import arg from "arg"; import arg from "arg";
import { config } from "dotenv"; import { config } from "dotenv";
import { main } from "./main.ts"; import { type ActionInputs, main } from "./main.ts";
import packageJson from "./package.json" with { type: "json" }; import packageJson from "./package.json" with { type: "json" };
import { runAct } from "./utils/act.ts"; import { runAct } from "./utils/act.ts";
import { setupGitHubInstallationToken } from "./utils/github.ts"; import { setupGitHubInstallationToken } from "./utils/github.ts";
@@ -36,38 +36,19 @@ export async function run(
console.log(prompt); console.log(prompt);
console.log("─".repeat(50)); console.log("─".repeat(50));
const { EXPECTED_INPUTS } = await import("./main.ts");
EXPECTED_INPUTS.forEach((inputName) => {
const value = process.env[inputName];
if (value) {
process.env[`INPUT_${inputName.toLowerCase()}`] = value;
}
});
const inputs: any = {
prompt,
anthropic_api_key: process.env.ANTHROPIC_API_KEY || "",
};
if (process.env.GITHUB_TOKEN) {
inputs.github_token = process.env.GITHUB_TOKEN;
}
console.log("🔑 Setting up GitHub installation token..."); console.log("🔑 Setting up GitHub installation token...");
const installationToken = await setupGitHubInstallationToken(); const installationToken = await setupGitHubInstallationToken();
inputs.github_installation_token = installationToken; process.env.GITHUB_INSTALLATION_TOKEN = installationToken;
console.log("✅ GitHub installation token setup successfully"); console.log("✅ GitHub installation token setup successfully");
const envWithToken = { const inputs: ActionInputs = {
...process.env, prompt,
GITHUB_INSTALLATION_TOKEN: installationToken, anthropic_api_key: process.env.ANTHROPIC_API_KEY,
} as Record<string, string>; github_installation_token: installationToken,
};
const result = await main({ const result = await main(inputs);
inputs,
env: envWithToken,
cwd: process.cwd(),
});
process.chdir(originalCwd); process.chdir(originalCwd);
+16 -15
View File
@@ -2,21 +2,22 @@
"compilerOptions": { "compilerOptions": {
"outDir": "./dist", "outDir": "./dist",
"module": "NodeNext", "module": "NodeNext",
"target": "ESNext", "target": "ESNext",
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"lib": ["ESNext"], "lib": ["ESNext"],
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": true, "rewriteRelativeImportExtensions": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"noUncheckedSideEffectImports": true, "noUncheckedSideEffectImports": true,
"declaration": true, "declaration": true,
"verbatimModuleSyntax": true, "verbatimModuleSyntax": true,
"esModuleInterop": true, "esModuleInterop": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"exactOptionalPropertyTypes": true, "exactOptionalPropertyTypes": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"stripInternal": true, "stripInternal": true,
"moduleDetection": "force" "moduleDetection": "force",
"useUnknownInCatchVariables": true
} }
} }