playwright-slack-report-burak 3.0.2 → 3.0.4

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,51 +70,35 @@ 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
77
-
78
- let currentShardIndex = process.env.MATRIX_SHARD !== undefined
79
- ? process.env.MATRIX_SHARD
80
- : (process.env.MATRIX_INDEX !== undefined ? process.env.MATRIX_INDEX : undefined);
81
-
82
- // Get shard info from ResultsParser which might have detected it from artifact fetching
83
- const parserShardIndex = this.resultsParser.shardIndex;
84
- const parserTotalShards = this.resultsParser.totalShardCount;
74
+ // Only shard 0 (0-based) should post when aggregating results from multiple shards
85
75
 
86
- // Use parser values if env vars not set
87
- const totalShards = process.env.MATRIX_COUNT ? parseInt(process.env.MATRIX_COUNT, 10) : parserTotalShards;
76
+ // Detect shard index from multiple sources (GitHub Actions compatible)
77
+ let currentShardIndex = process.env.strategy.job-total !== undefined
78
+ ? process.env.strategy.job-total
79
+ : undefined;
88
80
 
89
- // If we still don't have shard index, try to infer from parser
90
- if (currentShardIndex === undefined && parserShardIndex !== undefined) {
91
- currentShardIndex = parserShardIndex.toString();
92
- }
81
+ // Convert to number for comparison (default to 0 if undefined)
82
+ const shardIndexNum = currentShardIndex !== undefined ? parseInt(currentShardIndex, 10) : 0;
93
83
 
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).`);
84
+ // CRITICAL: For GitHub Actions with multiple shards, only shard 0 should post
85
+ // If we're in CI with multiple shards and don't know which shard we are, block all posts
86
+ // This prevents duplicate messages when MATRIX_SHARD/MATRIX_INDEX is not set
87
+ if (process.env.CI && totalShards > 1 && currentShardIndex === undefined) {
88
+ this.log(`❌ GitHub Actions detected with ${totalShards} shards but shard index not set (MATRIX_SHARD/MATRIX_INDEX missing).`);
101
89
  this.log(`❌ Skipping Slack report to prevent duplicate messages from all shards.`);
102
90
  this.log(`💡 Fix: Add these env vars to your workflow:`);
103
91
  this.log(`💡 env:`);
104
- this.log(`💡 MATRIX_SHARD: $\{\{ matrix.shard - 1 \}\} # 0-based (shard 1 posts)`);
92
+ this.log(`💡 MATRIX_SHARD: $\{\{ strategy.job-index \}\} # 0-based (only shard 0 posts)`);
105
93
  this.log(`💡 MATRIX_COUNT: $\{\{ strategy.job-total \}\}`);
106
- this.log(`💡 OR use 1-based: MATRIX_SHARD: $\{\{ matrix.shard \}\} (then only shard 1 posts)`);
107
94
  return;
108
95
  }
109
96
 
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
97
+ // Only allow shard 0 (0-based) to post when there are multiple shards
114
98
  // This ensures only one shard posts the aggregated report
115
- if (totalShards > 1 && shardIndexNum !== 0 && shardIndexNum !== 1) {
99
+ if (totalShards > 1 && shardIndexNum !== 0) {
116
100
  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.`);
101
+ this.log(`ℹ️ Only shard 0 will post the aggregated report.`);
118
102
  return;
119
103
  }
120
104
 
@@ -124,6 +108,8 @@ class SlackReporter {
124
108
  } else {
125
109
  this.log(`ℹ️ Multiple shards detected (${totalShards}). Shard ${currentShardIndex} will post aggregated report.`);
126
110
  }
111
+
112
+ const resultSummary = await this.resultsParser.getParsedResults();
127
113
  resultSummary.meta = this.meta;
128
114
  const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry));
129
115
  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.4",
35
35
  "main": "index.js",
36
36
  "types": "dist/index.d.ts",
37
37
  "author": "Burak B. <burak.boluk@hotmail.com>",