|
|
@@ -6,10 +6,13 @@ A modular Node.js server for receiving and processing Gogs webhooks. The server
|
|
|
|
|
|
- **Persistent Job Queue**: FIFO queue ensures sequential execution and crash recovery
|
|
|
- **Modular Architecture**: Clean separation of concerns (server, handler, queue, logger)
|
|
|
-- **Command Execution**: Execute shell commands on webhook events with variable substitution
|
|
|
-- **Environment Configuration**: Configure commands via .env file
|
|
|
+- **Command Execution**: Execute shell or Node.js commands on webhook events
|
|
|
+- **JSON Configuration**: Flexible command configuration via `commands.json`
|
|
|
+- **Multiple Commands per Event**: Run multiple commands for each webhook event type
|
|
|
- **Variable Substitution**: Access repo name, branch, pusher, issue details, and more in commands
|
|
|
- **Branch Filtering**: Execute commands only for specific branches
|
|
|
+- **Node.js & Shell Support**: Run both shell scripts and Node.js scripts
|
|
|
+- **Per-Command Settings**: Configure working directory and timeout per command
|
|
|
- **Extensible Callback System**: Register callbacks for specific events or all events
|
|
|
- **Console Logging**: Colored, formatted logging of all webhook events
|
|
|
- **Health Check Endpoint**: Built-in health monitoring
|
|
|
@@ -30,14 +33,17 @@ npm install
|
|
|
|
|
|
### Quick Start
|
|
|
|
|
|
-1. Copy the example environment file:
|
|
|
+1. Copy the example files:
|
|
|
```bash
|
|
|
cp .env.example .env
|
|
|
+cp commands.json.example commands.json
|
|
|
```
|
|
|
|
|
|
-2. Edit `.env` to configure commands for webhook events (see Configuration section below)
|
|
|
+2. Edit `.env` to enable/disable webhook events
|
|
|
|
|
|
-3. Start the server:
|
|
|
+3. Edit `commands.json` to configure commands for webhook events (see Configuration section below)
|
|
|
+
|
|
|
+4. Start the server:
|
|
|
```bash
|
|
|
npm start
|
|
|
```
|
|
|
@@ -52,13 +58,11 @@ npm run dev
|
|
|
|
|
|
### Configuration
|
|
|
|
|
|
-The server is configured using a `.env` file. Copy `.env.example` to `.env` and edit it:
|
|
|
-
|
|
|
-```bash
|
|
|
-cp .env.example .env
|
|
|
-```
|
|
|
+The server uses two configuration files:
|
|
|
+1. `.env` - Enable/disable webhook events and server settings
|
|
|
+2. `commands.json` - Define commands to execute for each event type
|
|
|
|
|
|
-#### Basic Server Configuration
|
|
|
+#### Basic Server Configuration (`.env`)
|
|
|
|
|
|
```env
|
|
|
HOST=0.0.0.0
|
|
|
@@ -72,9 +76,63 @@ WEBHOOK_SECRET=your-secret-here
|
|
|
- `WEBHOOK_PATH` - The URL path for webhooks (default: `/webhook`)
|
|
|
- `WEBHOOK_SECRET` - Optional secret for webhook verification
|
|
|
|
|
|
-#### Command Execution Configuration
|
|
|
+#### Enable/Disable Events (`.env`)
|
|
|
|
|
|
-Configure commands to execute when webhooks are received. Commands support variable substitution:
|
|
|
+```env
|
|
|
+WEBHOOK_PUSH_ENABLED=true
|
|
|
+WEBHOOK_PULL_REQUEST_ENABLED=false
|
|
|
+WEBHOOK_CREATE_ENABLED=false
|
|
|
+WEBHOOK_DELETE_ENABLED=false
|
|
|
+WEBHOOK_RELEASE_ENABLED=false
|
|
|
+WEBHOOK_ISSUES_ENABLED=false
|
|
|
+WEBHOOK_ISSUE_COMMENT_ENABLED=false
|
|
|
+WEBHOOK_GLOBAL_ENABLED=false
|
|
|
+```
|
|
|
+
|
|
|
+#### Command Configuration (`commands.json`)
|
|
|
+
|
|
|
+Commands are configured in a JSON file with the following structure:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "commands": {
|
|
|
+ "push": [
|
|
|
+ {
|
|
|
+ "name": "deploy-production",
|
|
|
+ "description": "Deploy to production on main branch",
|
|
|
+ "type": "shell",
|
|
|
+ "command": "/path/to/deploy.sh",
|
|
|
+ "args": ["{{branch}}", "{{repo}}", "{{pusher}}"],
|
|
|
+ "cwd": "/workspace",
|
|
|
+ "timeout": 600000,
|
|
|
+ "filterBranch": "main"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "issues": [
|
|
|
+ {
|
|
|
+ "name": "process-issue",
|
|
|
+ "description": "Process issue with Node.js script",
|
|
|
+ "type": "node",
|
|
|
+ "command": "./scripts/process-issue.js",
|
|
|
+ "args": ["--repo", "{{repo}}", "--issue", "{{issue_number}}"],
|
|
|
+ "cwd": null,
|
|
|
+ "timeout": 300000,
|
|
|
+ "filterBranch": null
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Command Fields:**
|
|
|
+- `name` - Unique identifier for the command
|
|
|
+- `description` - Human-readable description
|
|
|
+- `type` - Either `"shell"` (bash script) or `"node"` (Node.js script)
|
|
|
+- `command` - The command or script to execute
|
|
|
+- `args` - Array of arguments (supports variable substitution)
|
|
|
+- `cwd` - Working directory (null uses project root)
|
|
|
+- `timeout` - Timeout in milliseconds
|
|
|
+- `filterBranch` - Only run for specific branch (null = all branches)
|
|
|
|
|
|
**Available Variables:**
|
|
|
- `{{repo}}` - Repository name (e.g., "my-repo")
|
|
|
@@ -87,47 +145,22 @@ Configure commands to execute when webhooks are received. Commands support varia
|
|
|
- `{{pr_number}}` - Pull request number (for PR events)
|
|
|
- `{{pr_action}}` - Pull request action (opened, closed, etc.)
|
|
|
- `{{tag}}` - Tag name (for create/delete tag events)
|
|
|
+- `{{ref_type}}` - "branch" or "tag"
|
|
|
- `{{issue_number}}` - Issue number (for issue events)
|
|
|
- `{{issue_title}}` - Issue title (for issue events)
|
|
|
- `{{issue_action}}` - Issue action (opened, closed, reopened, etc.)
|
|
|
- `{{issue_body}}` - Issue description/body (for issue events)
|
|
|
- `{{comment_body}}` - Comment text (for issue_comment events)
|
|
|
|
|
|
-**Example .env configuration:**
|
|
|
-
|
|
|
-```env
|
|
|
-# Execute command on push events
|
|
|
-WEBHOOK_PUSH_ENABLED=true
|
|
|
-WEBHOOK_PUSH_COMMAND=echo "Push to {{branch}} by {{pusher}} in {{repo}}"
|
|
|
-
|
|
|
-# Deploy only when pushing to main branch
|
|
|
-WEBHOOK_PUSH_FILTER_BRANCH=main
|
|
|
-WEBHOOK_PUSH_COMMAND=/path/to/deploy.sh {{branch}} {{repo}} {{pusher}}
|
|
|
-
|
|
|
-# Execute command on pull request events
|
|
|
-WEBHOOK_PULL_REQUEST_ENABLED=true
|
|
|
-WEBHOOK_PULL_REQUEST_COMMAND=echo "PR #{{pr_number}} {{pr_action}} by {{pusher}}"
|
|
|
-
|
|
|
-# Global command (runs for all events)
|
|
|
-WEBHOOK_GLOBAL_ENABLED=true
|
|
|
-WEBHOOK_GLOBAL_COMMAND=/path/to/notify.sh {{event}} {{repo}} {{pusher}}
|
|
|
-```
|
|
|
-
|
|
|
**Supported Event Types:**
|
|
|
-- `WEBHOOK_PUSH_*` - Push events
|
|
|
-- `WEBHOOK_PULL_REQUEST_*` - Pull request events
|
|
|
-- `WEBHOOK_CREATE_*` - Branch/tag creation
|
|
|
-- `WEBHOOK_DELETE_*` - Branch/tag deletion
|
|
|
-- `WEBHOOK_RELEASE_*` - Release events
|
|
|
-- `WEBHOOK_ISSUES_*` - Issue events (opened, closed, reopened, etc.)
|
|
|
-- `WEBHOOK_ISSUE_COMMENT_*` - Issue comment events
|
|
|
-- `WEBHOOK_GLOBAL_*` - All events
|
|
|
-
|
|
|
-**Command Settings:**
|
|
|
-```env
|
|
|
-COMMAND_TIMEOUT=300000 # Command timeout in ms (default: 5 minutes)
|
|
|
-COMMAND_WORKING_DIR=/workspace # Working directory for commands
|
|
|
-```
|
|
|
+- `push` - Push events
|
|
|
+- `pull_request` - Pull request events
|
|
|
+- `create` - Branch/tag creation
|
|
|
+- `delete` - Branch/tag deletion
|
|
|
+- `release` - Release events
|
|
|
+- `issues` - Issue events (opened, closed, reopened, etc.)
|
|
|
+- `issue_comment` - Issue comment events
|
|
|
+- `global` - All events
|
|
|
|
|
|
### Endpoints
|
|
|
|
|
|
@@ -181,8 +214,26 @@ This file is automatically managed and should not be manually edited. It's exclu
|
|
|
**.env:**
|
|
|
```env
|
|
|
WEBHOOK_PUSH_ENABLED=true
|
|
|
-WEBHOOK_PUSH_FILTER_BRANCH=main
|
|
|
-WEBHOOK_PUSH_COMMAND=/home/deploy/deploy.sh {{repo}} {{branch}} {{commit}}
|
|
|
+```
|
|
|
+
|
|
|
+**commands.json:**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "commands": {
|
|
|
+ "push": [
|
|
|
+ {
|
|
|
+ "name": "deploy-production",
|
|
|
+ "description": "Deploy to production on main branch",
|
|
|
+ "type": "shell",
|
|
|
+ "command": "/home/deploy/deploy.sh",
|
|
|
+ "args": ["{{repo}}", "{{branch}}", "{{commit}}"],
|
|
|
+ "cwd": null,
|
|
|
+ "timeout": 600000,
|
|
|
+ "filterBranch": "main"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
**deploy.sh:**
|
|
|
@@ -205,15 +256,53 @@ systemctl restart $REPO
|
|
|
**.env:**
|
|
|
```env
|
|
|
WEBHOOK_GLOBAL_ENABLED=true
|
|
|
-WEBHOOK_GLOBAL_COMMAND=curl -X POST https://api.slack.com/webhook -d '{"text":"{{event}} in {{repo}} by {{pusher}}"}'
|
|
|
```
|
|
|
|
|
|
-### Example 3: Run tests on pull request
|
|
|
+**commands.json:**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "commands": {
|
|
|
+ "global": [
|
|
|
+ {
|
|
|
+ "name": "slack-notification",
|
|
|
+ "description": "Send Slack notification for all events",
|
|
|
+ "type": "shell",
|
|
|
+ "command": "curl",
|
|
|
+ "args": ["-X", "POST", "https://api.slack.com/webhook", "-d", "{\"text\":\"{{event}} in {{repo}} by {{pusher}}\"}"],
|
|
|
+ "cwd": null,
|
|
|
+ "timeout": 30000,
|
|
|
+ "filterBranch": null
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### Example 3: Run tests on pull request with Node.js
|
|
|
|
|
|
**.env:**
|
|
|
```env
|
|
|
WEBHOOK_PULL_REQUEST_ENABLED=true
|
|
|
-WEBHOOK_PULL_REQUEST_COMMAND=/home/scripts/run-tests.sh {{repo}} {{pr_number}} {{pusher}}
|
|
|
+```
|
|
|
+
|
|
|
+**commands.json:**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "commands": {
|
|
|
+ "pull_request": [
|
|
|
+ {
|
|
|
+ "name": "run-tests",
|
|
|
+ "description": "Run automated tests on pull request",
|
|
|
+ "type": "node",
|
|
|
+ "command": "./scripts/run-tests.js",
|
|
|
+ "args": ["--repo", "{{repo}}", "--pr", "{{pr_number}}", "--author", "{{pusher}}"],
|
|
|
+ "cwd": "/home/ci",
|
|
|
+ "timeout": 900000,
|
|
|
+ "filterBranch": null
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
## Extending with Callbacks
|
|
|
@@ -291,11 +380,14 @@ node examples/with-callbacks.js
|
|
|
│ ├── webhookHandler.js # Webhook processing and callbacks
|
|
|
│ ├── jobQueue.js # Persistent job queue with FIFO processing
|
|
|
│ ├── commandExecutor.js # Command execution with variable substitution
|
|
|
-│ ├── config.js # Configuration loader (.env parser)
|
|
|
+│ ├── config.js # Configuration loader (.env and commands.json)
|
|
|
│ └── logger.js # Logging utility
|
|
|
├── examples/
|
|
|
│ └── with-callbacks.js # Example with custom callbacks
|
|
|
-├── .env.example # Example configuration file
|
|
|
+├── .env.example # Example environment configuration
|
|
|
+├── commands.json.example # Example command configuration
|
|
|
+├── .env # Your environment configuration (not in git)
|
|
|
+├── commands.json # Your command configuration (not in git)
|
|
|
├── queue.json # Queue state (auto-generated, gitignored)
|
|
|
├── package.json
|
|
|
└── README.md
|
|
|
@@ -323,8 +415,9 @@ node examples/with-callbacks.js
|
|
|
- Provides queue statistics and status
|
|
|
|
|
|
### CommandExecutor (`src/commandExecutor.js`)
|
|
|
-- Executes shell commands on webhook events
|
|
|
-- Performs variable substitution
|
|
|
+- Executes shell and Node.js commands on webhook events
|
|
|
+- Performs variable substitution in commands and arguments
|
|
|
+- Supports both shell scripts and Node.js scripts
|
|
|
- Handles command timeouts and errors
|
|
|
- Extracts webhook payload data
|
|
|
|
|
|
@@ -334,9 +427,10 @@ node examples/with-callbacks.js
|
|
|
- Handles timestamp formatting
|
|
|
|
|
|
### Config (`src/config.js`)
|
|
|
-- Loads and parses .env file
|
|
|
+- Loads and parses .env file and commands.json
|
|
|
- Provides configuration access methods
|
|
|
- Merges environment variables with file config
|
|
|
+- Supports backward compatibility with legacy .env commands
|
|
|
|
|
|
## Testing
|
|
|
|