Skip to content

4.0.1

4.0.1 #19

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
lint:
name: Lint shell + validate manifests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Syntax-check all shell scripts (bash -n)
run: |
set -euo pipefail
fail=0
while IFS= read -r -d '' f; do
if bash -n "$f"; then echo "ok $f"; else echo "FAIL $f"; fail=1; fi
done < <(find . -name '*.sh' -not -path './.git/*' -print0)
exit "$fail"
- name: ShellCheck
run: |
sudo apt-get update -qq && sudo apt-get install -y shellcheck
shellcheck -S warning $(find plugins -name '*.sh')
- name: Validate JSON manifests
run: |
for f in .claude-plugin/marketplace.json \
plugins/xcloud/.claude-plugin/plugin.json \
.clawhubinfo.json; do
python3 -c "import json,sys; json.load(open('$f')); print('valid', '$f')"
done
- name: Version consistency across manifests
run: |
python3 - <<'PY'
import json, re, sys
plugin = json.load(open('plugins/xcloud/.claude-plugin/plugin.json'))['version']
market = json.load(open('.claude-plugin/marketplace.json'))['plugins'][0]['version']
clawhub = json.load(open('.clawhubinfo.json'))['version']
root = re.search(r'^version:\s*(\S+)', open('SKILL.md').read(), re.M).group(1)
versions = {'plugin.json': plugin, 'marketplace.json': market,
'.clawhubinfo.json': clawhub, 'SKILL.md': root}
print(versions)
sys.exit(0 if len(set(versions.values())) == 1 else 1)
PY
- name: Offline wrapper tests (URL hardening, token redaction, stdin bodies)
run: bash plugins/xcloud/scripts/tests/wrapper-test.sh
- name: Offline JSON-safety tests (legacy src builders)
run: |
sudo apt-get install -y jq >/dev/null 2>&1 || true
bash src/tests/json-safety-test.sh
- name: Script safety patterns
run: |
set -euo pipefail
fail=0
# Executable scripts must not put request bodies on curl's command line
# or pass -v to curl without redaction (docs are exempt; scripts are not).
if grep -rn -- '--data-raw' plugins/*/scripts/*.sh plugins/*/skills/*/tests/*.sh 2>/dev/null; then
echo "^ found --data-raw in scripts (bodies must go via stdin: --data-binary @-)"; fail=1
fi
if grep -rn 'curl .*-v\b' src/*.sh 2>/dev/null | grep -v redact; then
echo "^ found unredacted curl -v in src scripts"; fail=1
fi
exit "$fail"
smoke:
name: Read-only smoke suites
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run smoke suites (skipped when no token secret is configured)
env:
XCLOUD_API_TOKEN: ${{ secrets.XCLOUD_API_TOKEN }}
XCLOUD_API_BASE_URL: ${{ secrets.XCLOUD_API_BASE_URL }}
XCLOUD_TEST_SERVER_UUID: ${{ secrets.XCLOUD_TEST_SERVER_UUID }}
XCLOUD_TEST_SITE_UUID: ${{ secrets.XCLOUD_TEST_SITE_UUID }}
XCLOUD_TEST_WP_SITE_UUID: ${{ secrets.XCLOUD_TEST_WP_SITE_UUID }}
run: |
set -euo pipefail
if [ -z "${XCLOUD_API_TOKEN:-}" ]; then
echo "XCLOUD_API_TOKEN secret not configured — skipping live smoke suites."
exit 0
fi
export CLAUDE_PLUGIN_ROOT="$PWD/plugins/xcloud"
rc=0
if [ -n "${XCLOUD_TEST_SERVER_UUID:-}" ]; then
echo "== servers =="; plugins/xcloud/skills/servers/tests/smoke.sh || rc=1
fi
if [ -n "${XCLOUD_TEST_SITE_UUID:-}" ]; then
echo "== sites =="; plugins/xcloud/skills/sites/tests/smoke.sh || rc=1
echo "== ssl =="; plugins/xcloud/skills/ssl/tests/smoke.sh || rc=1
fi
echo "== account =="; plugins/xcloud/skills/account/tests/smoke.sh || rc=1
if [ -n "${XCLOUD_TEST_WP_SITE_UUID:-}" ]; then
echo "== wordpress =="; \
XCLOUD_TEST_SITE_UUID="$XCLOUD_TEST_WP_SITE_UUID" \
plugins/xcloud/skills/wordpress/tests/smoke.sh || rc=1
fi
exit "$rc"