Fail fast when pvesm is unavailable #104
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Verify split files | |
| # lib/tools.func, ui/build-ui.func and api/api.func are loaders whose | |
| # implementations sit beside them. A split can silently lose a function -- most | |
| # easily by cutting through a heredoc that contains a column-0 function | |
| # definition, which looks like a definition but is payload. That only surfaces | |
| # on a user's host at install time, so it is checked here instead. | |
| # | |
| # The same applies to the prefetch lists in core/build.func and | |
| # lxc/install.func: a .func missing from one still works, it just costs a round | |
| # trip nobody would notice. So they are checked, not trusted. | |
| on: | |
| pull_request: | |
| paths: | |
| - "core/**" | |
| - "lxc/**" | |
| - "host/**" | |
| - "api/**" | |
| - "lib/**" | |
| - "ui/**" | |
| - "vm/**" | |
| - "pve/**" | |
| - "incus/**" | |
| push: | |
| branches: [main] | |
| paths: | |
| - "core/**" | |
| - "lxc/**" | |
| - "host/**" | |
| - "api/**" | |
| - "lib/**" | |
| - "ui/**" | |
| - "vm/**" | |
| - "pve/**" | |
| - "incus/**" | |
| workflow_dispatch: | |
| env: | |
| ENGINE_DIRS: core lxc host api lib ui vm pve incus | |
| jobs: | |
| verify: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Every part parses | |
| run: | | |
| set -euo pipefail | |
| fail=0 | |
| while IFS= read -r f; do | |
| bash -n "$f" || { echo "::error file=$f::syntax error"; fail=1; } | |
| done < <(find $ENGINE_DIRS -name '*.func' -type f) | |
| exit $fail | |
| - name: Prefetch lists cover every engine file | |
| run: | | |
| set -euo pipefail | |
| fail=0 | |
| mapfile -t on_disk < <(find $ENGINE_DIRS -name '*.func' -type f | sort) | |
| mapfile -t listed < <( | |
| sed -n '/^_CS_ENGINE_FILES=(/,/^)/p' core/build.func | | |
| tr -s '[:space:]' '\n' | grep -E '\.func$' | sort | |
| ) | |
| for f in "${on_disk[@]}"; do | |
| # build.func is the file doing the fetching; it is already loaded. | |
| [[ "$f" == "core/build.func" ]] && continue | |
| printf '%s\n' "${listed[@]}" | grep -qxF "$f" || { | |
| echo "::error file=core/build.func::$f is missing from _CS_ENGINE_FILES" | |
| fail=1 | |
| } | |
| done | |
| for f in "${listed[@]}"; do | |
| [[ -f "$f" ]] || { | |
| echo "::error file=core/build.func::_CS_ENGINE_FILES lists $f, which does not exist" | |
| fail=1 | |
| } | |
| done | |
| # install.func fetches the subset a container needs. | |
| mapfile -t ct_listed < <( | |
| sed -n '/^_CS_CT_ENGINE_FILES=(/,/^)/p' lxc/install.func | | |
| tr -s '[:space:]' '\n' | grep -E '\.func$' | sort | |
| ) | |
| for f in "${ct_listed[@]}"; do | |
| [[ -f "$f" ]] || { | |
| echo "::error file=lxc/install.func::_CS_CT_ENGINE_FILES lists $f, which does not exist" | |
| fail=1 | |
| } | |
| done | |
| for f in lib/*.func; do | |
| printf '%s\n' "${ct_listed[@]}" | grep -qxF "$f" || { | |
| echo "::error file=lxc/install.func::$f is missing from _CS_CT_ENGINE_FILES" | |
| fail=1 | |
| } | |
| done | |
| echo "engine: ${#listed[@]} of ${#on_disk[@]} listed, container: ${#ct_listed[@]}" | |
| exit $fail | |
| - name: Each loader still defines its whole API | |
| run: | | |
| set -euo pipefail | |
| check() { | |
| local loader="$1" snapshot="$2" | |
| bash -c ' | |
| COMMUNITY_SCRIPTS_CORE_DIR="$PWD" | |
| _cs_source_func() { source "$COMMUNITY_SCRIPTS_CORE_DIR/$1"; } | |
| source "'"$loader"'" >/dev/null 2>&1 | |
| declare -F | awk "{print \$3}" | | |
| grep -vE "^(_cs_source_func|_tools_source_part|_build_ui_source|_api_source_part)$" | sort | |
| ' > /tmp/actual.txt | |
| if ! diff -u "$snapshot" /tmp/actual.txt; then | |
| echo "::error::$loader exports a different set of functions." | |
| echo "Intentional? Regenerate $snapshot in the same PR." | |
| return 1 | |
| fi | |
| echo "$loader: $(wc -l < /tmp/actual.txt) functions, unchanged" | |
| } | |
| fail=0 | |
| check lib/tools.func lib/API.txt || fail=1 | |
| check ui/build-ui.func ui/API.txt || fail=1 | |
| check api/api.func api/API.txt || fail=1 | |
| exit $fail |