mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2025-12-24 01:02:43 +00:00
# Add Gitea Actions support (secrets, variables, workflows, runs, jobs, logs)
## Summary
This PR adds comprehensive support for Gitea Actions API to the MCP server, enabling users to manage Actions secrets, variables, workflows, runs, jobs, and logs through the Model Context Protocol interface.
## New Features
### Actions Secrets (Repository & Organization Level)
- `list_repo_action_secrets` - List repository secrets (metadata only, values never exposed)
- `upsert_repo_action_secret` - Create or update a repository secret
- `delete_repo_action_secret` - Delete a repository secret
- `list_org_action_secrets` - List organization secrets
- `upsert_org_action_secret` - Create or update an organization secret
- `delete_org_action_secret` - Delete an organization secret
### Actions Variables (Repository & Organization Level)
- `list_repo_action_variables` - List repository variables
- `get_repo_action_variable` - Get a specific repository variable
- `create_repo_action_variable` - Create a repository variable
- `update_repo_action_variable` - Update a repository variable
- `delete_repo_action_variable` - Delete a repository variable
- `list_org_action_variables` - List organization variables
- `get_org_action_variable` - Get a specific organization variable
- `create_org_action_variable` - Create an organization variable
- `update_org_action_variable` - Update an organization variable
- `delete_org_action_variable` - Delete an organization variable
### Actions Workflows
- `list_repo_action_workflows` - List repository workflows
- `get_repo_action_workflow` - Get a specific workflow by ID
- `dispatch_repo_action_workflow` - Trigger (dispatch) a workflow run with optional inputs
### Actions Runs
- `list_repo_action_runs` - List workflow runs with optional status filtering
- `get_repo_action_run` - Get a specific run by ID
- `cancel_repo_action_run` - Cancel a running workflow
- `rerun_repo_action_run` - Rerun a workflow (with fallback routes for version compatibility)
### Actions Jobs
- `list_repo_action_jobs` - List all jobs in a repository
- `list_repo_action_run_jobs` - List jobs for a specific workflow run
### Actions Job Logs
- `get_repo_action_job_log_preview` - Get log preview with tail/limit support (chat-friendly)
- `download_repo_action_job_log` - Download full job logs to file (default: `~/.gitea-mcp/artifacts/actions-logs/`)
## Implementation Details
### Architecture
- Follows existing codebase patterns: new `operation/actions/` package with tools registered via `Tool.RegisterRead/Write()`
- Uses Gitea SDK (`code.gitea.io/sdk/gitea v0.22.1`) where endpoints are available
- Shared REST helper (`pkg/gitea/rest.go`) for endpoints not yet in SDK (workflows, runs, jobs, logs)
### Security
- **Secrets never expose values**: List/get operations return only safe metadata (name, description, created_at)
- Request-scoped token support: HTTP Bearer tokens properly respected (fixes issue where wiki REST calls were hardcoding `flag.Token`)
### Compatibility
- Fallback route logic for dispatch/rerun endpoints (handles Gitea version differences)
- Clear error messages when endpoints aren't available, referencing Gitea 1.24 API docs
- Graceful handling of 404/405 responses for unsupported endpoints
### Testing
- Unit tests for REST helper token precedence
- Unit tests for log truncation/formatting helpers
- All existing tests pass
## Files Changed
- **New**: `operation/actions/*` - Complete Actions module (secrets, variables, runs, logs)
- **New**: `pkg/gitea/rest.go` - Shared REST helper with token context support
- **New**: `pkg/gitea/rest_test.go` - Tests for REST helper
- **Modified**: `operation/operation.go` - Register Actions tools
- **Modified**: `operation/wiki/wiki.go` - Refactored to use shared REST helper (removed hardcoded token)
- **Modified**: `README.md` - Added all new tools to documentation
## Testing
```bash
# All tests pass
go test ./...
# Build succeeds
make build
```
## Example Usage
```python
# List repository secrets
mcp.call_tool("list_repo_action_secrets", {"owner": "user", "repo": "myrepo"})
# Trigger a workflow
mcp.call_tool("dispatch_repo_action_workflow", {
"owner": "user",
"repo": "myrepo",
"workflow_id": 123,
"ref": "main",
"inputs": {"deploy_env": "production"}
})
# Get job log preview (last 100 lines)
mcp.call_tool("get_repo_action_job_log_preview", {
"owner": "user",
"repo": "myrepo",
"job_id": 456,
"tail_lines": 100
})
```
## Breaking Changes
None - this is a purely additive change.
## Related Issues
Fixes #[issue-number] (if applicable)
## Checklist
- [x] Code follows existing patterns and conventions
- [x] All tests pass
- [x] Documentation updated (README.md)
- [x] No breaking changes
- [x] Security considerations addressed (secrets never expose values)
- [x] Error handling implemented with clear messages
- [x] Version compatibility considered (fallback routes)
Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/110
Reviewed-by: hiifong <f@f.style>
Co-authored-by: Shawn Anderson <sanderson@eye-catcher.com>
Co-committed-by: Shawn Anderson <sanderson@eye-catcher.com>
403 lines
16 KiB
Go
403 lines
16 KiB
Go
package actions
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"gitea.com/gitea/gitea-mcp/pkg/gitea"
|
|
"gitea.com/gitea/gitea-mcp/pkg/log"
|
|
"gitea.com/gitea/gitea-mcp/pkg/to"
|
|
|
|
gitea_sdk "code.gitea.io/sdk/gitea"
|
|
"github.com/mark3labs/mcp-go/mcp"
|
|
"github.com/mark3labs/mcp-go/server"
|
|
)
|
|
|
|
const (
|
|
ListRepoActionVariablesToolName = "list_repo_action_variables"
|
|
GetRepoActionVariableToolName = "get_repo_action_variable"
|
|
CreateRepoActionVariableToolName = "create_repo_action_variable"
|
|
UpdateRepoActionVariableToolName = "update_repo_action_variable"
|
|
DeleteRepoActionVariableToolName = "delete_repo_action_variable"
|
|
|
|
ListOrgActionVariablesToolName = "list_org_action_variables"
|
|
GetOrgActionVariableToolName = "get_org_action_variable"
|
|
CreateOrgActionVariableToolName = "create_org_action_variable"
|
|
UpdateOrgActionVariableToolName = "update_org_action_variable"
|
|
DeleteOrgActionVariableToolName = "delete_org_action_variable"
|
|
)
|
|
|
|
var (
|
|
ListRepoActionVariablesTool = mcp.NewTool(
|
|
ListRepoActionVariablesToolName,
|
|
mcp.WithDescription("List repository Actions variables"),
|
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
|
mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(1), mcp.Min(1)),
|
|
mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(100), mcp.Min(1)),
|
|
)
|
|
|
|
GetRepoActionVariableTool = mcp.NewTool(
|
|
GetRepoActionVariableToolName,
|
|
mcp.WithDescription("Get a repository Actions variable by name"),
|
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
)
|
|
|
|
CreateRepoActionVariableTool = mcp.NewTool(
|
|
CreateRepoActionVariableToolName,
|
|
mcp.WithDescription("Create a repository Actions variable"),
|
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
mcp.WithString("value", mcp.Required(), mcp.Description("variable value")),
|
|
)
|
|
|
|
UpdateRepoActionVariableTool = mcp.NewTool(
|
|
UpdateRepoActionVariableToolName,
|
|
mcp.WithDescription("Update a repository Actions variable"),
|
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
mcp.WithString("value", mcp.Required(), mcp.Description("new variable value")),
|
|
)
|
|
|
|
DeleteRepoActionVariableTool = mcp.NewTool(
|
|
DeleteRepoActionVariableToolName,
|
|
mcp.WithDescription("Delete a repository Actions variable"),
|
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
)
|
|
|
|
ListOrgActionVariablesTool = mcp.NewTool(
|
|
ListOrgActionVariablesToolName,
|
|
mcp.WithDescription("List organization Actions variables"),
|
|
mcp.WithString("org", mcp.Required(), mcp.Description("organization name")),
|
|
mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(1), mcp.Min(1)),
|
|
mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(100), mcp.Min(1)),
|
|
)
|
|
|
|
GetOrgActionVariableTool = mcp.NewTool(
|
|
GetOrgActionVariableToolName,
|
|
mcp.WithDescription("Get an organization Actions variable by name"),
|
|
mcp.WithString("org", mcp.Required(), mcp.Description("organization name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
)
|
|
|
|
CreateOrgActionVariableTool = mcp.NewTool(
|
|
CreateOrgActionVariableToolName,
|
|
mcp.WithDescription("Create an organization Actions variable"),
|
|
mcp.WithString("org", mcp.Required(), mcp.Description("organization name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
mcp.WithString("value", mcp.Required(), mcp.Description("variable value")),
|
|
mcp.WithString("description", mcp.Description("variable description")),
|
|
)
|
|
|
|
UpdateOrgActionVariableTool = mcp.NewTool(
|
|
UpdateOrgActionVariableToolName,
|
|
mcp.WithDescription("Update an organization Actions variable"),
|
|
mcp.WithString("org", mcp.Required(), mcp.Description("organization name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
mcp.WithString("value", mcp.Required(), mcp.Description("new variable value")),
|
|
mcp.WithString("description", mcp.Description("new variable description")),
|
|
)
|
|
|
|
DeleteOrgActionVariableTool = mcp.NewTool(
|
|
DeleteOrgActionVariableToolName,
|
|
mcp.WithDescription("Delete an organization Actions variable"),
|
|
mcp.WithString("org", mcp.Required(), mcp.Description("organization name")),
|
|
mcp.WithString("name", mcp.Required(), mcp.Description("variable name")),
|
|
)
|
|
)
|
|
|
|
func init() {
|
|
Tool.RegisterRead(server.ServerTool{Tool: ListRepoActionVariablesTool, Handler: ListRepoActionVariablesFn})
|
|
Tool.RegisterRead(server.ServerTool{Tool: GetRepoActionVariableTool, Handler: GetRepoActionVariableFn})
|
|
Tool.RegisterWrite(server.ServerTool{Tool: CreateRepoActionVariableTool, Handler: CreateRepoActionVariableFn})
|
|
Tool.RegisterWrite(server.ServerTool{Tool: UpdateRepoActionVariableTool, Handler: UpdateRepoActionVariableFn})
|
|
Tool.RegisterWrite(server.ServerTool{Tool: DeleteRepoActionVariableTool, Handler: DeleteRepoActionVariableFn})
|
|
|
|
Tool.RegisterRead(server.ServerTool{Tool: ListOrgActionVariablesTool, Handler: ListOrgActionVariablesFn})
|
|
Tool.RegisterRead(server.ServerTool{Tool: GetOrgActionVariableTool, Handler: GetOrgActionVariableFn})
|
|
Tool.RegisterWrite(server.ServerTool{Tool: CreateOrgActionVariableTool, Handler: CreateOrgActionVariableFn})
|
|
Tool.RegisterWrite(server.ServerTool{Tool: UpdateOrgActionVariableTool, Handler: UpdateOrgActionVariableFn})
|
|
Tool.RegisterWrite(server.ServerTool{Tool: DeleteOrgActionVariableTool, Handler: DeleteOrgActionVariableFn})
|
|
}
|
|
|
|
func ListRepoActionVariablesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called ListRepoActionVariablesFn")
|
|
owner, ok := req.GetArguments()["owner"].(string)
|
|
if !ok || owner == "" {
|
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
|
}
|
|
repo, ok := req.GetArguments()["repo"].(string)
|
|
if !ok || repo == "" {
|
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
|
}
|
|
page, _ := req.GetArguments()["page"].(float64)
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
pageSize, _ := req.GetArguments()["pageSize"].(float64)
|
|
if pageSize <= 0 {
|
|
pageSize = 100
|
|
}
|
|
|
|
query := url.Values{}
|
|
query.Set("page", fmt.Sprintf("%d", int(page)))
|
|
query.Set("limit", fmt.Sprintf("%d", int(pageSize)))
|
|
|
|
var result any
|
|
_, err := gitea.DoJSON(ctx, "GET", fmt.Sprintf("repos/%s/%s/actions/variables", url.PathEscape(owner), url.PathEscape(repo)), query, nil, &result)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("list repo action variables err: %v", err))
|
|
}
|
|
return to.TextResult(result)
|
|
}
|
|
|
|
func GetRepoActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called GetRepoActionVariableFn")
|
|
owner, ok := req.GetArguments()["owner"].(string)
|
|
if !ok || owner == "" {
|
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
|
}
|
|
repo, ok := req.GetArguments()["repo"].(string)
|
|
if !ok || repo == "" {
|
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
variable, _, err := client.GetRepoActionVariable(owner, repo, name)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get repo action variable err: %v", err))
|
|
}
|
|
return to.TextResult(variable)
|
|
}
|
|
|
|
func CreateRepoActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called CreateRepoActionVariableFn")
|
|
owner, ok := req.GetArguments()["owner"].(string)
|
|
if !ok || owner == "" {
|
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
|
}
|
|
repo, ok := req.GetArguments()["repo"].(string)
|
|
if !ok || repo == "" {
|
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
value, ok := req.GetArguments()["value"].(string)
|
|
if !ok || value == "" {
|
|
return to.ErrorResult(fmt.Errorf("value is required"))
|
|
}
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
resp, err := client.CreateRepoActionVariable(owner, repo, name, value)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("create repo action variable err: %v", err))
|
|
}
|
|
return to.TextResult(map[string]any{"message": "variable created", "status": resp.StatusCode})
|
|
}
|
|
|
|
func UpdateRepoActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called UpdateRepoActionVariableFn")
|
|
owner, ok := req.GetArguments()["owner"].(string)
|
|
if !ok || owner == "" {
|
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
|
}
|
|
repo, ok := req.GetArguments()["repo"].(string)
|
|
if !ok || repo == "" {
|
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
value, ok := req.GetArguments()["value"].(string)
|
|
if !ok || value == "" {
|
|
return to.ErrorResult(fmt.Errorf("value is required"))
|
|
}
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
resp, err := client.UpdateRepoActionVariable(owner, repo, name, value)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("update repo action variable err: %v", err))
|
|
}
|
|
return to.TextResult(map[string]any{"message": "variable updated", "status": resp.StatusCode})
|
|
}
|
|
|
|
func DeleteRepoActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called DeleteRepoActionVariableFn")
|
|
owner, ok := req.GetArguments()["owner"].(string)
|
|
if !ok || owner == "" {
|
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
|
}
|
|
repo, ok := req.GetArguments()["repo"].(string)
|
|
if !ok || repo == "" {
|
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
resp, err := client.DeleteRepoActionVariable(owner, repo, name)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("delete repo action variable err: %v", err))
|
|
}
|
|
return to.TextResult(map[string]any{"message": "variable deleted", "status": resp.StatusCode})
|
|
}
|
|
|
|
func ListOrgActionVariablesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called ListOrgActionVariablesFn")
|
|
org, ok := req.GetArguments()["org"].(string)
|
|
if !ok || org == "" {
|
|
return to.ErrorResult(fmt.Errorf("org is required"))
|
|
}
|
|
page, _ := req.GetArguments()["page"].(float64)
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
pageSize, _ := req.GetArguments()["pageSize"].(float64)
|
|
if pageSize <= 0 {
|
|
pageSize = 100
|
|
}
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
variables, _, err := client.ListOrgActionVariable(org, gitea_sdk.ListOrgActionVariableOption{
|
|
ListOptions: gitea_sdk.ListOptions{Page: int(page), PageSize: int(pageSize)},
|
|
})
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("list org action variables err: %v", err))
|
|
}
|
|
return to.TextResult(variables)
|
|
}
|
|
|
|
func GetOrgActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called GetOrgActionVariableFn")
|
|
org, ok := req.GetArguments()["org"].(string)
|
|
if !ok || org == "" {
|
|
return to.ErrorResult(fmt.Errorf("org is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
variable, _, err := client.GetOrgActionVariable(org, name)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get org action variable err: %v", err))
|
|
}
|
|
return to.TextResult(variable)
|
|
}
|
|
|
|
func CreateOrgActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called CreateOrgActionVariableFn")
|
|
org, ok := req.GetArguments()["org"].(string)
|
|
if !ok || org == "" {
|
|
return to.ErrorResult(fmt.Errorf("org is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
value, ok := req.GetArguments()["value"].(string)
|
|
if !ok || value == "" {
|
|
return to.ErrorResult(fmt.Errorf("value is required"))
|
|
}
|
|
description, _ := req.GetArguments()["description"].(string)
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
resp, err := client.CreateOrgActionVariable(org, gitea_sdk.CreateOrgActionVariableOption{
|
|
Name: name,
|
|
Value: value,
|
|
Description: description,
|
|
})
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("create org action variable err: %v", err))
|
|
}
|
|
return to.TextResult(map[string]any{"message": "variable created", "status": resp.StatusCode})
|
|
}
|
|
|
|
func UpdateOrgActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called UpdateOrgActionVariableFn")
|
|
org, ok := req.GetArguments()["org"].(string)
|
|
if !ok || org == "" {
|
|
return to.ErrorResult(fmt.Errorf("org is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
value, ok := req.GetArguments()["value"].(string)
|
|
if !ok || value == "" {
|
|
return to.ErrorResult(fmt.Errorf("value is required"))
|
|
}
|
|
description, _ := req.GetArguments()["description"].(string)
|
|
|
|
client, err := gitea.ClientFromContext(ctx)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
|
}
|
|
resp, err := client.UpdateOrgActionVariable(org, name, gitea_sdk.UpdateOrgActionVariableOption{
|
|
Value: value,
|
|
Description: description,
|
|
})
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("update org action variable err: %v", err))
|
|
}
|
|
return to.TextResult(map[string]any{"message": "variable updated", "status": resp.StatusCode})
|
|
}
|
|
|
|
func DeleteOrgActionVariableFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
log.Debugf("Called DeleteOrgActionVariableFn")
|
|
org, ok := req.GetArguments()["org"].(string)
|
|
if !ok || org == "" {
|
|
return to.ErrorResult(fmt.Errorf("org is required"))
|
|
}
|
|
name, ok := req.GetArguments()["name"].(string)
|
|
if !ok || name == "" {
|
|
return to.ErrorResult(fmt.Errorf("name is required"))
|
|
}
|
|
|
|
_, err := gitea.DoJSON(ctx, "DELETE", fmt.Sprintf("orgs/%s/actions/variables/%s", url.PathEscape(org), url.PathEscape(name)), nil, nil, nil)
|
|
if err != nil {
|
|
return to.ErrorResult(fmt.Errorf("delete org action variable err: %v", err))
|
|
}
|
|
return to.TextResult(map[string]any{"message": "variable deleted"})
|
|
}
|
|
|
|
|