haven-cypress-integration 1.0.0 โ†’ 1.1.0

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.
@@ -17,12 +17,14 @@ Commands:
17
17
 
18
18
  Options:
19
19
  --tag=name:version Docker image tag (default: haven-cypress-tests:latest)
20
- --push Push image to registry after building
20
+ --product=name Product name for ECR organization (required for --push)
21
+ --push Push image to ECR haven-test-images repository
21
22
  --automationIds=ID1,ID2 Run specific test cases
22
23
 
23
24
  Examples:
24
- npx haven-cypress build
25
- npx haven-cypress build --tag=my-tests:v1.0 --push
25
+ npx haven-cypress build --product=billexplainer
26
+ npx haven-cypress build --product=billexplainer --push
27
+ npx haven-cypress build --product=billexplainer --tag=v1.0 --push
26
28
  npx haven-cypress run --automationIds=TC-AUTO-123,TC-AUTO-124
27
29
  `);
28
30
  process.exit(1);
@@ -45,12 +47,12 @@ try {
45
47
  const tag = options.tag || 'haven-cypress-tests:latest';
46
48
  integration.buildImage(tag, options);
47
49
  break;
48
-
50
+
49
51
  case 'run':
50
52
  const automationIds = options.automationIds || '';
51
53
  integration.runTests(automationIds);
52
54
  break;
53
-
55
+
54
56
  default:
55
57
  console.error(`โŒ Unknown command: ${command}`);
56
58
  process.exit(1);
package/index.js CHANGED
@@ -14,39 +14,42 @@ class HavenCypressIntegration {
14
14
  */
15
15
  buildImage(tag = 'haven-cypress-tests:latest', options = {}) {
16
16
  console.log('๐Ÿณ Building Haven-integrated Docker image...');
17
-
17
+
18
+ // Validate product name if pushing
19
+ if (options.push && !options.product) {
20
+ throw new Error('โŒ --product is required when using --push');
21
+ }
22
+
18
23
  // Create temporary build directory
19
24
  const buildDir = path.join(process.cwd(), '.haven-build');
20
25
  if (fs.existsSync(buildDir)) {
21
26
  fs.rmSync(buildDir, { recursive: true });
22
27
  }
23
28
  fs.mkdirSync(buildDir, { recursive: true });
24
-
29
+
25
30
  try {
26
31
  // Copy user's project files
27
32
  console.log('๐Ÿ“ Copying project files...');
28
33
  this.copyProjectFiles(buildDir);
29
-
34
+
30
35
  // Copy Haven integration files
31
36
  console.log('๐Ÿ”ง Adding Haven integration files...');
32
37
  this.copyHavenFiles(buildDir);
33
-
38
+
34
39
  // Build Docker image
35
40
  console.log('๐Ÿ—๏ธ Building Docker image...');
36
- execSync(`docker build -t ${tag} .`, {
37
- cwd: buildDir,
38
- stdio: 'inherit'
41
+ execSync(`docker build -t ${tag} .`, {
42
+ cwd: buildDir,
43
+ stdio: 'inherit'
39
44
  });
40
-
45
+
41
46
  console.log(`โœ… Docker image built successfully: ${tag}`);
42
-
47
+
43
48
  // Push if requested
44
49
  if (options.push) {
45
- console.log('๐Ÿ“ค Pushing image to registry...');
46
- execSync(`docker push ${tag}`, { stdio: 'inherit' });
47
- console.log('โœ… Image pushed successfully');
50
+ this.pushToECR(tag, options.product);
48
51
  }
49
-
52
+
50
53
  } finally {
51
54
  // Cleanup build directory
52
55
  if (fs.existsSync(buildDir)) {
@@ -65,11 +68,11 @@ class HavenCypressIntegration {
65
68
  'cypress.config.js',
66
69
  'cypress'
67
70
  ];
68
-
71
+
69
72
  filesToCopy.forEach(file => {
70
73
  const src = path.join(process.cwd(), file);
71
74
  const dest = path.join(buildDir, file);
72
-
75
+
73
76
  if (fs.existsSync(src)) {
74
77
  if (fs.statSync(src).isDirectory()) {
75
78
  this.copyDir(src, dest);
@@ -92,17 +95,17 @@ class HavenCypressIntegration {
92
95
  'run-filtered.sh',
93
96
  'syncCypressResults.js'
94
97
  ];
95
-
98
+
96
99
  havenFiles.forEach(file => {
97
100
  const src = path.join(this.templatesDir, file);
98
101
  const dest = path.join(buildDir, file);
99
-
102
+
100
103
  if (fs.existsSync(src)) {
101
104
  fs.copyFileSync(src, dest);
102
105
  console.log(` โœ… Added ${file}`);
103
106
  }
104
107
  });
105
-
108
+
106
109
  // Make run-filtered.sh executable
107
110
  execSync('chmod +x run-filtered.sh', { cwd: buildDir });
108
111
  }
@@ -114,13 +117,13 @@ class HavenCypressIntegration {
114
117
  if (!fs.existsSync(dest)) {
115
118
  fs.mkdirSync(dest, { recursive: true });
116
119
  }
117
-
120
+
118
121
  const entries = fs.readdirSync(src, { withFileTypes: true });
119
-
122
+
120
123
  for (const entry of entries) {
121
124
  const srcPath = path.join(src, entry.name);
122
125
  const destPath = path.join(dest, entry.name);
123
-
126
+
124
127
  if (entry.isDirectory()) {
125
128
  this.copyDir(srcPath, destPath);
126
129
  } else {
@@ -129,6 +132,54 @@ class HavenCypressIntegration {
129
132
  }
130
133
  }
131
134
 
135
+ /**
136
+ * Push image to ECR with product organization
137
+ * @param {string} localTag - Local Docker image tag
138
+ * @param {string} product - Product name for organization
139
+ */
140
+ pushToECR(localTag, product) {
141
+ console.log(`๐Ÿ“ค Pushing image to ECR for product: ${product}`);
142
+
143
+ try {
144
+ // Get AWS account ID and region
145
+ console.log('๐Ÿ” Getting AWS account information...');
146
+ const accountId = execSync('aws sts get-caller-identity --query Account --output text', { encoding: 'utf8' }).trim();
147
+ const region = execSync('aws configure get region', { encoding: 'utf8' }).trim() || 'us-east-1';
148
+
149
+ console.log(`๐Ÿ“‹ Account: ${accountId}, Region: ${region}`);
150
+
151
+ // ECR repository and image details
152
+ const ecrRepo = 'haven-test-images';
153
+ const ecrUri = `${accountId}.dkr.ecr.${region}.amazonaws.com/${ecrRepo}`;
154
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
155
+ const ecrTag = `${product}/${localTag.split(':')[1] || 'latest'}-${timestamp}`;
156
+ const fullEcrUri = `${ecrUri}:${ecrTag}`;
157
+
158
+ console.log(`๐Ÿท๏ธ ECR tag: ${ecrTag}`);
159
+
160
+ // Login to ECR
161
+ console.log('๐Ÿ” Logging in to ECR...');
162
+ const loginCmd = `aws ecr get-login-password --region ${region} | docker login --username AWS --password-stdin ${ecrUri}`;
163
+ execSync(loginCmd, { stdio: 'inherit' });
164
+
165
+ // Tag image for ECR
166
+ console.log(`๐Ÿท๏ธ Tagging image: ${localTag} -> ${fullEcrUri}`);
167
+ execSync(`docker tag ${localTag} ${fullEcrUri}`, { stdio: 'inherit' });
168
+
169
+ // Push to ECR
170
+ console.log(`๐Ÿ“ค Pushing to ECR: ${fullEcrUri}`);
171
+ execSync(`docker push ${fullEcrUri}`, { stdio: 'inherit' });
172
+
173
+ console.log(`โœ… Image pushed successfully!`);
174
+ console.log(`๐Ÿ“ ECR URI: ${fullEcrUri}`);
175
+ console.log(`๐Ÿ—‚๏ธ Organization: ${ecrRepo}/${product}/`);
176
+
177
+ } catch (error) {
178
+ console.error(`โŒ Failed to push to ECR: ${error.message}`);
179
+ throw error;
180
+ }
181
+ }
182
+
132
183
  /**
133
184
  * Run tests with Haven integration
134
185
  * This is called by Haven when the container runs
@@ -136,7 +187,7 @@ class HavenCypressIntegration {
136
187
  runTests(automationIds = '') {
137
188
  console.log('๐Ÿงช Running Haven-integrated Cypress tests...');
138
189
  console.log(`๐Ÿ” Automation IDs: ${automationIds || 'All tests'}`);
139
-
190
+
140
191
  // This will be handled by run-filtered.sh when container runs
141
192
  // The library just provides the interface
142
193
  return { success: true, message: 'Tests will run via run-filtered.sh' };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haven-cypress-integration",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Seamless Cypress integration with HAVEN test case management",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -23,4 +23,4 @@
23
23
  "engines": {
24
24
  "node": ">=14.0.0"
25
25
  }
26
- }
26
+ }