-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathexecute-tests.js
175 lines (130 loc) · 4.77 KB
/
execute-tests.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Author: Mahan Fathi, https://github.com/Mahan-F/test-project-action
const axios = require('axios')
const core = require('@actions/core')
const API_URL = `https://api.testproject.io/v2/projects/${ strip(process.env.INPUT_PROJECT_ID) }/jobs`
const API_HEADER = {
'Authorization': strip(process.env.INPUT_API_KEY)
}
const CHECK_INTERVAL = parseInt(strip(process.env.INPUT_CHECK_INTERVAL)) * 1000
const WAIT_FOR_TESTS = strip(process.env.INPUT_WAIT_FOR_TESTS) === 'true' || strip(process.env.INPUT_WAIT_FOR_TESTS) === true
// Keep track of all jobs
const jobsStatus = []
async function main() {
core.info(`Getting a list of all jobs in project ${ strip(process.env.INPUT_PROJECT_ID) }`)
// Get a list of jobs
const jobs = await getJobs().catch( err => {
core.setFailed(`Unable to get jobs.`)
console.log(err)
return
})
await executeAllJobs(jobs)
if ( WAIT_FOR_TESTS ) {
console.log('Waiting for jobs to complete')
await periodicallyCheckJobStatus(jobs)
} else {
console.log('Not waiting for jobs to complete')
}
}
/**
* Get a list of all jobs that exist in the given project
* @returns Array of jobs from TestProject API
*/
async function getJobs() {
const jobs = await axios({
method: 'get',
url: API_URL,
headers: API_HEADER
})
core.info(`Found ${ jobs.data.length } test job(s) to execute.`)
return jobs.data
}
/**
* Executes all the jobs passed in the parameter and adds them to the `jobsStatus` array
* @param {*} jobs Array of jobs to execute
* @returns a promise once all executions are complete
*/
async function executeAllJobs(jobs) {
return new Promise((resolve, reject) => {
const executionPromises = []
for ( let i = 0; i < jobs.length; i++ ) {
const executeJob = axios({
method: 'post',
url: `${ API_URL }/${ jobs[i].id }/run`,
headers: API_HEADER
}).catch( err => {
core.setFailed(`Execution failed for job ${ jobs[i].id } (${ jobs[i].name })`)
console.log(err)
return
})
executionPromises.push( executeJob )
}
Promise.all( executionPromises ).then( results => {
results.forEach( (result, i) => {
core.info(`Executed job ${ jobs[i].id } (${ jobs[i].name }). Execution ID: ${ result.data.id }`)
jobsStatus.push({
...jobs[i],
status: 'Pending',
executionId: result.data.id
})
})
return resolve(true)
})
})
}
/**
* Calls TestProject state API for every pending job execution periodically until
* all executions are finished (Passed/Failed)
* @param {*} jobs Array of jobs to execute
*/
async function periodicallyCheckJobStatus(jobs) {
const jobStatusInterval = setInterval( async () => {
const pendingJobs = jobsStatus.filter( x => x.status === 'Pending' )
core.info(`Checking status of running tests (${ pendingJobs.length } test(s))`)
for ( let i = 0; i < pendingJobs.length; i++ ) {
const jobStatus = await axios({
method: 'get',
url: `${ API_URL }/${ pendingJobs[i].id }/executions/${ pendingJobs[i].executionId }/state`,
headers: API_HEADER
}).catch( err => {
core.setFailed(`Job state check failed for job ${ pendingJobs[i].id } (${ pendingJobs[i].name })`)
console.log(err)
return Promise.resolve(true)
})
if ( jobStatus.data.state === 'Executing' || jobStatus.data.state === 'Ready' ) {
continue;
} else if ( jobStatus.data.state === 'Failed' || jobStatus.data.state === 'Passed' ) {
// Update the status of the job
jobsStatus.find( x => x.id === pendingJobs[i].id ).status = jobStatus.data.state
// Log status of the job
if ( jobStatus.data.state === 'Passed' ) {
core.info(`Job execution ${ pendingJobs[i].executionId } (${ pendingJobs[i].name }) passed.`)
} else {
core.error(`Job execution ${ pendingJobs[i].executionId } (${ pendingJobs[i].name }) failed.`)
}
}
}
// If no more pending jobs are left, end
if ( jobsStatus.filter( x => x.status === 'Pending' ).length === 0 ) {
core.startGroup('Job data')
console.log(jobsStatus)
core.endGroup()
core.info('Finished running tests')
clearInterval(jobStatusInterval)
const failedJobs = jobsStatus.filter( x => x.status === 'Failed' )
if ( failedJobs.length ) {
core.error(`Failed Tests: ${ failedJobs.map( x => x.name ).join(', ') }`)
core.setFailed(`${ failedJobs.length } tests failed.`)
}
return Promise.resolve(true)
}
}, CHECK_INTERVAL);
}
/**
* Strip leading or trailing whitespace
* @param {*} val Value to strip
* @returns Stripped text
*/
function strip(val) {
return (val || '').replace(/^\s*|\s*$/g, '');
}
main()