Procházet zdrojové kódy

feat: add filterActions and filterAssignee configuration fields #17

Implemented filtering logic in commandExecutor.js to allow fine-grained control over which issue and PR actions trigger command execution.

Changes:
- Added filterActions array support to filter by specific actions (e.g., "assigned", "opened", "reopened")
- Added filterAssignee string support to filter by assignee username
- Updated commands.json.example with practical examples showing the new filters
- Updated CLAUDE.md documentation with comprehensive filter field descriptions
- Added logging when commands are skipped due to filters

Benefits:
- Move filtering logic from shell scripts to centralized configuration
- More declarative and maintainable command execution control
- Better visibility into why commands execute or skip

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Claude před 9 měsíci
rodič
revize
b2e468f9c3
3 změnil soubory, kde provedl 46 přidání a 4 odebrání
  1. 9 2
      CLAUDE.md
  2. 17 2
      commands.json.example
  3. 20 0
      src/commandExecutor.js

+ 9 - 2
CLAUDE.md

@@ -144,7 +144,9 @@ Copy from `commands.json.example` and configure commands for each event type.
         "args": ["arg1", "{{variable}}", "arg3"],
         "cwd": "/working/directory" | null,
         "timeout": 300000,
-        "filterBranch": "branch-name" | null
+        "filterBranch": "branch-name" | null,
+        "filterActions": ["action1", "action2"] | null,
+        "filterAssignee": "username" | null
       }
     ]
   }
@@ -164,6 +166,8 @@ Copy from `commands.json.example` and configure commands for each event type.
 - `cwd` - Working directory (null = project root)
 - `timeout` - Timeout in milliseconds
 - `filterBranch` - Only execute for specific branch (null = all branches)
+- `filterActions` - Only execute for specific actions (array, optional). Examples: `["assigned", "opened"]`, `["synchronize"]`. If omitted or empty, execute for all actions
+- `filterAssignee` - Only execute when issue/PR is assigned to specific user (string, optional). If omitted, execute regardless of assignee
 
 ## Important Patterns
 
@@ -174,7 +178,10 @@ Copy from `commands.json.example` and configure commands for each event type.
 5. **Configuration Files**: `.env` for enable/disable flags, `commands.json` for command definitions
 6. **Backward Compatibility**: Legacy .env command format still supported (deprecated)
 7. **Error Handling**: Try-catch blocks with logging; errors don't stop server
-8. **Branch Filtering**: Optional per-command branch filtering via `filterBranch` field
+8. **Command Filtering**: Optional per-command filtering via:
+   - `filterBranch` - Execute only for specific branches
+   - `filterActions` - Execute only for specific actions (e.g., `["assigned", "opened"]`)
+   - `filterAssignee` - Execute only when assigned to specific user (e.g., `"claude"`)
 9. **Multiple Commands**: Each event type can have multiple commands that execute sequentially
 10. **Shell & Node Execution**: Commands can be shell scripts or Node.js scripts
 

+ 17 - 2
commands.json.example

@@ -34,6 +34,17 @@
         "cwd": null,
         "timeout": 300000,
         "filterBranch": null
+      },
+      {
+        "name": "pr-ci-trigger",
+        "description": "Trigger CI only for opened or synchronized PRs",
+        "type": "shell",
+        "command": "/path/to/trigger-ci.sh",
+        "args": ["{{repo}}", "{{pr_number}}"],
+        "cwd": null,
+        "timeout": 300000,
+        "filterBranch": null,
+        "filterActions": ["opened", "synchronize"]
       }
     ],
     "create": [
@@ -91,7 +102,9 @@
         "args": ["{{repo_owner}}", "{{repo}}", "{{pusher}}", "{{issue_number}}", "{{issue_title}}", "{{issue_body}}", "{{issue_action}}", "", "{{issue_assignee}}"],
         "cwd": "~",
         "timeout": 600000,
-        "filterBranch": null
+        "filterBranch": null,
+        "filterActions": ["assigned", "opened", "reopened"],
+        "filterAssignee": "claude"
       },
       {
         "name": "triage-issue",
@@ -133,7 +146,9 @@
         "args": ["{{repo_owner}}", "{{repo}}", "{{pusher}}", "{{issue_number}}", "{{issue_title}}", "{{issue_body}}", "{{issue_action}}", "{{comment_body}}", "{{issue_assignee}}"],
         "cwd": "~",
         "timeout": 600000,
-        "filterBranch": null
+        "filterBranch": null,
+        "filterActions": ["created"],
+        "filterAssignee": "claude"
       },
       {
         "name": "check-comment-commands",

+ 20 - 0
src/commandExecutor.js

@@ -278,6 +278,26 @@ export class CommandExecutor {
       return null;
     }
 
+    // Apply action filter if configured
+    if (config.filterActions && Array.isArray(config.filterActions) && config.filterActions.length > 0) {
+      const action = variables.issue_action || variables.pr_action || payload.action || '';
+      if (!config.filterActions.includes(action)) {
+        const commandName = config.name || config.command || 'unknown';
+        logger.info(`Skipping command '${commandName}' - action '${action}' not in filterActions [${config.filterActions.join(', ')}]`);
+        return null;
+      }
+    }
+
+    // Apply assignee filter if configured
+    if (config.filterAssignee) {
+      const assignee = variables.issue_assignee || '';
+      if (assignee !== config.filterAssignee) {
+        const commandName = config.name || config.command || 'unknown';
+        logger.info(`Skipping command '${commandName}' - assignee '${assignee}' does not match filter '${config.filterAssignee}'`);
+        return null;
+      }
+    }
+
     let command, args, type;
 
     if (isNewFormat) {