diff --git a/scripts/pre-release-check.sh b/scripts/pre-release-check.sh deleted file mode 100644 index fc1e3e2..0000000 --- a/scripts/pre-release-check.sh +++ /dev/null @@ -1,404 +0,0 @@ -#!/usr/bin/env bash -# Pre-Release Validation Script for wgpu -# This script runs all quality checks before creating a release -# EXACTLY matches CI checks + additional validations -# -# Usage: -# bash scripts/pre-release-check.sh # Full check before release -# bash scripts/pre-release-check.sh --quick # Quick check during development -# -# On Windows with multiple Go versions, set GOROOT: -# GOROOT="/c/Program Files/Go" bash scripts/pre-release-check.sh - -set -e # Exit on first error - -# Handle GOROOT for Windows with multiple Go versions -if [[ -n "$GOROOT" ]]; then - export PATH="$GOROOT/bin:$PATH" -fi - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Logging functions -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Header -echo "" -echo "================================================" -echo " wgpu - Pre-Release Check" -echo "================================================" -echo "" - -# Track overall status -ERRORS=0 -WARNINGS=0 - -# 1. Check Go version -log_info "Checking Go version..." -GO_VERSION=$(go version | awk '{print $3}') -REQUIRED_VERSION="go1.25" -if [[ "$GO_VERSION" < "$REQUIRED_VERSION" ]]; then - log_error "Go version $REQUIRED_VERSION+ required, found $GO_VERSION" - ERRORS=$((ERRORS + 1)) -else - log_success "Go version: $GO_VERSION" -fi -echo "" - -# 2. Check git status -log_info "Checking git status..." -if git diff-index --quiet HEAD --; then - log_success "Working directory is clean" -else - log_warning "Uncommitted changes detected" - git status --short - WARNINGS=$((WARNINGS + 1)) -fi -echo "" - -# 3. Code formatting check (EXACT CI command) -log_info "Checking code formatting (gofmt -l .)..." -UNFORMATTED=$(gofmt -l .) -if [ -n "$UNFORMATTED" ]; then - log_error "The following files need formatting:" - echo "$UNFORMATTED" - echo "" - log_info "Run: go fmt ./..." - ERRORS=$((ERRORS + 1)) -else - log_success "All files are properly formatted" -fi -echo "" - -# 4. Go vet -log_info "Running go vet..." -# Skip hal/vulkan/vk and hal/gles due to intentional unsafe.Pointer FFI usage -# This matches CI behavior (see .github/workflows/ci.yml) -VET_PACKAGES=$(go list ./... | grep -v '/hal/vulkan/vk$' | grep -v '/hal/gles') -VET_OUTPUT=$(go vet $VET_PACKAGES 2>&1 || true) -# Filter out package headers -VET_FILTERED=$(echo "$VET_OUTPUT" | grep -v "^# " || true) -if [ -z "$VET_FILTERED" ]; then - log_success "go vet passed (excluding hal/vulkan/vk, hal/gles)" -else - echo "$VET_FILTERED" - log_error "go vet failed" - ERRORS=$((ERRORS + 1)) -fi -echo "" - -# 5. Build all packages -log_info "Building all packages..." -if go build ./... 2>&1; then - log_success "Build successful" -else - log_error "Build failed" - ERRORS=$((ERRORS + 1)) -fi -echo "" - -# 6. go.mod validation -log_info "Validating go.mod..." -go mod verify -if [ $? -eq 0 ]; then - log_success "go.mod verified" -else - log_error "go.mod verification failed" - ERRORS=$((ERRORS + 1)) -fi - -# Check if go.mod needs tidying -go mod tidy -if git diff --quiet go.mod go.sum 2>/dev/null; then - log_success "go.mod is tidy" -else - log_warning "go.mod needs tidying (run 'go mod tidy')" - git diff go.mod go.sum 2>/dev/null || true - WARNINGS=$((WARNINGS + 1)) -fi -echo "" - -# 6.5. Verify golangci-lint configuration -log_info "Verifying golangci-lint configuration..." -if command -v golangci-lint &> /dev/null; then - if golangci-lint config verify 2>&1; then - log_success "golangci-lint config is valid" - else - log_error "golangci-lint config is invalid" - ERRORS=$((ERRORS + 1)) - fi -else - log_warning "golangci-lint not installed (optional but recommended)" - log_info "Install: https://golangci-lint.run/welcome/install/" - WARNINGS=$((WARNINGS + 1)) -fi -echo "" - -# 7. Run tests with race detector (supports WSL2 fallback) -USE_WSL=0 -WSL_DISTRO="" - -# Helper function to find WSL distro with Go installed -# Note: WSL on Windows outputs UTF-16 which contains null bytes. -# We use printf (not echo) and filter nulls on the calling side. -find_wsl_distro() { - if ! command -v wsl &> /dev/null; then - return 1 - fi - - # Try common distros first - for distro in "Gentoo" "Ubuntu" "Debian" "Alpine"; do - # Redirect all WSL output to /dev/null to avoid UTF-16 null byte issues - if wsl -d "$distro" bash -c "command -v go" >/dev/null 2>&1; then - printf '%s' "$distro" - return 0 - fi - done - - return 1 -} - -if command -v gcc &> /dev/null || command -v clang &> /dev/null; then - log_info "Running tests with race detector..." - RACE_FLAG="-race" - TEST_CMD="go test -race ./... 2>&1" -else - # Try to find WSL distro with Go - # Filter null bytes from output (WSL UTF-16 encoding issue on Windows) - WSL_DISTRO=$(find_wsl_distro 2>/dev/null | tr -d '\0') - if [ -n "$WSL_DISTRO" ]; then - log_info "GCC not found locally, but WSL2 ($WSL_DISTRO) detected!" - log_info "Running tests with race detector via WSL2 $WSL_DISTRO..." - USE_WSL=1 - RACE_FLAG="-race" - - # Convert Windows path to WSL path (D:\projects\... -> /mnt/d/projects/...) - CURRENT_DIR=$(pwd) - if [[ "$CURRENT_DIR" =~ ^/([a-z])/ ]]; then - # Already in /d/... format (MSYS), convert to /mnt/d/... - WSL_PATH="/mnt${CURRENT_DIR}" - else - # Windows format D:\... convert to /mnt/d/... - DRIVE_LETTER=$(echo "$CURRENT_DIR" | cut -d: -f1 | tr '[:upper:]' '[:lower:]') - PATH_WITHOUT_DRIVE=${CURRENT_DIR#*:} - WSL_PATH="/mnt/$DRIVE_LETTER${PATH_WITHOUT_DRIVE//\\//}" - fi - - TEST_CMD="wsl -d \"$WSL_DISTRO\" bash -c \"cd \\\"$WSL_PATH\\\" && go test -race -ldflags '-linkmode=external' ./... 2>&1\"" - else - log_warning "GCC not found, running tests WITHOUT race detector" - log_info "Install GCC (mingw-w64) or setup WSL2 with Go for race detection" - WARNINGS=$((WARNINGS + 1)) - RACE_FLAG="" - TEST_CMD="go test ./... 2>&1" - fi -fi - -log_info "Running tests..." -WSL_BUILD_FAILED=0 -if [ $USE_WSL -eq 1 ]; then - TEST_OUTPUT=$(wsl -d "$WSL_DISTRO" bash -c "cd $WSL_PATH && timeout 180 stdbuf -oL -eL go test -race -ldflags '-linkmode=external' ./... 2>&1" || true) - # Check if it's a build failure (goffi/dl issue) vs actual test failure - if echo "$TEST_OUTPUT" | grep -qE "undefined: dl\.|build failed"; then - log_warning "WSL2 build failed (goffi/dl incompatibility), falling back to local tests" - WSL_BUILD_FAILED=1 - USE_WSL=0 - RACE_FLAG="" - TEST_OUTPUT=$(go test ./... 2>&1 || true) - elif [ -z "$TEST_OUTPUT" ]; then - log_warning "WSL2 tests timed out, falling back to local tests" - WSL_BUILD_FAILED=1 - USE_WSL=0 - RACE_FLAG="" - TEST_OUTPUT=$(go test ./... 2>&1 || true) - fi -else - TEST_OUTPUT=$(eval "$TEST_CMD") -fi - -if echo "$TEST_OUTPUT" | grep -q "^FAIL\|^---.*FAIL"; then - log_error "Tests failed" - echo "$TEST_OUTPUT" | grep -E "^(FAIL|---.*FAIL|.*_test\.go:)" | head -20 - ERRORS=$((ERRORS + 1)) -elif echo "$TEST_OUTPUT" | grep -q "PASS\|^ok"; then - if [ -n "$RACE_FLAG" ]; then - log_success "All tests passed with race detector" - elif [ $WSL_BUILD_FAILED -eq 1 ]; then - log_success "All tests passed (race detector skipped - goffi/WSL incompatibility)" - else - log_success "All tests passed (race detector not available)" - fi -else - log_warning "No tests found or unexpected output" - WARNINGS=$((WARNINGS + 1)) -fi -echo "" - -# 8. Test coverage check -log_info "Checking test coverage..." -COVERAGE=$(go test -cover ./... 2>&1 | grep "coverage:" | tail -1 | awk '{print $5}' | sed 's/%//') -if [ -n "$COVERAGE" ]; then - echo " overall coverage: ${COVERAGE}%" - if awk -v cov="$COVERAGE" 'BEGIN {exit !(cov >= 70.0)}'; then - log_success "Coverage meets requirement (>70%)" - else - log_warning "Coverage below 70% (${COVERAGE}%) - acceptable for early versions" - WARNINGS=$((WARNINGS + 1)) - fi -else - log_warning "Could not determine coverage (no tests yet)" - WARNINGS=$((WARNINGS + 1)) -fi -echo "" - -# 9. golangci-lint (same as CI) -log_info "Running golangci-lint..." -if command -v golangci-lint &> /dev/null; then - LINT_OUTPUT=$(golangci-lint run --timeout=5m ./... 2>&1 || true) - # Check for "0 issues" or empty output (success) - if echo "$LINT_OUTPUT" | grep -qE "(^0 issues|no issues)"; then - log_success "golangci-lint passed with 0 issues" - elif [ -z "$LINT_OUTPUT" ]; then - log_success "golangci-lint passed" - elif echo "$LINT_OUTPUT" | grep -q "issues:"; then - # Has issues - extract count - log_error "Linter found issues" - echo "$LINT_OUTPUT" | tail -20 - ERRORS=$((ERRORS + 1)) - else - log_success "golangci-lint passed" - fi -else - log_warning "golangci-lint not installed" - log_info "Install: https://golangci-lint.run/welcome/install/" - WARNINGS=$((WARNINGS + 1)) -fi -echo "" - -# 10. Ecosystem dependency validation -log_info "Validating ecosystem dependencies..." - -check_ecosystem_dep() { - local DEP_NAME=$1 - local REPO=$2 - - LOCAL_VERSION=$(grep "$DEP_NAME" go.mod 2>/dev/null | grep -v "^module" | awk '{print $2}') - - if [ -z "$LOCAL_VERSION" ]; then - return 0 # Dependency not used, skip - fi - - # Get latest release from GitHub - if command -v gh &> /dev/null; then - LATEST_VERSION=$(gh release view --repo "$REPO" --json tagName -q '.tagName' 2>/dev/null || echo "") - else - LATEST_VERSION="" - fi - - if [ -z "$LATEST_VERSION" ]; then - log_warning "$DEP_NAME: $LOCAL_VERSION (cannot check latest)" - WARNINGS=$((WARNINGS + 1)) - return 0 - fi - - if [ "$LOCAL_VERSION" = "$LATEST_VERSION" ]; then - log_success "$DEP_NAME: $LOCAL_VERSION (latest)" - else - log_error "$DEP_NAME: $LOCAL_VERSION (latest: $LATEST_VERSION)" - log_info " Run: go get $DEP_NAME@$LATEST_VERSION" - ERRORS=$((ERRORS + 1)) - fi -} - -check_ecosystem_dep "github.com/gogpu/naga" "gogpu/naga" -check_ecosystem_dep "github.com/go-webgpu/goffi" "go-webgpu/goffi" - -echo "" - -# 11. Check for TODO/FIXME comments -log_info "Checking for TODO/FIXME comments..." -TODO_COUNT=$(grep -r "TODO\|FIXME" --include="*.go" --exclude-dir=vendor . 2>/dev/null | wc -l) -if [ "$TODO_COUNT" -gt 0 ]; then - log_warning "Found $TODO_COUNT TODO/FIXME comments" - grep -r "TODO\|FIXME" --include="*.go" --exclude-dir=vendor . 2>/dev/null | head -5 - WARNINGS=$((WARNINGS + 1)) -else - log_success "No TODO/FIXME comments found" -fi -echo "" - -# 12. Check critical documentation files -log_info "Checking documentation..." -DOCS_MISSING=0 -REQUIRED_DOCS="README.md LICENSE" - -for doc in $REQUIRED_DOCS; do - if [ ! -f "$doc" ]; then - log_error "Missing: $doc" - DOCS_MISSING=1 - ERRORS=$((ERRORS + 1)) - fi -done - -if [ $DOCS_MISSING -eq 0 ]; then - log_success "All critical documentation files present" -fi -echo "" - -# Summary -echo "========================================" -echo " Summary" -echo "========================================" -echo "" - -if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then - log_success "All checks passed! Ready for release." - echo "" - log_info "Next steps for release (GitHub Flow):" - echo "" - echo " 1. Update CHANGELOG.md and README.md if needed" - echo "" - echo " 2. Commit changes:" - echo " git add -A" - echo " git commit -m \"chore: prepare vX.Y.Z release\"" - echo " git push" - echo "" - echo " 3. Wait for CI to pass on main" - echo "" - echo " 4. Create and push tag:" - echo " git tag -a vX.Y.Z -m \"Release vX.Y.Z\"" - echo " git push origin vX.Y.Z" - echo "" - exit 0 -elif [ $ERRORS -eq 0 ]; then - log_warning "Checks completed with $WARNINGS warning(s)" - echo "" - log_info "Review warnings above before proceeding with release" - echo "" - exit 0 -else - log_error "Checks failed with $ERRORS error(s) and $WARNINGS warning(s)" - echo "" - log_error "Fix errors before creating release" - echo "" - exit 1 -fi