A self-hosted webhook processing system that replaces Jira Automation's 3 core rules with a 1:1 alternative.
- Rule-01: Change Jira issue status from 'To Do' → 'In Progress' when branch is created
- Rule-02: Change Jira issue status to 'In Review' when PR is created
- Rule-03: Change Jira issue status to 'Done' when PR is merged
- Discord Notifications: Real-time notifications for each automation result
The following statuses must exist in your Jira project with appropriate transition paths:
Status Name | Used By | Transition Path |
---|---|---|
To Do | Rule-01 | Initial status |
In Progress | Rule-01 | To Do → In Progress |
In Review | Rule-02 | In Progress → In Review |
Done | Rule-03 | Any status → Done |
git clone <repository-url>
cd free-jira-github-integration
npm install
Copy .env.example
to create .env
file and configure values:
cp .env.example .env
# Server Configuration
PORT=3000
# GitHub Webhook Configuration
GITHUB_WEBHOOK_SECRET=your-github-webhook-secret-here
# Jira Configuration
JIRA_BASE_URL=https://your-domain.atlassian.net
JIRA_EMAIL=[email protected]
JIRA_API_TOKEN=your-jira-api-token-here
JIRA_PROJECT_KEY=PROJ
# Jira Status Names (customize according to your workflow)
JIRA_STATUS_TODO=To Do
JIRA_STATUS_IN_PROGRESS=In Progress
JIRA_STATUS_IN_REVIEW=In Review
JIRA_STATUS_DONE=Done
# Logging
LOG_LEVEL=info
# Discord Notifications (Optional)
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your-webhook-url
-
Navigate to Atlassian Account Settings
- 🌐 URL: https://id.atlassian.com/manage-profile/security/api-tokens
⚠️ Note: NOThttps://admin.atlassian.com/
!
-
Create API Token
- Click "Create API token" button
- Enter token name (e.g., "GitHub Integration")
- Copy the generated token (shown only once)
-
Set Environment Variable
- Set the copied token to
JIRA_API_TOKEN
- Set the copied token to
When the API token is correctly configured, you'll see logs like this:
POST https://your-worker.workers.dev/api/webhook/github - Ok
(log) Received create event
(log) Processing branch creation event
(log) Found Jira key: MAT-388
(log) Current status: To Do
(log) Successfully transitioned MAT-388 to In Progress
(log) Rule-01: MAT-388 transitioned from To Do to In Progress
If you see errors like this, the API token is incorrectly configured:
Rule-01 failed for MAT-388: Failed to get issue status: Issue MAT-388 not found
Solution:
- Delete existing token and create a new one
- Ensure no leading/trailing spaces when copying token
- Verify the account has access to the Jira project
Test the connection after setup:
curl -u "[email protected]:your-api-token" \
-X GET \
-H "Content-Type: application/json" \
"https://your-domain.atlassian.net/rest/api/3/myself"
Success returns account information in JSON format.
GitHub webhooks enable SSL verification by default, but it can be disabled when needed.
- HTTPS endpoint + SSL verification enabled
- Highest security level
- Requires domain with SSL certificate
- HTTP endpoint available (when SSL verification disabled)
- Local development:
http://localhost:3000
can be used directly - Lower security but convenient for development
# Option 1: HTTP + SSL verification disabled (simple)
# Use http://localhost:3000 directly
# Check "Disable SSL verification" in GitHub webhook settings
# Option 2: HTTPS tunnel (secure)
npx ngrok http 3000 # or
npx cloudflared tunnel --url http://localhost:3000
- GitHub Repository → Settings → Webhooks → Add webhook
- Payload URL:
- Production:
https://your-domain.com/api/webhook/github
- Local Development:
http://localhost:3000/api/webhook/github
- Production:
- Content type:
application/json
- Secret: Same value as
GITHUB_WEBHOOK_SECRET
in.env
- SSL verification:
- Production: Keep checked (default)
- Local Development: Check "Disable SSL verification"
- Events: Select
Branch or tag creation
,Pull requests
,Pushes
npm run dev
npm start
Endpoint to receive webhooks from GitHub.
Headers:
Content-Type
:application/json
X-GitHub-Event
: GitHub event typeX-Hub-Signature-256
: HMAC-SHA256 signature
Health check endpoint to verify server status.
(${projectKey}-\d+)
- Case-insensitive: Both
MAT-123
andmat-123
match - Result converted to uppercase: Finally unified as
MAT-123
format
✅ Working formats:
feature/MAT-123-add-login
bugfix/mat-456-fix-navigation (case-insensitive)
MAT-789
hotfix/MAT-999-urgent-fix
feat/MAT-123/hello-world
release/v1.0-MAT-111-final-changes
❌ Non-working formats:
feature/PROJ-123 (different project key)
feature/MAT (no issue number)
feature/add-login (no Jira key)
- 1st Priority: Try extracting from PR title
- 2nd Priority: Try extracting from branch name (fallback)
Branch Creation:
git checkout -b "feat/MAT-123/implement-auth"
# → Changes MAT-123 issue from 'To Do' → 'In Progress'
PR Creation:
PR Title: "MAT-456: Add user authentication"
Branch Name: "feature/auth-system"
# → Extracts MAT-456 from PR title and changes to 'In Review'
-
Branch Creation (
create
event)- Changes to 'In Progress' only if current status is 'To Do'
-
PR Creation (
pull_request
-opened
)- Always changes to 'In Review' without conditions
-
PR Merge (
pull_request
-closed
+merged: true
)- Changes to 'Done' only if current status is not 'Done'
All rules are idempotent, so multiple executions of the same request are safe:
- Skips work if already in target status
- Maintains data consistency even with GitHub webhook retries
The system can send real-time notifications to Discord for each automation result.
-
Create Discord Webhook:
- Open Discord server → Text channel → Settings → Integrations → Webhooks
- Click "New Webhook" → Copy webhook URL
- Set the URL to
DISCORD_WEBHOOK_URL
environment variable
-
Notification Types:
- ✅ Success: When automation rules execute successfully
- ❌ Failure: When automation rules fail with error details
- ⏭️ Skipped: When rules are skipped (e.g., already in target status)
- 🔇 Ignored: No notifications sent for ignored events (no Jira key found)
-
Example Notifications:
Success Notification:
✅ Sync Success 📋 Issue: MAT-462 🔄 Action: In Progress → In Review
Failure Notification:
❌ Sync Failed 📋 Issue: MAT-456 🔄 Action: Jira status transition ⚠️ Error: Issue not found
Discord notifications are optional. If DISCORD_WEBHOOK_URL
is not set, the system will:
- Log a warning message once
- Continue normal operation without notifications
- Still log all activities to console
When all rules work correctly, you'll see logs like this:
POST https://your-worker.workers.dev/api/webhook/github - Ok
(log) Received create event
(log) Processing branch creation event
(log) Found Jira key: MAT-388
(log) Current status: To Do
(log) Successfully transitioned MAT-388 to In Progress
(log) Rule-01: MAT-388 transitioned from To Do to In Progress
POST https://your-worker.workers.dev/api/webhook/github - Ok
(log) Received push event
(log) Ignoring event: push
POST https://your-worker.workers.dev/api/webhook/github - Ok
(log) Received pull_request event
(log) Processing PR opened event
(log) Found Jira key: MAT-388
(log) Successfully transitioned MAT-388 to In Review
(log) Rule-02: MAT-388 transitioned to In Review
POST https://your-worker.workers.dev/api/webhook/github - Ok
(log) Received push event
(log) Ignoring event: push
POST https://your-worker.workers.dev/api/webhook/github - Ok
(log) Received pull_request event
(log) Processing PR merged event
(log) Found Jira key: MAT-388
(log) Current status: In Review
(log) Successfully transitioned MAT-388 to Done
(log) Rule-03: MAT-388 transitioned from In Review to Done
- All processes are logged to console
- Detailed error messages on failures
- Success/failure tracking for each rule
- Skip operations due to idempotency are also logged
Consider the following for production environments:
- HTTPS Required: GitHub webhooks only support HTTPS endpoints
- Process Management: Use PM2 etc. for zero-downtime service operation
- Log Management: Integrate with appropriate log collection systems
- Monitoring: Set up server status and webhook processing failure alerts
Free and convenient serverless deployment option
# Install wrangler (already included in package.json)
npm install
# Login to Cloudflare account
npx wrangler login
If you haven't created a Worker yet, please agree to create one when setting up your first environment variable.
In Cloudflare Workers, environment variables must be set as secrets:
# Set required environment variables as secrets
npx wrangler secret put GITHUB_WEBHOOK_SECRET
npx wrangler secret put JIRA_BASE_URL
npx wrangler secret put JIRA_EMAIL
npx wrangler secret put JIRA_API_TOKEN
npx wrangler secret put JIRA_PROJECT_KEY
# Optional environment variables (can be omitted if using defaults)
npx wrangler secret put JIRA_STATUS_TODO
npx wrangler secret put JIRA_STATUS_IN_PROGRESS
npx wrangler secret put JIRA_STATUS_IN_REVIEW
npx wrangler secret put JIRA_STATUS_DONE
# Discord notifications (optional)
npx wrangler secret put DISCORD_WEBHOOK_URL
# Production deployment
npm run deploy:worker
# Or use wrangler directly
npx wrangler deploy
# Test Workers environment locally
npm run dev:worker
# View real-time logs
npm run worker:tail
Set the Workers URL provided after deployment to GitHub Webhook:
- URL:
https://your-worker.your-subdomain.workers.dev/api/webhook/github
- Free: Up to 100,000 requests per month
- Global Deployment: Runs on edge servers worldwide
- Auto-scaling: Automatically scales with traffic
- Zero Server Management: No infrastructure management needed
- Fast Cold Start: Quick serverless function startup
- Invalid signature: GitHub webhook secret is incorrect
- Issue not found: Jira issue key doesn't exist
- No transition available: Transition to target status not possible in Jira workflow
- HTTP 404: Not Found: Jira API token expired or insufficient permissions
If you encounter errors like:
Rule-02 failed for MAT-462: Failed to transition issue: Failed to get transitions: HTTP 404: Not Found
Possible Causes:
- Expired API Token: Jira API tokens may have expired
Set log level to 'debug' for more detailed information:
LOG_LEVEL=debug
MIT