playwright-slack-report-burak 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -343,19 +343,53 @@ class ResultsParser {
343
343
 
344
344
  async fetchAllArtifacts() {
345
345
  const summariesDir = path.join('./', 'playwright-report');
346
- while (!this.allNodeSummaryFilesExist() || !this.allBlobZipsExist()) {
347
- console.log('Waiting for all blob zips to exist...');
348
- if (!fs.existsSync(summariesDir)) {
349
- fs.mkdirSync(summariesDir, { recursive: true });
350
- }
351
- // Fetch artifacts for shards 1 to totalShardCount-1 (if using 1-based) or 0 to totalShardCount-1 (if 0-based)
352
- // Since we're shard 0, we need to fetch from other shards
353
- // The workflow uses 1-based shards (1, 2, 3...), but we need to map them to 0-based internally (0, 1, 2...)
354
- // So shard 1 in workflow = shard 0 internally, shard 2 = shard 1, etc.
355
- for (let i = 1; i < this.totalShardCount; i++) {
356
- await this.fetchArtifact(i, `node_summary_${i}.json`, summariesDir);
357
- await this.fetchArtifact(i, `blob-report-node-${i}.zip`, summariesDir);
358
- }
346
+ if (!fs.existsSync(summariesDir)) {
347
+ fs.mkdirSync(summariesDir, { recursive: true });
348
+ }
349
+
350
+ console.log(`Shard 0: Waiting for artifacts from ${this.totalShardCount - 1} other shard(s)...`);
351
+
352
+ // Fetch artifacts for shards 1 to totalShardCount-1 (since we're shard 0)
353
+ // We need to fetch from all other shards before proceeding
354
+ for (let i = 1; i < this.totalShardCount; i++) {
355
+ console.log(`Shard 0: Fetching artifacts from shard ${i}...`);
356
+ await this.fetchArtifact(i, `node_summary_${i}.json`, summariesDir);
357
+ await this.fetchArtifact(i, `blob-report-node-${i}.zip`, summariesDir);
358
+ }
359
+
360
+ // After fetching, verify all files exist and wait if needed
361
+ let retryCount = 0;
362
+ const maxRetries = 60; // Wait up to 10 minutes (60 * 10 seconds)
363
+
364
+ while ((!this.allNodeSummaryFilesExist() || !this.allBlobZipsExist()) && retryCount < maxRetries) {
365
+ console.log(`Shard 0: Waiting for all artifacts to be available (attempt ${retryCount + 1}/${maxRetries})...`);
366
+
367
+ // Re-fetch any missing artifacts
368
+ for (let i = 1; i < this.totalShardCount; i++) {
369
+ const nodeSummaryFile = path.join(summariesDir, `node_summary_${i}.json`);
370
+ const blobZipFile = path.join(summariesDir, `blob-report-node-${i}.zip`);
371
+
372
+ if (!fs.existsSync(nodeSummaryFile)) {
373
+ console.log(`Shard 0: Re-fetching missing node_summary_${i}.json...`);
374
+ await this.fetchArtifact(i, `node_summary_${i}.json`, summariesDir);
375
+ }
376
+
377
+ if (!fs.existsSync(blobZipFile)) {
378
+ console.log(`Shard 0: Re-fetching missing blob-report-node-${i}.zip...`);
379
+ await this.fetchArtifact(i, `blob-report-node-${i}.zip`, summariesDir);
380
+ }
381
+ }
382
+
383
+ retryCount++;
384
+ if (!this.allNodeSummaryFilesExist() || !this.allBlobZipsExist()) {
385
+ await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds before retry
386
+ }
387
+ }
388
+
389
+ if (this.allNodeSummaryFilesExist() && this.allBlobZipsExist()) {
390
+ console.log(`Shard 0: Successfully fetched all artifacts from ${this.totalShardCount - 1} other shard(s).`);
391
+ } else {
392
+ console.warn(`Shard 0: Warning - Some artifacts may still be missing after ${maxRetries} attempts.`);
359
393
  }
360
394
  }
361
395
 
@@ -70,16 +70,15 @@ class SlackReporter {
70
70
  this.log(message);
71
71
  return;
72
72
  }
73
- const resultSummary = await this.resultsParser.getParsedResults();
74
73
  // SHARDING SUPPORT - Stop slack messages for non-zero index shard(s)
75
- // The workflow uses 1-based shards (1, 2, 3...), but we need to determine which shard we are
76
- // Only shard 0 (0-based) or shard 1 (1-based) should post when aggregating
74
+ // Only shard 0 (0-based) should post when aggregating results from multiple shards
77
75
 
76
+ // Detect shard index from multiple sources (GitHub Actions compatible)
78
77
  let currentShardIndex = process.env.MATRIX_SHARD !== undefined
79
78
  ? process.env.MATRIX_SHARD
80
79
  : (process.env.MATRIX_INDEX !== undefined ? process.env.MATRIX_INDEX : undefined);
81
80
 
82
- // Get shard info from ResultsParser which might have detected it from artifact fetching
81
+ // Get shard info from ResultsParser which might have detected it
83
82
  const parserShardIndex = this.resultsParser.shardIndex;
84
83
  const parserTotalShards = this.resultsParser.totalShardCount;
85
84
 
@@ -91,30 +90,27 @@ class SlackReporter {
91
90
  currentShardIndex = parserShardIndex.toString();
92
91
  }
93
92
 
94
- // CRITICAL: If we're in CI and don't know which shard we are, we MUST block posting
95
- // This prevents all shards from posting when MATRIX_SHARD is not set
96
- // Exception: If we're certain it's a single shard (totalShards === 1 AND no artifacts to fetch)
97
- if (process.env.CI && currentShardIndex === undefined) {
98
- // In CI without shard index = assume multiple shards and block all posts
99
- // Only shard 0/1 should post when aggregating, but we can't detect it without MATRIX_SHARD
100
- this.log(`❌ CI environment detected but shard index not set (MATRIX_SHARD/MATRIX_INDEX missing).`);
93
+ // Convert to number for comparison (default to 0 if undefined)
94
+ const shardIndexNum = currentShardIndex !== undefined ? parseInt(currentShardIndex, 10) : 0;
95
+
96
+ // CRITICAL: For GitHub Actions with multiple shards, only shard 0 should post
97
+ // If we're in CI with multiple shards and don't know which shard we are, block all posts
98
+ // This prevents duplicate messages when MATRIX_SHARD/MATRIX_INDEX is not set
99
+ if (process.env.CI && totalShards > 1 && currentShardIndex === undefined) {
100
+ this.log(`❌ GitHub Actions detected with ${totalShards} shards but shard index not set (MATRIX_SHARD/MATRIX_INDEX missing).`);
101
101
  this.log(`❌ Skipping Slack report to prevent duplicate messages from all shards.`);
102
102
  this.log(`💡 Fix: Add these env vars to your workflow:`);
103
103
  this.log(`💡 env:`);
104
- this.log(`💡 MATRIX_SHARD: $\{\{ matrix.shard - 1 \}\} # 0-based (shard 1 posts)`);
104
+ this.log(`💡 MATRIX_SHARD: $\{\{ strategy.job-index \}\} # 0-based (only shard 0 posts)`);
105
105
  this.log(`💡 MATRIX_COUNT: $\{\{ strategy.job-total \}\}`);
106
- this.log(`💡 OR use 1-based: MATRIX_SHARD: $\{\{ matrix.shard \}\} (then only shard 1 posts)`);
107
106
  return;
108
107
  }
109
108
 
110
- // Convert to number for comparison
111
- const shardIndexNum = currentShardIndex !== undefined ? parseInt(currentShardIndex, 10) : 0;
112
-
113
- // Only allow shard 0 (0-based) or shard 1 (1-based) to post when there are multiple shards
109
+ // Only allow shard 0 (0-based) to post when there are multiple shards
114
110
  // This ensures only one shard posts the aggregated report
115
- if (totalShards > 1 && shardIndexNum !== 0 && shardIndexNum !== 1) {
111
+ if (totalShards > 1 && shardIndexNum !== 0) {
116
112
  this.log(`❌ Stopping reporter for non-zero index shard ${currentShardIndex} of ${totalShards}`);
117
- this.log(`ℹ️ Only shard 0 (0-based) or shard 1 (1-based) will post the aggregated report.`);
113
+ this.log(`ℹ️ Only shard 0 will post the aggregated report.`);
118
114
  return;
119
115
  }
120
116
 
@@ -124,6 +120,8 @@ class SlackReporter {
124
120
  } else {
125
121
  this.log(`ℹ️ Multiple shards detected (${totalShards}). Shard ${currentShardIndex} will post aggregated report.`);
126
122
  }
123
+
124
+ const resultSummary = await this.resultsParser.getParsedResults();
127
125
  resultSummary.meta = this.meta;
128
126
  const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry));
129
127
  if (this.sendResults === 'on-failure'
package/package.json CHANGED
@@ -31,7 +31,7 @@
31
31
  "lint-fix": "npx eslint . --ext .ts --fix"
32
32
  },
33
33
  "name": "playwright-slack-report-burak",
34
- "version": "3.0.2",
34
+ "version": "3.0.3",
35
35
  "main": "index.js",
36
36
  "types": "dist/index.d.ts",
37
37
  "author": "Burak B. <burak.boluk@hotmail.com>",