playwright-slack-report-burak 3.5.0 → 3.5.2

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.
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  const fs = require('fs');
10
10
  const os = require('os');
11
11
  const path = require('path');
12
- const axios = require('axios');
13
12
  const { exec, execFileSync } = require('child_process');
14
13
  let AdmZip;
15
14
  try {
@@ -31,25 +30,19 @@ const PLAYWRIGHT_REPORT_DIR = path.join('./', 'playwright-report');
31
30
  const GITHUB_RUN_ID = process.env.GITHUB_RUN_ID || 'local';
32
31
  const GITHUB_RUN_ATTEMPT = process.env.GITHUB_RUN_ATTEMPT || '1';
33
32
 
34
- // Google Cloud Storage configuration
35
- const GCS_BUCKET_NAME = process.env.GCS_BUCKET_NAME;
36
- const GCS_SERVICE_ACCOUNT_KEY = process.env.GCS_SERVICE_ACCOUNT_KEY;
37
- const GCS_REPORTS_FOLDER_PREFIX = process.env.GCS_REPORTS_FOLDER_PREFIX;
38
- const GCS_UPLOAD_API_BASE_URL = process.env.GCS_UPLOAD_API_BASE_URL;
39
-
40
- // MinIO artifact storage configuration (artifacts uploaded by shards 2+ as
41
- // <run_id>-<run_attempt>/shard-<shard>.tar.zst, a zstd-compressed tar of playwright-report)
33
+ // MinIO storage configuration. Artifacts uploaded by shards 2+ as
34
+ // <bucket>/shard-artifacts/<run_id>-<run_attempt>/shard-<shard>.tar.zst (a zstd-compressed tar of playwright-report),
35
+ // merged HTML reports uploaded by shard 1 under <bucket>/playwright-reports/<run_id>-<run_attempt>/
42
36
  const MINIO_ENDPOINT = process.env.MINIO_ENDPOINT;
43
37
  const MINIO_ACCESS_KEY = process.env.MINIO_ACCESS_KEY;
44
38
  const MINIO_SECRET_KEY = process.env.MINIO_SECRET_KEY;
45
39
  const MINIO_BUCKET = process.env.MINIO_BUCKET;
46
- const MINIO_ALIAS = 'shard-artifacts';
47
-
48
- const getMinioObjectPath = (shard) => `${MINIO_ALIAS}/${MINIO_BUCKET}/${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}/shard-${shard}.tar.zst`;
40
+ const MINIO_ALIAS = 'minio';
41
+ const MINIO_ARTIFACTS_DIR = 'shard-artifacts';
42
+ const MINIO_REPORTS_DIR = 'playwright-reports';
49
43
 
50
- // Helper functions for report paths
51
- const getRunFolder = () => `${GCS_REPORTS_FOLDER_PREFIX}/${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}`;
52
- const getGcsObjectPath = (relativePath) => `${getRunFolder()}/${relativePath}`;
44
+ const getMinioObjectPath = (shard) => `${MINIO_ALIAS}/${MINIO_BUCKET}/${MINIO_ARTIFACTS_DIR}/${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}/shard-${shard}.tar.zst`;
45
+ const getMinioReportsPath = () => `${MINIO_ALIAS}/${MINIO_BUCKET}/${MINIO_REPORTS_DIR}/${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}`;
53
46
 
54
47
  // ============================================================================
55
48
 
@@ -184,7 +177,7 @@ class ResultsParser {
184
177
  }
185
178
 
186
179
  await this.mergeReports();
187
- await this.pushReportsToGCS();
180
+ await this.pushReportsToMinio();
188
181
  } else if (singleShardNoBlob) {
189
182
  // Single shard without blob (e.g. different reporter config): use node summary for Slack report
190
183
  const nodeSummaryFile = path.join(SUMMARIES_DIR, 'node_summary_1.json');
@@ -572,130 +565,32 @@ class ResultsParser {
572
565
  }
573
566
  }
