Skip to content

Add weekly testing digest workflow for #core-test#155

Draft
juanmaguitar wants to merge 2 commits intoWordPress:trunkfrom
juanma-wp:weekly-testing-digest
Draft

Add weekly testing digest workflow for #core-test#155
juanmaguitar wants to merge 2 commits intoWordPress:trunkfrom
juanma-wp:weekly-testing-digest

Conversation

@juanmaguitar
Copy link
Copy Markdown
Collaborator

Summary

Adds a scheduled GitHub Actions workflow that posts a weekly testing backlog digest to #core-test, addressing #131.

  • Gutenberg: Fetches open issues and PRs labeled "Needs Testing" via the GitHub Search API
  • Trac: Scrapes versioned-milestone ticket counts from core.trac.wordpress.org using Playwright (Trac blocks all API/curl requests with a browser challenge)
  • Schedule: Every Monday at 9:00 UTC + manual workflow_dispatch
  • Slack: Posts via a Workflow webhook (skips gracefully when the secret is not configured)

How it works

The workflow runs .github/scripts/weekly-testing-digest.mjs which:

  1. Queries GitHub Search API for Gutenberg issues/PRs with "Needs Testing" label
  2. Launches headless Chromium to scrape the Trac needs-testing query, grouped by milestone
  3. Filters Trac tickets to versioned milestones only (e.g. 7.0, 7.1)
  4. Builds a JSON payload and posts it to a Slack Workflow webhook

Sample output (dry-run)

Gutenberg: 8 open (8 issues, 0 PRs)

Trac: 10 tickets in versioned milestones
  7.0: 2 tickets
  7.1: 8 tickets

What's needed to activate

  1. Slack Workflow: Someone with permissions in #core-test needs to create a Slack Workflow that accepts the webhook payload and formats the message
  2. Repo secret: Add SLACK_WEEKLY_TESTING_DIGEST_WEBHOOK_URL to this repo's Actions secrets with the webhook URL from step 1

Until the secret is configured, the workflow runs in dry-run mode and logs the payload.

Payload format (for the Slack Workflow)

{
  "gutenberg_issue_count": "8",
  "gutenberg_pr_count": "0",
  "gutenberg_total": "8",
  "trac_milestones": [{"milestone": "7.0", "count": 2}, {"milestone": "7.1", "count": 8}],
  "trac_total": "10",
  "gutenberg_issues_url": "...",
  "gutenberg_prs_url": "...",
  "trac_url": "https://core.trac.wordpress.org/tickets/needs-testing",
  "date": "2026-04-16"
}

Test plan

  • Trigger workflow manually via Actions tab on the fork to verify data collection
  • Verify Gutenberg counts match GitHub filtered view
  • Verify Trac counts match Trac query
  • Test with a Slack webhook to confirm message delivery

🤖 Generated with Claude Code

Adds a scheduled GitHub Actions workflow that collects open "Needs Testing"
counts from both Gutenberg (via GitHub Search API) and WordPress Trac
(via headless browser to bypass bot protection), then posts a digest
to #core-test via a Slack Workflow webhook.

Refs WordPress#131

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@3kori
Copy link
Copy Markdown
Collaborator

3kori commented Apr 29, 2026

I tested this action and these are the results:

❌ Trigger workflow manually via Actions tab on the fork to verify data collection

I had to create a repo to test this GH Action. I ran into a couple of issues:

  • The Checkout process fails; I was able to fix it by giving the workflow the correct permissions.
permissions:
  contents: read
checkout-error
  • The dry-run process also fails because it is missing playwright. Fix:
- name: Install Playwright
  run: npm install playwright

Place this step just before the - name: Install Playwright Chromium step.
dry-run-error

After fixing all these, the workflow now runs flawlessly.
digest-done

Verify Gutenberg counts match

❌ Total

Received: 13
Expected: 15
gh-total

❌ Issues

Received: 11
Expected: 13
issues-count

✅ PR

Received: 2
Expected: 2
pr-count

Verify Core counts match && milestone

✅ Counts

Received: 8
Expected: 8

✅ Milestone

Received: 7.1
Expected: 7.1
trac-url

Verify links in JSON payload

With these, I might be wrong about what the expected URL should be. Could you confirm if this is right?

✅ gutenberg_issues_url

https://github.com/WordPress/gutenberg/issues?q=is%3Aopen+label%3A%22Needs%20Testing%22 redirects to: https://github.com/WordPress/gutenberg/issues?q=is%3Aopen+label%3A%22Needs%20Testing%22

❌ gutenberg_prs_url

https://github.com/WordPress/gutenberg/pulls?q=is%3Aopen+label%3A%22Needs%20Testing%22 redirects to: https://github.com/WordPress/gutenberg/issues?q=state%3Aopen%20label%3A%22Needs%20Testing%22
Expected: https://github.com/WordPress/gutenberg/pulls?q=is%3Aopen+is%3Apr+label%3A%22Needs+Testing%22

❌ trac_url

https://core.trac.wordpress.org/tickets/needs-testing redirects to: https://core.trac.wordpress.org/tickets/needs-testing
Expected: https://core.trac.wordpress.org/query?status=accepted&status=assigned&status=new&status=reopened&status=reviewing&keywords=~needs-testing&group=milestone

Test message delivery

I don't have the necessary permissions to test this on Slack, so I created a mock server for testing.

  • Set up:
  1. Create a mock-server.js file (not inside the handbook repo), and add this code:
// mock-server.js
import express from "express";

const app = express();
app.use(express.json());

app.post("/", (req, res) => {
  console.log("Received payload:", req.body);
  res.sendStatus(200);
});

