diff --git a/.github/workflows/completion.yml b/.github/workflows/completion.yml new file mode 100644 index 0000000..e3de9b6 --- /dev/null +++ b/.github/workflows/completion.yml @@ -0,0 +1,34 @@ +name: completion + +# The completion scripts run inside shells no unit test starts: check each one for real. +on: + pull_request: + paths: ['src/completion.ts', 'src/cli.tsx', 'scripts/check-completion.sh', '.github/workflows/completion.yml'] + push: + branches: [main] + paths: ['src/completion.ts', 'src/cli.tsx', 'scripts/check-completion.sh', '.github/workflows/completion.yml'] + workflow_dispatch: + +permissions: + contents: read + +jobs: + shells: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + # bash and PowerShell come with the runner image. + - run: sudo apt-get update -q && sudo apt-get install -y -q zsh fish + - run: npm ci && npm run build && npm link + - name: Shell versions + run: | + bash --version | head -1 + zsh --version + fish --version + pwsh -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' + - run: bash scripts/check-completion.sh diff --git a/scripts/check-completion.sh b/scripts/check-completion.sh new file mode 100755 index 0000000..8ecc6a5 --- /dev/null +++ b/scripts/check-completion.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Checks the shell completion scripts: syntax, then a real completion in each shell. +# Needs skills-atlas on PATH (npm run build && npm link) and bash, zsh, fish, pwsh. +# Usage: scripts/check-completion.sh [shell...] (default: all four) +set -u +dir=$(mktemp -d) +failed=0 +pass() { echo "ok $1"; } +fail() { echo "FAIL $1"; failed=1; } +# `skills-atlas ins` must offer `install`. +expect_install() { grep -qx 'install' && pass "$1" || fail "$1"; } + +for shell in "${@:-bash zsh fish powershell}"; do + for sh in $shell; do + file="$dir/completion.$sh" + skills-atlas completion "$sh" > "$file" || { fail "$sh: script not generated"; continue; } + case "$sh" in + bash) + bash -n "$file" && pass "bash: syntax" || fail "bash: syntax" + bash -c "source '$file'; COMP_LINE='skills-atlas ins'; COMP_POINT=\${#COMP_LINE}; _skills_atlas; printf '%s\n' \"\${COMPREPLY[@]}\"" \ + | expect_install "bash: completes 'skills-atlas ins'" + ;; + zsh) + zsh -n "$file" && pass "zsh: syntax" || fail "zsh: syntax" + # compdef and compadd belong to the completion system: stand-ins print what would be offered. + zsh -c "compdef() { :; }; compadd() { [[ \$1 == -- ]] && shift; print -l -- \"\$@\"; }; source '$file'; words=(skills-atlas ins); CURRENT=2; _skills_atlas" \ + | expect_install "zsh: completes 'skills-atlas ins'" + ;; + fish) + fish -n "$file" && pass "fish: syntax" || fail "fish: syntax" + fish -c "source '$file'; complete -C 'skills-atlas ins'" | cut -f1 \ + | expect_install "fish: completes 'skills-atlas ins'" + ;; + powershell) + pwsh -NoProfile -Command "\$e = \$null; [void][System.Management.Automation.Language.Parser]::ParseFile('$file', [ref]\$null, [ref]\$e); if (\$e.Count) { \$e; exit 1 }" \ + && pass "powershell: syntax" || fail "powershell: syntax" + pwsh -NoProfile -Command ". '$file'; (TabExpansion2 -inputScript 'skills-atlas ins' -cursorColumn 16).CompletionMatches | ForEach-Object CompletionText" \ + | tr -d '\r' | expect_install "powershell: completes 'skills-atlas ins'" + ;; + *) fail "$sh: unknown shell" ;; + esac + done +done +rm -rf "$dir" +exit $failed