A webhook receiver service that listens for Harness FME feature flag changes and triggers GitHub Actions workflows. Perfect for demonstrating how feature flag changes can automatically trigger CI/CD pipelines, deployments, tests, and other automated workflows.
This project demonstrates how to integrate feature flag management with GitHub Actions:
- Harness FME sends a webhook when a flag changes
- This webhook receiver processes the payload
- GitHub Actions workflow is triggered automatically
- Workflow runs your tests, deployments, or any custom automation
gh-post/
├── server.js # Express server
├── src/
│ ├── logger.js # Logging utility
│ ├── webhook-handler.js # Webhook processing logic
│ └── github-dispatcher.js # GitHub API integration
├── .github/workflows/
│ ├── feature-flag-deploy.yml # Main demo workflow
│ └── test-dispatch.yml # Simple test workflow
├── examples/
│ ├── webhook-payload.json # Sample Harness FME payload
│ └── test-webhook.sh # Local testing script
├── package.json
├── .env.example
└── README.md
npm installCopy the example environment file:
cp .env.example .envEdit .env with your values:
GITHUB_TOKEN=ghp_your_token_here
GITHUB_OWNER=your-github-username
GITHUB_REPO=gh-post
PORT=3000
NODE_ENV=development- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Click "Generate new token (classic)"
- Give it a descriptive name (e.g., "Feature Flag Webhook")
- Select scopes:
- Check
repo(Full control of private repositories) - This includes the necessary
actions:writepermission
- Check
- Click "Generate token"
- Copy the token and add it to your
.envfile
git init
git add .
git commit -m "Initial commit: Feature flag webhook receiver"Create a new repository on GitHub named gh-post, then:
git remote add origin https://github.com/YOUR_USERNAME/gh-post.git
git branch -M main
git push -u origin mainThis step is important because the GitHub Actions workflows need to exist in your repository for the repository_dispatch event to work.
npm run devYou should see:
[2025-12-11T...] [INFO] Server started on port 3000
[2025-12-11T...] [INFO] Endpoints:
[2025-12-11T...] [INFO] POST http://localhost:3000/webhook - Receive feature flag webhooks
[2025-12-11T...] [INFO] GET http://localhost:3000/health - Health check
curl http://localhost:3000/healthnpm run testOr manually:
curl -X POST http://localhost:3000/webhook \
-H "Content-Type: application/json" \
-d @examples/webhook-payload.jsonGo to your GitHub repository → Actions tab. You should see a new workflow run for "Feature Flag Deploy".
To receive webhooks from Harness FME, you need to expose your local server:
# macOS
brew install ngrok
# Or download from https://ngrok.com/downloadngrok http 3000You'll see output like:
Forwarding https://abc123def456.ngrok.io -> http://localhost:3000
Copy the https:// URL (e.g., https://abc123def456.ngrok.io)
- Go to your Harness FME project
- Navigate to FNE Settings → Integrations → Webhooks
- Add a new Audit Log Webhook
- URL:
https://abc123def456.ngrok.io/webhook
- URL:
- Go to your Harness FME dashboard
- Make a change to any feature flag (enable/disable, change targeting, etc.)
- Watch your server logs for the incoming webhook
- Check GitHub Actions for the triggered workflow
Harness FME Feature Flag Change
↓
(HTTP POST)
↓
Your Webhook Receiver (this app)
↓
Validates & Transforms Payload
↓
GitHub API (repository_dispatch)
↓
GitHub Actions Workflow Triggered
↓
Runs Tests/Deployments/Etc.
Harness FME sends:
{
"name": "new-checkout-flow",
"environmentName": "production",
"editor": "developer@example.com",
...
}We transform and send to GitHub:
{
"event_type": "feature-flag-changed",
"client_payload": {
"flag_name": "new-checkout-flow",
"environment": "production",
"editor": "developer@example.com",
...
}
}GitHub Actions receives:
Access via ${{ github.event.client_payload.flag_name }}, etc.
Main workflow that demonstrates:
- Extracting feature flag metadata from the webhook
- Logging change information
- Running tests
- Simulating deployment
- Notification steps
Customize this workflow to:
- Run your actual test suite
- Deploy to staging/production based on environment
- Send Slack/email notifications
- Update documentation
- Trigger dependent workflows
Simple workflow for testing the integration:
- Can be triggered manually via workflow_dispatch
- Can be triggered via repository_dispatch with
test-eventtype - Displays all event data for debugging
Edit src/github-dispatcher.js to send different event types:
const eventType = payload.environment === 'production'
? 'feature-flag-production'
: 'feature-flag-staging';
await octokit.repos.createDispatchEvent({
owner,
repo,
event_type: eventType,
client_payload: payload
});Then create separate workflows for each event type.
To add HMAC signature verification:
-
Add to
.env:WEBHOOK_SECRET=your-secret-key -
Update
src/webhook-handler.js:const crypto = require('crypto'); function verifySignature(payload, signature) { const hmac = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET); const digest = hmac.update(JSON.stringify(payload)).digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(digest) ); }
- Verify your
GITHUB_TOKENin.envis correct - Ensure the token has
reposcope - Check the token hasn't expired
- Verify
GITHUB_OWNERandGITHUB_REPOare correct - Ensure you've pushed the repository to GitHub
- Check the GitHub Actions workflows exist in
.github/workflows/
- Verify the workflows are committed and pushed to GitHub
- Check that the
event_typein the dispatcher matches the workflow trigger - Look at server logs to confirm the dispatch was sent successfully
- Ensure GitHub Actions is enabled for your repository
- Make sure ngrok is running while testing
- The URL changes each time you restart ngrok (use a static domain with paid plan)
- Verify the webhook URL in Harness matches your current ngrok URL
For production use, deploy this service to:
- Heroku:
git push heroku main - Railway: Connect your GitHub repo
- Render: Connect your GitHub repo
- Google Cloud Run: Deploy as container
- AWS Lambda: Use serverless framework
Remember to:
- Set environment variables in your hosting platform
- Use managed secrets (not
.envfiles) - Add webhook signature verification
- Implement rate limiting
- Add monitoring and logging
- Use HTTPS (handled by most platforms automatically)
Apache 2.0
Feel free to submit issues or pull requests!