1- const Octokit = require ( '@octokit/rest' ) ;
2- const fs = require ( 'fs' ) ;
3- let { parseArgs} = require ( 'util' ) ;
1+ import Octokit from "@octokit/rest" ;
2+ import fs from 'fs' ;
3+ import { parseArgs } from 'node:util' ;
4+ import remarkParse from 'remark-parse' ;
5+ import { toString } from 'mdast-util-to-string' ;
6+ import { unified } from 'unified' ;
47
58/**
69 * Instructions:
710 *
8- * 1. Update Octokit to use your token
9- * 2. Run the following script: node scripts/getCommitsForTesting.js 2025-10-07 2025-10-18
10- * 3. Go to output.csv, copy it to Google sheets, highlight the rows, go to "Data" in the toolbar -> split text to columns -> separator: comma
11+ * 1. Run the following script: node scripts/getCommitsForTesting.js 2025-10-07 2025-10-18
12+ * 2. Go to output.csv, copy it to Google sheets, highlight the rows, go to "Data" in the toolbar -> split text to columns -> separator: comma
1113 */
1214
13- const octokit = new Octokit ( ) ;
15+ const octokit = new Octokit ( {
16+ auth : `token ${ process . env . GITHUB_TOKEN } `
17+ } ) ;
1418
1519let options = {
1620 startDate : {
@@ -46,27 +50,22 @@ async function writeTestingCSV() {
4650 let info = await getPR ( num ) ;
4751
4852 // Get testing instructions if it exists
49- // let content = info.data.body;
50- // let match = undefined;
51- // if (content) {
52- // match = content.match(/## 📝 Test Instructions:\s*([\s\S]*?)(?=##|$)/);
53- // }
54- // let testInstructions = '';
55- // if (match) {
56- // testInstructions = match[1];
57- // testInstructions = testInstructions.replace(/<!--[\s\S]*?-->/g, '');
58- // testInstructions = testInstructions.trim();
59- // testInstructions = escapeCSV(testInstructions);
60- // }
61-
62- // if (testInstructions.length > 350) {
63- // row.push('See PR for testing instructions');
64- // } else {
65- // row.push(testInstructions);
66- // }
67- row . push ( ',' ) ;
53+ let content = info . data . body ;
54+ let testInstructions = escapeCSV ( extractTestInstructions ( content ) ) ;
55+
56+ if ( testInstructions . length > 350 ) {
57+ row . push ( 'See PR for testing instructions' ) ;
58+ } else {
59+ console . log ( testInstructions ) ;
60+ console . log ( ) ;
61+ row . push ( testInstructions ) ;
62+ }
63+
64+ // Add PR url to the row
6865 row . push ( info . data . html_url ) ;
6966
67+ // Categorize commit into V3, RAC, S2, or other
68+ // I feel like maybe we should use labels rather than looking at the PR title for this but we would need to get into the habit of doing that
7069 if ( ( / \b s 2 \b / gi) . test ( title ) ) {
7170 s2PRs . push ( row ) ;
7271 } else if ( ( / \b r a c \b / gi) . test ( title ) ) {
@@ -79,6 +78,7 @@ async function writeTestingCSV() {
7978 }
8079 }
8180
81+ // Prepare to write into CSV
8282 let csvRows = '' ;
8383 csvRows += 'V3 \n' ;
8484 for ( let v3 of v3PRs ) {
@@ -144,6 +144,50 @@ async function getPR(num) {
144144 return res ;
145145}
146146
147+ function getHeadingText ( node ) {
148+ return node . children
149+ . map ( child => child . value || '' )
150+ . join ( '' )
151+ . trim ( )
152+ }
153+
154+ function extractTestInstructions ( contents ) {
155+ if ( ! contents ) {
156+ return '' ;
157+ }
158+
159+ let tree = unified ( ) . use ( remarkParse ) . parse ( contents ) ;
160+
161+ let collecting = false ;
162+ let headingDepth = null ;
163+ let collected = [ ] ;
164+
165+ for ( let node of tree . children ) {
166+ if ( node . type === 'heading' ) {
167+ let text = getHeadingText ( node ) . toLowerCase ( ) ;
168+
169+ if ( text . includes ( 'test instructions' ) ) {
170+ collecting = true ;
171+ headingDepth = node . depth ;
172+ continue ;
173+ }
174+
175+ // Stop when we reach another heading of same or higher level
176+ if ( collecting && node . depth <= headingDepth ) {
177+ break ;
178+ }
179+ }
180+
181+ if ( collecting ) {
182+ collected . push ( node ) ;
183+ }
184+
185+ }
186+
187+ return collected . map ( node => toString ( node ) ) . join ( '\n' ) . trim ( ) ;
188+ }
189+
190+
147191function escapeCSV ( value ) {
148192 if ( ! value ) {
149193 return '' ;
0 commit comments