Attempt to make this work

This commit is contained in:
Mark Wylde
2025-05-30 22:41:48 +01:00
parent 4b1c3d000d
commit 4b69e8485a
5 changed files with 93 additions and 18 deletions

View File

@@ -75,7 +75,7 @@ jobs:
| `direct_prompt` | Direct prompt for Claude to execute automatically without needing a trigger (for automated workflows) | No | - | | `direct_prompt` | Direct prompt for Claude to execute automatically without needing a trigger (for automated workflows) | No | - |
| `timeout_minutes` | Timeout in minutes for execution | No | `30` | | `timeout_minutes` | Timeout in minutes for execution | No | `30` |
| `github_token` | GitHub token for Claude to operate with. **Only include this if you're connecting a custom GitHub app of your own!** | No | - | | `github_token` | GitHub token for Claude to operate with. **Only include this if you're connecting a custom GitHub app of your own!** | No | - |
| `gitea_api_url` | Gitea API URL (e.g., `https://gitea.example.com/api/v1`) for Gitea installations. Leave empty for GitHub. | No | GitHub API | | `gitea_api_url` | Gitea server URL (e.g., `https://gitea.example.com`) for Gitea installations. Leave empty for GitHub. | No | GitHub API |
| `model` | Model to use (provider-specific format required for Bedrock/Vertex) | No | - | | `model` | Model to use (provider-specific format required for Bedrock/Vertex) | No | - |
| `anthropic_model` | **DEPRECATED**: Use `model` instead. Kept for backward compatibility. | No | - | | `anthropic_model` | **DEPRECATED**: Use `model` instead. Kept for backward compatibility. | No | - |
| `use_bedrock` | Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API | No | `false` | | `use_bedrock` | Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API | No | `false` |
@@ -96,7 +96,7 @@ This action has been enhanced to work with Gitea installations. The main differe
1. **Local Git Operations**: Instead of using API-based file operations (which have limited support in Gitea), this action uses local git commands to create branches, commit files, and push changes. 1. **Local Git Operations**: Instead of using API-based file operations (which have limited support in Gitea), this action uses local git commands to create branches, commit files, and push changes.
2. **API URL Configuration**: You must specify your Gitea API URL using the `gitea_api_url` input. 2. **API URL Configuration**: You must specify your Gitea server URL using the `gitea_api_url` input.
### Example Gitea Workflow ### Example Gitea Workflow
@@ -114,7 +114,7 @@ jobs:
- uses: anthropics/claude-code-action@beta - uses: anthropics/claude-code-action@beta
with: with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
gitea_api_url: "https://gitea.example.com/api/v1" gitea_api_url: "https://gitea.example.com"
github_token: ${{ secrets.GITEA_TOKEN }} github_token: ${{ secrets.GITEA_TOKEN }}
``` ```

View File

@@ -48,7 +48,7 @@ inputs:
description: "GitHub token with repo and pull request permissions (defaults to GITHUB_TOKEN)" description: "GitHub token with repo and pull request permissions (defaults to GITHUB_TOKEN)"
required: false required: false
gitea_api_url: gitea_api_url:
description: "Gitea API URL (e.g., https://gitea.example.com/api/v1, defaults to GitHub API)" description: "Gitea server URL (e.g., https://gitea.example.com, defaults to GitHub API)"
required: false required: false
use_bedrock: use_bedrock:
description: "Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API" description: "Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API"

View File

@@ -29,8 +29,11 @@ const BASE_ALLOWED_TOOLS = [
"LS", "LS",
"Read", "Read",
"Write", "Write",
"mcp__github_file_ops__commit_files", "mcp__local_git_ops__commit_files",
"mcp__github_file_ops__delete_files", "mcp__local_git_ops__delete_files",
"mcp__local_git_ops__push_branch",
"mcp__local_git_ops__create_pull_request",
"mcp__local_git_ops__git_status",
]; ];
const DISALLOWED_TOOLS = ["WebSearch", "WebFetch"]; const DISALLOWED_TOOLS = ["WebSearch", "WebFetch"];
@@ -530,13 +533,13 @@ ${context.directPrompt ? ` - DIRECT INSTRUCTION: A direct instruction was prov
${ ${
eventData.isPR && !eventData.claudeBranch eventData.isPR && !eventData.claudeBranch
? ` ? `
- Push directly using mcp__github_file_ops__commit_files to the existing branch (works for both new and existing files). - Push directly using mcp__local_git_ops__commit_files to the existing branch (works for both new and existing files).
- Use mcp__github_file_ops__commit_files to commit files atomically in a single commit (supports single or multiple files). - Use mcp__local_git_ops__commit_files to commit files atomically in a single commit (supports single or multiple files).
- When pushing changes with this tool and TRIGGER_USERNAME is not "Unknown", include a "Co-authored-by: ${context.triggerUsername} <${context.triggerUsername}@users.noreply.github.com>" line in the commit message.` - When pushing changes with this tool and TRIGGER_USERNAME is not "Unknown", include a "Co-authored-by: ${context.triggerUsername} <${context.triggerUsername}@users.noreply.github.com>" line in the commit message.`
: ` : `
- You are already on the correct branch (${eventData.claudeBranch || "the PR branch"}). Do not create a new branch. - You are already on the correct branch (${eventData.claudeBranch || "the PR branch"}). Do not create a new branch.
- Push changes directly to the current branch using mcp__github_file_ops__commit_files (works for both new and existing files) - Push changes directly to the current branch using mcp__local_git_ops__commit_files (works for both new and existing files)
- Use mcp__github_file_ops__commit_files to commit files atomically in a single commit (supports single or multiple files). - Use mcp__local_git_ops__commit_files to commit files atomically in a single commit (supports single or multiple files).
- When pushing changes and TRIGGER_USERNAME is not "Unknown", include a "Co-authored-by: ${context.triggerUsername} <${context.triggerUsername}@users.noreply.github.com>" line in the commit message. - When pushing changes and TRIGGER_USERNAME is not "Unknown", include a "Co-authored-by: ${context.triggerUsername} <${context.triggerUsername}@users.noreply.github.com>" line in the commit message.
${ ${
eventData.claudeBranch eventData.claudeBranch
@@ -571,7 +574,7 @@ ${context.directPrompt ? ` - DIRECT INSTRUCTION: A direct instruction was prov
- Always update the GitHub comment to reflect the current todo state. - Always update the GitHub comment to reflect the current todo state.
- When all todos are completed, remove the spinner and add a brief summary of what was accomplished, and what was not done. - When all todos are completed, remove the spinner and add a brief summary of what was accomplished, and what was not done.
- Note: If you see previous Claude comments with headers like "**Claude finished @user's task**" followed by "---", do not include this in your comment. The system adds this automatically. - Note: If you see previous Claude comments with headers like "**Claude finished @user's task**" followed by "---", do not include this in your comment. The system adds this automatically.
- If you changed any files locally, you must update them in the remote branch via mcp__github_file_ops__commit_files before saying that you're done. - If you changed any files locally, you must update them in the remote branch via mcp__local_git_ops__commit_files before saying that you're done.
${eventData.claudeBranch ? `- If you created anything in your branch, your comment must include the PR URL with prefilled title and body mentioned above.` : ""} ${eventData.claudeBranch ? `- If you created anything in your branch, your comment must include the PR URL with prefilled title and body mentioned above.` : ""}
Important Notes: Important Notes:
@@ -581,10 +584,10 @@ Important Notes:
- You communicate exclusively by editing your single comment - not through any other means. - You communicate exclusively by editing your single comment - not through any other means.
- Use this spinner HTML when work is in progress: <img src="https://github.com/user-attachments/assets/5ac382c7-e004-429b-8e35-7feb3e8f9c6f" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" /> - Use this spinner HTML when work is in progress: <img src="https://github.com/user-attachments/assets/5ac382c7-e004-429b-8e35-7feb3e8f9c6f" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />
${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing branch when triggered on a PR.` : `- IMPORTANT: You are already on the correct branch (${eventData.claudeBranch || "the created branch"}). Never create new branches when triggered on issues or closed/merged PRs.`} ${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing branch when triggered on a PR.` : `- IMPORTANT: You are already on the correct branch (${eventData.claudeBranch || "the created branch"}). Never create new branches when triggered on issues or closed/merged PRs.`}
- Use mcp__github_file_ops__commit_files for making commits (works for both new and existing files, single or multiple). Use mcp__github_file_ops__delete_files for deleting files (supports deleting single or multiple files atomically), or mcp__github__delete_file for deleting a single file. Edit files locally, and the tool will read the content from the same path on disk. - Use mcp__local_git_ops__commit_files for making commits (works for both new and existing files, single or multiple). Use mcp__local_git_ops__delete_files for deleting files (supports deleting single or multiple files atomically), or mcp__github__delete_file for deleting a single file. Edit files locally, and the tool will read the content from the same path on disk.
Tool usage examples: Tool usage examples:
- mcp__github_file_ops__commit_files: {"files": ["path/to/file1.js", "path/to/file2.py"], "message": "feat: add new feature"} - mcp__local_git_ops__commit_files: {"files": ["path/to/file1.js", "path/to/file2.py"], "message": "feat: add new feature"}
- mcp__github_file_ops__delete_files: {"files": ["path/to/old.js"], "message": "chore: remove deprecated file"} - mcp__local_git_ops__delete_files: {"files": ["path/to/old.js"], "message": "chore: remove deprecated file"}
- Display the todo list as a checklist in the GitHub comment and mark things off as you go. - Display the todo list as a checklist in the GitHub comment and mark things off as you go.
- REPOSITORY SETUP INSTRUCTIONS: The repository's CLAUDE.md file(s) contain critical repo-specific setup instructions, development guidelines, and preferences. Always read and follow these files, particularly the root CLAUDE.md, as they provide essential context for working with the codebase effectively. - REPOSITORY SETUP INSTRUCTIONS: The repository's CLAUDE.md file(s) contain critical repo-specific setup instructions, development guidelines, and preferences. Always read and follow these files, particularly the root CLAUDE.md, as they provide essential context for working with the codebase effectively.
- Use h3 headers (###) for section titles in your comments, not h1 headers (#). - Use h3 headers (###) for section titles in your comments, not h1 headers (#).

View File

@@ -100,6 +100,10 @@ export async function setupBranch(
console.log(`Working in directory: ${repoDir}`); console.log(`Working in directory: ${repoDir}`);
try { try {
// Check if we're in a git repository
console.log(`Checking if we're in a git repository...`);
await $`git status`;
// Ensure we have the latest version of the source branch // Ensure we have the latest version of the source branch
console.log(`Fetching latest ${sourceBranch}...`); console.log(`Fetching latest ${sourceBranch}...`);
await $`git fetch origin ${sourceBranch}`; await $`git fetch origin ${sourceBranch}`;
@@ -109,18 +113,38 @@ export async function setupBranch(
await $`git checkout ${sourceBranch}`; await $`git checkout ${sourceBranch}`;
// Pull latest changes // Pull latest changes
console.log(`Pulling latest changes for ${sourceBranch}...`);
await $`git pull origin ${sourceBranch}`; await $`git pull origin ${sourceBranch}`;
// Create and checkout the new branch // Create and checkout the new branch
console.log(`Creating new branch: ${newBranch}`); console.log(`Creating new branch: ${newBranch}`);
await $`git checkout -b ${newBranch}`; await $`git checkout -b ${newBranch}`;
console.log(`Successfully created and checked out branch: ${newBranch}`); // Verify the branch was created
} catch (gitError: any) { const currentBranch = await $`git branch --show-current`;
console.log( console.log(
`Local git operations completed. Branch ${newBranch} ready for use.`, `Current branch after creation: ${currentBranch.stdout.trim()}`,
);
if (currentBranch.stdout.trim() === newBranch) {
console.log(
`✅ Successfully created and checked out branch: ${newBranch}`,
);
} else {
throw new Error(
`Branch creation failed. Expected ${newBranch}, got ${currentBranch.stdout.trim()}`,
);
}
} catch (gitError: any) {
console.error(`❌ Git operations failed:`, gitError);
console.error(`Error message: ${gitError.message}`);
console.error(`Error stdout: ${gitError.stdout}`);
console.error(`Error stderr: ${gitError.stderr}`);
// This is a critical failure - the branch MUST be created for Claude to work
throw new Error(
`Failed to create branch ${newBranch}: ${gitError.message}`,
); );
// Don't fail here - the branch will be created when files are committed
} }
console.log(`Branch setup completed for: ${newBranch}`); console.log(`Branch setup completed for: ${newBranch}`);

View File

@@ -258,6 +258,54 @@ server.tool(
}, },
); );
// Delete files tool
server.tool(
"delete_files",
"Delete one or more files and commit the deletion using local git operations",
{
files: z
.array(z.string())
.describe(
'Array of file paths relative to repository root (e.g. ["src/old-file.js", "docs/deprecated.md"])',
),
message: z.string().describe("Commit message for the deletion"),
},
async ({ files, message }) => {
try {
// Remove the specified files
for (const file of files) {
const filePath = file.startsWith("/") ? file.slice(1) : file;
runGitCommand(`git rm "${filePath}"`);
}
// Commit the deletions
runGitCommand(`git commit -m "${message}"`);
return {
content: [
{
type: "text",
text: `Successfully deleted and committed ${files.length} file(s): ${files.join(", ")}`,
},
],
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
return {
content: [
{
type: "text",
text: `Error deleting files: ${errorMessage}`,
},
],
error: errorMessage,
isError: true,
};
}
},
);
// Get git status tool // Get git status tool
server.tool("git_status", "Get the current git status", {}, async () => { server.tool("git_status", "Get the current git status", {}, async () => {
try { try {