generated from coulomb/repo-seed
Add release smoke path for pre-store verification (WP-0002)
Introduce npm run smoke with automated build, test, lint, dist, and metadata-only compliance checks. Document manual Chrome steps in RELEASE_SMOKE.md and fix unused imports blocking lint.
This commit is contained in:
143
scripts/release-smoke.sh
Executable file
143
scripts/release-smoke.sh
Executable file
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env bash
|
||||
# Release smoke path — automated pre-flight checks before Chrome manual verification.
|
||||
# Run: npm run smoke or ./scripts/release-smoke.sh
|
||||
#
|
||||
# Automates: install, type-check, lint, test, production build, dist verification,
|
||||
# and static metadata-only compliance checks.
|
||||
# Manual Chrome steps are printed at the end (see RELEASE_SMOKE.md).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
DIST="$ROOT/dist"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
step=0
|
||||
pass() { echo -e "${GREEN}✅ [$((++step))] $1${NC}"; }
|
||||
fail() { echo -e "${RED}❌ $1${NC}"; exit 1; }
|
||||
info() { echo -e "${BLUE} $1${NC}"; }
|
||||
warn() { echo -e "${YELLOW}⚠️ $1${NC}"; }
|
||||
|
||||
echo ""
|
||||
echo "BinectChrome — Release Smoke (automated)"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
cd "$ROOT"
|
||||
|
||||
# --- Prerequisites ---
|
||||
if ! command -v node >/dev/null 2>&1; then
|
||||
fail "Node.js is required"
|
||||
fi
|
||||
if ! command -v npm >/dev/null 2>&1; then
|
||||
fail "npm is required"
|
||||
fi
|
||||
if [ ! -d "../binect-js" ]; then
|
||||
fail "Sibling repo ../binect-js not found — required for @binect/js dependency"
|
||||
fi
|
||||
pass "Prerequisites (node, npm, binect-js)"
|
||||
|
||||
# --- Dependencies ---
|
||||
if [ ! -d node_modules ] || [ ! -f node_modules/.bin/jest ]; then
|
||||
info "Installing dependencies..."
|
||||
npm install
|
||||
fi
|
||||
pass "Dependencies ready"
|
||||
|
||||
# --- Static analysis ---
|
||||
info "Running type-check..."
|
||||
npm run type-check
|
||||
pass "Type-check"
|
||||
|
||||
info "Running lint..."
|
||||
npm run lint
|
||||
pass "Lint"
|
||||
|
||||
info "Running unit tests..."
|
||||
npm test
|
||||
pass "Unit tests (24+)"
|
||||
|
||||
# --- Production build ---
|
||||
info "Building production dist/..."
|
||||
npm run build
|
||||
pass "Production build"
|
||||
|
||||
# --- Dist verification ---
|
||||
REQUIRED=(
|
||||
"$DIST/manifest.json"
|
||||
"$DIST/background.js"
|
||||
"$DIST/popup.html"
|
||||
"$DIST/popup.js"
|
||||
"$DIST/tracking.html"
|
||||
"$DIST/tracking.js"
|
||||
"$DIST/icons/icon-128.png"
|
||||
"$DIST/_locales/en/messages.json"
|
||||
)
|
||||
for f in "${REQUIRED[@]}"; do
|
||||
[ -f "$f" ] || fail "Missing dist artifact: $f"
|
||||
done
|
||||
|
||||
MANIFEST="$DIST/manifest.json"
|
||||
grep -q '"manifest_version": 3' "$MANIFEST" || fail "manifest.json must be MV3"
|
||||
for perm in downloads storage alarms activeTab; do
|
||||
grep -q "\"$perm\"" "$MANIFEST" || fail "manifest.json missing permission: $perm"
|
||||
done
|
||||
grep -q 'https://api.binect.de' "$MANIFEST" || fail "manifest.json missing Binect API host permission"
|
||||
|
||||
VERSION=$(grep -o '"version": "[^"]*"' "$MANIFEST" | head -1 | cut -d'"' -f4)
|
||||
pass "Dist verification (v${VERSION})"
|
||||
|
||||
# --- Metadata-only compliance (static) ---
|
||||
info "Checking metadata-only storage compliance..."
|
||||
|
||||
# Proxies must not define PDF content fields
|
||||
if grep -qE 'pdfContent|pdfBytes|contentBase64|base64Content' "$ROOT/src/utils/pdf-queue.ts"; then
|
||||
fail "pdf-queue.ts must not store PDF content fields"
|
||||
fi
|
||||
|
||||
# No chrome.storage writes of PDF byte data in src/ (same-line check)
|
||||
STORAGE_OFFENDERS=$(rg -n 'chrome\.storage.*\.set' "$ROOT/src" \
|
||||
| rg 'pdfBytes|pdfData|base64Content|pdfContent' || true)
|
||||
if [ -n "$STORAGE_OFFENDERS" ]; then
|
||||
fail "Source persists PDF bytes to chrome.storage — violates zero-retention"
|
||||
fi
|
||||
|
||||
# Upload path: bytes fetched in-memory only, not written to storage
|
||||
rg -q 'fetchPDFBytes' "$ROOT/src/popup/popup.ts" \
|
||||
|| fail "popup.ts must fetch PDF bytes at send time"
|
||||
rg -q 'uploadPDF' "$ROOT/src/popup/popup.ts" \
|
||||
|| fail "popup.ts must call uploadPDF for Binect dispatch"
|
||||
|
||||
pass "Metadata-only compliance (no PDF persistence in storage)"
|
||||
|
||||
# --- Summary ---
|
||||
echo ""
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}Automated smoke checks: ALL PASSED${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
echo "Dist ready at: $DIST"
|
||||
echo " background.js $(du -h "$DIST/background.js" | cut -f1)"
|
||||
echo " popup.js $(du -h "$DIST/popup.js" | cut -f1)"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Manual Chrome verification (required before store submission):${NC}"
|
||||
echo ""
|
||||
echo " 1. Open chrome://extensions/ → Developer mode ON"
|
||||
echo " 2. Load unpacked → select: $DIST"
|
||||
echo " 3. Open test PDF:"
|
||||
echo " https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
|
||||
echo " 4. Click extension icon → confirm PDF detected (filename, domain)"
|
||||
echo " 5. Sign in with Binect credentials → Send PDF to Binect"
|
||||
echo " 6. Confirm upload success and document ID in popup"
|
||||
echo " 7. Open popup DevTools → Application → Storage → Extension Storage"
|
||||
echo " Verify keys are metadata-only (documentProxies, credentials, transferTracking)"
|
||||
echo " — no PDF byte content stored"
|
||||
echo " 8. Open tracking page (?) → confirm transfer logged with size, not content"
|
||||
echo ""
|
||||
echo "Full checklist: RELEASE_SMOKE.md"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user