Skip to content

feat(useBooleanState): support lazy initialization for initial value … #1362

feat(useBooleanState): support lazy initialization for initial value …

feat(useBooleanState): support lazy initialization for initial value … #1362

Workflow file for this run

name: Integration
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
quality:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
command: ['format', 'lint', 'type', 'docs', 'skill', 'codemod']
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Run test:${{ matrix.command }}
run: yarn run test:${{ matrix.command }}
spec:
name: spec (node ${{ matrix.node }})
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
node: ['22', '24']
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Run test:coverage
run: yarn run test:coverage
- name: Upload coverage reports to Codecov
if: ${{ matrix.node == '24' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/react-simplikit/coverage/coverage-final.json
spec-compiled:
name: spec (react compiler compiled)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Run test:compiled
run: yarn run test:compiled
check-changes:
runs-on: ubuntu-latest
outputs:
changed: ${{ steps.filter.outputs.changed }}
changed_files: ${{ steps.filter.outputs.changed_files }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Check for changes in .ts and .tsx files
id: filter
uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
with:
list-files: shell
filters: |
changed:
- added|modified:
- 'packages/*/src/components/**/!(index|*.spec|*.test).ts'
- 'packages/*/src/components/**/!(*.spec|*.test).tsx'
- 'packages/*/src/hooks/**/!(index|*.spec|*.test).ts'
- 'packages/*/src/hooks/**/!(*.spec|*.test).tsx'
- 'packages/*/src/utils/**/!(index|*.spec|*.test).ts'
- 'packages/*/src/utils/**/!(*.spec|*.test).tsx'
verify-test:
runs-on: ubuntu-latest
needs: check-changes
if: ${{ needs.check-changes.outputs.changed == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Run tests and generate coverage
run: yarn run test:coverage
- name: Verify test coverage
run: |
changed_files="${{ needs.check-changes.outputs.changed_files }}"
for file in $changed_files; do
package_dir="${file%%/src/*}"
coverage_file="$package_dir/coverage/coverage-final.json"
if [ ! -f "$coverage_file" ]; then
echo "Coverage file not found: $coverage_file"
exit 1
fi
dir_name=$(basename $(dirname "$file"))
base_name=$(basename $dir_name)
test_file=""
for candidate in "$base_name.spec.ts" "$base_name.spec.tsx" "$base_name.test.ts" "$base_name.test.tsx"; do
if [ -f "$(dirname "$file")/$candidate" ]; then
test_file="$(dirname "$file")/$candidate"
break
fi
done
if [ -z "$test_file" ]; then
echo "Test file missing for $base_name"
exit 1
fi
# Debugging: Print the file path
echo "Checking coverage for: $file"
# Calculate coverage percentage for each matching entry
total_lines=0
covered_lines=0
# Iterate over each matching coverage data entry
for entry in $(jq -c --arg base_name "$base_name" '. | to_entries[] | select(.key | contains($base_name)) | .value' "$coverage_file"); do
entry_total_lines=$(echo "$entry" | jq '.s | length')
entry_covered_lines=$(echo "$entry" | jq '[.s[] | select(. > 0)] | length')
# Accumulate total and covered lines
total_lines=$((total_lines + entry_total_lines))
covered_lines=$((covered_lines + entry_covered_lines))
done
if [ "$total_lines" -eq 0 ]; then
echo "No coverage data found for $base_name"
exit 1
fi
# Calculate overall coverage percentage
coverage=$(echo "scale=2; ($covered_lines / $total_lines) * 100" | bc)
# Debugging: Print accumulated total and covered lines
echo "Total lines: $total_lines, Covered lines: $covered_lines"
echo "Coverage: $coverage%"
# Correct the condition to check if coverage is less than 100
if (( $(echo "$coverage < 100" | bc -l) )); then
echo "Test coverage for $base_name is not 100%: $coverage%"
exit 1
fi
done
verify-jsdoc:
runs-on: ubuntu-latest
needs: check-changes
if: ${{ needs.check-changes.outputs.changed == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check for JSDoc comments
run: |
for file in ${{ needs.check-changes.outputs.changed_files }}; do
dir_name=$(basename $(dirname "$file"))
base_name=$(basename $dir_name)
implementation="$(dirname "$file")/$base_name.ts"
if [ ! -f "$implementation" ]; then
implementation="$(dirname "$file")/$base_name.tsx"
if [ ! -f "$implementation" ]; then
echo "Implementation missing for $file"
exit 1
fi
fi
if ! grep -q "/\*\*" "$implementation"; then
echo "JSDoc comments missing in $implementation"
exit 1
fi
if ! grep -q "@description" "$implementation"; then
echo "@description tag missing in $implementation"
exit 1
fi
if ! grep -q "@example" "$implementation"; then
echo "@example tag missing in $implementation"
exit 1
fi
done
verify-jsdoc-structure:
runs-on: ubuntu-latest
needs: check-changes
if: ${{ needs.check-changes.outputs.changed == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Check JSDoc structure
run: |
for file in ${{ needs.check-changes.outputs.changed_files }}; do
directory=$(basename "$(dirname "$file")")
filename=$(basename $file)
filename="${filename%%.*}"
if [ "$directory" != "$filename" ]; then
continue
fi
if ! grep -e "@description" "$file"; then
echo "@description tag missing in $file"
exit 1
fi
if ! grep -e "@example" "$file"; then
echo "@example tag missing in $file"
exit 1
fi
if grep -q "@param" "$file"; then
if ! grep -q "@param {.*}" "$file"; then
echo "Parameter type missing in @param tag in $file"
exit 1
fi
# A bracketed optional parameter may carry a default that contains spaces
# (`[initialState=new Set()]`), so the name is matched as either form.
if ! grep -qE "@param \{.*\} (\[[^]]*\]|[^ -]*) - .+" "$file"; then
echo "Parameter description missing in @param tag in $file"
exit 1
fi
fi
if grep -q "@returns" "$file"; then
if grep -q "@returns {\\[.*:.*\\]}" "$file"; then
tuple_vars=$(grep "@returns {\\[.*\\]}" "$file" | sed -E 's/.*\[(.*)\].*/\1/' | tr ',' '\n' | sed 's/^ //' | sed -E 's/([^:]): (.+)$/\1 \`\2\`/')
while read -r var_type; do
if ! grep -qe "- $var_type - .*;" "$file"; then
echo "Missing or invalid description for tuple member with [$var_type] in $file"
exit 1
fi
done <<< "$tuple_vars"
else
if ! grep -q "@returns {.*}" "$file"; then
echo "Return type missing in @returns tag in $file"
exit 1
fi
fi
fi
done
verify-exports:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check exports
run: |
IMPL_DIRS=("components" "hooks" "utils")
ERROR_LOG=""
HAS_ERROR=0
FOUND=0
# Every implementation must be exported from the package root barrel:
# it is the only public entry.
for pkg in packages/*/; do
ROOT_INDEX="${pkg}src/index.ts"
if [ ! -f "$ROOT_INDEX" ]; then
continue
fi
for dir in "${IMPL_DIRS[@]}"; do
for impl_dir in ${pkg}src/$dir/*/; do
if [ ! -d "$impl_dir" ]; then
continue
fi
impl_name=$(basename "$impl_dir")
impl_index="$impl_dir/index.ts"
impl_file=""
if [ -f "$impl_dir$impl_name.ts" ]; then
impl_file="$impl_name.ts"
elif [ -f "$impl_dir$impl_name.tsx" ]; then
impl_file="$impl_name.tsx"
else
ERROR_LOG+="❌ Implementation file not found for $impl_name\n"
HAS_ERROR=1
continue
fi
FOUND=$((FOUND + 1))
if [ ! -f "$impl_index" ]; then
ERROR_LOG+="❌ Missing index.ts in $impl_dir\n"
HAS_ERROR=1
continue
fi
# `from` alone, not `export.*from`: prettier splits long re-exports
# across lines, leaving `export {` and `} from './x.ts'` on different lines
if ! grep -q "from.*['\"]\./$impl_file['\"]" "$impl_index"; then
ERROR_LOG+="❌ $impl_name is not exported in $impl_index\n"
HAS_ERROR=1
fi
relative_path="./$dir/$impl_name/index.ts"
if ! grep -q "from.*['\"]$relative_path['\"]" "$ROOT_INDEX"; then
ERROR_LOG+="❌ $impl_name is not exported in $ROOT_INDEX\n"
HAS_ERROR=1
fi
done
done
done
if [ "$FOUND" -eq 0 ]; then
echo "🚨 Scanned 0 implementations — the paths in this check no longer match the repository layout."
exit 1
fi
echo "Scanned $FOUND implementations."
if [ $HAS_ERROR -eq 1 ]; then
echo -e "\n🚨 Export Validation Errors:\n"
echo -e "$ERROR_LOG"
echo -e "\nPlease fix the above export issues."
exit 1
else
echo "✅ All exports are valid!"
fi
verify-compiler:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Verify React Compiler compatibility
run: yarn verify:compiler
verify-pack:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Verify packaging
run: yarn verify:pack
verify-examples:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enable Corepack
run: corepack enable
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Build and pack
# Naming the shell adds `-o pipefail`, which the default `bash -e {0}` lacks:
# without it a failed `npm pack` is masked by `tail` exiting 0, and the empty
# tarball path only surfaces several steps later as a resolution error.
# Scoped to this step -- `release.yml` and `verify-jsdoc` pipe through `grep`,
# where a no-match exit 1 is expected and pipefail would break them.
shell: bash
run: |
yarn workspaces foreach -Apt --include 'packages/*' run build
LIB_TGZ=$(cd packages/react-simplikit && npm pack --pack-destination "$RUNNER_TEMP" | tail -1)
echo "LIB_TGZ=$RUNNER_TEMP/$LIB_TGZ" >> "$GITHUB_ENV"
- name: Point examples at tarballs
run: |
for example in examples/with-vite examples/with-nextjs; do
jq --arg lib "file:$LIB_TGZ" \
'.dependencies |= with_entries(
if .key == "react-simplikit" then .value = $lib
else . end)' \
"$example/package.json" > "$example/package.json.tmp"
mv "$example/package.json.tmp" "$example/package.json"
done
YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install
- name: Build examples against tarballs
run: |
yarn workspace with-vite run build
yarn workspace with-nextjs run build