Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ef44eb254 | |||
| 5a21d40d27 |
+1
-4
@@ -1,6 +1,3 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
# Ensure lockfile is up to date
|
# Ensure lockfile is up to date
|
||||||
echo "🔒 Updating lockfile..."
|
echo "🔒 Updating lockfile..."
|
||||||
pnpm install --lockfile-only
|
pnpm install --lockfile-only
|
||||||
@@ -10,4 +7,4 @@ echo "🔨 Building action..."
|
|||||||
pnpm build
|
pnpm 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 entry.js pnpm-lock.yaml
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ inputs:
|
|||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "node20"
|
using: "node20"
|
||||||
main: "entry.cjs"
|
main: "entry.js"
|
||||||
|
|
||||||
branding:
|
branding:
|
||||||
icon: "code"
|
icon: "code"
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build entry point - wraps entry.ts to avoid top-level await in CJS output
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as core from "@actions/core";
|
|
||||||
import { type } from "arktype";
|
|
||||||
import { Inputs, main } from "./main.ts";
|
|
||||||
import packageJson from "./package.json" with { type: "json" };
|
|
||||||
import { log } from "./utils/cli.ts";
|
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
|
||||||
try {
|
|
||||||
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
|
||||||
|
|
||||||
const inputsJson = process.env.INPUTS_JSON;
|
|
||||||
if (!inputsJson) {
|
|
||||||
throw new Error("INPUTS_JSON environment variable not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsed = type("string.json.parse").assert(inputsJson);
|
|
||||||
const inputs = Inputs.assert(parsed);
|
|
||||||
|
|
||||||
const result = await main(inputs);
|
|
||||||
|
|
||||||
if (!result.success) {
|
|
||||||
throw new Error(result.error || "Agent execution failed");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
||||||
core.setFailed(`Action failed: ${errorMessage}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap in IIFE to avoid top-level await in CJS
|
|
||||||
(async () => {
|
|
||||||
await run();
|
|
||||||
})();
|
|
||||||
@@ -7,9 +7,13 @@
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { type } from "arktype";
|
import { type } from "arktype";
|
||||||
import { Inputs, main } from "./main.ts";
|
import { Inputs, main } from "./main.ts";
|
||||||
|
import { createMcpServer } from "./mcp/server.ts";
|
||||||
import packageJson from "./package.json" with { type: "json" };
|
import packageJson from "./package.json" with { type: "json" };
|
||||||
import { log } from "./utils/cli.ts";
|
import { log } from "./utils/cli.ts";
|
||||||
|
|
||||||
|
// Export createMcpServer so it can be called from the spawned MCP process
|
||||||
|
export { createMcpServer };
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
||||||
|
|||||||
+12
-6
@@ -3,17 +3,23 @@ import { build } from "esbuild";
|
|||||||
// Build the GitHub Action bundle only
|
// Build the GitHub Action bundle only
|
||||||
// For npm package builds, use zshy (pnpm build:npm)
|
// For npm package builds, use zshy (pnpm build:npm)
|
||||||
await build({
|
await build({
|
||||||
entryPoints: ["./entry.build.ts"],
|
entryPoints: ["./entry.ts"],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
outfile: "./entry.cjs",
|
outfile: "./entry.js",
|
||||||
format: "cjs",
|
format: "esm",
|
||||||
platform: "node",
|
platform: "node",
|
||||||
target: "node20",
|
target: "node20",
|
||||||
minify: true,
|
minify: true,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
// @actions/core is provided by GitHub Actions runtime, but we still need it bundled
|
// Mark all node_modules as external - Node.js will handle ESM/CJS interop natively
|
||||||
// for local testing. However, we can mark it to reduce duplication if needed.
|
// This avoids esbuild's require() polyfill which doesn't work in ESM
|
||||||
external: [],
|
packages: "external",
|
||||||
|
// Mark optional peer dependencies as external
|
||||||
|
external: [
|
||||||
|
"@valibot/to-json-schema",
|
||||||
|
"effect",
|
||||||
|
"sury",
|
||||||
|
],
|
||||||
// Enable tree-shaking to remove unused code
|
// Enable tree-shaking to remove unused code
|
||||||
treeShaking: true,
|
treeShaking: true,
|
||||||
// Drop console statements in production (but keep for debugging)
|
// Drop console statements in production (but keep for debugging)
|
||||||
|
|||||||
+10
-4
@@ -3,11 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { McpServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
import type { McpServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
||||||
import { fromHere } from "@ark/fs";
|
|
||||||
import { parseRepoContext } from "../utils/github.ts";
|
import { parseRepoContext } from "../utils/github.ts";
|
||||||
|
|
||||||
const actionPath = fromHere("..");
|
|
||||||
|
|
||||||
export const ghPullfrogMcpName = "gh-pullfrog";
|
export const ghPullfrogMcpName = "gh-pullfrog";
|
||||||
|
|
||||||
export type McpName = typeof ghPullfrogMcpName;
|
export type McpName = typeof ghPullfrogMcpName;
|
||||||
@@ -18,10 +15,19 @@ export function createMcpConfigs(githubInstallationToken: string): McpConfigs {
|
|||||||
const repoContext = parseRepoContext();
|
const repoContext = parseRepoContext();
|
||||||
const githubRepository = `${repoContext.owner}/${repoContext.name}`;
|
const githubRepository = `${repoContext.owner}/${repoContext.name}`;
|
||||||
|
|
||||||
|
// Get absolute path to entry.js - use GITHUB_ACTION_PATH if available, otherwise current directory
|
||||||
|
const entryPath = process.env.GITHUB_ACTION_PATH
|
||||||
|
? `${process.env.GITHUB_ACTION_PATH}/entry.js`
|
||||||
|
: `${process.cwd()}/entry.js`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[ghPullfrogMcpName]: {
|
[ghPullfrogMcpName]: {
|
||||||
command: "node",
|
command: "node",
|
||||||
args: [`${actionPath}/mcp/server.ts`],
|
args: [
|
||||||
|
"--input-type=module",
|
||||||
|
"-e",
|
||||||
|
`import('${entryPath.replace(/'/g, "\\'")}').then(m => m.createMcpServer())`,
|
||||||
|
],
|
||||||
env: {
|
env: {
|
||||||
GITHUB_INSTALLATION_TOKEN: githubInstallationToken,
|
GITHUB_INSTALLATION_TOKEN: githubInstallationToken,
|
||||||
GITHUB_REPOSITORY: githubRepository,
|
GITHUB_REPOSITORY: githubRepository,
|
||||||
|
|||||||
+15
-13
@@ -8,18 +8,20 @@ import { PullRequestInfoTool } from "./prInfo.ts";
|
|||||||
import { ReviewTool } from "./review.ts";
|
import { ReviewTool } from "./review.ts";
|
||||||
import { addTools } from "./shared.ts";
|
import { addTools } from "./shared.ts";
|
||||||
|
|
||||||
const server = new FastMCP({
|
export function createMcpServer(): void {
|
||||||
name: "gh-pullfrog",
|
const server = new FastMCP({
|
||||||
version: "0.0.1",
|
name: "gh-pullfrog",
|
||||||
});
|
version: "0.0.1",
|
||||||
|
});
|
||||||
|
|
||||||
addTools(server, [
|
addTools(server, [
|
||||||
CreateCommentTool,
|
CreateCommentTool,
|
||||||
EditCommentTool,
|
EditCommentTool,
|
||||||
IssueTool,
|
IssueTool,
|
||||||
PullRequestTool,
|
PullRequestTool,
|
||||||
ReviewTool,
|
ReviewTool,
|
||||||
PullRequestInfoTool,
|
PullRequestInfoTool,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pullfrog/action",
|
"name": "@pullfrog/action",
|
||||||
"version": "0.0.74",
|
"version": "0.0.76",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"files": [
|
"files": [
|
||||||
"index.js",
|
"index.js",
|
||||||
|
|||||||
@@ -50,8 +50,16 @@ export function setupGitConfig(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup git authentication using GitHub token
|
* Setup git authentication using GitHub token
|
||||||
|
* Only runs in GitHub Actions environment to avoid breaking local git remotes
|
||||||
*/
|
*/
|
||||||
export function setupGitAuth(githubToken: string, repoContext: RepoContext): void {
|
export function setupGitAuth(githubToken: string, repoContext: RepoContext): void {
|
||||||
|
// Only set up git auth in GitHub Actions environment
|
||||||
|
// In local testing, this would overwrite the real git remote with fake credentials
|
||||||
|
if (!process.env.GITHUB_ACTIONS) {
|
||||||
|
log.info("⚠️ Skipping git authentication setup (not in GitHub Actions)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
log.info("🔐 Setting up git authentication...");
|
log.info("🔐 Setting up git authentication...");
|
||||||
|
|
||||||
// Remove existing git auth headers that actions/checkout might have set
|
// Remove existing git auth headers that actions/checkout might have set
|
||||||
|
|||||||
Reference in New Issue
Block a user