574
567
 
575
- async getGcsAccessToken() {
576
- if (!GCS_SERVICE_ACCOUNT_KEY) {
577
- throw new Error('GCS_SERVICE_ACCOUNT_KEY environment variable is required');
568
+ async pushReportsToMinio() {
569
+ if (!process.env.CI) {
570
+ console.log('Skipping MinIO push: not in CI');
571
+ return;
578
572
  }
579
-
580
- let serviceAccount;
581
- try {
582
- serviceAccount = JSON.parse(GCS_SERVICE_ACCOUNT_KEY);
583
- } catch (e) {
584
- // Try reading from file path
585
- if (fs.existsSync(GCS_SERVICE_ACCOUNT_KEY)) {
586
- serviceAccount = JSON.parse(fs.readFileSync(GCS_SERVICE_ACCOUNT_KEY, 'utf-8'));
587
- } else {
588
- throw new Error('Invalid GCS_SERVICE_ACCOUNT_KEY: must be JSON string or file path');
589
- }
573
+ if (!MINIO_ENDPOINT || !MINIO_ACCESS_KEY || !MINIO_SECRET_KEY || !MINIO_BUCKET) {
574
+ throw new Error('MinIO configuration is required: set MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY and MINIO_BUCKET');
590
575
  }
591
-
592
- // Request OAuth2 token from Google
593
- const jwt = require('jsonwebtoken');
594
- const now = Math.floor(Date.now() / 1000);
595
- const token = jwt.sign(
596
- {
597
- iss: serviceAccount.client_email,
598
- scope: 'https://www.googleapis.com/auth/devstorage.full_control',
599
- aud: 'https://oauth2.googleapis.com/token',
600
- exp: now + 3600,
601
- iat: now
602
- },
603
- serviceAccount.private_key,
604
- { algorithm: 'RS256' }
605
- );
606
-
607
- const tokenResponse = await axios.post('https://oauth2.googleapis.com/token', {
608
- grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
609
- assertion: token
610
- });
611
-
612
- return tokenResponse.data.access_token;
613
- }
614
-
615
- async pushReportsToGCS() {
616
- // Only push in CI environment with required configuration
617
- if (!process.env.CI || !GCS_SERVICE_ACCOUNT_KEY) {
618
- console.log('Skipping GCS push: not in CI or missing GCS_SERVICE_ACCOUNT_KEY');
576
+ if (!fs.existsSync(PLAYWRIGHT_REPORT_DIR)) {
577
+ console.warn('Warning: playwright-report directory not found, nothing to upload to MinIO');
619
578
  return;
620
579
  }
621
-
580
+ const destination = getMinioReportsPath();
581
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mc-reports-'));
582
+ const mcConfigDir = path.join(tmpDir, '.mc');
622
583
  try {
623
- console.log(`Uploading playwright-report files to GCS bucket: ${GCS_BUCKET_NAME} in folder: ${getRunFolder()}`);
624
-
625
- // Get access token
626
- const accessToken = await this.getGcsAccessToken();
627
-
628
- // Collect all files from playwright-report directory
629
- const files = this.getAllFilesRecursive(PLAYWRIGHT_REPORT_DIR);
630
-
631
- // Normalize the base directory path for path replacement
632
- const baseDirPath = path.resolve(PLAYWRIGHT_REPORT_DIR);
633
-
634
- // Upload all files to GCS
635
- for (const file of files) {
636
- // Get relative path from playwright-report directory
637
- const relativePath = path.relative(baseDirPath, file).replace(/\\/g, '/');
638
- const objectPath = getGcsObjectPath(relativePath);
639
- const content = fs.readFileSync(file);
640
-
641
- // Upload file to GCS
642
- const uploadUrl = `${GCS_UPLOAD_API_BASE_URL}/b/${GCS_BUCKET_NAME}/o?uploadType=media&name=${encodeURIComponent(objectPath)}`;
643
-
644
- await axios.post(uploadUrl, content, {
645
- headers: {
646
- 'Authorization': `Bearer ${accessToken}`,
647
- 'Content-Type': this.getContentType(file)
648
- }
649
- });
650
- }
651
-
652
- console.log(`Successfully uploaded ${files.length} files to GCS bucket: ${GCS_BUCKET_NAME} in folder: ${getRunFolder()}`);
584
+ console.log(`Uploading playwright-report to MinIO: ${destination}`);
585
+ // Pass credentials as separate args (not embedded in a URL) to avoid encoding issues.
586
+ execFileSync('mc', ['--config-dir', mcConfigDir, 'alias', 'set', MINIO_ALIAS, MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY], { stdio: 'ignore' });
587
+ execFileSync('mc', ['--config-dir', mcConfigDir, 'cp', '--recursive', `${PLAYWRIGHT_REPORT_DIR}/`, `${destination}/`], { stdio: 'inherit' });
588
+ console.log(`Successfully uploaded playwright-report to MinIO: ${destination}`);
653
589
  } catch (error) {
654
- console.warn('Warning: Failed to push reports to GCS. This may not affect the overall process.', error.message);
655
- if (error.response) {
656
- console.warn('GCS API error:', error.response.data);
657
- }
658
- }
659
- }
660
-
661
- getContentType(filePath) {
662
- const ext = path.extname(filePath).toLowerCase();
663
- const contentTypes = {
664
- '.html': 'text/html',
665
- '.css': 'text/css',
666
- '.js': 'application/javascript',
667
- '.json': 'application/json',
668
- '.png': 'image/png',
669
- '.jpg': 'image/jpeg',
670
- '.jpeg': 'image/jpeg',
671
- '.gif': 'image/gif',
672
- '.svg': 'image/svg+xml',
673
- '.zip': 'application/zip',
674
- '.txt': 'text/plain',
675
- '.xml': 'application/xml'
676
- };
677
- return contentTypes[ext] || 'application/octet-stream';
678
- }
679
-
680
- getAllFilesRecursive(dir, fileList = []) {
681
- if (!fs.existsSync(dir)) {
682
- return fileList;
683
- }
684
-
685
- const files = fs.readdirSync(dir);
686
-
687
- for (const file of files) {
688
- const filePath = path.join(dir, file);
689
- const stat = fs.statSync(filePath);
690
-
691
- if (stat.isDirectory()) {
692
- this.getAllFilesRecursive(filePath, fileList);
693
- } else {
694
- fileList.push(filePath);
695
- }
590
+ console.warn('Warning: Failed to push reports to MinIO. This may not affect the overall process.', error.message);
591
+ } finally {
592
+ fs.rmSync(tmpDir, { recursive: true, force: true });
696
593
  }
697
-
698
- return fileList;
699
594
  }
700
595
  }
701
596
  exports.default = ResultsParser;
@@ -86,7 +86,7 @@ class SlackReporter {
86
86
  return;
87
87
  }
88
88
  if (this.sendResults === 'branch') {
89
- this.log('🛑 Branch mode: skipping Slack post (GCS upload completed)');
89
+ this.log('🛑 Branch mode: skipping Slack post (MinIO upload completed)');
90
90
  return;
91
91
  }
92
92
  const agent = this.proxy ? new https_proxy_agent_1.HttpsProxyAgent(this.proxy) : undefined;
package/package.json CHANGED
@@ -33,7 +33,7 @@
33
33
  "lint-fix": "npx eslint . --ext .ts --fix"
34
34
  },
35
35
  "name": "playwright-slack-report-burak",
36
- "version": "3.5.0",
36
+ "version": "3.5.2",
37
37
  "main": "index.js",
38
38
  "types": "dist/index.d.ts",
39
39
  "author": "Burak B. <burak.boluk@hotmail.com>",