This repository was archived by the owner on Dec 28, 2025. It is now read-only.
Validate Apache Release (New) #1
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: "Validate Apache Release (New)" | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_version: | |
| required: true | |
| description: svn release version | |
| default: '1.7.0' | |
| gpg_user: | |
| required: true | |
| description: current release manager (gpg username) | |
| default: 'pengjunzhi' | |
| java_version: | |
| required: false | |
| description: Java version to validate | |
| default: '11' | |
| type: choice | |
| options: | |
| - '11' | |
| - '17' | |
| push: | |
| branches: | |
| - 'release-*' | |
| pull_request: | |
| branches: | |
| - 'release-*' | |
| jobs: | |
| validate: | |
| name: "Validate Release On ${{ matrix.os }} (java-${{ matrix.java_version }})" | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| RELEASE_VERSION: ${{ inputs.release_version || '1.7.0' }} | |
| GPG_USER: ${{ inputs.gpg_user || 'pengjunzhi' }} | |
| JAVA_VERSION: ${{ inputs.java_version || matrix.java_version || '11' }} | |
| SVN_URL_PREFIX: https://dist.apache.org/repos/dist/dev/incubator/hugegraph | |
| KEYS_URL: https://downloads.apache.org/incubator/hugegraph/KEYS | |
| MAX_FILE_SIZE: 800k | |
| SERVER_START_DELAY: 3 | |
| # License Patterns (ASF Category X - Prohibited) | |
| CATEGORY_X: '\bGPL|\bLGPL|Sleepycat License|BSD-4-Clause|\bBCL\b|JSR-275|Amazon Software License|\bRSAL\b|\bQPL\b|\bSSPL|\bCPOL|\bNPL1|Creative Commons Non-Commercial|JSON\.org' | |
| # License Patterns (ASF Category B - Must be documented) | |
| CATEGORY_B: '\bCDDL1|\bCPL|\bEPL|\bIPL|\bMPL|\bSPL|OSL-3.0|UnRAR License|Erlang Public License|\bOFL\b|Ubuntu Font License Version 1.0|IPA Font License Agreement v1.0|EPL2.0|CC-BY' | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| - name: Install JDK ${{ env.JAVA_VERSION }} | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: ${{ env.JAVA_VERSION }} | |
| distribution: 'adopt' | |
| - name: Install dependencies | |
| run: | | |
| if [[ "${{ runner.os }}" == "macOS" ]]; then | |
| brew install svn wget perl | |
| elif [[ "${{ runner.os }}" == "Linux" ]]; then | |
| sudo apt-get update | |
| sudo apt-get install -y subversion wget perl | |
| fi | |
| # Verify all required commands | |
| for cmd in svn gpg shasum mvn java wget tar curl awk grep find perl; do | |
| if ! command -v "$cmd" &> /dev/null; then | |
| echo "Error: Missing required dependency: $cmd" | |
| exit 1 | |
| fi | |
| echo "✓ $cmd: $(command -v $cmd)" | |
| done | |
| - name: Cache Maven packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.m2 | |
| key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: ${{ runner.os }}-m2 | |
| - name: Step 1 - Check Dependencies | |
| run: | | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [1/9]: Check Dependencies" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| # Check Java version | |
| CURRENT_JAVA=$(java -version 2>&1 | head -n 1 | awk -F '"' '{print $2}' | awk -F '.' '{print $1}') | |
| echo "Current Java version: $CURRENT_JAVA (Required: ${{ env.JAVA_VERSION }})" | |
| if [[ "$CURRENT_JAVA" != "${{ env.JAVA_VERSION }}" ]]; then | |
| echo "Error: Java version mismatch! Current: Java $CURRENT_JAVA, Required: Java ${{ env.JAVA_VERSION }}" | |
| exit 1 | |
| fi | |
| echo "✓ Java version check passed: Java $CURRENT_JAVA" | |
| - name: Step 2 - Prepare Release Files | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [2/9]: Prepare Release Files" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| DIST_DIR="dist/${{ env.RELEASE_VERSION }}" | |
| echo "Downloading from SVN to: ${DIST_DIR}" | |
| rm -rf "${DIST_DIR}" | |
| mkdir -p "${DIST_DIR}" | |
| if ! svn co "${SVN_URL_PREFIX}/${{ env.RELEASE_VERSION }}" "${DIST_DIR}"; then | |
| echo "Error: Failed to download from SVN: ${SVN_URL_PREFIX}/${{ env.RELEASE_VERSION }}" | |
| exit 1 | |
| fi | |
| echo "✓ Downloaded release files from SVN" | |
| cd "${DIST_DIR}" | |
| ls -lh | |
| - name: Step 3 - Import & Trust GPG Keys | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [3/9]: Import & Trust GPG Keys" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| echo "Downloading KEYS file from ${KEYS_URL}..." | |
| if ! wget -q "${KEYS_URL}" -O KEYS; then | |
| echo "Error: Failed to download KEYS file from ${KEYS_URL}" | |
| exit 1 | |
| fi | |
| echo "✓ KEYS file downloaded" | |
| echo "Importing GPG keys..." | |
| IMPORT_OUTPUT=$(gpg --import KEYS 2>&1) | |
| IMPORTED_COUNT=$(echo "$IMPORT_OUTPUT" | grep -c "imported" || echo "0") | |
| if [[ "$IMPORTED_COUNT" == "0" ]]; then | |
| echo "⚠ No new keys imported (may already exist in keyring)" | |
| else | |
| echo "✓ Imported GPG keys" | |
| fi | |
| # Trust specific user key | |
| if ! gpg --list-keys "${{ env.GPG_USER }}" &>/dev/null; then | |
| echo "Error: User '${{ env.GPG_USER }}' key not found in imported keys. Please verify the username." | |
| exit 1 | |
| fi | |
| echo "Trusting GPG key for user: ${{ env.GPG_USER }}" | |
| echo -e "5\ny\n" | gpg --batch --command-fd 0 --edit-key "${{ env.GPG_USER }}" trust 2>/dev/null | |
| echo "✓ Trusted key for ${{ env.GPG_USER }}" | |
| # Trust all imported keys | |
| echo "Trusting all imported public keys..." | |
| TRUSTED=0 | |
| for key in $(gpg --no-tty --list-keys --with-colons | awk -F: '/^pub/ {print $5}'); do | |
| echo -e "5\ny\n" | gpg --batch --command-fd 0 --edit-key "$key" trust 2>/dev/null | |
| TRUSTED=$((TRUSTED + 1)) | |
| done | |
| echo "✓ Trusted $TRUSTED GPG keys" | |
| - name: Step 4 - Verify SHA512 & GPG Signatures | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [4/9]: Verify SHA512 & GPG Signatures" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| PACKAGE_COUNT=0 | |
| for pkg in *.tar.gz; do | |
| if [[ -f "$pkg" ]]; then | |
| PACKAGE_COUNT=$((PACKAGE_COUNT + 1)) | |
| fi | |
| done | |
| CURRENT=0 | |
| for pkg in *.tar.gz; do | |
| if [[ ! -f "$pkg" ]]; then | |
| continue | |
| fi | |
| CURRENT=$((CURRENT + 1)) | |
| echo " [${CURRENT}/${PACKAGE_COUNT}] $pkg" | |
| # Check SHA512 | |
| if shasum -a 512 --check "${pkg}.sha512"; then | |
| echo " ✓ SHA512 verified: $pkg" | |
| else | |
| echo " ✗ SHA512 verification failed: $pkg" | |
| exit 1 | |
| fi | |
| # Check GPG signature | |
| if gpg --verify "${pkg}.asc" "$pkg" 2>&1 | grep -q "Good signature"; then | |
| echo " ✓ GPG signature verified: $pkg" | |
| else | |
| echo " ✗ GPG signature verification failed: $pkg" | |
| exit 1 | |
| fi | |
| done | |
| - name: Step 5 - Validate Source Packages | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [5/9]: Validate Source Packages" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| SRC_PACKAGES=() | |
| for pkg in *-src.tar.gz; do | |
| if [[ -f "$pkg" ]]; then | |
| SRC_PACKAGES+=("$pkg") | |
| fi | |
| done | |
| echo "Found ${#SRC_PACKAGES[@]} source package(s)" | |
| for src_pkg in "${SRC_PACKAGES[@]}"; do | |
| echo "" | |
| echo "Validating source package: $src_pkg" | |
| # Extract package | |
| PACKAGE_DIR=$(basename "$src_pkg" .tar.gz) | |
| rm -rf "$PACKAGE_DIR" | |
| tar -xzf "$src_pkg" | |
| if [[ ! -d "$PACKAGE_DIR" ]]; then | |
| echo "Error: Failed to extract package: $src_pkg" | |
| exit 1 | |
| fi | |
| pushd "$PACKAGE_DIR" | |
| # 5.1: Check incubating name | |
| if [[ ! "$src_pkg" =~ "incubating" ]]; then | |
| echo "Error: Package name '$src_pkg' should include 'incubating'" | |
| exit 1 | |
| fi | |
| echo " ✓ Package name includes 'incubating'" | |
| # 5.2: Check required files | |
| if [[ ! -f "LICENSE" ]]; then | |
| echo "Error: Package '$src_pkg' missing LICENSE file" | |
| exit 1 | |
| fi | |
| echo " ✓ LICENSE file exists" | |
| if [[ ! -f "NOTICE" ]]; then | |
| echo "Error: Package '$src_pkg' missing NOTICE file" | |
| exit 1 | |
| fi | |
| echo " ✓ NOTICE file exists" | |
| if [[ ! -f "DISCLAIMER" ]]; then | |
| echo "Error: Package '$src_pkg' missing DISCLAIMER file" | |
| exit 1 | |
| fi | |
| echo " ✓ DISCLAIMER file exists" | |
| # 5.3: Check license categories (Category X - Prohibited) | |
| CAT_X_MATCHES=$(grep -r -E "${{ env.CATEGORY_X }}" LICENSE NOTICE 2>/dev/null || true) | |
| CAT_X_COUNT=$(echo "$CAT_X_MATCHES" | grep -v '^$' | wc -l | tr -d ' ') | |
| if [[ $CAT_X_COUNT -ne 0 ]]; then | |
| echo "Error: Package '$src_pkg' contains $CAT_X_COUNT prohibited ASF Category X license(s):" | |
| echo "$CAT_X_MATCHES" | |
| exit 1 | |
| fi | |
| echo " ✓ No Category X licenses found" | |
| # 5.4: Check license categories (Category B - Warning) | |
| CAT_B_COUNT=$(grep -r -E "${{ env.CATEGORY_B }}" LICENSE NOTICE 2>/dev/null | wc -l | tr -d ' ' || echo "0") | |
| if [[ $CAT_B_COUNT -ne 0 ]]; then | |
| echo " ⚠ Warning: Package '$src_pkg' contains $CAT_B_COUNT ASF Category B license(s) - please verify documentation" | |
| else | |
| echo " ✓ No Category B licenses found" | |
| fi | |
| # 5.5: Check empty files and directories | |
| EMPTY_DIRS=$(find . -type d -empty 2>/dev/null || true) | |
| EMPTY_FILES=$(find . -type f -empty 2>/dev/null || true) | |
| if [[ -n "$EMPTY_DIRS" ]]; then | |
| echo "Error: Package '$src_pkg' contains empty director(y/ies):" | |
| echo "$EMPTY_DIRS" | |
| exit 1 | |
| fi | |
| if [[ -n "$EMPTY_FILES" ]]; then | |
| echo "Error: Package '$src_pkg' contains empty file(s):" | |
| echo "$EMPTY_FILES" | |
| exit 1 | |
| fi | |
| echo " ✓ No empty files or directories" | |
| # 5.6: Check file sizes | |
| LARGE_FILES=$(find . -type f -size "+${{ env.MAX_FILE_SIZE }}" 2>/dev/null || true) | |
| if [[ -n "$LARGE_FILES" ]]; then | |
| echo "Error: Package '$src_pkg' contains file(s) larger than ${{ env.MAX_FILE_SIZE }}:" | |
| echo "$LARGE_FILES" | |
| exit 1 | |
| fi | |
| echo " ✓ All files are within size limit" | |
| # 5.7: Check binary files | |
| BINARY_COUNT=0 | |
| UNDOCUMENTED_COUNT=0 | |
| while IFS= read -r binary_file; do | |
| BINARY_COUNT=$((BINARY_COUNT + 1)) | |
| FILE_NAME=$(basename "$binary_file") | |
| if ! grep -q "$FILE_NAME" LICENSE 2>/dev/null; then | |
| echo "Error: Undocumented binary file: $binary_file" | |
| UNDOCUMENTED_COUNT=$((UNDOCUMENTED_COUNT + 1)) | |
| fi | |
| done < <(find . -type f 2>/dev/null | perl -lne 'print if -B $_' || true) | |
| if [[ $BINARY_COUNT -eq 0 ]]; then | |
| echo " ✓ No binary files found" | |
| elif [[ $UNDOCUMENTED_COUNT -eq 0 ]]; then | |
| echo " ✓ All $BINARY_COUNT binary file(s) are documented" | |
| else | |
| echo "Error: Found $UNDOCUMENTED_COUNT undocumented binary file(s)" | |
| exit 1 | |
| fi | |
| # 5.8: Check license headers in source files | |
| echo " Checking for ASF license headers in source files..." | |
| # Define file patterns to check | |
| FILE_PATTERNS=("*.java" "*.sh" "*.py" "*.go" "*.js" "*.ts" "*.jsx" "*.tsx" "*.c" "*.h" "*.cpp" "*.cc" "*.cxx" "*.hpp" "*.scala" "*.groovy" "*.gradle" "*.rs" "*.kt" "*.proto") | |
| # Files to exclude | |
| EXCLUDE_PATTERNS=("*.min.js" "*.min.css" "*node_modules*" "*target*" "*build*" "*.pb.go" "*generated*" "*third_party*" "*vendor*") | |
| FILES_WITHOUT_LICENSE=() | |
| TOTAL_CHECKED=0 | |
| EXCLUDED_COUNT=0 | |
| DOCUMENTED_COUNT=0 | |
| # Build find command | |
| FIND_CMD="find . -type f \\(" | |
| FIRST=1 | |
| for pattern in "${FILE_PATTERNS[@]}"; do | |
| if [[ $FIRST -eq 1 ]]; then | |
| FIND_CMD="$FIND_CMD -name \"$pattern\"" | |
| FIRST=0 | |
| else | |
| FIND_CMD="$FIND_CMD -o -name \"$pattern\"" | |
| fi | |
| done | |
| FIND_CMD="$FIND_CMD \\) 2>/dev/null" | |
| # Check each source file | |
| while IFS= read -r source_file; do | |
| # Skip if file matches exclude patterns | |
| SHOULD_EXCLUDE=0 | |
| for exclude_pattern in "${EXCLUDE_PATTERNS[@]}"; do | |
| if [[ "$source_file" == $exclude_pattern ]]; then | |
| SHOULD_EXCLUDE=1 | |
| EXCLUDED_COUNT=$((EXCLUDED_COUNT + 1)) | |
| break | |
| fi | |
| done | |
| if [[ $SHOULD_EXCLUDE -eq 1 ]]; then | |
| continue | |
| fi | |
| TOTAL_CHECKED=$((TOTAL_CHECKED + 1)) | |
| # Check first 30 lines for Apache license header | |
| if ! head -n 30 "$source_file" | grep -q "Licensed to the Apache Software Foundation"; then | |
| # Check if documented in LICENSE file | |
| FILE_NAME=$(basename "$source_file") | |
| FILE_PATH_RELATIVE=$(echo "$source_file" | sed 's|^\./||') | |
| if [[ -f "LICENSE" ]] && (grep -q "$FILE_NAME" LICENSE 2>/dev/null || grep -q "$FILE_PATH_RELATIVE" LICENSE 2>/dev/null); then | |
| DOCUMENTED_COUNT=$((DOCUMENTED_COUNT + 1)) | |
| else | |
| FILES_WITHOUT_LICENSE+=("$source_file") | |
| fi | |
| fi | |
| done < <(eval "$FIND_CMD") | |
| echo " Checked $TOTAL_CHECKED source file(s) for ASF license headers (excluded $EXCLUDED_COUNT generated/vendored files)" | |
| if [[ $DOCUMENTED_COUNT -gt 0 ]]; then | |
| echo " Found $DOCUMENTED_COUNT source file(s) documented in LICENSE as third-party code (allowed)" | |
| fi | |
| if [[ ${#FILES_WITHOUT_LICENSE[@]} -gt 0 ]]; then | |
| echo "Error: Found ${#FILES_WITHOUT_LICENSE[@]} source file(s) without ASF license headers:" | |
| SHOW_COUNT=${#FILES_WITHOUT_LICENSE[@]} | |
| if [[ $SHOW_COUNT -gt 20 ]]; then | |
| SHOW_COUNT=20 | |
| fi | |
| for ((i=0; i<SHOW_COUNT; i++)); do | |
| echo " ${FILES_WITHOUT_LICENSE[$i]}" | |
| done | |
| if [[ ${#FILES_WITHOUT_LICENSE[@]} -gt 20 ]]; then | |
| echo " ... and $((${#FILES_WITHOUT_LICENSE[@]} - 20)) more files" | |
| fi | |
| echo "All source files must include the Apache License header or be documented in LICENSE file" | |
| exit 1 | |
| else | |
| echo " ✓ All $TOTAL_CHECKED source file(s) have ASF license headers or are documented in LICENSE" | |
| fi | |
| # 5.9: Check version consistency (skip for Python projects) | |
| if [[ ! "$src_pkg" =~ 'hugegraph-ai' ]]; then | |
| echo " Checking version consistency (revision property)..." | |
| ROOT_POM="" | |
| REVISION_VALUE="" | |
| while IFS= read -r pom_file; do | |
| if grep -q "<revision>" "$pom_file" 2>/dev/null; then | |
| REVISION_VALUE=$(grep "<revision>" "$pom_file" | head -1 | sed 's/.*<revision>\(.*\)<\/revision>.*/\1/') | |
| ROOT_POM="$pom_file" | |
| break | |
| fi | |
| done < <(find . -name "pom.xml" -type f 2>/dev/null) | |
| if [[ -n "$ROOT_POM" ]]; then | |
| echo " Found revision property in $ROOT_POM: <revision>$REVISION_VALUE</revision>" | |
| if [[ "$REVISION_VALUE" != "${{ env.RELEASE_VERSION }}" ]]; then | |
| echo "Error: Version mismatch: <revision>$REVISION_VALUE</revision> in $ROOT_POM (expected: ${{ env.RELEASE_VERSION }})" | |
| exit 1 | |
| fi | |
| echo " ✓ Version consistency check passed: revision=$REVISION_VALUE" | |
| else | |
| echo " ⚠ Warning: No <revision> property found in pom.xml files - skipping version check" | |
| fi | |
| else | |
| echo " Skipping version check for Python project: $src_pkg" | |
| fi | |
| # 5.10: Check NOTICE year | |
| if [[ -f "NOTICE" ]]; then | |
| CURRENT_YEAR=$(date +%Y) | |
| if ! grep -q "$CURRENT_YEAR" NOTICE; then | |
| echo " ⚠ Warning: NOTICE file may not contain current year ($CURRENT_YEAR). Please verify copyright dates." | |
| else | |
| echo " ✓ NOTICE file contains current year" | |
| fi | |
| fi | |
| # 5.11: Compile source package | |
| echo " Compiling source package: $src_pkg" | |
| if [[ "$src_pkg" =~ 'hugegraph-ai' ]]; then | |
| echo " ⚠ Skipping compilation for AI module (not required)" | |
| elif [[ "$src_pkg" =~ "hugegraph-computer" ]]; then | |
| if cd computer 2>/dev/null && mvn clean package -DskipTests -Dcheckstyle.skip=true -ntp -e; then | |
| echo " ✓ Compilation successful: $src_pkg" | |
| else | |
| echo "Error: Compilation failed: $src_pkg" | |
| exit 1 | |
| fi | |
| cd .. | |
| else | |
| if mvn clean package -DskipTests -Dcheckstyle.skip=true -ntp -e; then | |
| echo " ✓ Compilation successful: $src_pkg" | |
| else | |
| echo "Error: Compilation failed: $src_pkg" | |
| exit 1 | |
| fi | |
| fi | |
| popd | |
| echo "✓ Finished validating source package: $src_pkg" | |
| done | |
| - name: Step 6 - Test Compiled Server Package | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [6/9]: Test Compiled Server Package" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| # Find server directory | |
| SERVER_DIR=$(find . -maxdepth 3 -type d -path "*hugegraph-incubating*src/hugegraph-server/*hugegraph*${{ env.RELEASE_VERSION }}" 2>/dev/null | head -n1) | |
| if [[ -z "$SERVER_DIR" ]]; then | |
| echo "Error: Could not find compiled server directory" | |
| exit 1 | |
| fi | |
| echo "Starting HugeGraph server from: $SERVER_DIR" | |
| pushd "$SERVER_DIR" | |
| if bin/init-store.sh; then | |
| echo " ✓ Store initialized" | |
| else | |
| echo "Error: Failed to initialize store" | |
| exit 1 | |
| fi | |
| sleep ${{ env.SERVER_START_DELAY }} | |
| if bin/start-hugegraph.sh; then | |
| echo " ✓ Server started" | |
| else | |
| echo "Error: Failed to start server" | |
| exit 1 | |
| fi | |
| popd | |
| - name: Step 7 - Test Compiled Toolchain Packages | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [7/9]: Test Compiled Toolchain Packages" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| TOOLCHAIN_SRC=$(find . -maxdepth 3 -type d -path "*toolchain*src" 2>/dev/null | head -n1) | |
| if [[ -n "$TOOLCHAIN_SRC" ]]; then | |
| pushd "$TOOLCHAIN_SRC" | |
| TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "*toolchain*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$TOOLCHAIN_DIR" ]]; then | |
| pushd "$TOOLCHAIN_DIR" | |
| # Test Loader | |
| echo "Testing HugeGraph Loader..." | |
| LOADER_DIR=$(find . -maxdepth 1 -type d -name "*loader*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$LOADER_DIR" ]]; then | |
| pushd "$LOADER_DIR" | |
| if bin/hugegraph-loader.sh -f ./example/file/struct.json -s ./example/file/schema.groovy -g hugegraph; then | |
| echo " ✓ Loader test passed" | |
| else | |
| echo "Error: Loader test failed" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| # Test Tool | |
| echo "Testing HugeGraph Tool..." | |
| TOOL_DIR=$(find . -maxdepth 1 -type d -name "*tool*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$TOOL_DIR" ]]; then | |
| pushd "$TOOL_DIR" | |
| if bin/hugegraph gremlin-execute --script 'g.V().count()' && \ | |
| bin/hugegraph task-list && \ | |
| bin/hugegraph backup -t all --directory ./backup-test; then | |
| echo " ✓ Tool test passed" | |
| else | |
| echo "Error: Tool test failed" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| # Test Hubble | |
| echo "Testing HugeGraph Hubble..." | |
| HUBBLE_DIR=$(find . -maxdepth 1 -type d -name "*hubble*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$HUBBLE_DIR" ]]; then | |
| pushd "$HUBBLE_DIR" | |
| if bin/start-hubble.sh; then | |
| echo " ✓ Hubble started" | |
| sleep 2 | |
| bin/stop-hubble.sh | |
| echo " ✓ Hubble stopped" | |
| else | |
| echo "Error: Hubble test failed" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| popd | |
| fi | |
| popd | |
| fi | |
| # Stop server after toolchain tests | |
| SERVER_DIR=$(find . -maxdepth 3 -type d -path "*hugegraph-incubating*src/hugegraph-server/*hugegraph*${{ env.RELEASE_VERSION }}" 2>/dev/null | head -n1) | |
| if [[ -n "$SERVER_DIR" ]]; then | |
| echo "Stopping server..." | |
| pushd "$SERVER_DIR" | |
| bin/stop-hugegraph.sh | |
| echo " ✓ Server stopped" | |
| popd | |
| fi | |
| - name: Step 8 - Validate Binary Packages | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [8/9]: Validate Binary Packages" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| BIN_PACKAGES=() | |
| for pkg in *.tar.gz; do | |
| if [[ "$pkg" != *-src.tar.gz ]] && [[ -f "$pkg" ]]; then | |
| BIN_PACKAGES+=("$pkg") | |
| fi | |
| done | |
| echo "Found ${#BIN_PACKAGES[@]} binary package(s)" | |
| for bin_pkg in "${BIN_PACKAGES[@]}"; do | |
| echo "" | |
| echo "Validating binary package: $bin_pkg" | |
| # Extract package | |
| PACKAGE_DIR=$(basename "$bin_pkg" .tar.gz) | |
| rm -rf "$PACKAGE_DIR" | |
| tar -xzf "$bin_pkg" | |
| if [[ ! -d "$PACKAGE_DIR" ]]; then | |
| echo "Error: Failed to extract package: $bin_pkg" | |
| exit 1 | |
| fi | |
| pushd "$PACKAGE_DIR" | |
| # 8.1: Check incubating name | |
| if [[ ! "$bin_pkg" =~ "incubating" ]]; then | |
| echo "Error: Package name '$bin_pkg' should include 'incubating'" | |
| exit 1 | |
| fi | |
| echo " ✓ Package name includes 'incubating'" | |
| # 8.2: Check required files | |
| if [[ ! -f "LICENSE" ]]; then | |
| echo "Error: Package '$bin_pkg' missing LICENSE file" | |
| exit 1 | |
| fi | |
| echo " ✓ LICENSE file exists" | |
| if [[ ! -f "NOTICE" ]]; then | |
| echo "Error: Package '$bin_pkg' missing NOTICE file" | |
| exit 1 | |
| fi | |
| echo " ✓ NOTICE file exists" | |
| if [[ ! -f "DISCLAIMER" ]]; then | |
| echo "Error: Package '$bin_pkg' missing DISCLAIMER file" | |
| exit 1 | |
| fi | |
| echo " ✓ DISCLAIMER file exists" | |
| # 8.3: Check licenses directory | |
| if [[ ! -d "licenses" ]]; then | |
| echo "Error: Package '$bin_pkg' missing licenses directory" | |
| exit 1 | |
| fi | |
| echo " ✓ licenses directory exists" | |
| # 8.4: Check license categories (Category X - Prohibited) | |
| CAT_X_MATCHES=$(grep -r -E "${{ env.CATEGORY_X }}" LICENSE NOTICE licenses 2>/dev/null || true) | |
| CAT_X_COUNT=$(echo "$CAT_X_MATCHES" | grep -v '^$' | wc -l | tr -d ' ') | |
| if [[ $CAT_X_COUNT -ne 0 ]]; then | |
| echo "Error: Package '$bin_pkg' contains $CAT_X_COUNT prohibited ASF Category X license(s):" | |
| echo "$CAT_X_MATCHES" | |
| exit 1 | |
| fi | |
| echo " ✓ No Category X licenses found" | |
| # 8.5: Check license categories (Category B - Warning) | |
| CAT_B_COUNT=$(grep -r -E "${{ env.CATEGORY_B }}" LICENSE NOTICE licenses 2>/dev/null | wc -l | tr -d ' ' || echo "0") | |
| if [[ $CAT_B_COUNT -ne 0 ]]; then | |
| echo " ⚠ Warning: Package '$bin_pkg' contains $CAT_B_COUNT ASF Category B license(s) - please verify documentation" | |
| else | |
| echo " ✓ No Category B licenses found" | |
| fi | |
| # 8.6: Check empty files and directories | |
| EMPTY_DIRS=$(find . -type d -empty 2>/dev/null || true) | |
| EMPTY_FILES=$(find . -type f -empty 2>/dev/null || true) | |
| if [[ -n "$EMPTY_DIRS" ]]; then | |
| echo "Error: Package '$bin_pkg' contains empty director(y/ies):" | |
| echo "$EMPTY_DIRS" | |
| exit 1 | |
| fi | |
| if [[ -n "$EMPTY_FILES" ]]; then | |
| echo "Error: Package '$bin_pkg' contains empty file(s):" | |
| echo "$EMPTY_FILES" | |
| exit 1 | |
| fi | |
| echo " ✓ No empty files or directories" | |
| popd | |
| echo "✓ Finished validating binary package: $bin_pkg" | |
| done | |
| - name: Step 9 - Test Binary Server & Toolchain | |
| run: | | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "Step [9/9]: Test Binary Server & Toolchain" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| cd dist/${{ env.RELEASE_VERSION }} | |
| # Test binary server | |
| BIN_SERVER_DIR=$(find . -maxdepth 3 -type d -path "*hugegraph-incubating*${{ env.RELEASE_VERSION }}/*hugegraph-server-incubating*${{ env.RELEASE_VERSION }}" 2>/dev/null | head -n1) | |
| if [[ -n "$BIN_SERVER_DIR" ]]; then | |
| echo "Testing binary server package..." | |
| pushd "$BIN_SERVER_DIR" | |
| if bin/init-store.sh && sleep ${{ env.SERVER_START_DELAY }} && bin/start-hugegraph.sh; then | |
| echo " ✓ Binary server started" | |
| else | |
| echo "Error: Failed to start binary server" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| # Test binary toolchain | |
| BIN_TOOLCHAIN=$(find . -maxdepth 3 -type d -path "*toolchain*${{ env.RELEASE_VERSION }}" 2>/dev/null | head -n1) | |
| if [[ -n "$BIN_TOOLCHAIN" ]]; then | |
| pushd "$BIN_TOOLCHAIN" | |
| # Test binary loader | |
| BIN_LOADER=$(find . -maxdepth 1 -type d -name "*loader*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$BIN_LOADER" ]]; then | |
| pushd "$BIN_LOADER" | |
| if bin/hugegraph-loader.sh -f ./example/file/struct.json -s ./example/file/schema.groovy -g hugegraph; then | |
| echo " ✓ Binary loader test passed" | |
| else | |
| echo "Error: Binary loader test failed" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| # Test binary tool | |
| BIN_TOOL=$(find . -maxdepth 1 -type d -name "*tool*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$BIN_TOOL" ]]; then | |
| pushd "$BIN_TOOL" | |
| if bin/hugegraph gremlin-execute --script 'g.V().count()' && \ | |
| bin/hugegraph task-list && \ | |
| bin/hugegraph backup -t all --directory ./backup-test; then | |
| echo " ✓ Binary tool test passed" | |
| else | |
| echo "Error: Binary tool test failed" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| # Test binary hubble | |
| BIN_HUBBLE=$(find . -maxdepth 1 -type d -name "*hubble*${{ env.RELEASE_VERSION }}" | head -n1) | |
| if [[ -n "$BIN_HUBBLE" ]]; then | |
| pushd "$BIN_HUBBLE" | |
| if bin/start-hubble.sh; then | |
| echo " ✓ Binary hubble started" | |
| sleep 2 | |
| bin/stop-hubble.sh | |
| echo " ✓ Binary hubble stopped" | |
| else | |
| echo "Error: Binary hubble test failed" | |
| exit 1 | |
| fi | |
| popd | |
| fi | |
| popd | |
| fi | |
| # Stop binary server | |
| if [[ -n "$BIN_SERVER_DIR" ]]; then | |
| pushd "$BIN_SERVER_DIR" | |
| bin/stop-hugegraph.sh | |
| echo " ✓ Binary server stopped" | |
| popd | |
| fi | |
| echo "" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo " VALIDATION SUMMARY " | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "" | |
| echo "✓ VALIDATION PASSED" | |
| echo "" | |
| echo "Please review the validation results and provide feedback in the" | |
| echo "release voting thread on the mailing list." | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| java_version: ['11'] | |
| os: [ubuntu-latest, macos-latest] | |