diff --git a/.github/workflows/check_contributing_guidelines_acceptance.yml b/.github/workflows/check_contributing_guidelines_acceptance.yml new file mode 100755 index 000000000000..ff3b44ef6e81 --- /dev/null +++ b/.github/workflows/check_contributing_guidelines_acceptance.yml @@ -0,0 +1,88 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2024 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: check_contributing_guidelines_acceptance + +# Workflow triggers: +on: + # Allow the workflow to be triggered by other workflows + workflow_call: + # Define the input parameters for the workflow: + inputs: + pull_request_number: + description: 'Pull request number' + required: true + type: number + user: + required: true + type: string + # Define the secrets accessible by the workflow: + secrets: + STDLIB_BOT_GITHUB_TOKEN: + description: 'stdlib-bot GitHub token to create pull request comments' + required: true + + # Trigger on pull request events: + pull_request_target: + types: [opened, edited, synchronize, reopened] + +# Global permissions: +permissions: + # Allow read-only access to the repository contents: + contents: read + + # Allow write access to pull requests: + pull-requests: write + +# Workflow jobs: +jobs: + + # Define a job for checking the contributing guidelines acknowledgment... + check_acknowledgment: + + # Define a display name: + name: 'Check Contributing Guidelines Acknowledgment' + + # Define the type of virtual host machine: + runs-on: ubuntu-latest + + # Define the sequence of job steps... + steps: + # Checkout the repository: + - name: 'Checkout repository' + # Pin action to full length commit SHA + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + # Specify whether to remove untracked files before checking out the repository: + clean: true + + # Limit clone depth to the most recent commit: + fetch-depth: 1 + + # Specify whether to download Git-LFS files: + lfs: false + timeout-minutes: 10 + + # Check contributing guidelines acceptance: + - name: 'Check contributing guidelines acceptance' + env: + GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number || inputs.pull_request_number }} + run: | + . "$GITHUB_WORKSPACE/.github/workflows/scripts/check_contributing_guidelines_acceptance" $PR_NUMBER diff --git a/.github/workflows/scripts/check_contributing_guidelines_acceptance b/.github/workflows/scripts/check_contributing_guidelines_acceptance new file mode 100755 index 000000000000..e670f5f796f2 --- /dev/null +++ b/.github/workflows/scripts/check_contributing_guidelines_acceptance @@ -0,0 +1,118 @@ +#!/usr/bin/env bash +# +# @license Apache-2.0 +# +# Copyright (c) 2024 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Script to check if a pull request contains the checked contributing guidelines acknowledgment checkbox. +# +# Usage: check_contributing_guidelines PR_NUMBER +# +# Arguments: +# +# PR_NUMBER Pull request number. +# +# Environment variables: +# +# GITHUB_TOKEN GitHub token for authentication. + +# Ensure that the exit status of pipelines is non-zero in the event that at least one of the commands in a pipeline fails: +set -o pipefail + +# VARIABLES # + +# Get the pull request number: +pr_number="$1" + +# Set the repository name: +GITHUB_REPOSITORY="stdlib-js/stdlib" + +# Set the contributing guidelines link: +CONTRIBUTING_LINK="https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md" + +# FUNCTIONS # + +# Error handler. +# +# $1 - error status +on_error() { + echo 'ERROR: An error was encountered during execution.' >&2 + exit "$1" +} + +# Prints a success message. +print_success() { + echo 'Success!' >&2 +} + +# Main execution sequence. +main() { + echo "Checking contributing guidelines acknowledgment for PR #${pr_number}..." + + # Fetch the pull request body: + if ! pr_body=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" | \ + jq -r .body); then + echo "Failed to fetch PR body." + on_error 1 + fi + + # Check for the contributing guidelines checkbox: + if echo "${pr_body}" | grep -qE '^\s*-\s*\[x\]\s*Read,\s*understood,\s*and\s*followed\s*the\s*\[contributing\s*guidelines\]'; then + echo "Contributing guidelines acknowledged." + print_success + exit 0 + else + echo "Contributing guidelines not acknowledged." + + # Post a comment on the PR: + comment="Hello! Thank you for your contribution to stdlib. + +We noticed that the contributing guidelines acknowledgment is missing from your pull request. Here's what you need to do: + +1. Please read our [contributing guidelines][contributing]. +2. Update your pull request description to include this checked box: + + \`- [x] Read, understood, and followed the [contributing guidelines](https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md)\` + +This acknowledgment confirms that you've read the guidelines, which include: + +- The developer's certificate of origin +- Your agreement to license your contributions under the project's terms + +We can't review or accept contributions without this acknowledgment. + +Thank you for your understanding and cooperation. We look forward to reviewing your contribution! + +[contributing]: ${CONTRIBUTING_LINK}" + + if ! curl -s -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${pr_number}/comments" \ + -d "{\"body\":$(echo "$comment" | jq -R -s -c .)}"; then + echo "Failed to post comment on PR." + on_error 1 + fi + + exit 1 + fi +} + +# Set an error handler to print captured output and perform any clean-up tasks: +trap 'on_error' ERR + +# Run main: +main diff --git a/.github/workflows/scripts/lint_javascript_files b/.github/workflows/scripts/lint_javascript_files index 6526a6e5da7b..dd3a0875aa2f 100755 --- a/.github/workflows/scripts/lint_javascript_files +++ b/.github/workflows/scripts/lint_javascript_files @@ -54,35 +54,35 @@ files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '\.js$' | grep -v -e '/exam # Build native addons if present: packages=$(echo "${files}" | tr ' ' '\n' | sed 's/^lib\/node_modules\///g' | sed 's/\/lib\/.*//g' | sort | uniq) for pkg in ${packages}; do - if [ -f "lib/node_modules/${pkg}/binding.gyp" ]; then - NODE_ADDONS_PATTERN="${pkg}" make install-node-addons - fi + if [ -f "lib/node_modules/${pkg}/binding.gyp" ]; then + NODE_ADDONS_PATTERN="${pkg}" make install-node-addons + fi done if [[ -n "${files}" ]]; then - make lint-javascript-files FIX="${fix}" FILES="${files}" + make lint-javascript-files FIX="${fix}" FILES="${files}" fi # Lint JavaScript command-line interfaces... file=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '\.js$' | grep -E '/bin/cli$' | tr '\n' ' ' | sed 's/ $//') if [[ -n "${file}" ]]; then - make lint-javascript-files FIX="${fix}" FILES="${file}" + make lint-javascript-files FIX="${fix}" FILES="${file}" fi # Lint JavaScript example files: files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '/examples/.*\.js$' | tr '\n' ' ' | sed 's/ $//') if [[ -n "${files}" ]]; then - make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_examples_conf}" + make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_examples_conf}" fi # Lint JavaScript test files: files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '/test/.*\.js$' | tr '\n' ' ' | sed 's/ $//') if [[ -n "${files}" ]]; then - make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_tests_conf}" + make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_tests_conf}" fi # Lint JavaScript benchmark files: files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '/benchmark/.*\.js$' | tr '\n' ' ' | sed 's/ $//') if [[ -n "${files}" ]]; then - make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_benchmarks_conf}" + make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_benchmarks_conf}" fi diff --git a/.github/workflows/scripts/remove_related_packages b/.github/workflows/scripts/remove_related_packages index 4b7b41f33fde..37ea09dfd202 100755 --- a/.github/workflows/scripts/remove_related_packages +++ b/.github/workflows/scripts/remove_related_packages @@ -32,30 +32,30 @@ set -o pipefail for file in ${@}; do - if [[ $file == *README.md ]]; then - awk ' - BEGIN { print_mode = 1; in_related = 0; in_related_links = 0 } - /"; - in_related = 1; print_mode = 0; next - } - /<\/section>/ { - if (in_related) { in_related = 0; print_mode = 1 } - else { print } - next - } - // { - print; print ""; print ""; - in_related_links = 1; print_mode = 0; next - } - // { - if (in_related_links) { in_related_links = 0; print_mode = 1 } - else { print } - next - } - { if (print_mode == 1) print } - ' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file" - fi + if [[ $file == *README.md ]]; then + awk ' + BEGIN { print_mode = 1; in_related = 0; in_related_links = 0 } + /"; + in_related = 1; print_mode = 0; next + } + /<\/section>/ { + if (in_related) { in_related = 0; print_mode = 1 } + else { print } + next + } + // { + print; print ""; print ""; + in_related_links = 1; print_mode = 0; next + } + // { + if (in_related_links) { in_related_links = 0; print_mode = 1 } + else { print } + next + } + { if (print_mode == 1) print } + ' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file" + fi done echo "All files processed successfully." diff --git a/.github/workflows/scripts/track_fixmes b/.github/workflows/scripts/track_fixmes index 659b2251e905..2d92c4ad6c25 100644 --- a/.github/workflows/scripts/track_fixmes +++ b/.github/workflows/scripts/track_fixmes @@ -25,25 +25,25 @@ comment=" # Search for FIXME annotations in the codebase: for file in $(find bin dist docs tools etc examples lib test tools -type f); do - fixmes=$(grep -E -on "FIXME:" $file) || true - for fixme in $fixmes; do - if [ -n "$fixme" ]; then - # Since a maximum of 65,535 characters can be included in a GitHub comment body, we break out of the loop if the comment body would exceed this limit. - if [ $(( ${#comment} + ${#fixme} )) -gt 65535 ]; then - break - fi - lineNumber=$(echo $fixme | cut -d ":" -f 1) - lineContent=$(awk "NR==$lineNumber" $file) - lineContent=$(echo $lineContent | sed -e 's//\\-->/g') - if [ ${#lineContent} -gt 80 ]; then - lineContent=$(echo $lineContent | cut -c 1-80) - lineContent="$lineContent..." - continue - fi - comment="$comment + fixmes=$(grep -E -on "FIXME:" $file) || true + for fixme in $fixmes; do + if [ -n "$fixme" ]; then + # Since a maximum of 65,535 characters can be included in a GitHub comment body, we break out of the loop if the comment body would exceed this limit. + if [ $(( ${#comment} + ${#fixme} )) -gt 65535 ]; then + break + fi + lineNumber=$(echo $fixme | cut -d ":" -f 1) + lineContent=$(awk "NR==$lineNumber" $file) + lineContent=$(echo $lineContent | sed -e 's//\\-->/g') + if [ ${#lineContent} -gt 80 ]; then + lineContent=$(echo $lineContent | cut -c 1-80) + lineContent="$lineContent..." + continue + fi + comment="$comment - [$file#L$lineNumber](https://github.com/stdlib-js/stdlib/blob/develop/$file#L$lineNumber): $lineContent" - fi - done + fi + done done echo "$comment" diff --git a/.github/workflows/scripts/track_todos b/.github/workflows/scripts/track_todos index bb1b7fd5c037..3bdec5b5813c 100644 --- a/.github/workflows/scripts/track_todos +++ b/.github/workflows/scripts/track_todos @@ -25,25 +25,25 @@ comment=" # Search for TODO annotations in the codebase: for file in $(find bin dist docs tools etc examples lib test tools -type f); do - todos=$(grep -E -on "TODO:" $file) || true - for todo in $todos; do - if [ -n "$todo" ]; then - # Since a maximum of 65,535 characters can be included in a GitHub comment body, we break out of the loop if the comment body would exceed this limit. - if [ $(( ${#comment} + ${#todo} )) -gt 65535 ]; then - break - fi - lineNumber=$(echo $todo | cut -d ":" -f 1) - lineContent=$(awk "NR==$lineNumber" $file) - lineContent=$(echo $lineContent | sed -e 's//\\-->/g') - if [ ${#lineContent} -gt 80 ]; then - lineContent=$(echo $lineContent | cut -c 1-80) - lineContent="$lineContent..." - continue - fi - comment="$comment + todos=$(grep -E -on "TODO:" $file) || true + for todo in $todos; do + if [ -n "$todo" ]; then + # Since a maximum of 65,535 characters can be included in a GitHub comment body, we break out of the loop if the comment body would exceed this limit. + if [ $(( ${#comment} + ${#todo} )) -gt 65535 ]; then + break + fi + lineNumber=$(echo $todo | cut -d ":" -f 1) + lineContent=$(awk "NR==$lineNumber" $file) + lineContent=$(echo $lineContent | sed -e 's//\\-->/g') + if [ ${#lineContent} -gt 80 ]; then + lineContent=$(echo $lineContent | cut -c 1-80) + lineContent="$lineContent..." + continue + fi + comment="$comment - [$file#L$lineNumber](https://github.com/stdlib-js/stdlib/blob/develop/$file#L$lineNumber): $lineContent" - fi - done + fi + done done echo "$comment" diff --git a/.github/workflows/scripts/update_copyright_years b/.github/workflows/scripts/update_copyright_years index 02d09c5ec72d..41037f940c81 100755 --- a/.github/workflows/scripts/update_copyright_years +++ b/.github/workflows/scripts/update_copyright_years @@ -29,18 +29,18 @@ current_year=$(date +"%Y") for file in ${@}; do - if [[ ! -f "$file" ]]; then - echo "File not found: $file" - continue - fi - echo "Updating copyright notice in $file..." - if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS, where sed requires '' after -i to specify no backup... - sed -i '' "s/Copyright (c) [0-9]\{4\} The Stdlib Authors./Copyright \(c\) $current_year The Stdlib Authors./g" "$file" - else - # Linux and others, no '' required... - sed -i "s/Copyright (c) [0-9]\{4\} The Stdlib Authors./Copyright \(c\) $current_year The Stdlib Authors./g" "$file" - fi + if [[ ! -f "$file" ]]; then + echo "File not found: $file" + continue + fi + echo "Updating copyright notice in $file..." + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS, where sed requires '' after -i to specify no backup... + sed -i '' "s/Copyright (c) [0-9]\{4\} The Stdlib Authors./Copyright \(c\) $current_year The Stdlib Authors./g" "$file" + else + # Linux and others, no '' required... + sed -i "s/Copyright (c) [0-9]\{4\} The Stdlib Authors./Copyright \(c\) $current_year The Stdlib Authors./g" "$file" + fi done echo "Copyright notices updated to $current_year." diff --git a/lib/node_modules/@stdlib/math/base/special/fresnel/benchmark/c/native/benchmark.c b/lib/node_modules/@stdlib/math/base/special/fresnel/benchmark/c/native/benchmark.c index 2da231964e91..43d699388deb 100644 --- a/lib/node_modules/@stdlib/math/base/special/fresnel/benchmark/c/native/benchmark.c +++ b/lib/node_modules/@stdlib/math/base/special/fresnel/benchmark/c/native/benchmark.c @@ -101,13 +101,13 @@ static double benchmark( void ) { for ( i = 0; i < ITERATIONS; i++ ) { x = ( 20.0 * rand_double() ) - 10.0; stdlib_base_fresnel( x, &S, &C ); - if ( C != C || S != S) { + if ( C != C || S != S ) { printf( "unexpected results\n" ); break; } } elapsed = tic() - t; - if ( C != C || S != S) { + if ( C != C || S != S ) { printf( "unexpected results\n" ); } return elapsed; diff --git a/lib/node_modules/@stdlib/math/base/special/fresnel/lib/native.js b/lib/node_modules/@stdlib/math/base/special/fresnel/lib/native.js index f65d25565adf..864408e813f5 100644 --- a/lib/node_modules/@stdlib/math/base/special/fresnel/lib/native.js +++ b/lib/node_modules/@stdlib/math/base/special/fresnel/lib/native.js @@ -31,7 +31,7 @@ var addon = require( './../src/addon.node' ); * * @private * @param {number} x - input value -* @returns {Array} S(x) and C(x) +* @returns {Float64Array} S(x) and C(x) * * @example * var v = fresnel( 0.0 ); diff --git a/lib/node_modules/@stdlib/math/base/special/powm1/lib/main.js b/lib/node_modules/@stdlib/math/base/special/powm1/lib/main.js index 370c03a8b883..36ee0f1f48a4 100644 --- a/lib/node_modules/@stdlib/math/base/special/powm1/lib/main.js +++ b/lib/node_modules/@stdlib/math/base/special/powm1/lib/main.js @@ -121,7 +121,7 @@ function powm1( b, x ) { } result = pow( b, x ) - 1.0; if ( isinfinite( result ) || isnan( result ) ) { - return 0.0 / 0.0; // NaN + return NaN; } return result; } diff --git a/lib/node_modules/@stdlib/math/base/special/powm1/test/test.js b/lib/node_modules/@stdlib/math/base/special/powm1/test/test.js index 011a978941b3..ff2febeb23b4 100644 --- a/lib/node_modules/@stdlib/math/base/special/powm1/test/test.js +++ b/lib/node_modules/@stdlib/math/base/special/powm1/test/test.js @@ -141,3 +141,9 @@ tape( 'the function returns `NaN` if provided a `NaN` for the base', function te t.equal( isnan( y ), true, 'returns NaN' ); t.end(); }); + +tape( 'the function returns `NaN` if provided a `1e308` for the base and `2.0` for the exponent', function test( t ) { + var y = powm1( 1e308, 2.0 ); + t.equal( isnan( y ), true, 'returns expected value' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/math/base/special/powm1/test/test.native.js b/lib/node_modules/@stdlib/math/base/special/powm1/test/test.native.js index 9e13e924aa9f..f360ec474011 100644 --- a/lib/node_modules/@stdlib/math/base/special/powm1/test/test.native.js +++ b/lib/node_modules/@stdlib/math/base/special/powm1/test/test.native.js @@ -150,3 +150,9 @@ tape( 'the function returns `NaN` if provided a `NaN` for the base', opts, funct t.equal( isnan( y ), true, 'returns expected value' ); t.end(); }); + +tape( 'the function returns `NaN` if provided a `1e308` for the base and `2.0` for the exponent', opts, function test( t ) { + var y = powm1( 1e308, 2.0 ); + t.equal( isnan( y ), true, 'returns expected value' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/math/base/special/sincos/src/main.c b/lib/node_modules/@stdlib/math/base/special/sincos/src/main.c index f5bf17ad1595..1dc08528ce5c 100644 --- a/lib/node_modules/@stdlib/math/base/special/sincos/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/sincos/src/main.c @@ -125,7 +125,8 @@ void stdlib_base_sincos( const double x, double* sine, double* cosine ) { *cosine = 0.0; } } - return kernelSincos( x, 0.0, sine, cosine ); + kernelSincos( x, 0.0, sine, cosine ); + return; } // Case: x is NaN or infinity diff --git a/lib/node_modules/@stdlib/math/base/special/sincospi/lib/native.js b/lib/node_modules/@stdlib/math/base/special/sincospi/lib/native.js index 2ac0807fca57..f32e21d86068 100644 --- a/lib/node_modules/@stdlib/math/base/special/sincospi/lib/native.js +++ b/lib/node_modules/@stdlib/math/base/special/sincospi/lib/native.js @@ -31,7 +31,7 @@ var addon = require( './../src/addon.node' ); * * @private * @param {number} x - input value -* @returns {Array} two-element array containing sin(πx) and cos(πx) +* @returns {Float64Array} two-element array containing sin(πx) and cos(πx) * * @example * var v = sincospi( 0.0 ); diff --git a/lib/node_modules/@stdlib/math/base/special/sincospi/src/main.c b/lib/node_modules/@stdlib/math/base/special/sincospi/src/main.c index 00f5c2101ae3..fd8be3d48632 100644 --- a/lib/node_modules/@stdlib/math/base/special/sincospi/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/sincospi/src/main.c @@ -25,7 +25,6 @@ #include "stdlib/math/base/assert/is_infinite.h" #include "stdlib/math/base/assert/is_nan.h" #include "stdlib/constants/float64/pi.h" -#include /** * Simultaneously computes the sine and cosine of a number times π. diff --git a/tools/make/lib/git/Makefile b/tools/make/lib/git/Makefile index edfc20a3f0c4..5902a43903e1 100644 --- a/tools/make/lib/git/Makefile +++ b/tools/make/lib/git/Makefile @@ -22,6 +22,7 @@ include $(TOOLS_MAKE_LIB_DIR)/git/commitizen.mk include $(TOOLS_MAKE_LIB_DIR)/git/notes.mk + # RULES # #/ diff --git a/tools/make/lib/git/notes.mk b/tools/make/lib/git/notes.mk index 2caec8d1da36..db7c10115946 100644 --- a/tools/make/lib/git/notes.mk +++ b/tools/make/lib/git/notes.mk @@ -21,6 +21,7 @@ # Define the directory containing git notes: GIT_NOTES_DIR ?= $(ROOT_DIR)/docs/git-notes + # RULES # #/ @@ -28,13 +29,13 @@ GIT_NOTES_DIR ?= $(ROOT_DIR)/docs/git-notes # # ## Notes # -# - This rule applies git notes where the file name (without the .txt extension) is the git commit hash and the content is the note. +# - This rule applies Git notes where the file name (without the .txt extension) is the Git commit hash and the content is the note. # # @example # make apply-git-notes #/ apply-git-notes: - $(QUIET) echo "Applying git notes..." + $(QUIET) echo "Applying Git notes..." $(QUIET) for note in $(GIT_NOTES_DIR)/*.txt; do \ if [ -f "$$note" ]; then \ commit_hash=$$(basename "$$note" .txt); \