Skip to content

Commit cedf877

Browse files
committed
Add CI script
1 parent b2b4ae4 commit cedf877

File tree

2 files changed

+307
-0
lines changed

2 files changed

+307
-0
lines changed

tools/ci/github/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2019 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# GitHub
22+
23+
> [GitHub][github-actions] scripts.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
This directory contains utilities for managing the build lifecycle on [GitHub][github-actions].
30+
31+
</section>
32+
33+
<!-- /.intro -->
34+
35+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
36+
37+
<section class="links">
38+
39+
[github-actions]: https://help.github.com/en/articles/about-github-actions
40+
41+
</section>
42+
43+
<!-- /.links -->

tools/ci/github/script

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
#!/usr/bin/env bash
2+
#
3+
# @license Apache-2.0
4+
#
5+
# Copyright (c) 2019 The Stdlib Authors.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
# Build script to run continuous integration on [GitHub][1].
20+
#
21+
# [1]: https://help.github.com/en/articles/about-github-actions
22+
23+
# shellcheck disable=SC2181
24+
25+
26+
# VARIABLES #
27+
28+
# Get the name of the build task as the first argument to the build script:
29+
task="$1"
30+
31+
# Define an output file to store log output:
32+
log_dir='./var/log'
33+
log_file="${log_dir}/ci.log"
34+
35+
# Define a heartbeat interval to periodically print messages in order to prevent CI from prematurely ending a build due to long running commands:
36+
heartbeat_interval='30s'
37+
38+
# Declare a variable for storing the heartbeat process id:
39+
heartbeat_pid=""
40+
41+
42+
# FUNCTIONS #
43+
44+
# Defines an error handler.
45+
#
46+
# $1 - error status
47+
on_error() {
48+
echo 'ERROR: An error was encountered during execution.' >&2
49+
cleanup
50+
exit "$1"
51+
}
52+
53+
# Runs clean-up tasks.
54+
cleanup() {
55+
stop_heartbeat
56+
}
57+
58+
# Starts a heartbeat.
59+
#
60+
# $1 - heartbeat interval
61+
start_heartbeat() {
62+
echo 'Starting heartbeat...' >&2
63+
64+
# Create a heartbeat and send to background:
65+
heartbeat "$1" &
66+
67+
# Capture the heartbeat pid:
68+
heartbeat_pid=$!
69+
echo "Heartbeat pid: ${heartbeat_pid}" >&2
70+
}
71+
72+
# Runs an infinite print loop.
73+
#
74+
# $1 - heartbeat interval
75+
heartbeat() {
76+
while true; do
77+
echo "$(date) - heartbeat..." >&2;
78+
sleep "$1";
79+
done
80+
}
81+
82+
# Stops the heartbeat print loop.
83+
stop_heartbeat() {
84+
echo 'Stopping heartbeat...' >&2
85+
kill "${heartbeat_pid}"
86+
}
87+
88+
# Creates an output log file.
89+
#
90+
# $1 - log directory
91+
# $2 - log file path
92+
create_log_file() {
93+
echo "Creating an output log file: $2." >&2
94+
mkdir -p "$1"
95+
touch "$2"
96+
}
97+
98+
# Prints a success message.
99+
print_success() {
100+
echo 'Success!' >&2
101+
}
102+
103+
# Runs unit tests.
104+
#
105+
# $1 - log file
106+
run_tests() {
107+
echo 'Running tests...' >&2
108+
make test >> "$1" 2>&1
109+
if [[ "$?" -ne 0 ]]; then
110+
echo 'Tests failed.' >&2
111+
return 1
112+
fi
113+
echo 'Tests passed.' >&2
114+
return 0
115+
}
116+
117+
# Runs test coverage.
118+
#
119+
# $1 - log file
120+
run_test_coverage() {
121+
echo 'Running test coverage...' >&2
122+
make test-cov >> "$1" 2>&1
123+
if [[ "$?" -ne 0 ]]; then
124+
echo 'Tests failed.' >&2
125+
return 1
126+
fi
127+
echo 'Tests passed.' >&2
128+
return 0
129+
}
130+
131+
# Sends test coverage to coverage service.
132+
#
133+
# $1 - report title
134+
# $2 - log file
135+
send_coverage() {
136+
echo 'Sending coverage report to coverage service...' >&2
137+
make COVERAGE_NAME="$1" coverage >> "$2" 2>&1
138+
if [[ "$?" -ne 0 ]]; then
139+
echo 'Sending coverage report to coverage service failed.' >&2
140+
return 1
141+
fi
142+
echo 'Coverage report sent to coverage service.' >&2
143+
return 0
144+
}
145+
146+
# Runs benchmarks.
147+
#
148+
# $1 - log file
149+
run_benchmarks() {
150+
echo 'Running benchmarks...' >&2
151+
make benchmark >> "$1" 2>&1
152+
if [[ "$?" -ne 0 ]]; then
153+
echo 'Benchmarks failed.' >&2
154+
return 1
155+
fi
156+
echo 'Successfully ran benchmarks.' >&2
157+
return 0
158+
}
159+
160+
# Runs examples.
161+
#
162+
# $1 - log file
163+
run_examples() {
164+
echo 'Running examples...' >&2
165+
make examples >> "$1" 2>&1
166+
if [[ "$?" -ne 0 ]]; then
167+
echo 'Examples failed.' >&2
168+
return 1
169+
fi
170+
echo 'Successfully ran examples.' >&2
171+
return 0
172+
}
173+
174+
# Tests whether the project successfully installs via `npm`.
175+
#
176+
# $1 - log file
177+
test_npm_install() {
178+
echo 'Testing npm install...' >&2
179+
make test-npm-install >> "$1" 2>&1
180+
if [[ "$?" -ne 0 ]]; then
181+
echo 'Installation failed.' >&2
182+
return 1
183+
fi
184+
echo 'Successfully installed.' >&2
185+
186+
echo 'Testing npm install (via GitHub)...' >&2
187+
make test-npm-install-github >> "$1" 2>&1
188+
if [[ "$?" -ne 0 ]]; then
189+
echo 'Installation (via GitHub) failed.' >&2
190+
return 1
191+
fi
192+
echo 'Successfully installed (via GitHub).' >&2
193+
194+
return 0
195+
}
196+
197+
# Checks dependencies.
198+
#
199+
# $1 - log file
200+
check_deps() {
201+
echo 'Checking dependencies...' >&2
202+
make check-deps >> "$1" 2>&1
203+
if [[ "$?" -ne 0 ]]; then
204+
echo 'Dependencies are out-of-date.' >&2
205+
return 1
206+
fi
207+
echo 'Dependencies are up-to-date.' >&2
208+
return 0
209+
}
210+
211+
# Main execution sequence.
212+
main() {
213+
create_log_file "${log_dir}" "${log_file}"
214+
start_heartbeat "${heartbeat_interval}"
215+
216+
echo "Task: ${task}." >&2
217+
if [[ "${task}" = "test-npm-install" ]]; then
218+
test_npm_install "${log_file}"
219+
if [[ "$?" -ne 0 ]]; then
220+
on_error 1
221+
fi
222+
elif [[ "${task}" = "test" ]]; then
223+
run_tests "${log_file}"
224+
if [[ "$?" -ne 0 ]]; then
225+
on_error 1
226+
fi
227+
elif [[ "${task}" = "benchmark" ]]; then
228+
run_benchmarks "${log_file}"
229+
if [[ "$?" -ne 0 ]]; then
230+
on_error 1
231+
fi
232+
elif [[ "${task}" = "examples" ]]; then
233+
run_examples "${log_file}"
234+
if [[ "$?" -ne 0 ]]; then
235+
on_error 1
236+
fi
237+
elif [[ "${task}" = "test-coverage" ]]; then
238+
run_test_coverage "${log_file}"
239+
if [[ "$?" -ne 0 ]]; then
240+
on_error 1
241+
fi
242+
send_coverage "unit_test" "${log_file}"
243+
if [[ "$?" -ne 0 ]]; then
244+
on_error 1
245+
fi
246+
elif [[ "${task}" = "check-deps" ]]; then
247+
check_deps "${log_file}"
248+
if [[ "$?" -ne 0 ]]; then
249+
on_error 1
250+
fi
251+
else
252+
echo "ERROR: unknown task: ${task}." >&2
253+
on_error 1
254+
fi
255+
cleanup
256+
print_success
257+
exit 0
258+
}
259+
260+
# Set an error handler to print captured output and perform any clean-up tasks:
261+
trap 'on_error' ERR
262+
263+
# Run main:
264+
main

0 commit comments

Comments
 (0)