Skip to content

Commit 719b3a2

Browse files
committed
Merge branch 'develop' of https://github.com/stdlib-js/stdlib into develop
2 parents 63ca872 + fab1183 commit 719b3a2

File tree

131 files changed

+249
-307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+249
-307
lines changed

.github/workflows/run_tests_coverage.yml

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@
147147

148148
# Run JavaScript tests:
149149
- name: 'Run JavaScript tests'
150+
id: extract-coverage
151+
env:
152+
GITHUB_REPO: ${{ github.repository }}
153+
GITHUB_REF: ${{ github.ref }}
150154
run: |
151155
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
152156
directories="${{ steps.changed-directories-user-input.outputs.directories }}"
@@ -156,38 +160,16 @@
156160
. "$GITHUB_WORKSPACE/.github/workflows/scripts/run_tests_coverage" "$directories"
157161
timeout-minutes: 30
158162

159-
# Extract coverage values and assign to output:
160-
- name: 'Extract coverage values and assign to output'
161-
id: extract-coverage
163+
# Create final coverage report:
164+
- name: 'Create final coverage report'
165+
id: create-report
162166
run: |
163-
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
164-
directories="${{ steps.changed-directories-user-input.outputs.directories }}"
165-
else
166-
directories="${{ steps.changed-directories.outputs.directories }}"
167-
fi
168-
directories=$(echo "${directories}" | tr ' ' '\n' | grep '^lib/node_modules/@stdlib') || true
169-
directories=$(echo "${directories}" | tr ' ' '\n' | sed -E 's/\/(benchmark|bin|data|docs|etc|examples|include|lib|src|test)(\/.*)?$//')
170-
directories=$(echo "${directories}" | uniq)
171-
172-
# For each package, extract coverage value from the respective coverage report:
173-
coverage=''
174-
for package in $directories; do
175-
pkg=`echo $package | sed -E 's/^.*stdlib\///'`
176-
pkg_cov=`cat reports/coverage/lcov-report/$pkg/lib/index.html | grep "fraction" | grep -oP '\d+/\d+' | printf %s "$(cat)" | jq -R -s -c 'split("\n")'`
177-
pkg_url="https://github.com/${{ github.repository }}/tree/${{ github.ref }}/$package"
178-
pkg_link="<a href="$pkg_url">$pkg</a>"
179-
coverage="$coverage\n| $pkg_link $pkg_cov"
180-
done
181-
182-
# Format coverage as Markdown table row:
183-
table_body=`echo $coverage | sed -e 's/,/|/g; s/"/ /g; s/\[/|/g; s/\]/|/g'`
184-
table_header="| Package | Statements | Branches | Functions | Lines |\n| --------- | ------------ | ---------- | ----------- | ----- |"
185-
table="${table_header}${table_body}"
167+
table="${{ steps.extract-coverage.outputs.table }}"
186168
187169
if [ "${{ github.event_name }}" == "pull_request" ]; then
188170
compare_url="https://github.com/stdlib-js/stdlib/compare/${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}"
189171
compare_txt="The above coverage report was generated for the [changes in this PR]($compare_url)."
190-
else if [ "${{ github.event_name }}" == "push" ]; then
172+
elif [ "${{ github.event_name }}" == "push" ]; then
191173
compare_url="https://github.com/stdlib-js/stdlib/compare/${{ github.event.before }}...${{ github.event.after }}"
192174
compare_txt="The above coverage report was generated for the [changes in this push]($compare_url)."
193175
else
@@ -208,7 +190,7 @@
208190
issue_number: context.issue.number,
209191
owner: context.repo.owner,
210192
repo: context.repo.repo,
211-
body: '${{ steps.extract-coverage.outputs.report }}'
193+
body: '${{ steps.create-report.outputs.report }}'
212194
})
213195
214196
# Post report as comment to commit:
@@ -222,5 +204,43 @@
222204
commit_sha: context.sha,
223205
owner: context.repo.owner,
224206
repo: context.repo.repo,
225-
body: '${{ steps.extract-coverage.outputs.report }}'
207+
body: '${{ steps.create-report.outputs.report }}'
226208
})
209+
210+
# Checkout coverage repository:
211+
- name: 'Checkout coverage repository'
212+
uses: actions/checkout@v3
213+
with:
214+
# Code coverage repository:
215+
repository: 'stdlib-js/www-test-code-coverage'
216+
217+
# File path to checkout to:
218+
path: './www-test-code-coverage'
219+
220+
# Specify whether to remove untracked files before checking out the repository:
221+
clean: false
222+
223+
# Limit clone depth to the most recent commit:
224+
fetch-depth: 1
225+
226+
# Token for accessing the repository:
227+
token: ${{ secrets.REPO_GITHUB_TOKEN }}
228+
229+
# Copy artifacts to the repository:
230+
- name: 'Copy artifacts to the repository'
231+
run: |
232+
cp -R ./artifacts/* ./www-test-code-coverage
233+
234+
# Commit and push changes:
235+
- name: 'Commit and push changes'
236+
env:
237+
REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
238+
USER_NAME: stdlib-bot
239+
run: |
240+
cd ./www-test-code-coverage
241+
git add .
242+
git config --local user.email "noreply@stdlib.io"
243+
git config --local user.name "stdlib-bot"
244+
git commit -m "Update artifacts"
245+
git push "https://$USER_NAME:$REPO_GITHUB_TOKEN@github.com/stdlib-js/www-test-code-coverage.git" main
246+

.github/workflows/scripts/run_tests_coverage

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#
3030
# Environment variables:
3131
#
32+
# GITHUB_REPO GitHub repository.
33+
# GITHUB_REF GitHub branch or tag.
3234
# LOG_FILE Log file.
3335
#
3436

@@ -43,6 +45,12 @@ set -o pipefail
4345
# Get the list of changed files:
4446
changed="$*"
4547

48+
# Get the GitHub repository:
49+
github_repo="${GITHUB_REPO}"
50+
51+
# Get the GitHub branch or tag:
52+
github_ref="${GITHUB_REF}"
53+
4654
# Get the path to a log file as the third argument to the build script:
4755
log_file="${LOG_FILE}"
4856

@@ -104,6 +112,31 @@ print_success() {
104112
echo 'Success!' >&2
105113
}
106114

115+
# Calculates the percentage change in code coverage and prints a formatted string.
116+
#
117+
# $1 - previous coverage value as a decimal (e.g., 0.85 for 85% coverage)
118+
# $2 - new coverage value as a decimal
119+
compare_cov() {
120+
old_cov_value="$1"
121+
new_cov_value="$2"
122+
123+
if [ "$old_cov_value" == 0 ]; then
124+
new_cov_percentage=$(awk "BEGIN {printf \"%.1f\", $new_cov_value*100}")
125+
echo "\$\\\\color{green}+$new_cov_percentage\\\\%\$"
126+
else
127+
percentage_change=$(awk "BEGIN {printf \"%.1f\", (($new_cov_value - $old_cov_value) / $old_cov_value) * 100}")
128+
color="green"
129+
sign=""
130+
if [ $(awk "BEGIN {if ($percentage_change > 0) print 1; else print 0}") -eq 1 ]; then
131+
sign="+"
132+
elif [ $(awk "BEGIN {if ($percentage_change < 0) print 1; else print 0}") -eq 1 ]; then
133+
sign="-"
134+
color="red"
135+
fi
136+
echo "\$\\\\color{$color}$sign$percentage_change\\\\%\$"
137+
fi
138+
}
139+
107140
# Main execution sequence.
108141
main() {
109142
start_heartbeat "${heartbeat_interval}"
@@ -121,15 +154,62 @@ main() {
121154
exit 0
122155
fi
123156

124-
# Find all test files in package directories:
125-
files=$(find ${directories} -maxdepth 2 -wholename '**/test/test*.js' | grep -v '/fixtures/' | sort -u | tr '\n' ' ') || true
157+
mkdir -p artifacts
158+
coverage=''
159+
for package in ${directories}; do
160+
make test-javascript-cov TESTS_FILTER=".*/${package}/.*"
161+
162+
# For each package, extract coverage values from the respective coverage report:
163+
pkg=`echo $package | sed -E 's/^.*stdlib\///'`
164+
pkg_cov_values=($(cat reports/coverage/lcov-report/$pkg/lib/index.html | grep "fraction" | grep -oP '\d+/\d+' | awk -F'/' '{print $1/$2}'))
165+
pkg_statements_cov=${pkg_cov_values[0]}
166+
pkg_branches_cov=${pkg_cov_values[1]}
167+
pkg_functions_cov=${pkg_cov_values[2]}
168+
pkg_lines_cov=${pkg_cov_values[3]}
169+
170+
pkg_cov_fractions=($(cat reports/coverage/lcov-report/$pkg/lib/index.html | grep "fraction" | grep -oP '\d+/\d+' | awk -F'/' '{if ($1<$2) print "$\\\\color{red}" $0 "$"; else print "$\\\\color{green}" $0 "$"}'))
171+
pkg_statements_cov_fraction=${pkg_cov_fractions[0]}
172+
pkg_branches_cov_fraction=${pkg_cov_fractions[1]}
173+
pkg_functions_cov_fraction=${pkg_cov_fractions[2]}
174+
pkg_lines_cov_fraction=${pkg_cov_fractions[3]}
175+
176+
old_cov_report=$(curl -s --fail "https://coverage.stdlib.io/${pkg}/lib/index.html" 2>/dev/null)
177+
status=$?
178+
if [ $status -ne 0 ]; then
179+
old_statements_cov=0
180+
old_branches_cov=0
181+
old_functions_cov=0
182+
old_lines_cov=0
183+
else
184+
old_cov_values=$(echo "$old_cov_report" | grep "fraction" | grep -oP '\d+/\d+' | awk -F'/' '{print $1/$2}')
185+
old_statements_cov=${old_cov_values[0]}
186+
old_branches_cov=${old_cov_values[1]}
187+
old_functions_cov=${old_cov_values[2]}
188+
old_lines_cov=${old_cov_values[3]}
189+
fi
190+
191+
cov_change_statements=$(compare_cov "$old_statements_cov" "$pkg_statements_cov")
192+
cov_change_branches=$(compare_cov "$old_branches_cov" "$pkg_branches_cov")
193+
cov_change_functions=$(compare_cov "$old_functions_cov" "$pkg_functions_cov")
194+
cov_change_lines=$(compare_cov "$old_lines_cov" "$pkg_lines_cov")
195+
196+
echo $pkg_statements_cov_fraction
197+
pkg_cov="| $pkg_statements_cov_fraction$cov_change_statements) | $pkg_branches_cov_fraction$cov_change_branches) | $pkg_functions_cov_fraction$cov_change_functions) | $pkg_lines_cov_fraction$cov_change_lines) |"
198+
199+
pkg_url="https://github.com/${github_repo}/tree/${github_ref}/${package}"
200+
pkg_link="<a href="$pkg_url">$pkg</a>"
201+
coverage="$coverage\n| $pkg_link $pkg_cov"
202+
203+
# Copy coverage report of the package to artifacts directory:
204+
mkdir -p "artifacts/${pkg}" && cp -r "reports/coverage/lcov-report/${pkg}"/* "artifacts/${pkg}/"
205+
done
126206

127-
# Exclude files residing in test fixtures directories:
128-
files=$(echo "${files}" | grep -v '/fixtures/') || true
207+
# Format coverage as Markdown table row:
208+
table_body=`echo $coverage | sed -e 's/,/|/g; s/"/ /g; s/\[/|/g; s/\]/|/g'`
209+
table_header="| Package | Statements | Branches | Functions | Lines |\n| --------- | ------------ | ---------- | ----------- | ----- |"
210+
table="${table_header}${table_body}"
129211

130-
if [[ -n "${files}" ]]; then
131-
make test-javascript-cov-files FILES="${files}"
132-
fi
212+
echo "table=$table" >> $GITHUB_OUTPUT
133213

134214
cleanup
135215
print_success

etc/eslint/rules/stdlib.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3993,7 +3993,7 @@ rules[ 'stdlib/new-cap-regexp' ] = 'error';
39933993
rules[ 'stdlib/no-dynamic-require' ] = 'error';
39943994

39953995
/**
3996-
* Require that comments are not empty.
3996+
* Disallow empty comments.
39973997
*
39983998
* @name no-empty-comments
39993999
* @memberof rules

lib/node_modules/@stdlib/_tools/bundle/pkg-list/lib/setdiff.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ var debug = logger( 'bundle-pkg-list:setdiff' );
3939
*
4040
* - We assume that `A` is a list of namespaces and `B` is a list of packages. We exclude all namespaces from the output array, _except_ those that have aliases in the global alias namespace.
4141
*
42-
*
4342
* @private
4443
* @param {Array} A - first set
4544
* @param {Array} B - second set

lib/node_modules/@stdlib/_tools/bundle/pkg-list/lib/tree_filter.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ var debug = logger( 'bundle-pkg-list:tree-filter' );
4242
* - If namespace packages with listed children were allowed, we would end up trying to override namespace properties which are read-only. So, our stance is that, if you want a namespace, you should provide a namespace only. And if you only want certain children, then provide the children, but not the namespace. Providing both signals confusion.
4343
* - The one exception we allow is when a namespace has an alias in the global alias namespace, which indicates that a package is not a "traditional" namespace, possibly providing a function API to namespace packages (e.g., `@stdlib/datasets`).
4444
*
45-
*
4645
* @private
4746
* @param {StringArray} pkgs - list of packages (unique and sorted lexicographically)
4847
* @returns {StringArray} filtered list
@@ -55,7 +54,7 @@ var debug = logger( 'bundle-pkg-list:tree-filter' );
5554
* ];
5655
*
5756
* var out = filter( pkgs );
58-
* // returns [ '@stdlib/random/base', '@stdlib/math/base/special/erf' ]
57+
* // returns [ '@stdlib/math/base', '@stdlib/random/base', '@stdlib/math/base/special/erf' ]
5958
*/
6059
function filter( pkgs ) {
6160
var out;

lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-fenced-code-flag/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@stdlib/_tools/eslint/rules/jsdoc-fenced-code-marker",
2+
"name": "@stdlib/_tools/eslint/rules/jsdoc-fenced-code-flag",
33
"version": "0.0.0",
44
"description": "ESLint rule to enforce fenced Markdown code blocks to have a language flag in JSDoc descriptions.",
55
"license": "Apache-2.0",

lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-main-export/lib/main.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ function main( context ) {
6969
// Get the part starting with `@stdlib`, shift by one to avoid leading `@`:
7070
modulePath = modulePath.substr( modulePath.indexOf( '@stdlib' )+1 );
7171

72+
// Replace Windows path separators with POSIX path separators (if present):
73+
modulePath = replace( modulePath, '\\', '/' );
74+
7275
activate = false;
7376
ending = '/lib/index.js';
7477
if ( endsWith( modulePath, ending ) && !contains( source.text, '@namespace' ) ) {
@@ -100,7 +103,15 @@ function main( context ) {
100103
* @param {Object} loc - lines of code (object with `start` and `end` properties)
101104
*/
102105
function checkExample( tag, loc ) {
103-
if ( !RE_REQUIRE.test( tag.description ) ) {
106+
var match;
107+
108+
match = RE_REQUIRE.exec( tag.description );
109+
if ( match ) {
110+
// The main export should be required last, so no `require` calls should follow:
111+
if ( match.index !== tag.description.lastIndexOf( 'require' ) ) {
112+
report( 'Example code of main export should require itself last, i.e. contain `require( \'@'+modulePath+'\' )` as the last `require` call', loc );
113+
}
114+
} else {
104115
report( 'Example code of main export should require itself, i.e. contain `require( \'@'+modulePath+'\' )`', loc );
105116
}
106117
}

lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-main-export/test/fixtures/invalid.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,35 @@ test = {
4848
};
4949
invalid.push( test );
5050

51+
test = {
52+
'code': [
53+
'/**',
54+
'* Test if a value is an array.',
55+
'*',
56+
'* @module @stdlib/assert/is-array',
57+
'*',
58+
'* @example',
59+
'* var isArray = require( \'@stdlib/assert/is-array\' );',
60+
'* var filled = require( \'@stdlib/array/filled\' );',
61+
'*',
62+
'* var arr = filled( 0, 10 );',
63+
'* var bool = isArray( arr );',
64+
'* // returns true',
65+
'*',
66+
'* bool = isArray( {} );',
67+
'* // returns false',
68+
'*/'
69+
].join( '\n' ),
70+
'filename': '/path/to/@stdlib/assert/is-array/lib/index.js',
71+
'errors': [
72+
{
73+
'message': 'Example code of main export should require itself last, i.e. contain `require( \'@stdlib/assert/is-array\' )` as the last `require` call',
74+
'type': null
75+
}
76+
]
77+
};
78+
invalid.push( test );
79+
5180
test = {
5281
'code': [
5382
'/**',

lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-main-export/test/fixtures/valid.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,29 @@ test = {
4242
};
4343
valid.push( test );
4444

45+
test = {
46+
'code': [
47+
'/**',
48+
'* Test if a value is an array.',
49+
'*',
50+
'* @module @stdlib/assert/is-array',
51+
'*',
52+
'* @example',
53+
'* var filled = require( \'@stdlib/array/filled\' );',
54+
'* var isArray = require( \'@stdlib/assert/is-array\' );',
55+
'*',
56+
'* var arr = filled( 0, 10 );',
57+
'* var bool = isArray( arr );',
58+
'* // returns true',
59+
'*',
60+
'* bool = isArray( {} );',
61+
'* // returns false',
62+
'*/'
63+
].join( '\n' ),
64+
'filename': '/path/to/@stdlib/assert/is-array/lib/index.js'
65+
};
66+
valid.push( test );
67+
4568
test = {
4669
'code': [
4770
'/**',

lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-no-space-aligned-asterisks/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ limitations under the License.
2020

2121
# No Space-Aligned Asterisks
2222

23-
> [ESLint rule][eslint-rules] to prevent prevent space-aligned asterisks for JSDoc comments.
23+
> [ESLint rule][eslint-rules] to disallow space-aligned asterisks for JSDoc comments.
2424
2525
<section class="intro">
2626

@@ -38,7 +38,7 @@ var rule = require( '@stdlib/_tools/eslint/rules/jsdoc-no-space-aligned-asterisk
3838

3939
#### rule
4040

41-
[ESLint rule][eslint-rules] to prevent space-aligned asterisks for JSDoc comments.
41+
[ESLint rule][eslint-rules] to disallow space-aligned asterisks for JSDoc comments.
4242

4343
**Bad**:
4444

lib/node_modules/@stdlib/_tools/eslint/rules/jsdoc-no-space-aligned-asterisks/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@stdlib/_tools/eslint/rules/jsdoc-no-space-aligned-asterisks",
33
"version": "0.0.0",
4-
"description": "ESLint rule to prevent space-aligned asterisks for JSDoc comments.",
4+
"description": "ESLint rule to disallow space-aligned asterisks for JSDoc comments.",
55
"license": "Apache-2.0",
66
"author": {
77
"name": "The Stdlib Authors",

0 commit comments

Comments
 (0)