CASAN Supply Chain and Provenance / verify-scan-attest (push) Canceled after 0s
CASAN CI Gate / Frontend Tests (H3 gate) (push) Canceled after 0s
CASAN CI Gate / CASAN Security Gate + Vault KMS (H4/H5) (push) Canceled after 0s
CASAN CI Gate / Build & Deploy OKR → /opt/webapps/okr (push) Canceled after 0s
CASAN Harness CI / harness (push) Canceled after 0s
108 lines
3.3 KiB
Bash
Executable File
108 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Smoke the release exactly as a customer receives it. This intentionally
|
|
# extracts into a fresh directory and never resolves files from the source tree.
|
|
#
|
|
# Usage: scripts/smoke-release-artifact.sh dist/casan-<bundle>-vX.Y.Z.tar.gz
|
|
# Env: CASAN_ARTIFACT_SMOKE_RUN_TESTS=1 # platform: npm ci + tests + build
|
|
|
|
ARCHIVE="${1:-}"
|
|
[[ -n "$ARCHIVE" && -f "$ARCHIVE" ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=archive_missing path=${ARCHIVE:-unset}" >&2
|
|
exit 64
|
|
}
|
|
ARCHIVE="$(cd "$(dirname "$ARCHIVE")" && pwd)/$(basename "$ARCHIVE")"
|
|
|
|
WORK="$(mktemp -d)"
|
|
cleanup() { rm -rf "$WORK"; }
|
|
trap cleanup EXIT
|
|
|
|
tar -xzf "$ARCHIVE" -C "$WORK"
|
|
roots=()
|
|
while IFS= read -r directory; do
|
|
roots+=("$directory")
|
|
done < <(find "$WORK" -mindepth 1 -maxdepth 1 -type d -print)
|
|
[[ "${#roots[@]}" -eq 1 ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=unexpected_root_count count=${#roots[@]}" >&2
|
|
exit 1
|
|
}
|
|
ROOT="${roots[0]}"
|
|
|
|
required=(
|
|
BUNDLE-MANIFEST.txt
|
|
SHA256SUMS
|
|
VERSION
|
|
bin/casan
|
|
packages/casan-harness
|
|
.codex-plugin/plugin.json
|
|
.claude-plugin/plugin.json
|
|
.claude-plugin/marketplace.json
|
|
skills/casan/SKILL.md
|
|
)
|
|
for path in "${required[@]}"; do
|
|
[[ -e "$ROOT/$path" ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=required_path_missing path=$path" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
for path in \
|
|
packages/casan-harness/tests \
|
|
packages/casan-harness/level5 \
|
|
packages/casan-harness/scripts/bash/ci-harness-gate.sh \
|
|
packages/casan-harness/scripts/bash/security-gate.sh \
|
|
packages/casan-harness/scripts/bash/test-integrity.py \
|
|
packages/casan-devkit/tests; do
|
|
[[ ! -e "$ROOT/$path" ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=source_only_path_present path=$path" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
(cd "$ROOT" && shasum -a 256 -c SHA256SUMS >/dev/null)
|
|
VERSION="$(tr -d '[:space:]' < "$ROOT/VERSION")"
|
|
CLI_VERSION="$(cd "$ROOT" && ./bin/casan version)"
|
|
[[ "$CLI_VERSION" == "casan $VERSION" ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=cli_version_mismatch expected=$VERSION actual=$CLI_VERSION" >&2
|
|
exit 1
|
|
}
|
|
(cd "$ROOT" && ./bin/casan help >/dev/null)
|
|
|
|
STATUS="$(awk '/^status:/ {print $2}' "$ROOT/BUNDLE-MANIFEST.txt")"
|
|
BUNDLE="$(awk '/^bundle:/ {print $2}' "$ROOT/BUNDLE-MANIFEST.txt")"
|
|
|
|
if [[ "$BUNDLE" == "platform" ]]; then
|
|
platform_required=(
|
|
packages/casan-control-panel/backend/package.json
|
|
packages/casan-control-panel/frontend/package.json
|
|
Dockerfile.control-panel-api
|
|
Dockerfile.control-panel-ui
|
|
docker-compose.control-panel.yml
|
|
docker-compose.control-panel.local.yml
|
|
nginx/control-panel.conf
|
|
infra/production/README.md
|
|
docs/security/CONTROL_PANEL_AUTH_HARDENING.md
|
|
)
|
|
for path in "${platform_required[@]}"; do
|
|
[[ -e "$ROOT/$path" ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=platform_path_missing path=$path" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
[[ -f "$ROOT/PREVIEW-INCOMPLETE.txt" ]] || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=preview_marker_missing" >&2
|
|
exit 1
|
|
}
|
|
|
|
if [[ "${CASAN_ARTIFACT_SMOKE_RUN_TESTS:-0}" == "1" ]]; then
|
|
command -v npm >/dev/null 2>&1 || {
|
|
echo "ARTIFACT_SMOKE_FAIL reason=npm_missing" >&2
|
|
exit 1
|
|
}
|
|
(cd "$ROOT" && npm ci && npm run console:test && npm run console:build)
|
|
fi
|
|
fi
|
|
|
|
echo "ARTIFACT_SMOKE_PASS bundle=$BUNDLE status=$STATUS version=$VERSION extracted=true checksums=true"
|