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.
- package/bin/haven-cypress.js +7 -5
- package/index.js +73 -22
- package/package.json +2 -2
package/bin/haven-cypress.js
CHANGED
|
@@ -17,12 +17,14 @@ Commands:
|
|
|
17
17
|
|
|
18
18
|
Options:
|
|
19
19
|
--tag=name:version Docker image tag (default: haven-cypress-tests:latest)
|
|
20
|
-
--
|
|
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 --
|
|
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
|
-
|
|
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.
|
|
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
|
+
}
|