-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Repository: https://github.com/chandrakalahanchinal/queuepilot
The Magento 2.4-develop PR queue typically contains 3–8 PRs waiting to merge at any given time. Each PR runs functional tests across three editions — CE, EE, and B2B — producing separate Allure reports and Jenkins builds. PRs are often re-triggered multiple times as fixes land.
Manually triaging this means:
- Opening 3–8 PRs individually on GitHub
- Clicking into each CE / EE / B2B check run
- Opening each Allure report and scrolling through failures
- Cross-referencing Jira to find whether a failure is a known flake or a real regression
- Repeating this for every previous re-run whose results are buried in PR comments
- Doing all of this every time the queue changes — often multiple times a day
This takes 20–40 minutes per triage cycle, is error-prone, and produces inconsistent results across team members.
QueuePilot automates the entire triage workflow end-to-end. One Slack message triggers everything:
- Detects
@qmbot dq 2.4-developin#pr-queue-dashboard - Waits for qmbot to reply with the PR list, then waits 5 minutes for test data to settle
- Fetches GitHub check runs for every PR in the queue
- Scrapes Allure failure data from the current run and all previous runs found in PR comments — no failure is missed across re-runs
- Looks up each unique failing test in Jira (ACQE project) to surface active tickets
- Posts a structured summary as a thread reply to qmbot's message — PR count, unique failing tests with occurrence counts and Jira links, per-PR CE/EE/B2B breakdown
The full triage that took 20–40 minutes now takes under 10 minutes of automated work and appears directly in the Slack thread where the team is already looking.
- How It Works
- Full Integration Flow
- How the Slack Result Looks
- HTML Dashboard
- Cost
- Setup
- Tokens
- Running Manually
- CLI Reference
- Architecture
- Troubleshooting
You → @qmbot dq 2.4-develop (#pr-queue-dashboard)
qmbot → replies with PR list (channel message)
Watcher (watch.py)→ detects reply, waits 5 min (macOS LaunchAgent, always running)
QueuePilot → analyzes all PRs in parallel (GitHub + Allure + Jira)
Slack Connect bot → posts report in qmbot's thread (one reply, nothing at top level)
The 5-minute wait gives Jenkins and Allure time to finish writing test data before QueuePilot reads it.
- Polls
#pr-queue-dashboard(C0B400Y1ZU2) every 30 seconds viaconversations.history - When any user sends a message containing
dq 2.4-develop, a 10-minute window opens - When qmbot (
W015DAXESG0) replies within that window with GitHub PR URLs:- Records qmbot's message
tsin.watcher_state.jsonasqmbot_reply_ts - Schedules the report to fire 5 minutes later
- Records qmbot's message
- At fire time, calls
queuepilot.py --reply-to-ts <qmbot_reply_ts> - After posting, clears all state and resets
- PR metadata (title, author, URL) via
gh pr view - All check runs via
gh api repos/{repo}/commits/{sha}/check-runs - Identifies CE, EE, B2B check runs by name prefix; reads
conclusionandoutput.summary - No separate GitHub token needed — uses whatever
gh authis configured
When a check run has conclusion: failure, QueuePilot:
- Extracts Allure report URL from check-run summary (falls back to scraping Jenkins page)
- Fetches
data/categories.json(fallback:suites.json→behaviors.json) - Walks the tree collecting all leaf nodes with status
failedorbroken - For each UID calls
data/test-cases/{uid}.jsonto get the fully-qualified Java test method name - Up to 10 test-case fetches in parallel per PR; up to 5 PRs in parallel
Retries up to --allure-attempts times (10-second pauses). Falls back to Prometheus stats if retries are exhausted.
Previous runs via PR body and comments: PRs are often re-triggered multiple times. Each run posts a bot comment containing Allure links; the PR description may also contain Allure URLs from earlier runs. QueuePilot scrapes both the PR body and all PR comments for Allure report URLs (get_pr_allure_urls), fetches failures from every previous run, then unions them with the current run — deduplicated by test method name. This ensures no failure is missed across re-runs.
Checks still running: When a PR's latest check is in_progress or queued, QueuePilot still fetches failures from all available previous-run Allure URLs and returns them, marking the edition with an ⏳ RUNNING · N prev fail badge so you can act on known failures while the latest run finishes.
If JIRA_TOKEN is set, QueuePilot searches jira.corp.adobe.com for each unique failing test:
- JQL:
project = ACQE AND summary ~ "{test_method_name}" ORDER BY created DESC - Only non-Done, non-Cancelled tickets are surfaced; picks most recently created active ticket
- Up to 5 Jira lookups in parallel
- Results attached to each failure, shown in both the Slack summary and the HTML report
- Posted via
chat.postMessagewiththread_ts= qmbot's messagets - One bot reply in qmbot's thread — nothing posted at top level of the channel
- The Slack Connect bot identity (the
SLACK_TOKENowner) is used - No file attachments — summary message only
A self-contained HTML dashboard is saved to reports/ in the project directory.
The report is posted as a single thread reply inside qmbot's message. It has three parts:
🐛 QueuePilot — `2.4-develop`
*3 PR(s)* in queue · *5 unique failing test(s)*
Each line shows the test method name, how many times it failed in total across all PRs and all editions (CE + EE + B2B combined), and the linked Jira ticket if one exists.
• `AdminUserSetStatusForEachSourceItemTest` *4x* → ACQE-9629 _Tech Analysis_
• `StorefrontCheckTermsAndConditionIsPresentTest` *3x* → ACQE-10249 _Options Queue_
• `StockStatusChangedForConfigurableProductTest` *2x*
• `CreateConfigurableProductWithTierPriceTest` *1x*
4x means that test failed 4 times in total — for example CE+EE for PR1 and CE for PR2. It is not a PR count.
One block per PR showing the GitHub link, author, CE/EE/B2B badge, and a deduplicated list of failing test names (union across all editions):
*#10762* Fix cart total rounding issue
by *harshityadav90* · CE: *2 FAIL* EE: ✅ PASS B2B: *3 FAIL*
• `AdminUserSetStatusForEachSourceItemTest`
• `StorefrontCheckTermsAndConditionIsPresentTest`
• `StockStatusChangedForConfigurableProductTest`
*#10758* Support Tier-4 flowers bugfixes
by *thiaramus* · CE: *1 FAIL* EE: *4 FAIL* B2B: ✅ PASS
• `CreateConfigurableProductWithTierPriceTest`
Badge meanings:
| Badge | Meaning |
|---|---|
N FAIL |
N tests failed in this edition |
✅ PASS |
All checks passed |
⏳ RUNNING |
Check still in progress, no previous failures available |
⏳ RUNNING · N prev fail |
Check running; N failures found from previous runs |
N/A |
Check has not run for this edition |
Saved to reports/ in the project directory. Contains:
PR count and unique failing test count.
One row per PR with CE / EE / B2B status badges.
Every unique failing test across all PRs and editions, sorted by total failure count, with Jira ticket links.
3-column layout (CE / EE / B2B). Each column shows full test method names with color-coded status (red = failed, amber = broken), Jira badge, Allure link, and Jenkins link.
All integrations are free — no LLM, no third-party service, no usage fees:
| Integration | API | Cost |
|---|---|---|
| Slack read | conversations.history |
Free (bot token) |
| Slack write | chat.postMessage |
Free (bot token) |
| GitHub |
gh CLI + REST API |
Free (authenticated user) |
| Allure | Static JSON from internal report URL | Free |
| Jira | REST API v2 search | Free (internal PAT) |
| Tool | Install | Verify |
|---|---|---|
| Python 3.10+ | python.org | python3 --version |
| GitHub CLI | brew install gh |
gh --version |
git clone https://github.com/chandrakalahanchinal/queuepilot.git
cd queuepilot
bash setup.shsetup.sh will:
- Install Python dependencies (
pip install -r requirements.txt) - Authenticate GitHub CLI if not already done
- Prompt for
SLACK_TOKENand optionallyJIRA_TOKEN - Install and start the watcher as a macOS LaunchAgent (auto-starts at every login)
tail -f watcher.log # live logs
launchctl unload ~/Library/LaunchAgents/com.queuepilot.watcher.plist # stop
bash setup.sh # start / update tokens| Token | Where to get it | Required? |
|---|---|---|
SLACK_TOKEN |
Slack app settings → OAuth tokens → Bot token (xoxb-...) |
Yes |
JIRA_TOKEN |
Jira → Profile → Personal Access Tokens | No — enables Jira links |
# Auto mode — reads qmbot's latest message, analyzes, posts to Slack
export SLACK_TOKEN=xoxb-your-token-here
export JIRA_TOKEN=your-jira-token
python3 queuepilot.py 2.4-develop
# Pass PR numbers directly — skip Slack read
python3 queuepilot.py 2.4-develop --prs 10737 10740 10741
# HTML only — no Slack post
python3 queuepilot.py 2.4-develop --no-slack
# Reply into a specific qmbot thread (watcher sets this automatically)
python3 queuepilot.py 2.4-develop --reply-to-ts 1718000000.123456python3 queuepilot.py <branch> [options]
positional:
branch Queue branch name, e.g. 2.4-develop
options:
--output FILE HTML output path (default: reports/queuepilot-{branch}-{date}-{n}.html)
--no-slack Generate HTML only, skip Slack post
--prs N [N ...] Analyze these PR numbers; skip reading from Slack
--jira-token TOKEN Jira PAT for ACQE ticket lookup (or set JIRA_TOKEN env var)
--allure-attempts N Allure retry count, default 2 (~10s each)
--reply-to-ts TS Slack message ts to post summary as thread reply
(set automatically by watcher — rarely needed manually)
| File | Purpose |
|---|---|
queuepilot.py |
Main analysis + Slack reporting script |
watch.py |
Background watcher daemon — triggers queuepilot.py
|
setup.sh |
One-command install and LaunchAgent setup |
requirements.txt |
Python dependencies (requests) |
reports/ |
Generated HTML dashboards |
.watcher_state.json |
Watcher runtime state (last processed ts, fire time, qmbot reply ts) |
| Constant | Value | Description |
|---|---|---|
POLL_INTERVAL |
30s | Slack polling frequency |
TRIGGER_WINDOW |
600s | Time allowed for qmbot to reply after trigger |
WAIT_BEFORE_FIRE |
300s | Wait after qmbot replies before running analysis |
Transitions:
- Any user sends
dq 2.4-develop→ savespending_trigger_ts - qmbot replies with PR URLs within 10 min → saves
fire_after_ts+qmbot_reply_ts -
fire_after_tsreached → runsqueuepilot.py --reply-to-ts <qmbot_reply_ts>→ clears state
| Layer | Function | Purpose |
|---|---|---|
| Slack | slack_history |
Fetch channel messages after a given timestamp |
| Slack | parse_pr_list |
Extract repo + PR number pairs from qmbot's GitHub URLs |
| Slack | slack_post_dashboard |
Post formatted summary blocks as thread reply |
| GitHub | analyze_pr |
Fetch PR info and check runs; dispatch per-edition analysis |
| GitHub | _analyze_edition |
Check one edition's conclusion; fetch Allure failures if failed |
| GitHub | find_allure_url_from_jenkins |
Scrape Jenkins page as fallback for Allure URL |
| Allure | get_failed_uids |
Walk categories/suites/behaviors JSON; collect failed/broken UIDs |
| Allure | resolve_failures |
Resolve all UIDs → method names (10 parallel workers) |
| Allure | get_prometheus_stats |
Fallback: read failure counts from prometheusData.txt |
| Jira | search_jira_for_test |
JQL search in ACQE project for one test method name |
| Jira | fetch_jira_tickets |
Parallel lookup for all unique failing tests (5 workers) |
| HTML | render_all_failures_table |
Aggregated failures sorted by total occurrence count |
| HTML | render_html |
Assembles complete self-contained HTML page |
| Level | Workers |
|---|---|
| PR analysis | 5 (PR_WORKER_MAX) |
| Test name resolution per PR | 10 (ALLURE_WORKER_MAX) |
| Jira ticket lookup | 5 |
| Problem | Fix |
|---|---|
| Watcher not firing |
tail -f watcher.log — common causes: SLACK_TOKEN expired (re-run bash setup.sh), token lacks channels:history scope, stuck state (delete .watcher_state.json) |
| Report at top level instead of thread | Watcher sets --reply-to-ts automatically. For manual runs pass --reply-to-ts <ts>
|
ERROR: SLACK_TOKEN env var is required |
Use --prs: python3 queuepilot.py 2.4-develop --prs 10762 10758
|
| CE/EE/B2B shows "test data fetch failed" | Allure data not ready — build likely crashed before tests ran. Check Jenkins directly |
| Jira tickets not showing | Verify: curl -H "Authorization: Bearer <token>" https://jira.corp.adobe.com/rest/api/2/myself
|
| Test names show as UIDs |
test-cases/{uid}.json not yet uploaded. Wait a few minutes and re-run |
gh: command not found |
brew install gh && gh auth login |