app.listen(3000, () => console.log("Mock server running on port 3000"));
  1. In your terminal, run node mock-server.js. express should be present in your system. Now your server is running.
  2. In another terminal tab, inside the test-handbook repo, run node node .github/scripts/weekly-testing-digest.mjs --post http://localhost:3000.
  3. In the terminal tab that your server is running on, you should see this output:
Received payload: {
  gutenberg_issue_count: '11',
  gutenberg_pr_count: '2',
  gutenberg_total: '13',
  trac_milestones: [ { milestone: '7.1', count: 8 } ],
  trac_total: '8',
  gutenberg_issues_url: 'https://github.com/WordPress/gutenberg/issues?q=is%3Aopen+label%3A%22Needs%20Testing%22',
  gutenberg_prs_url: 'https://github.com/WordPress/gutenberg/pulls?q=is%3Aopen+label%3A%22Needs%20Testing%22',
  trac_url: 'https://core.trac.wordpress.org/tickets/needs-testing',
  date: '2026-04-28'
}

Other Issues

The dry-run output has some differences when running locally and on GitHub Actions
dry-run-output

Could you also adjust the trac timeouts? To 60000ms and 45000ms, respectively.

		await page.goto( TRAC_QUERY_URL, { timeout: 45000 } );
		await page.waitForSelector( 'table.listing', { timeout: 30000 } );

@3kori
Copy link
Copy Markdown
Collaborator

3kori commented Apr 30, 2026

I finally managed to set up a workspace where I can test the Slack webhook message delivery.
Currently, using the payload output as variables for the workflow, including the trac_milestones: [ { milestone: '7.1', count: 8 } ], array makes the GH action exit with an error.

array-input-error

I guess Slack doesn't play well with Arrays. These are the changes I made to the code to get it to run (added: tracSummary, changed payload output, dry-run output):

	const gutenbergTotal = issueCount + prCount;
	const tracTotal = tracMilestones.reduce( ( sum, m ) => sum + m.count, 0 );
	const date = new Date().toISOString().split( 'T' )[ 0 ];
	const tracSummary = tracMilestones
	.map( ( m ) => `${ m.milestone }: ${ m.count }` )
	.join( ' • ' );

	const payload = {
		gutenberg_issue_count: String( issueCount ),
		gutenberg_pr_count: String( prCount ),
		gutenberg_total: String( gutenbergTotal ),
		trac_milestones_count: String( tracSummary ),
		trac_total: String( tracTotal ),
		gutenberg_issues_url: buildGitHubURL( 'issues' ),
		gutenberg_prs_url: buildGitHubURL( 'pulls' ),
		trac_url: TRAC_REPORT_URL,
		date,
	};

	if ( mode === 'dry-run' ) {
		// Human-readable summary
		console.error( '' );
		console.error( '=== Weekly Testing Digest ===' );
		console.error( `Date: ${ date }` );
		console.error( '' );
		console.error(
			`Gutenberg: ${ gutenbergTotal } open (${ issueCount } issues, ${ prCount } PRs)`
		);
		console.error( '' );
		console.error(
			`Trac: ${ tracTotal } tickets in versioned milestones`
		);
		for ( const m of tracMilestones ) {
			console.error( ` Trac summary ${ m.milestone }: ${ m.count } tickets` );
		}

Then used trac_milestones_count instead of trac_milestone in my Slack webhook variables.
After all this, the message is successfully sent and here are the results:

testing-digest

This is ready for review by the whole team.

I currently don't have permission in #core-test to create workflows. I'd like to create the workflow.

@3kori 3kori marked this pull request as ready for review April 30, 2026 02:43
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org>
Co-authored-by: 3kori <r1k0@git.wordpress.org>
Co-authored-by: ozgursar <ozgursar@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@ozgursar
Copy link
Copy Markdown
Collaborator

@3kori I didn't understand where the express server will be running to fetch the trac ticket results? Does Slack handle that?

@juanmaguitar juanmaguitar marked this pull request as draft April 30, 2026 15:13
@ozgursar
Copy link
Copy Markdown
Collaborator

ozgursar commented May 1, 2026

pp

I tested @3kori 's code and it works correctly with both Playwright and Puppeteer.
In my screenshot above, first payload received was with the test with Playwright, and the second with Puppeteer.
I think Puppeteer is a better solution here because it is lightweight and we don't need the complexity of Playwright.

Copy link
Copy Markdown
Collaborator

@ozgursar ozgursar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works for me.

@nikunj8866
Copy link
Copy Markdown
Collaborator

@3kori @juanmaguitar @ozgursar I've tried using the mock-server.js.

I've getting below in the console.

Received payload: {
  gutenberg_issue_count: '11',
  gutenberg_pr_count: '3',
  gutenberg_total: '14',
  trac_milestones: [ { milestone: '7.1', count: 8 } ],
  trac_total: '8',
  gutenberg_issues_url: 'https://github.com/WordPress/gutenberg/issues?q=is%3Aopen+label%3A%22Needs%20Testing%22',
  gutenberg_prs_url: 'https://github.com/WordPress/gutenberg/pulls?q=is%3Aopen+label%3A%22Needs%20Testing%22',
  trac_url: 'https://core.trac.wordpress.org/tickets/needs-testing',
  date: '2026-05-01'
}

@3kori
Copy link
Copy Markdown
Collaborator

3kori commented May 1, 2026

This is the repo I made to test this workflow: Weekly Digest Test repo.

@3kori
Copy link
Copy Markdown
Collaborator

3kori commented May 1, 2026

I've getting below in the console.

That's the correct output, but it needs a few changes to work smoothly with Slack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants