* feat: add base_branch input to specify source branch for new Claude branches - Add base_branch input parameter to action.yml allowing users to specify which branch to use as source - Update setupBranch function to accept and use the base branch parameter - Defaults to repository default branch if no base branch is specified - Addresses issue #62 for better branch control Co-authored-by: ashwin-ant <ashwin-ant@users.noreply.github.com> * perf: optimize setupBranch to avoid unnecessary default branch fetch Only fetch repository default branch when actually needed: - Skip initial fetch when baseBranch is provided - Fetch default branch at end only for return value and GitHub Actions output - Eliminates unnecessary API call when users specify base branch Co-authored-by: ashwin-ant <ashwin-ant@users.noreply.github.com> * fix: properly handle base branch throughout the action workflow - Fix TypeScript error where defaultBranch was used before being assigned - Replace DEFAULT_BRANCH with BASE_BRANCH in subsequent workflow steps - Update PR creation and branch comparison to use the actual base branch - Ensure custom base_branch input is respected in all operations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: move BASE_BRANCH env reading into parseGitHubContext - Move BASE_BRANCH environment variable reading into parseGitHubContext for consistency - Update setupBranch to use context.inputs.baseBranch instead of process.env - Fix test descriptions to correctly reference BASE_BRANCH instead of DEFAULT_BRANCH - Update test environment setup to use BASE_BRANCH 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: ashwin-ant <ashwin-ant@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
265 lines
8.6 KiB
TypeScript
265 lines
8.6 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
import { describe, test, expect, beforeEach, afterEach } from "bun:test";
|
|
import { prepareContext } from "../src/create-prompt";
|
|
import {
|
|
createMockContext,
|
|
mockIssueOpenedContext,
|
|
mockIssueAssignedContext,
|
|
mockIssueCommentContext,
|
|
mockPullRequestCommentContext,
|
|
mockPullRequestReviewContext,
|
|
mockPullRequestReviewCommentContext,
|
|
} from "./mockContext";
|
|
|
|
const BASE_ENV = {
|
|
CLAUDE_COMMENT_ID: "12345",
|
|
GITHUB_TOKEN: "test-token",
|
|
};
|
|
|
|
describe("parseEnvVarsWithContext", () => {
|
|
let originalEnv: typeof process.env;
|
|
|
|
beforeEach(() => {
|
|
originalEnv = { ...process.env };
|
|
process.env = {};
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env = originalEnv;
|
|
});
|
|
|
|
describe("issue_comment event", () => {
|
|
describe("on issue", () => {
|
|
beforeEach(() => {
|
|
process.env = {
|
|
...BASE_ENV,
|
|
BASE_BRANCH: "main",
|
|
CLAUDE_BRANCH: "claude/issue-67890-20240101_120000",
|
|
};
|
|
});
|
|
|
|
test("should parse issue_comment event correctly", () => {
|
|
const result = prepareContext(
|
|
mockIssueCommentContext,
|
|
"12345",
|
|
"main",
|
|
"claude/issue-67890-20240101_120000",
|
|
);
|
|
|
|
expect(result.repository).toBe("test-owner/test-repo");
|
|
expect(result.claudeCommentId).toBe("12345");
|
|
expect(result.triggerPhrase).toBe("@claude");
|
|
expect(result.triggerUsername).toBe("contributor-user");
|
|
expect(result.eventData.eventName).toBe("issue_comment");
|
|
expect(result.eventData.isPR).toBe(false);
|
|
if (
|
|
result.eventData.eventName === "issue_comment" &&
|
|
!result.eventData.isPR
|
|
) {
|
|
expect(result.eventData.issueNumber).toBe("55");
|
|
expect(result.eventData.commentId).toBe("12345678");
|
|
expect(result.eventData.claudeBranch).toBe(
|
|
"claude/issue-67890-20240101_120000",
|
|
);
|
|
expect(result.eventData.baseBranch).toBe("main");
|
|
expect(result.eventData.commentBody).toBe(
|
|
"@claude can you help explain how to configure the logging system?",
|
|
);
|
|
}
|
|
});
|
|
|
|
test("should throw error when CLAUDE_BRANCH is missing", () => {
|
|
expect(() =>
|
|
prepareContext(mockIssueCommentContext, "12345", "main"),
|
|
).toThrow("CLAUDE_BRANCH is required for issue_comment event");
|
|
});
|
|
|
|
test("should throw error when BASE_BRANCH is missing", () => {
|
|
expect(() =>
|
|
prepareContext(
|
|
mockIssueCommentContext,
|
|
"12345",
|
|
undefined,
|
|
"claude/issue-67890-20240101_120000",
|
|
),
|
|
).toThrow("BASE_BRANCH is required for issue_comment event");
|
|
});
|
|
});
|
|
|
|
describe("on PR", () => {
|
|
test("should parse PR issue_comment event correctly", () => {
|
|
process.env = BASE_ENV;
|
|
const result = prepareContext(mockPullRequestCommentContext, "12345");
|
|
|
|
expect(result.eventData.eventName).toBe("issue_comment");
|
|
expect(result.eventData.isPR).toBe(true);
|
|
expect(result.triggerUsername).toBe("reviewer-user");
|
|
if (
|
|
result.eventData.eventName === "issue_comment" &&
|
|
result.eventData.isPR
|
|
) {
|
|
expect(result.eventData.prNumber).toBe("789");
|
|
expect(result.eventData.commentId).toBe("87654321");
|
|
expect(result.eventData.commentBody).toBe(
|
|
"/claude please review the changes and ensure we're not introducing any new memory issues",
|
|
);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("pull_request_review event", () => {
|
|
test("should parse pull_request_review event correctly", () => {
|
|
process.env = BASE_ENV;
|
|
const result = prepareContext(mockPullRequestReviewContext, "12345");
|
|
|
|
expect(result.eventData.eventName).toBe("pull_request_review");
|
|
expect(result.eventData.isPR).toBe(true);
|
|
expect(result.triggerUsername).toBe("senior-developer");
|
|
if (result.eventData.eventName === "pull_request_review") {
|
|
expect(result.eventData.prNumber).toBe("321");
|
|
expect(result.eventData.commentBody).toBe(
|
|
"@claude can you check if the error handling is comprehensive enough in this PR?",
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("pull_request_review_comment event", () => {
|
|
test("should parse pull_request_review_comment event correctly", () => {
|
|
process.env = BASE_ENV;
|
|
const result = prepareContext(
|
|
mockPullRequestReviewCommentContext,
|
|
"12345",
|
|
);
|
|
|
|
expect(result.eventData.eventName).toBe("pull_request_review_comment");
|
|
expect(result.eventData.isPR).toBe(true);
|
|
expect(result.triggerUsername).toBe("code-reviewer");
|
|
if (result.eventData.eventName === "pull_request_review_comment") {
|
|
expect(result.eventData.prNumber).toBe("999");
|
|
expect(result.eventData.commentId).toBe("99988877");
|
|
expect(result.eventData.commentBody).toBe(
|
|
"/claude is this the most efficient way to implement this algorithm?",
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("issues event", () => {
|
|
beforeEach(() => {
|
|
process.env = {
|
|
...BASE_ENV,
|
|
BASE_BRANCH: "main",
|
|
CLAUDE_BRANCH: "claude/issue-42-20240101_120000",
|
|
};
|
|
});
|
|
|
|
test("should parse issue opened event correctly", () => {
|
|
const result = prepareContext(
|
|
mockIssueOpenedContext,
|
|
"12345",
|
|
"main",
|
|
"claude/issue-42-20240101_120000",
|
|
);
|
|
|
|
expect(result.eventData.eventName).toBe("issues");
|
|
expect(result.eventData.isPR).toBe(false);
|
|
expect(result.triggerUsername).toBe("john-doe");
|
|
if (
|
|
result.eventData.eventName === "issues" &&
|
|
result.eventData.eventAction === "opened"
|
|
) {
|
|
expect(result.eventData.issueNumber).toBe("42");
|
|
expect(result.eventData.baseBranch).toBe("main");
|
|
expect(result.eventData.claudeBranch).toBe(
|
|
"claude/issue-42-20240101_120000",
|
|
);
|
|
}
|
|
});
|
|
|
|
test("should parse issue assigned event correctly", () => {
|
|
const result = prepareContext(
|
|
mockIssueAssignedContext,
|
|
"12345",
|
|
"main",
|
|
"claude/issue-123-20240101_120000",
|
|
);
|
|
|
|
expect(result.eventData.eventName).toBe("issues");
|
|
expect(result.eventData.isPR).toBe(false);
|
|
expect(result.triggerUsername).toBe("jane-smith");
|
|
if (
|
|
result.eventData.eventName === "issues" &&
|
|
result.eventData.eventAction === "assigned"
|
|
) {
|
|
expect(result.eventData.issueNumber).toBe("123");
|
|
expect(result.eventData.baseBranch).toBe("main");
|
|
expect(result.eventData.claudeBranch).toBe(
|
|
"claude/issue-123-20240101_120000",
|
|
);
|
|
expect(result.eventData.assigneeTrigger).toBe("@claude-bot");
|
|
}
|
|
});
|
|
|
|
test("should throw error when CLAUDE_BRANCH is missing for issues", () => {
|
|
expect(() =>
|
|
prepareContext(mockIssueOpenedContext, "12345", "main"),
|
|
).toThrow("CLAUDE_BRANCH is required for issues event");
|
|
});
|
|
|
|
test("should throw error when BASE_BRANCH is missing for issues", () => {
|
|
expect(() =>
|
|
prepareContext(
|
|
mockIssueOpenedContext,
|
|
"12345",
|
|
undefined,
|
|
"claude/issue-42-20240101_120000",
|
|
),
|
|
).toThrow("BASE_BRANCH is required for issues event");
|
|
});
|
|
});
|
|
|
|
describe("optional fields", () => {
|
|
test("should include custom instructions when provided", () => {
|
|
process.env = BASE_ENV;
|
|
const contextWithCustomInstructions = createMockContext({
|
|
...mockPullRequestCommentContext,
|
|
inputs: {
|
|
...mockPullRequestCommentContext.inputs,
|
|
customInstructions: "Be concise",
|
|
},
|
|
});
|
|
const result = prepareContext(contextWithCustomInstructions, "12345");
|
|
|
|
expect(result.customInstructions).toBe("Be concise");
|
|
});
|
|
|
|
test("should include allowed tools when provided", () => {
|
|
process.env = BASE_ENV;
|
|
const contextWithAllowedTools = createMockContext({
|
|
...mockPullRequestCommentContext,
|
|
inputs: {
|
|
...mockPullRequestCommentContext.inputs,
|
|
allowedTools: "Tool1,Tool2",
|
|
},
|
|
});
|
|
const result = prepareContext(contextWithAllowedTools, "12345");
|
|
|
|
expect(result.allowedTools).toBe("Tool1,Tool2");
|
|
});
|
|
});
|
|
|
|
test("should throw error for unsupported event type", () => {
|
|
process.env = BASE_ENV;
|
|
const unsupportedContext = createMockContext({
|
|
eventName: "unsupported_event",
|
|
eventAction: "whatever",
|
|
});
|
|
expect(() => prepareContext(unsupportedContext, "12345")).toThrow(
|
|
"Unsupported event type: unsupported_event",
|
|
);
|
|
});
|
|
});
|