Skip to content

add to docs

add to docs #1

Workflow file for this run

name: NPM Tests

Check failure on line 1 in .github/workflows/tests-npm.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/tests-npm.yml

Invalid workflow file

(Line: 17, Col: 9): Unexpected value 'pull_ghcr'
on:
workflow_call:
inputs:
env_vars:
required: false
type: string
default: "{}"
npm_build_command:
required: false
type: string
default: ""
pre_test_command:
required: false
type: string
default: ""
pull_ghcr:
required: false
type: boolean
default: false
docker_compose_file:
required: false
type: string
default: docker-compose.yml
node_version:
required: false
type: string
default: 24.x
tests:
required: false
type: string
default: '["test:unit", "test:integration"]'
coverage:
required: false
type: boolean
default: true
coverage_config_json:
required: false
type: string
default: ""
jobs:
setup:
permissions:
contents: read
name: Setup branch matrix
runs-on: ubuntu-latest
outputs:
branches: ${{ steps.set-branches.outputs.branches }}
is-main: ${{ steps.check-branch.outputs.is-main }}
artifact-prefix: ${{ steps.set-prefix.outputs.prefix }}
steps:
- name: Check if running on main
id: check-branch
run: |
CURRENT_BRANCH="${{ github.head_ref || github.ref_name }}"
if [ "$CURRENT_BRANCH" = "main" ]; then
echo "is-main=true" >> $GITHUB_OUTPUT
else
echo "is-main=false" >> $GITHUB_OUTPUT
fi
- name: Set branch matrix
id: set-branches
run: |
CURRENT_BRANCH="${{ github.head_ref || github.ref_name }}"
if [ "${{ inputs.coverage }}" = "false" ] || [ "$CURRENT_BRANCH" = "main" ]; then
BRANCHES="[\"$CURRENT_BRANCH\"]"
else
BRANCHES="[\"$CURRENT_BRANCH\", \"main\"]"
fi
echo "branches=$BRANCHES" >> "$GITHUB_OUTPUT"
- name: Generate artifact prefix
id: set-prefix
run: echo "prefix=$(uuidgen)" >> $GITHUB_OUTPUT
tests:
permissions:
contents: read
packages: read
name: Run tests - ${{ matrix.command }} - ${{ matrix.branch }}
needs: setup
strategy:
fail-fast: false
matrix:
command: ${{ fromJson(inputs.tests) }}
branch: ${{ fromJson(needs.setup.outputs.branches) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ matrix.branch }}
- name: Set environment variables from JSON
env:
ENV_VARS_JSON: "${{ inputs.env_vars }}"
run: |
echo "Parsing JSON environment variables..."
echo "$ENV_VARS_JSON" | jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' >> $GITHUB_ENV
- uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node_version }}
- name: Cache Node.js modules
uses: actions/cache@v5
with:
path: ~/.npm
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.OS }}-node-
${{ runner.OS }}-
- name: Install Packages
run: npm ci
- name: Build
run: ${{ inputs.npm_build_command }}
if: inputs.npm_build_command != ''
- name: Create environment file
run: touch .env
- name: Login to GitHub Container Registry
if: ${{ inputs.pull_ghcr == true }}
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup dependencies
run: docker compose -f ${{ inputs.docker_compose_file }} up -d --quiet-pull
if: inputs.docker_compose_file != ''
- name: Sleep
uses: kibertoad/wait-action@1.0.1
with:
time: "30s"
if: inputs.docker_compose_file != ''
- name: Run pre-test command
run: ${{ inputs.pre_test_command }}
if: inputs.pre_test_command != ''
- name: Run tests with coverage
run: npx c8 --temp-directory coverage/tmp npm run ${{ matrix.command }}
if: inputs.coverage
- name: Run tests without coverage
run: npm run ${{ matrix.command }}
if: ${{ !inputs.coverage }}
- name: Set artifact name
id: artifact-name
run: |
COMMAND_SAFE=$(echo "${{ matrix.command }}" | sed 's/[:\";<>|*?\/\\ \r\n]/-/g')
if [ "${{ needs.setup.outputs.is-main }}" = "true" ]; then
echo "name=${{ needs.setup.outputs.artifact-prefix }}-coverage-current-$COMMAND_SAFE" >> $GITHUB_OUTPUT
else
echo "name=${{ needs.setup.outputs.artifact-prefix }}-coverage-${{ matrix.branch == 'main' && 'main' || 'current' }}-$COMMAND_SAFE" >> $GITHUB_OUTPUT
fi
if: inputs.coverage
- name: Upload coverage JSON summary
uses: actions/upload-artifact@v6
with:
name: ${{ steps.artifact-name.outputs.name }}
path: coverage/tmp
if: inputs.coverage
coverage:
permissions:
contents: read
pull-requests: write
name: Coverage
runs-on: ubuntu-latest
needs: [tests, setup]
if: inputs.coverage
env:
COVERAGE_CURRENT_DIR: coverage
COVERAGE_MAIN_DIR: coverage-main
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node_version }}
- name: Setup c8 config
run: |
if [ -n "${{ inputs.coverage_config_json }}" ]; then
echo "Copying repo config '${{ inputs.coverage_config_json }}' to .c8rc.workflow.json"
cp ${{ inputs.coverage_config_json }} .c8rc.workflow.json
else
echo "Using default .c8rc.workflow.json"
cat > .c8rc.workflow.json << 'EOF'
{
"lines": 50,
"branches": 0,
"functions": 0,
"statements": 0,
"exclude": [
"coverage/**",
"packages/*/test{,s}/**",
"**/*.d.ts",
"test{,s}/**",
"test{,-*}.js",
"**/*{.,-}test.js",
"**/__tests__/**",
"**/node_modules/**",
"**/babel.config.js",
"**/*.tsx"
]
}
EOF
fi
- name: Download current branch coverage summaries
uses: actions/download-artifact@v7
with:
path: ${{ env.COVERAGE_CURRENT_DIR }}/tmp
pattern: ${{ needs.setup.outputs.artifact-prefix }}-coverage-current-*
merge-multiple: true
- name: Download main branch coverage summaries
uses: actions/download-artifact@v7
with:
path: ${{ env.COVERAGE_MAIN_DIR }}/tmp
pattern: ${{ needs.setup.outputs.artifact-prefix }}-coverage-main-*
merge-multiple: true
if: needs.setup.outputs.is-main == 'false'
- name: Generate reports
run: npx c8 --config .c8rc.workflow.json --temp-directory ${{ env.COVERAGE_CURRENT_DIR }}/tmp --reports-dir ${{ env.COVERAGE_CURRENT_DIR }} report --reporter=html --reporter=json-summary --reporter=json
- name: Generate main branch reports
if: needs.setup.outputs.is-main == 'false'
run: npx c8 --config .c8rc.workflow.json --temp-directory ${{ env.COVERAGE_MAIN_DIR }}/tmp --reports-dir ${{ env.COVERAGE_MAIN_DIR }} report --reporter=json-summary --reporter=json
- name: Setup vite config if none exists
run: |
if ! compgen -G "{vite,vitest}.config.{ts,mts,cts,js,mjs,cjs}" > /dev/null; then
echo "No vite config found, creating minimal vite.config.js"
echo "export default {}" > vite.config.js
else
echo "Vite config found"
fi
- name: Pretty coverage summary
uses: davelosert/vitest-coverage-report-action@v2
with:
file-coverage-mode: all
json-summary-compare-path: ${{ needs.setup.outputs.is-main == 'false' && format('{0}/coverage-summary.json', env.COVERAGE_MAIN_DIR) || '' }}
- name: Upload reports for current branch
uses: actions/upload-artifact@v6
with:
name: ${{ needs.setup.outputs.artifact-prefix }}-coverage-current-all
path: |
${{ env.COVERAGE_CURRENT_DIR }}/**
!${{ env.COVERAGE_CURRENT_DIR }}/tmp/**
- name: Fail if under thresholds
run: npx c8 --config .c8rc.workflow.json --temp-directory ${{ env.COVERAGE_CURRENT_DIR }}/tmp check-coverage