Move Java wrappers to FFM using jextract and java 25 (#5957)

FFM build requires Java 25, Jextract 25.
Generates FFM bindings during configure.
JNI is default when the requirements are not met or can be forced.
Presets added for maven and FFM - JNI is default selection.
Enhanced Maven options will work with either JNI or FFM
New Workflows for testing and maven uploads.
Extensive documentation changes for java.
This commit is contained in:
Allen Byrne
2025-11-04 14:03:06 -06:00
committed by GitHub
parent 18297c1923
commit b754dcb8f2
621 changed files with 104632 additions and 4346 deletions
+187
View File
@@ -0,0 +1,187 @@
name: 'Setup jextract'
description: 'Install jextract for FFM binding generation across all platforms'
inputs:
java-version:
description: 'Java version for jextract (24, 25, latest)'
required: false
default: '25'
outputs:
jextract-home:
description: 'Path to jextract installation'
value: ${{ steps.setup-jextract.outputs.jextract-home }}
jextract-version:
description: 'Version of jextract installed'
value: ${{ steps.setup-jextract.outputs.jextract-version }}
runs:
using: 'composite'
steps:
- name: Setup jextract (Linux/macOS)
id: setup-jextract-unix
if: runner.os != 'Windows'
shell: bash
run: |
echo "Installing jextract for $RUNNER_OS..."
# Determine platform
if [[ "$RUNNER_OS" == "macOS" ]]; then
PLATFORM="macos-x64"
else
PLATFORM="linux-x64"
fi
# Try different jextract versions (from latest to older)
# Check https://jdk.java.net/jextract/ for available builds
JEXTRACT_URLS=(
"https://download.java.net/java/early_access/jextract/22/6/openjdk-22-jextract+6-47_${PLATFORM}_bin.tar.gz"
"https://download.java.net/java/early_access/jextract/21/5/openjdk-21-jextract+5-31_${PLATFORM}_bin.tar.gz"
"https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_${PLATFORM}_bin.tar.gz"
)
mkdir -p $HOME/jextract
cd $HOME/jextract
SUCCESS=false
for URL in "${JEXTRACT_URLS[@]}"; do
echo "Trying to download from: $URL"
if curl -L -f -o jextract.tar.gz "$URL" 2>/dev/null; then
echo "✓ Download successful from $URL"
tar -xzf jextract.tar.gz --strip-components=1
rm jextract.tar.gz
SUCCESS=true
break
else
echo "✗ Failed to download from $URL, trying next..."
fi
done
if [ "$SUCCESS" = false ]; then
echo "ERROR: Failed to download jextract from any known source"
echo "Please check https://jdk.java.net/jextract/ for available builds"
exit 1
fi
# Set outputs
echo "jextract-home=$HOME/jextract" >> $GITHUB_OUTPUT
# Verify installation
if $HOME/jextract/bin/jextract --version 2>&1; then
VERSION=$($HOME/jextract/bin/jextract --version 2>&1 | head -1 || echo "unknown")
echo "jextract-version=$VERSION" >> $GITHUB_OUTPUT
echo "✓ jextract installed successfully: $VERSION"
else
echo "jextract-version=unknown" >> $GITHUB_OUTPUT
echo "✓ jextract installed (version check not supported)"
fi
- name: Setup jextract (Windows)
id: setup-jextract-windows
if: runner.os == 'Windows'
shell: pwsh
run: |
Write-Host "Installing jextract for Windows..."
# Try multiple jextract versions (latest to older)
# Windows now uses .tar.gz format
$JextractUrls = @(
"https://download.java.net/java/early_access/jextract/22/6/openjdk-22-jextract+6-47_windows-x64_bin.tar.gz",
"https://download.java.net/java/early_access/jextract/21/5/openjdk-21-jextract+5-31_windows-x64_bin.tar.gz",
"https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_windows-x64_bin.tar.gz"
)
$JextractHome = "$env:USERPROFILE\jextract"
New-Item -ItemType Directory -Force -Path $JextractHome | Out-Null
$Success = $false
foreach ($Url in $JextractUrls) {
Write-Host "Trying to download from: $Url"
$TarPath = "$JextractHome\jextract.tar.gz"
try {
Invoke-WebRequest -Uri $Url -OutFile $TarPath -ErrorAction Stop
Write-Host "✓ Download successful from $Url"
# Extract using tar (available in Windows 10+)
$TempExtract = "$JextractHome\temp"
New-Item -ItemType Directory -Force -Path $TempExtract | Out-Null
tar -xzf "$TarPath" -C "$TempExtract" 2>&1 | Out-Null
# Find jextract.bat
$JextractBat = Get-ChildItem -Path $TempExtract -Filter "jextract.bat" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($JextractBat) {
Write-Host "Found jextract.bat at: $($JextractBat.FullName)"
# Move contents to JextractHome
$JextractRoot = $JextractBat.Directory.Parent.FullName
Get-ChildItem -Path $JextractRoot | ForEach-Object {
Move-Item -Path $_.FullName -Destination $JextractHome -Force
}
# Clean up
Remove-Item -Path $TempExtract -Recurse -Force
Remove-Item -Path $TarPath -Force
# Verify
if (Test-Path "$JextractHome\bin\jextract.bat") {
Write-Host "✓ jextract extracted successfully to $JextractHome"
$Success = $true
break
}
} else {
Write-Host "✗ Could not find jextract.bat in extracted files"
Remove-Item -Path $TempExtract -Recurse -Force -ErrorAction SilentlyContinue
}
}
catch {
Write-Host "✗ Failed to download or extract from $Url"
Write-Host "Error: $_"
}
}
if (-not $Success) {
Write-Host "ERROR: Failed to download jextract from any known source"
Write-Host "Please check https://jdk.java.net/jextract/ for available builds"
exit 1
}
# Set outputs
echo "jextract-home=$JextractHome" >> $env:GITHUB_OUTPUT
# Verify installation
try {
$Version = & "$JextractHome\bin\jextract.bat" --version 2>&1 | Select-Object -First 1
echo "jextract-version=$Version" >> $env:GITHUB_OUTPUT
Write-Host "✓ jextract installed successfully: $Version"
} catch {
echo "jextract-version=unknown" >> $env:GITHUB_OUTPUT
Write-Host "✓ jextract installed (version check not supported)"
}
- name: Set environment variables
id: setup-jextract
shell: bash
run: |
if [[ "$RUNNER_OS" == "Windows" ]]; then
JEXTRACT_HOME="${{ steps.setup-jextract-windows.outputs.jextract-home }}"
JEXTRACT_VERSION="${{ steps.setup-jextract-windows.outputs.jextract-version }}"
else
JEXTRACT_HOME="${{ steps.setup-jextract-unix.outputs.jextract-home }}"
JEXTRACT_VERSION="${{ steps.setup-jextract-unix.outputs.jextract-version }}"
fi
echo "JEXTRACT_HOME=$JEXTRACT_HOME" >> $GITHUB_ENV
echo "jextract-home=$JEXTRACT_HOME" >> $GITHUB_OUTPUT
echo "jextract-version=$JEXTRACT_VERSION" >> $GITHUB_OUTPUT
# Add to PATH
if [[ "$RUNNER_OS" == "Windows" ]]; then
echo "$JEXTRACT_HOME\bin" >> $GITHUB_PATH
else
echo "$JEXTRACT_HOME/bin" >> $GITHUB_PATH
fi
echo "✓ jextract setup complete"
echo " JEXTRACT_HOME=$JEXTRACT_HOME"
echo " Version: $JEXTRACT_VERSION"
+379
View File
@@ -0,0 +1,379 @@
#!/bin/bash
# Test script for validating Java FFM and JNI implementations across different Java versions
# Usage: test-java-implementations.sh [java_version] [implementation] [test_mode]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
# Default values
JAVA_VERSION="${1:-24}"
IMPLEMENTATION="${2:-auto}" # auto, ffm, jni
TEST_MODE="${3:-build}" # build, maven, full
# 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"
}
# Test matrix configuration
declare -A JAVA_VERSIONS=(
["11"]="JNI only"
["17"]="JNI only"
["21"]="JNI only"
["24"]="JNI default, FFM optional"
["25"]="JNI default, FFM optional"
)
declare -A TEST_PRESETS_FFM=(
["build"]="ci-StdShar-GNUC-FFM"
["maven"]="ci-MinShar-GNUC-Maven-FFM"
)
declare -A TEST_PRESETS_JNI=(
["build"]="ci-StdShar-GNUC"
["maven"]="ci-MinShar-GNUC-Maven"
)
# Validate Java version support
validate_java_version() {
local version=$1
local impl=$2
if [[ ! ${JAVA_VERSIONS[$version]+_} ]]; then
log_error "Unsupported Java version: $version"
log_info "Supported versions: ${!JAVA_VERSIONS[@]}"
return 1
fi
if [[ $version -lt 25 && "$impl" == "ffm" ]]; then
log_error "FFM implementation requires Java 25, got Java $version"
return 1
fi
log_info "Java $version validation: ${JAVA_VERSIONS[$version]}"
return 0
}
# Determine implementation based on Java version and user preference
determine_implementation() {
local version=$1
local requested=$2
case "$requested" in
"auto")
# JNI is default for HDF5 2.0, regardless of Java version
echo "jni"
;;
"ffm")
if [[ $version -ge 25 ]]; then
echo "ffm"
else
log_error "FFM requires Java 25+, got Java $version"
return 1
fi
;;
"jni")
echo "jni"
;;
*)
log_error "Invalid implementation: $requested (use auto, ffm, or jni)"
return 1
;;
esac
}
# Create build directory with unique name
create_build_dir() {
local impl=$1
local mode=$2
BUILD_DIR="${PROJECT_ROOT}/build-test-java${JAVA_VERSION}-${impl}-${mode}"
if [[ -d "$BUILD_DIR" ]]; then
log_warning "Removing existing build directory: $BUILD_DIR"
rm -rf "$BUILD_DIR"
fi
mkdir -p "$BUILD_DIR"
log_info "Created build directory: $BUILD_DIR"
}
# Test basic build configuration
test_build_config() {
local impl=$1
local preset_key="build"
log_info "Testing $impl build configuration..."
if [[ "$impl" == "ffm" ]]; then
preset=${TEST_PRESETS_FFM[$preset_key]}
else
preset=${TEST_PRESETS_JNI[$preset_key]}
fi
log_info "Using preset: $preset"
cd "$PROJECT_ROOT"
# Configure with preset
if ! cmake --preset "$preset" -B "$BUILD_DIR"; then
log_error "CMake configuration failed for $impl implementation"
return 1
fi
# Verify implementation detection
# Note: CMake uses HDF5_ENABLE_JNI (not HDF5_ENABLE_FFM)
# JNI enabled (ON or not set) = JNI implementation
# JNI disabled (OFF) = FFM implementation
if [ "$impl" = "jni" ]; then
# For JNI, verify it's not explicitly disabled
if grep -q "HDF5_ENABLE_JNI:BOOL=OFF" "$BUILD_DIR/CMakeCache.txt"; then
log_error "Implementation detection failed - expected JNI but found HDF5_ENABLE_JNI=OFF"
cat "$BUILD_DIR/CMakeCache.txt" | grep "HDF5_ENABLE_JNI" || true
return 1
fi
log_info "JNI implementation verified (HDF5_ENABLE_JNI not OFF)"
elif [ "$impl" = "ffm" ]; then
# For FFM, verify JNI is explicitly disabled
if ! grep -q "HDF5_ENABLE_JNI:BOOL=OFF" "$BUILD_DIR/CMakeCache.txt"; then
log_error "Implementation detection failed - expected HDF5_ENABLE_JNI=OFF for FFM"
cat "$BUILD_DIR/CMakeCache.txt" | grep "HDF5_ENABLE_JNI" || true
return 1
fi
log_info "FFM implementation verified (HDF5_ENABLE_JNI=OFF)"
fi
log_success "Build configuration test passed for $impl"
return 0
}
# Test Maven artifact generation
test_maven_artifacts() {
local impl=$1
local preset_key="maven"
log_info "Testing $impl Maven artifact generation..."
if [[ "$impl" == "ffm" ]]; then
preset=${TEST_PRESETS_FFM[$preset_key]}
expected_artifact="hdf5-java-ffm"
else
preset=${TEST_PRESETS_JNI[$preset_key]}
expected_artifact="hdf5-java-jni"
fi
cd "$PROJECT_ROOT"
# Configure with Maven preset
if ! cmake --preset "$preset" -B "$BUILD_DIR"; then
log_error "Maven configuration failed for $impl implementation"
return 1
fi
# Build the project
if ! cmake --build "$BUILD_DIR" --parallel 4; then
log_error "Build failed for $impl implementation"
return 1
fi
# Verify artifact generation
jar_pattern="$BUILD_DIR/java/**/target/${expected_artifact}-*.jar"
if ! ls $jar_pattern 1> /dev/null 2>&1; then
log_error "Expected JAR artifact not found: $expected_artifact"
log_info "Looking for JARs in build directory:"
find "$BUILD_DIR" -name "*.jar" -type f || true
return 1
fi
# Verify JAR manifest
jar_file=$(ls $jar_pattern | head -1)
log_info "Checking JAR manifest: $jar_file"
if ! unzip -q -c "$jar_file" META-INF/MANIFEST.MF | grep -q "HDF5-Java-Implementation: ${impl^^}"; then
log_error "JAR manifest missing implementation metadata"
unzip -q -c "$jar_file" META-INF/MANIFEST.MF || true
return 1
fi
log_success "Maven artifact test passed for $impl"
return 0
}
# Test POM file generation
test_pom_generation() {
local impl=$1
log_info "Testing POM file generation for $impl..."
if [[ "$impl" == "ffm" ]]; then
expected_artifact="hdf5-java-ffm"
expected_desc="Java Foreign Function"
else
expected_artifact="hdf5-java-jni"
expected_desc="Java Native Interface"
fi
# Find generated POM file
pom_file=$(find "$BUILD_DIR" -name "pom.xml" -path "*/java/*" | head -1)
if [[ ! -f "$pom_file" ]]; then
log_error "POM file not found for $impl implementation"
return 1
fi
log_info "Checking POM file: $pom_file"
# Verify artifact ID
if ! grep -q "<artifactId>$expected_artifact</artifactId>" "$pom_file"; then
log_error "POM artifact ID incorrect - expected $expected_artifact"
grep "<artifactId>" "$pom_file" || true
return 1
fi
# Verify description
if ! grep -q "$expected_desc" "$pom_file"; then
log_error "POM description missing expected text: $expected_desc"
grep "<description>" "$pom_file" || true
return 1
fi
log_success "POM generation test passed for $impl"
return 0
}
# Run comprehensive test suite
run_test_suite() {
local impl=$1
local mode=$2
log_info "Running test suite for Java $JAVA_VERSION with $impl implementation (mode: $mode)"
case "$mode" in
"build")
create_build_dir "$impl" "build"
test_build_config "$impl"
;;
"maven")
create_build_dir "$impl" "maven"
test_maven_artifacts "$impl"
test_pom_generation "$impl"
;;
"full")
create_build_dir "$impl" "build"
test_build_config "$impl"
create_build_dir "$impl" "maven"
test_maven_artifacts "$impl"
test_pom_generation "$impl"
;;
*)
log_error "Invalid test mode: $mode (use build, maven, or full)"
return 1
;;
esac
}
# Cleanup function
cleanup() {
if [[ -n "${BUILD_DIR:-}" && -d "$BUILD_DIR" ]]; then
log_info "Cleaning up build directory: $BUILD_DIR"
rm -rf "$BUILD_DIR"
fi
}
# Main execution
main() {
log_info "Java Implementation Test Suite"
log_info "=============================="
log_info "Java Version: $JAVA_VERSION"
log_info "Implementation: $IMPLEMENTATION"
log_info "Test Mode: $TEST_MODE"
log_info ""
# Validate inputs
if ! validate_java_version "$JAVA_VERSION" "$IMPLEMENTATION"; then
exit 1
fi
# Determine actual implementation
actual_impl=$(determine_implementation "$JAVA_VERSION" "$IMPLEMENTATION")
if [[ $? -ne 0 ]]; then
exit 1
fi
log_info "Selected implementation: $actual_impl"
log_info ""
# Set trap for cleanup
trap cleanup EXIT
# Run tests
if run_test_suite "$actual_impl" "$TEST_MODE"; then
log_success "All tests passed for Java $JAVA_VERSION with $actual_impl implementation!"
exit 0
else
log_error "Tests failed for Java $JAVA_VERSION with $actual_impl implementation"
exit 1
fi
}
# Help function
show_help() {
cat << EOF
Java Implementation Test Suite
Usage: $0 [java_version] [implementation] [test_mode]
Arguments:
java_version Java version to test (11, 17, 21, 24, 25) [default: 24] (25+ required for FFM)
implementation Implementation to test (auto, ffm, jni) [default: auto]
test_mode Test mode (build, maven, full) [default: build]
Examples:
$0 # Test Java 25 with auto implementation (JNI - default)
$0 25 ffm build # Test Java 25 with FFM (optional), build only
$0 11 jni maven # Test Java 11 with JNI, Maven artifacts
$0 25 auto full # Test Java 25 with auto selection (JNI), full suite
Test Modes:
build - Basic build configuration test
maven - Maven artifact generation and validation
full - Both build and Maven tests
Supported Matrix:
EOF
for version in "${!JAVA_VERSIONS[@]}"; do
echo " Java $version: ${JAVA_VERSIONS[$version]}"
done
}
# Check for help request
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
show_help
exit 0
fi
# Run main function
main
+126
View File
@@ -0,0 +1,126 @@
#!/bin/bash
# Test script to validate deployed Maven artifacts
# Usage: ./test-maven-consumer.sh [version] [repository-url]
set -e
VERSION="${1:-2.0.0-3}"
REPOSITORY_URL="${2:-https://maven.pkg.github.com/HDFGroup/hdf5}"
echo "=== Testing HDF5 Maven Artifacts ==="
echo "Version: ${VERSION}"
echo "Repository: ${REPOSITORY_URL}"
echo ""
# Create temporary test directory
TEST_DIR=$(mktemp -d)
echo "Test directory: ${TEST_DIR}"
cd "${TEST_DIR}"
# Create a simple Maven test project
cat > pom.xml << EOF
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hdfgroup.test</groupId>
<artifactId>hdf5-maven-test</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<hdf5.version>${VERSION}</hdf5.version>
</properties>
<repositories>
<repository>
<id>github-hdf5</id>
<url>${REPOSITORY_URL}</url>
</repository>
</repositories>
<dependencies>
<!-- HDF5 Java Library (platform-specific) -->
<dependency>
<groupId>org.hdfgroup</groupId>
<artifactId>hdf5-java</artifactId>
<version>\${hdf5.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<!-- HDF5 Java Examples -->
<dependency>
<groupId>org.hdfgroup</groupId>
<artifactId>hdf5-java-examples</artifactId>
<version>\${hdf5.version}</version>
</dependency>
</dependencies>
</project>
EOF
# Create a simple test class
mkdir -p src/main/java/org/hdfgroup/test
cat > src/main/java/org/hdfgroup/test/TestConsumer.java << 'EOF'
package org.hdfgroup.test;
public class TestConsumer {
public static void main(String[] args) {
System.out.println("Testing HDF5 Maven artifact consumption...");
try {
// Try to load HDF5 Java classes
Class.forName("hdf.hdf5lib.H5");
System.out.println("✓ HDF5 Java library classes found");
} catch (ClassNotFoundException e) {
System.out.println("⚠ HDF5 Java library classes not found: " + e.getMessage());
}
System.out.println("✓ Maven artifact consumption test completed");
}
}
EOF
echo "=== Testing Maven Dependency Resolution ==="
# Test dependency resolution
if mvn dependency:resolve -q; then
echo "✓ Maven dependencies resolved successfully"
else
echo "❌ Maven dependency resolution failed"
exit 1
fi
# Test compilation
echo "=== Testing Compilation ==="
if mvn compile -q; then
echo "✓ Compilation successful"
else
echo "❌ Compilation failed"
exit 1
fi
# List resolved dependencies
echo "=== Resolved Dependencies ==="
mvn dependency:list | grep org.hdfgroup || echo "No org.hdfgroup dependencies found"
# Show artifact details
echo "=== Artifact Details ==="
find ~/.m2/repository/org/hdfgroup -name "*.jar" 2>/dev/null | head -10 | while read jar; do
echo "Found: $(basename "$jar") ($(du -h "$jar" | cut -f1))"
done
echo ""
echo "=== Test Summary ==="
echo "✓ Maven artifact consumption test completed successfully"
echo "✓ HDF5 Java artifacts are accessible via Maven"
echo "✓ Dependencies resolve and compile correctly"
echo ""
echo "Cleanup: rm -rf ${TEST_DIR}"
# Cleanup
cd /
rm -rf "${TEST_DIR}"
+579
View File
@@ -0,0 +1,579 @@
#!/bin/bash
#
# Enhanced validation framework for Maven artifacts before deployment
# This script validates JAR files, POM files, and deployment readiness
#
set -euo pipefail
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
ARTIFACTS_DIR="${1:-./artifacts}"
VALIDATION_LOG="/tmp/maven-validation-$(date +%s).log"
# 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} $*" | tee -a "${VALIDATION_LOG}"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $*" | tee -a "${VALIDATION_LOG}"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" | tee -a "${VALIDATION_LOG}"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $*" | tee -a "${VALIDATION_LOG}"
}
# Validation counters
VALIDATION_ERRORS=0
VALIDATION_WARNINGS=0
# Error tracking
add_error() {
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
log_error "$*"
}
add_warning() {
VALIDATION_WARNINGS=$((VALIDATION_WARNINGS + 1))
log_warn "$*"
}
# Java/Maven environment validation
validate_environment() {
log_info "Validating build environment..."
# Check Java availability
if ! command -v java &> /dev/null; then
add_error "Java is not installed or not in PATH"
return 1
fi
JAVA_VERSION=$(java -version 2>&1 | head -n1 | cut -d'"' -f2)
log_info "Java version: ${JAVA_VERSION}"
# Check Maven availability
if ! command -v mvn &> /dev/null; then
add_warning "Maven is not installed - some validations will be skipped"
else
MVN_VERSION=$(mvn -version | head -n1 | cut -d' ' -f3)
log_info "Maven version: ${MVN_VERSION}"
fi
# Check JAR command
if ! command -v jar &> /dev/null; then
add_error "jar command is not available"
return 1
fi
log_success "Environment validation completed"
return 0
}
# JAR file validation
validate_jar_file() {
local jar_file="$1"
local jar_basename
jar_basename=$(basename "${jar_file}")
log_info "Validating JAR: ${jar_basename}"
# Check file exists and is readable
if [[ ! -f "${jar_file}" ]]; then
add_error "JAR file not found: ${jar_file}"
return 1
fi
if [[ ! -r "${jar_file}" ]]; then
add_error "JAR file not readable: ${jar_file}"
return 1
fi
# Check file size (must be > 1KB)
local file_size
file_size=$(stat -c%s "${jar_file}" 2>/dev/null || stat -f%z "${jar_file}" 2>/dev/null || echo "0")
if [[ ${file_size} -lt 1024 ]]; then
add_error "JAR file too small: ${jar_file} (${file_size} bytes)"
return 1
fi
log_info "JAR size: ${file_size} bytes"
# Test JAR integrity
if ! jar tf "${jar_file}" > /dev/null 2>&1; then
add_error "JAR file is corrupted or invalid: ${jar_file}"
return 1
fi
# Check for required HDF5 Java classes
local temp_dir
temp_dir=$(mktemp -d)
trap "rm -rf '${temp_dir}'" EXIT
if ! (cd "${temp_dir}" && jar xf "${jar_file}"); then
add_error "Failed to extract JAR: ${jar_file}"
rm -rf "${temp_dir}"
return 1
fi
# Check for essential HDF5 classes based on JAR type
# FFM builds have two separate JARs:
# - javahdf5-*.jar: FFM bindings (org/hdfgroup/javahdf5/*)
# - jarhdf5-*.jar: Wrapper classes (hdf/hdf5lib/*)
# JNI builds have single JAR with hdf/hdf5lib/* classes
if [[ "${jar_basename}" == *"javahdf5"* ]]; then
# This is the FFM bindings JAR - check for FFM classes
local ffm_classes=(
"org/hdfgroup/javahdf5/hdf5_h.class"
)
local has_ffm=false
for class_file in "${ffm_classes[@]}"; do
if [[ -f "${temp_dir}/${class_file}" ]]; then
has_ffm=true
log_info "Found FFM binding class: ${class_file}"
break
fi
done
if [[ "${has_ffm}" == "false" ]]; then
add_error "FFM bindings JAR missing required FFM classes (expected org/hdfgroup/javahdf5/hdf5_h.class)"
fi
else
# This is a wrapper/JNI JAR - check for hdf.hdf5lib classes
local required_classes=(
"hdf/hdf5lib/H5.class"
"hdf/hdf5lib/HDF5Constants.class"
"hdf/hdf5lib/HDFArray.class"
"hdf/hdf5lib/HDFNativeData.class"
)
for class_file in "${required_classes[@]}"; do
if [[ ! -f "${temp_dir}/${class_file}" ]]; then
add_error "Missing required class in JAR: ${class_file}"
fi
done
fi
# Check manifest
if [[ -f "${temp_dir}/META-INF/MANIFEST.MF" ]]; then
if grep -q "Enable-Native-Access: ALL-UNNAMED" "${temp_dir}/META-INF/MANIFEST.MF"; then
log_info "Native access enabled in manifest"
else
add_warning "Native access not found in manifest - may cause runtime issues"
fi
else
add_warning "No manifest found in JAR"
fi
rm -rf "${temp_dir}"
log_success "JAR validation completed: ${jar_basename}"
return 0
}
# POM file validation
validate_pom_file() {
local pom_file="$1"
log_info "Validating POM: $(basename "${pom_file}")"
# Check file exists
if [[ ! -f "${pom_file}" ]]; then
add_error "POM file not found: ${pom_file}"
return 1
fi
# Check XML validity
if command -v xmllint &> /dev/null; then
if ! xmllint --noout "${pom_file}" 2>/dev/null; then
add_error "POM file is not valid XML: ${pom_file}"
return 1
fi
else
add_warning "xmllint not available - skipping XML validation"
fi
# Check required Maven coordinates
if ! grep -q "<groupId>org.hdfgroup</groupId>" "${pom_file}"; then
add_error "Invalid or missing groupId in POM"
fi
if ! grep -qE "<artifactId>hdf5-java(-ffm|-jni)?</artifactId>" "${pom_file}"; then
add_error "Invalid or missing artifactId in POM (expected hdf5-java, hdf5-java-ffm, or hdf5-java-jni)"
fi
# Extract version
local version
version=$(grep -o '<version>[^<]*</version>' "${pom_file}" | head -1 | sed 's/<[^>]*>//g' || echo "")
if [[ -z "${version}" ]]; then
add_error "No version found in POM"
else
log_info "POM version: ${version}"
# Validate version format
if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?(-SNAPSHOT)?$ ]]; then
add_warning "Version format may not comply with Maven conventions: ${version}"
fi
fi
# Check for required sections
local required_sections=(
"<name>"
"<description>"
"<url>"
"<licenses>"
"<developers>"
"<scm>"
)
for section in "${required_sections[@]}"; do
if ! grep -q "${section}" "${pom_file}"; then
add_warning "Missing recommended section in POM: ${section}"
fi
done
# Check dependencies
if grep -q "<dependencies>" "${pom_file}"; then
log_info "Dependencies section found in POM"
else
add_warning "No dependencies section in POM"
fi
log_success "POM validation completed"
return 0
}
# Version consistency validation
validate_version_consistency() {
local pom_file="$1"
shift
local jar_files=("$@")
log_info "Validating version consistency across artifacts..."
# Extract version from POM
local pom_version
pom_version=$(grep -o '<version>[^<]*</version>' "${pom_file}" | head -1 | sed 's/<[^>]*>//g' || echo "")
if [[ -z "${pom_version}" ]]; then
add_error "Cannot extract version from POM for consistency check"
return 1
fi
log_info "POM version: ${pom_version}"
# Check JAR filenames for version consistency
for jar_file in "${jar_files[@]}"; do
local jar_basename
jar_basename=$(basename "${jar_file}")
# Extract version from JAR filename (allowing for classifiers)
local jar_version
jar_version=$(echo "${jar_basename}" | sed -E 's/.*-([0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?(-SNAPSHOT)?)(-[^.]+)?\.jar$/\1/' || echo "")
if [[ -z "${jar_version}" ]]; then
add_warning "Cannot extract version from JAR filename: ${jar_basename}"
elif [[ "${jar_version}" != "${pom_version}" ]]; then
add_error "Version mismatch: POM=${pom_version}, JAR=${jar_version} (${jar_basename})"
else
log_info "Version consistency verified: ${jar_basename}"
fi
done
return 0
}
# Platform classifier validation
validate_platform_classifiers() {
local jar_files=("$@")
log_info "Validating platform classifiers..."
local valid_classifiers=(
"linux-x86_64"
"windows-x86_64"
"macos-x86_64"
"macos-aarch64"
)
for jar_file in "${jar_files[@]}"; do
local jar_basename
jar_basename=$(basename "${jar_file}")
# Skip universal JARs (no classifier)
if [[ ! "${jar_basename}" =~ -[a-z]+-[a-z0-9_]+\.jar$ ]]; then
log_info "Universal JAR (no classifier): ${jar_basename}"
continue
fi
# Extract classifier
local classifier
classifier=$(echo "${jar_basename}" | sed -E 's/.*-([a-z]+-[a-z0-9_]+)\.jar$/\1/' || echo "")
if [[ -z "${classifier}" ]]; then
add_warning "Cannot extract classifier from JAR: ${jar_basename}"
continue
fi
# Validate classifier
local valid=false
for valid_classifier in "${valid_classifiers[@]}"; do
if [[ "${classifier}" == "${valid_classifier}" ]]; then
valid=true
break
fi
done
if [[ "${valid}" == "true" ]]; then
log_info "Valid platform classifier: ${classifier} (${jar_basename})"
else
add_error "Invalid platform classifier: ${classifier} (${jar_basename})"
fi
done
return 0
}
# Maven dependency simulation
simulate_maven_dependency() {
local pom_file="$1"
if ! command -v mvn &> /dev/null; then
add_warning "Maven not available - skipping dependency simulation"
return 0
fi
log_info "Simulating Maven dependency resolution..."
# Create temporary Maven project
local temp_project
temp_project=$(mktemp -d)
trap "rm -rf '${temp_project}'" EXIT
# Extract coordinates from POM
local group_id artifact_id version
group_id=$(grep -o '<groupId>[^<]*</groupId>' "${pom_file}" | head -1 | sed 's/<[^>]*>//g' || echo "")
artifact_id=$(grep -o '<artifactId>[^<]*</artifactId>' "${pom_file}" | head -1 | sed 's/<[^>]*>//g' || echo "")
version=$(grep -o '<version>[^<]*</version>' "${pom_file}" | head -1 | sed 's/<[^>]*>//g' || echo "")
# Find the JAR file in the artifacts directory
local jar_file
jar_file=$(find "$(dirname "${pom_file}")" -maxdepth 2 -name "${artifact_id}-${version}.jar" -o -name "${artifact_id}-*.jar" | head -1)
if [ -z "${jar_file}" ]; then
add_warning "Could not find JAR file for ${artifact_id}:${version} - skipping dependency simulation"
return 0
fi
# Install artifact to local Maven repository first
log_info "Installing artifact to local Maven repository: ${group_id}:${artifact_id}:${version}"
if ! mvn install:install-file \
-Dfile="${jar_file}" \
-DgroupId="${group_id}" \
-DartifactId="${artifact_id}" \
-Dversion="${version}" \
-Dpackaging=jar \
-DpomFile="${pom_file}" \
-q 2>&1 | tee -a "${VALIDATION_LOG}"; then
add_warning "Failed to install artifact to local Maven repository"
return 0
fi
# Create test POM
cat > "${temp_project}/pom.xml" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>maven-validation-test</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>${group_id}</groupId>
<artifactId>${artifact_id}</artifactId>
<version>${version}</version>
</dependency>
</dependencies>
</project>
EOF
# Test dependency resolution
if (cd "${temp_project}" && mvn dependency:resolve -q); then
log_success "Maven dependency simulation passed"
else
add_warning "Maven dependency simulation failed - may indicate packaging issues"
fi
rm -rf "${temp_project}"
return 0
}
# Deployment readiness check
check_deployment_readiness() {
local artifacts_dir="$1"
log_info "Checking deployment readiness..."
# Check for required files
local jar_files pom_files
# Only count HDF5 JAR files, exclude dependencies like slf4j
jar_files=($(find "${artifacts_dir}" -name "*hdf5*.jar" -not -name "*test*" 2>/dev/null || true))
pom_files=($(find "${artifacts_dir}" -name "pom.xml" 2>/dev/null || true))
if [[ ${#jar_files[@]} -eq 0 ]]; then
add_error "No JAR files found in artifacts directory"
return 1
fi
if [[ ${#pom_files[@]} -eq 0 ]]; then
add_error "No POM files found in artifacts directory"
return 1
fi
log_info "Found ${#jar_files[@]} JAR file(s) and ${#pom_files[@]} POM file(s)"
# Check environment variables for deployment
if [[ -z "${MAVEN_USERNAME:-}" ]]; then
add_warning "MAVEN_USERNAME not set - deployment will fail"
fi
if [[ -z "${MAVEN_PASSWORD:-}" ]]; then
add_warning "MAVEN_PASSWORD not set - deployment will fail"
fi
return 0
}
# Generate validation report
generate_report() {
local artifacts_dir="$1"
log_info "=== Maven Artifact Validation Report ==="
log_info "Timestamp: $(date)"
log_info "Artifacts directory: ${artifacts_dir}"
log_info "Validation log: ${VALIDATION_LOG}"
echo
# Summary
if [[ ${VALIDATION_ERRORS} -eq 0 ]]; then
if [[ ${VALIDATION_WARNINGS} -eq 0 ]]; then
log_success "✅ All validations passed with no warnings"
else
log_warn "⚠️ All validations passed with ${VALIDATION_WARNINGS} warning(s)"
fi
else
log_error "❌ Validation failed with ${VALIDATION_ERRORS} error(s) and ${VALIDATION_WARNINGS} warning(s)"
fi
echo
log_info "Full validation log available at: ${VALIDATION_LOG}"
return ${VALIDATION_ERRORS}
}
# Main validation function
main() {
local artifacts_dir="${1:-./artifacts}"
log_info "Starting Maven artifact validation..."
log_info "Artifacts directory: ${artifacts_dir}"
# Check artifacts directory
if [[ ! -d "${artifacts_dir}" ]]; then
add_error "Artifacts directory not found: ${artifacts_dir}"
generate_report "${artifacts_dir}"
exit 1
fi
# Environment validation
validate_environment
# Find artifacts
local jar_files pom_files all_jars
# Only validate HDF5 JAR files, exclude dependencies like slf4j
jar_files=($(find "${artifacts_dir}" -name "*hdf5*.jar" -not -name "*test*" 2>/dev/null || true))
pom_files=($(find "${artifacts_dir}" -name "pom.xml" 2>/dev/null || true))
all_jars=($(find "${artifacts_dir}" -name "*.jar" 2>/dev/null || true))
# Log what we found
log_info "Found ${#all_jars[@]} total JAR file(s), ${#jar_files[@]} HDF5 JAR file(s) to validate"
if [[ ${#all_jars[@]} -gt ${#jar_files[@]} ]]; then
log_info "Skipping non-HDF5 JAR files (dependencies like slf4j, etc.)"
for jar in "${all_jars[@]}"; do
if [[ ! "$(basename "$jar")" =~ hdf5 ]]; then
log_info " Skipping: $(basename "$jar")"
fi
done
fi
# Basic readiness check
check_deployment_readiness "${artifacts_dir}"
# Validate each JAR file
for jar_file in "${jar_files[@]}"; do
validate_jar_file "${jar_file}"
done
# Validate each POM file
for pom_file in "${pom_files[@]}"; do
validate_pom_file "${pom_file}"
done
# Version consistency check
if [[ ${#pom_files[@]} -gt 0 && ${#jar_files[@]} -gt 0 ]]; then
validate_version_consistency "${pom_files[0]}" "${jar_files[@]}"
fi
# Platform classifier validation
if [[ ${#jar_files[@]} -gt 0 ]]; then
validate_platform_classifiers "${jar_files[@]}"
fi
# Maven dependency simulation
if [[ ${#pom_files[@]} -gt 0 ]]; then
simulate_maven_dependency "${pom_files[0]}"
fi
# Generate final report
generate_report "${artifacts_dir}"
exit ${VALIDATION_ERRORS}
}
# Show usage if no arguments provided
if [[ $# -eq 0 ]]; then
echo "Usage: $0 <artifacts_directory>"
echo
echo "Enhanced validation framework for Maven artifacts before deployment"
echo
echo "This script validates:"
echo " - JAR file integrity and content"
echo " - POM file structure and compliance"
echo " - Version consistency across artifacts"
echo " - Platform classifier conventions"
echo " - Maven dependency resolution simulation"
echo " - Deployment readiness"
echo
echo "Environment variables:"
echo " MAVEN_USERNAME - Maven repository username (optional for validation)"
echo " MAVEN_PASSWORD - Maven repository password (optional for validation)"
echo
exit 1
fi
# Run main function with arguments
main "$@"
+4
View File
@@ -35,7 +35,10 @@ There are a few that only get triggered manually.
* tarball.yml to create a source.zip and source.tar.gz
* ctest.yml to create signed binaries
* abi-report.yml to compare ABI to last released binaries
* maven-staging.yml to generate and test Maven artifacts with Java examples across all platforms
* maven-deploy.yml to deploy Maven artifacts to repositories
* release-files.yml uploads new binaries to releases page
- java-examples-maven-test.yml comprehensive Java examples testing with Maven artifacts
## Triggered Workflows
- clang-format-check.yml runs clang-format and reports issues
@@ -61,6 +64,7 @@ There are a few that only get triggered manually.
* in release mode and -Werror compiler option
* with minimum CMake Version 3.18
- main.yml configure, build, test, and package HDF5 on Ubuntu, macOS, and Windows
- main-static.yml configure, build, test static only HDF5 on Ubuntu, macOS, and Windows
- bintest.yml test binary packages created by main.yml
- main-par.yml configure, build, and test HDF5 with openmpi
- main-par-spc.yml configure, build, and test HDF5 with HDF5_ENABLE_WARNINGS_AS_ERRORS=ON
+47 -16
View File
@@ -8,6 +8,16 @@ on:
description: "release vs. debug build"
required: true
type: string
save_binary:
description: "binary-ext-name or missing"
required: true
default: "skip"
type: string
java_version:
description: "Java version to use for testing (19, 21, 24, 25, latest)"
required: false
default: "19"
type: string
permissions:
contents: read
@@ -22,11 +32,16 @@ jobs:
- name: Install Dependencies (Windows)
run: choco install ninja
- name: Set up JDK 19
- name: Set up JDK ${{ inputs.java_version }}
uses: actions/setup-java@v5
with:
java-version: '19'
distribution: 'temurin'
java-version: |
${{
inputs.save_binary == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
distribution: ${{ inputs.save_binary == 'ffm' && 'oracle' || 'temurin' }}
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1.13.0
@@ -35,7 +50,7 @@ jobs:
- name: Get published binary (Windows)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: zip-vs2022_cl-${{ inputs.build_mode }}-binary
name: zip-vs2022_cl-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ github.workspace }}/hdf5
- name: Uncompress hdf5 binary (Win)
@@ -100,16 +115,21 @@ jobs:
sudo apt-get update
sudo apt-get install ninja-build doxygen graphviz
- name: Set up JDK 19
- name: Set up JDK ${{ inputs.java_version }}
uses: actions/setup-java@v5
with:
java-version: '19'
distribution: 'temurin'
java-version: |
${{
inputs.save_binary == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
distribution: ${{ inputs.save_binary == 'ffm' && 'oracle' || 'temurin' }}
- name: Get published binary (Linux)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: tgz-ubuntu-2404_gcc-${{ inputs.build_mode }}-binary
name: tgz-ubuntu-2404_gcc-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ github.workspace }}
- name: Uncompress hdf5 binary (Linux)
@@ -152,16 +172,21 @@ jobs:
- name: Install Dependencies (MacOS_latest)
run: brew install ninja doxygen
- name: Set up JDK 21
- name: Set up JDK ${{ inputs.java_version }}
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
java-version: |
${{
inputs.save_binary == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
distribution: ${{ inputs.save_binary == 'ffm' && 'oracle' || 'temurin' }}
- name: Get published binary (MacOS_latest)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: tgz-macos14_clang-${{ inputs.build_mode }}-binary
name: tgz-macos14_clang-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ github.workspace }}
- name: Uncompress hdf5 binary (MacOS_latest)
@@ -215,16 +240,21 @@ jobs:
sudo apt-get update
sudo apt-get install ninja-build doxygen graphviz
- name: Set up JDK 19
- name: Set up JDK ${{ inputs.java_version }}
uses: actions/setup-java@v5
with:
java-version: '19'
distribution: 'temurin'
java-version: |
${{
inputs.save_binary == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
distribution: ${{ inputs.save_binary == 'ffm' && 'oracle' || 'temurin' }}
- name: Get published binary (Linux)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: tgz-ubuntu-2404_gcc-${{ inputs.build_mode }}-binary
name: tgz-ubuntu-2404_gcc-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ github.workspace }}
- name: Uncompress hdf5 binary (Linux)
@@ -259,3 +289,4 @@ jobs:
sh ./test-pc.sh ${{ steps.set-hdf5lib-name.outputs.HDF5_ROOT }}/share/HDF5Examples ${{ steps.set-hdf5lib-name.outputs.HDF5_ROOT }}/share/build .
shell: bash
+254
View File
@@ -0,0 +1,254 @@
name: Build aws-c-s3 library
# Reusable workflow to build aws-c-s3 library from source for Ubuntu
# This workflow is called by vfd-ros3.yml and other workflows that need aws-c-s3
on:
workflow_call:
inputs:
build_mode:
description: "Build type (CMAKE_BUILD_TYPE)"
required: true
type: string
aws_c_s3_tag:
description: "Tag of aws-c-s3 to use when building from source"
required: false
type: string
default: ""
permissions:
contents: read
jobs:
check_artifact:
name: "Check for existing aws-c-s3 artifact"
runs-on: ubuntu-latest
outputs:
has_artifact: ${{ steps.check_artifact.outputs.exists }}
steps:
- name: Check if 'libaws-c-s3-${{ inputs.build_mode }}' exists
id: check_artifact
uses: softwareforgood/check-artifact-v4-existence@v0
with:
name: libaws-c-s3-${{ inputs.build_mode }}
- name: Status of artifact check
if: steps.check_artifact.outputs.exists == 'true'
run: echo "Artifact 'libaws-c-s3-${{ inputs.build_mode }}' exists.."
# Build the aws-c-s3 library from source using the specified tag
# and cache the results, currently only on Ubuntu. The result is
# compressed into a 'libaws-c-s3.tar' archive to preserve permissions
# and then is uploaded as the artifact 'libaws-c-s3' which can later
# be downloaded with 'actions/download-artifact' and then uncompressed
# with 'tar xvf libaws-c-s3.tar -C <directory>'. The uncompressed build
# directory will be called 'aws-c-s3-build'.
build_aws_c_s3:
# Ubuntu doesn't have a package for aws-c-s3 yet
name: "Build aws-c-s3 library from source"
runs-on: ubuntu-latest
needs: check_artifact
if: ${{ needs.check_artifact.outputs.has_artifact == 'false' }}
steps:
- name: Get aws-c-s3 sources (main)
if: inputs.aws_c_s3_tag == ''
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-s3
path: aws-c-s3
- name: Get aws-c-s3 sources (tag)
if: inputs.aws_c_s3_tag != ''
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-s3
path: aws-c-s3
ref: ${{ inputs.aws_c_s3_tag }}
- name: Get aws-c-s3 commit hash
shell: bash
id: get-sha
run: |
cd $GITHUB_WORKSPACE/aws-c-s3
export AWSCS3_SHA=$(git rev-parse HEAD)
echo "AWSCS3_SHA=$AWSCS3_SHA" >> $GITHUB_ENV
echo "sha=$AWSCS3_SHA" >> $GITHUB_OUTPUT
# Output SHA for debugging
echo "AWSCS3_SHA=$AWSCS3_SHA"
- name: Cache/Restore aws-c-s3 (GCC) installation
id: cache-aws-c-s3-ubuntu-gcc
uses: actions/cache@v4
with:
path: ${{ runner.workspace }}/aws-c-s3-build
key: ${{ runner.os }}-${{ runner.arch }}-gcc-aws-c-s3-${{ steps.get-sha.outputs.sha }}-${{ inputs.build_mode }}
- name: Get aws-lc sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: aws/aws-lc
path: aws-lc
- name: Get s2n-tls sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: aws/s2n-tls
path: s2n-tls
- name: Get aws-c-common sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-common
path: aws-c-common
- name: Get aws-checksums sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-checksums
path: aws-checksums
- name: Get aws-c-cal sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-cal
path: aws-c-cal
- name: Get aws-c-io sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-io
path: aws-c-io
- name: Get aws-c-compression sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-compression
path: aws-c-compression
- name: Get aws-c-http sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-http
path: aws-c-http
- name: Get aws-c-sdkutils sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-sdkutils
path: aws-c-sdkutils
- name: Get aws-c-auth sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-auth
path: aws-c-auth
- name: Build aws-c-s3 from source
if: ${{ (steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true') }}
run: |
# Build aws-lc
echo "Building aws-lc"
cmake -S aws-lc -B aws-lc/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-lc/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build s2n-tls
echo "Building s2n-tls"
cmake -S s2n-tls -B s2n-tls/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build s2n-tls/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-common
echo "Building aws-c-common"
cmake -S aws-c-common -B aws-c-common/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-common/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-checksums
echo "Building aws-checksums"
cmake -S aws-checksums -B aws-checksums/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-checksums/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-cal
echo "Building aws-c-cal"
cmake -S aws-c-cal -B aws-c-cal/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-cal/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-io
echo "Building aws-c-io"
cmake -S aws-c-io -B aws-c-io/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-io/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-compression
echo "Building aws-c-compression"
cmake -S aws-c-compression -B aws-c-compression/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-compression/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-http
echo "Building aws-c-http"
cmake -S aws-c-http -B aws-c-http/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-http/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-sdkutils
echo "Building aws-c-sdkutils"
cmake -S aws-c-sdkutils -B aws-c-sdkutils/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-sdkutils/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-auth
echo "Building aws-c-auth"
cmake -S aws-c-auth -B aws-c-auth/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-auth/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-s3
echo "Building aws-c-s3"
cmake -S aws-c-s3 -B aws-c-s3/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-s3/build --parallel 3 --config ${{ inputs.build_mode }} --target install
- name: Tar aws-c-s3 installation to preserve permissions for artifact
run: tar -cvf libaws-c-s3.tar -C ${{ runner.workspace }} aws-c-s3-build
- name: Save aws-c-s3 installation artifact
uses: actions/upload-artifact@v5
with:
name: libaws-c-s3-${{ inputs.build_mode }}
path: libaws-c-s3.tar
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
+108 -15
View File
@@ -22,22 +22,40 @@ concurrency:
permissions:
contents: read
packages: write
pull-requests: write
jobs:
call-workflow-special-cmake:
name: "Special Workflows"
uses: ./.github/workflows/main-spc.yml
# Build aws-c-s3 library for ROS3 workflows
build-aws-c-s3-release:
name: "Build aws-c-s3 (Release)"
uses: ./.github/workflows/build-aws-c-s3.yml
with:
build_mode: "Release"
aws_c_s3_tag: "v0.8.0"
call-workflow-ros3-cmake:
name: "ROS3 VFD Workflows"
needs: build-aws-c-s3-release
uses: ./.github/workflows/vfd-ros3.yml
with:
build_mode: "Release"
build_aws_c_s3_only: false
aws_c_s3_build_type: "package"
# Use latest release for building from source on Ubuntu
# until a package is available to install
aws_c_s3_tag: "v0.8.0"
call-workflow-ros3-ffm-cmake:
name: "ROS3 VFD FFM Workflows"
needs: build-aws-c-s3-release
uses: ./.github/workflows/vfd-ros3.yml
with:
build_mode: "Release"
aws_c_s3_build_type: "package"
save_binary: "ffm"
java_version: "latest"
force_java_implementation: "ffm"
call-debug-concurrent-cmake:
name: "Debug Concurrency Workflows"
@@ -48,6 +66,15 @@ jobs:
thread_safety: ""
build_mode: "Debug"
call-static-debug-concurrent-cmake:
name: "Debug Static Concurrency Workflows"
uses: ./.github/workflows/main-static.yml
with:
cmake_version: "latest"
concurrent: "CC"
thread_safety: ""
build_mode: "Debug"
call-release-concurrent-cmake:
name: "Release Concurrency Workflows"
uses: ./.github/workflows/main.yml
@@ -66,6 +93,15 @@ jobs:
thread_safety: "TS"
build_mode: "Debug"
call-static-debug-thread-cmake:
name: "Debug Static Thread-Safety Workflows"
uses: ./.github/workflows/main-static.yml
with:
cmake_version: "latest"
concurrent: ""
thread_safety: "TS"
build_mode: "Debug"
call-release-thread-cmake:
name: "Release Thread-Safety Workflows"
uses: ./.github/workflows/main.yml
@@ -83,6 +119,16 @@ jobs:
concurrent: ""
thread_safety: ""
build_mode: "Debug"
force_java_implementation: "jni"
call-debug-static-cmake:
name: "Debug Static Workflows"
uses: ./.github/workflows/main-static.yml
with:
cmake_version: "latest"
concurrent: ""
thread_safety: ""
build_mode: "Debug"
call-release-cross:
name: "Release Cross Compile Workflows"
@@ -99,10 +145,11 @@ jobs:
thread_safety: ""
build_mode: "Release"
save_binary: "std"
force_java_implementation: "jni"
call-release-cmake4:
name: "CMake 4 Release Workflows"
uses: ./.github/workflows/main.yml
call-release-static:
name: "Release Static Workflows"
uses: ./.github/workflows/main-static.yml
with:
cmake_version: "latest"
concurrent: ""
@@ -117,6 +164,30 @@ jobs:
concurrent: ""
thread_safety: ""
build_mode: "Release"
force_java_implementation: "jni"
call-jni-latest-java:
name: "JNI Latest Java Testing"
uses: ./.github/workflows/main.yml
with:
cmake_version: "latest"
concurrent: ""
thread_safety: ""
build_mode: "Release"
java_version: "latest"
force_java_implementation: "jni"
call-ffm-latest-java:
name: "FFM Latest Java Testing"
uses: ./.github/workflows/main.yml
with:
cmake_version: "latest"
concurrent: ""
thread_safety: ""
build_mode: "Release"
save_binary: "ffm"
java_version: "latest"
force_java_implementation: "ffm"
call-arm64-cmake:
name: "arm64 Workflows"
@@ -137,21 +208,43 @@ jobs:
thread_safety: ""
build_mode: "Debug"
call-arm64-cmake4:
name: "CMake 4 arm64 Workflows"
uses: ./.github/workflows/arm-main.yml
call-maven-staging:
name: "Maven Staging Tests"
needs: call-release-cmake
uses: ./.github/workflows/maven-staging.yml
with:
cmake_version: "latest"
concurrent: ""
thread_safety: ""
build_mode: "Release"
test_maven_deployment: true
use_snapshot_version: true
java_implementation: "jni"
platforms: "all-platforms"
call-maven-ffm-staging:
name: "Maven Staging Tests"
needs: call-ffm-latest-java
uses: ./.github/workflows/maven-staging.yml
with:
test_maven_deployment: true
use_snapshot_version: true
java_implementation: "ffm"
platforms: "all-platforms"
call-release-bintest:
name: "Test Release Binaries"
needs: call-release-cmake
needs: [call-release-cmake, call-maven-staging]
uses: ./.github/workflows/bintest.yml
with:
build_mode: "Release"
save_binary: "std"
java_version: "21"
call-release-ffm-bintest:
name: "Test FFM Release Binaries"
needs: [call-ffm-latest-java, call-maven-ffm-staging]
uses: ./.github/workflows/bintest.yml
with:
build_mode: "Release"
save_binary: "ffm"
java_version: "latest"
call-release-par:
name: "Parallel Release Workflows"
+68 -6
View File
@@ -26,6 +26,11 @@ on:
description: "3.26.0 or later, latest"
required: true
type: string
maven_enabled:
description: 'Enable Maven artifact generation and upload'
type: boolean
required: false
default: false
secrets:
APPLE_CERTS_BASE64:
required: true
@@ -102,6 +107,12 @@ jobs:
which cmake
cmake --version
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Set file base name (Windows)
id: set-file-base
run: |
@@ -249,6 +260,12 @@ jobs:
which cmake
cmake --version
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Set file base name (Linux)
id: set-file-base
run: |
@@ -278,9 +295,23 @@ jobs:
run: tar -zxvf ${{ github.workspace }}/${{ steps.set-file-base.outputs.FILE_BASE }}.tar.gz
- name: Run CTest (Linux)
id: run-ctest
run: |
cd "${{ runner.workspace }}/hdf5/${{ steps.set-file-base.outputs.SOURCE_BASE }}"
cmake --workflow --preset=${{ inputs.preset_name }}-GNUC --fresh
if [ "${{ inputs.maven_enabled }}" == "true" ]; then
if [ "${{ inputs.use_environ }}" == "release" ]; then
echo "Building with Maven release preset"
ACTIVE_PRESET_BASE=$(echo "${{ inputs.preset_name }}-GNUC-Maven")
else
echo "Building with Maven snapshot preset"
ACTIVE_PRESET_BASE=$(echo "${{ inputs.preset_name }}-GNUC-Maven-Snapshot")
fi
else
echo "Building with standard preset"
ACTIVE_PRESET_BASE=$(echo "${{ inputs.preset_name }}-GNUC")
fi
echo "ACTIVE_PRESET=$ACTIVE_PRESET_BASE" >> $GITHUB_OUTPUT
cmake --workflow --preset=$ACTIVE_PRESET_BASE --fresh
shell: bash
- name: Publish binary (Linux)
@@ -289,8 +320,8 @@ jobs:
mkdir "${{ runner.workspace }}/build"
mkdir "${{ runner.workspace }}/build/hdf5"
cp ${{ runner.workspace }}/hdf5/${{ steps.set-file-base.outputs.SOURCE_BASE }}/LICENSE ${{ runner.workspace }}/build/hdf5
cp ${{ runner.workspace }}/hdf5/build/${{ inputs.preset_name }}-GNUC/README.md ${{ runner.workspace }}/build/hdf5
cp ${{ runner.workspace }}/hdf5/build/${{ inputs.preset_name }}-GNUC/*.tar.gz ${{ runner.workspace }}/build/hdf5
cp ${{ runner.workspace }}/hdf5/build/${{ steps.run-ctest.outputs.ACTIVE_PRESET }}/README.md ${{ runner.workspace }}/build/hdf5
cp ${{ runner.workspace }}/hdf5/build/${{ steps.run-ctest.outputs.ACTIVE_PRESET }}/*.tar.gz ${{ runner.workspace }}/build/hdf5
cd "${{ runner.workspace }}/build"
tar -zcvf ${{ steps.set-file-base.outputs.FILE_BASE }}-ubuntu-2404_gcc.tar.gz hdf5
shell: bash
@@ -299,14 +330,14 @@ jobs:
id: publish-ctest-deb-binary
run: |
mkdir "${{ runner.workspace }}/builddeb"
cp ${{ runner.workspace }}/hdf5/build/${{ inputs.preset_name }}-GNUC/*.deb ${{ runner.workspace }}/builddeb/${{ steps.set-file-base.outputs.FILE_BASE }}-ubuntu-2404_gcc.deb
cp ${{ runner.workspace }}/hdf5/build/${{ steps.run-ctest.outputs.ACTIVE_PRESET }}/*.deb ${{ runner.workspace }}/builddeb/${{ steps.set-file-base.outputs.FILE_BASE }}-ubuntu-2404_gcc.deb
shell: bash
- name: Publish rpm binary (Linux)
id: publish-ctest-rpm-binary
run: |
mkdir "${{ runner.workspace }}/buildrpm"
cp ${{ runner.workspace }}/hdf5/build/${{ inputs.preset_name }}-GNUC/*.rpm ${{ runner.workspace }}/buildrpm/${{ steps.set-file-base.outputs.FILE_BASE }}-ubuntu-2404_gcc.rpm
cp ${{ runner.workspace }}/hdf5/build/${{ steps.run-ctest.outputs.ACTIVE_PRESET }}/*.rpm ${{ runner.workspace }}/buildrpm/${{ steps.set-file-base.outputs.FILE_BASE }}-ubuntu-2404_gcc.rpm
shell: bash
- name: List files in the space (Linux)
@@ -341,9 +372,40 @@ jobs:
uses: actions/upload-artifact@v5
with:
name: docs-doxygen
path: ${{ runner.workspace }}/hdf5/build/${{ inputs.preset_name }}-GNUC/hdf5lib_docs/html
path: ${{ runner.workspace }}/hdf5/build/${{ steps.run-ctest.outputs.ACTIVE_PRESET }}/hdf5lib_docs/html
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
# Upload Maven artifacts when Maven deployment is enabled
- name: Collect Maven artifacts (Linux)
if: ${{ inputs.maven_enabled == true }}
run: |
echo "Collecting Maven artifacts for deployment..."
mkdir -p ${{ runner.workspace }}/maven-artifacts
# Determine the build directory based on Maven preset used
BUILD_DIR="${{ runner.workspace }}/hdf5/build/${{ steps.run-ctest.outputs.ACTIVE_PRESET }}"
echo "Looking for artifacts in: ${BUILD_DIR}"
# Copy JAR files
find "${BUILD_DIR}" -name "*.jar" -not -name "*test*" -not -name "*H5Ex_*" -exec cp {} ${{ runner.workspace }}/maven-artifacts/ \;
# Copy POM files
find "${BUILD_DIR}" -name "pom.xml" -exec cp {} ${{ runner.workspace }}/maven-artifacts/ \;
# List collected artifacts
echo "Collected Maven artifacts:"
ls -la ${{ runner.workspace }}/maven-artifacts/
shell: bash
- name: Upload Maven artifacts (Linux)
if: ${{ inputs.maven_enabled == true }}
uses: actions/upload-artifact@v5
with:
name: Linux-${{ inputs.preset_name }}-artifacts
path: ${{ runner.workspace }}/maven-artifacts
if-no-files-found: warn
build_and_test_mac_latest:
# MacOS w/ Clang
#
+2 -4
View File
@@ -69,13 +69,11 @@ jobs:
call-aws-c-s3-build:
needs: call-workflow-tarball
name: "Build aws-c-s3 library"
uses: ./.github/workflows/vfd-ros3.yml
uses: ./.github/workflows/build-aws-c-s3.yml
with:
build_mode: "Release"
build_aws_c_s3_only: true
aws_c_s3_build_type: "source"
# Use latest release for building from source on Ubuntu
# until a package is available to install
# until a package is available to install
aws_c_s3_tag: "v0.8.0"
if: ${{ ((needs.call-workflow-tarball.outputs.has_changes == 'true') || (needs.get-old-names.outputs.run-ignore == 'ignore')) }}
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Get Sources
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.7
uses: actions/checkout@v5.0.0
with:
fetch-depth: 0
ref: '${{ github.head_ref || github.ref_name }}'
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v5.0.0
- name: Build and test on FreeBSD
uses: vmactions/freebsd-vm@v1
@@ -0,0 +1,474 @@
name: Java Examples Maven Testing
on:
workflow_call:
inputs:
build_mode:
description: "release vs. debug build"
required: true
type: string
maven_artifacts_version:
description: "HDF5 Maven artifacts version to test against"
required: true
type: string
permissions:
contents: read
jobs:
# Parallel testing by platform and example category
test-examples-linux:
name: "Test Examples Linux (${{ matrix.category }})"
runs-on: ubuntu-latest
continue-on-error: true # Non-blocking failures
strategy:
fail-fast: false
matrix:
category: [H5D, H5T, H5G, TUTR]
steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
- name: Download Maven artifacts (Linux)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-linux-x86_64
path: ./maven-artifacts
continue-on-error: true
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-examples-${{ hashFiles('**/pom-examples.xml*') }}
restore-keys: |
${{ runner.os }}-maven-examples-
${{ runner.os }}-maven-
- name: Identify HDF5 JAR files
run: |
echo "=== Identifying HDF5 JAR files ==="
# Find HDF5 JAR files (not dependencies)
HDF5_JARS=$(find ./maven-artifacts -name "*hdf5*.jar" -o -name "jarhdf5*.jar")
DEP_JARS=$(find ./maven-artifacts -name "*.jar" ! -name "*hdf5*" ! -name "jarhdf5*")
echo "HDF5 JARs found:"
echo "$HDF5_JARS"
echo ""
echo "Dependency JARs found:"
echo "$DEP_JARS"
if [ -z "$HDF5_JARS" ]; then
echo "❌ No HDF5 JAR files found!"
echo "All available JARs:"
find ./maven-artifacts -name "*.jar"
exit 1
fi
- name: Test Examples Category ${{ matrix.category }}
id: test-examples
run: |
cd HDF5Examples/JAVA/${{ matrix.category }}
echo "=== Testing ${{ matrix.category }} Examples ==="
# Create test results directory
mkdir -p ../../../test-results/${{ matrix.category }}
FAILED_EXAMPLES=""
TOTAL_EXAMPLES=0
PASSED_EXAMPLES=0
# Test each Java example in the category
for java_file in *.java; do
if [ -f "$java_file" ]; then
TOTAL_EXAMPLES=$((TOTAL_EXAMPLES + 1))
example_name=$(basename "$java_file" .java)
echo "--- Testing $example_name ---"
# Build classpath (use platform-specific artifacts)
MAVEN_ARTIFACTS_DIR="../../../maven-artifacts"
HDF5_JAR=$(find "$MAVEN_ARTIFACTS_DIR" -name "*hdf5*.jar" -o -name "jarhdf5*.jar" | head -1)
DEP_JARS=$(find "$MAVEN_ARTIFACTS_DIR" -name "slf4j-api*.jar" -o -name "slf4j-simple*.jar")
if [ -z "$HDF5_JAR" ]; then
echo "❌ No HDF5 JAR found"
find "$MAVEN_ARTIFACTS_DIR" -name "*.jar" | head -10
continue
fi
CLASSPATH="$HDF5_JAR"
for dep_jar in $DEP_JARS; do
CLASSPATH="$CLASSPATH:$dep_jar"
done
# Compile the example
if javac -cp "$CLASSPATH" "$java_file"; then
echo "✓ Compilation successful for $example_name"
# Run the example and capture output
if timeout 30s java -cp ".:$CLASSPATH" "$example_name" > "../../../test-results/${{ matrix.category }}/${example_name}.output" 2>&1; then
# Validate output using pattern matching
output_file="../../../test-results/${{ matrix.category }}/${example_name}.output"
# Check for common success patterns
if grep -q -i -E "(dataset|datatype|group|success|created|written|read)" "$output_file" && \
! grep -q -i -E "(error|exception|failed|cannot)" "$output_file"; then
echo "✓ Execution and validation successful for $example_name"
PASSED_EXAMPLES=$((PASSED_EXAMPLES + 1))
else
echo "✗ Output validation failed for $example_name"
FAILED_EXAMPLES="$FAILED_EXAMPLES $example_name"
echo "Output:"
cat "$output_file"
fi
else
# Check if failure is due to expected native library issue (acceptable for Maven-only testing)
output_file="../../../test-results/${{ matrix.category }}/${example_name}.output"
if grep -q "UnsatisfiedLinkError.*hdf5_java.*java.library.path" "$output_file"; then
echo "✓ Expected native library error for Maven-only testing: $example_name"
echo " (This confirms JAR structure is correct)"
PASSED_EXAMPLES=$((PASSED_EXAMPLES + 1))
else
echo "✗ Unexpected execution failure for $example_name"
FAILED_EXAMPLES="$FAILED_EXAMPLES $example_name"
echo "Output:"
cat "$output_file"
fi
fi
else
echo "✗ Compilation failed for $example_name"
FAILED_EXAMPLES="$FAILED_EXAMPLES $example_name"
fi
echo ""
fi
done
# Summary
echo "=== ${{ matrix.category }} Summary ==="
echo "Total examples: $TOTAL_EXAMPLES"
echo "Passed: $PASSED_EXAMPLES"
echo "Failed: $((TOTAL_EXAMPLES - PASSED_EXAMPLES))"
if [ -n "$FAILED_EXAMPLES" ]; then
echo "Failed examples:$FAILED_EXAMPLES"
echo "failed-examples=$FAILED_EXAMPLES" >> $GITHUB_OUTPUT
echo "test-status=FAILED" >> $GITHUB_OUTPUT
else
echo "All examples passed!"
echo "test-status=PASSED" >> $GITHUB_OUTPUT
fi
echo "total-examples=$TOTAL_EXAMPLES" >> $GITHUB_OUTPUT
echo "passed-examples=$PASSED_EXAMPLES" >> $GITHUB_OUTPUT
- name: Upload failure artifacts (Linux ${{ matrix.category }})
if: steps.test-examples.outputs.test-status == 'FAILED'
uses: actions/upload-artifact@v5
with:
name: java-examples-failure-linux-${{ matrix.category }}-${{ github.run_id }}
path: |
test-results/${{ matrix.category }}/
HDF5Examples/JAVA/${{ matrix.category }}/*.class
HDF5Examples/JAVA/${{ matrix.category }}/*.h5
retention-days: 7
test-examples-windows:
name: "Test Examples Windows (${{ matrix.category }})"
runs-on: windows-latest
continue-on-error: true
strategy:
fail-fast: false
matrix:
category: [H5D, H5T, H5G, TUTR]
steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
- name: Download Maven artifacts (Windows)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-windows-x86_64
path: ./maven-artifacts
continue-on-error: true
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-examples-${{ hashFiles('**/pom-examples.xml*') }}
- name: Test Examples Category ${{ matrix.category }}
id: test-examples
shell: pwsh
run: |
cd HDF5Examples/JAVA/${{ matrix.category }}
Write-Host "=== Testing ${{ matrix.category }} Examples ==="
# Create test results directory
New-Item -ItemType Directory -Force -Path "../../../test-results/${{ matrix.category }}"
$FAILED_EXAMPLES = @()
$TOTAL_EXAMPLES = 0
$PASSED_EXAMPLES = 0
# Test each Java example in the category
Get-ChildItem -Filter "*.java" | ForEach-Object {
$TOTAL_EXAMPLES++
$example_name = $_.BaseName
Write-Host "--- Testing $example_name ---"
# Compile the example
$compile_result = javac -cp "../../../maven-artifacts/*.jar" $_.Name
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ Compilation successful for $example_name"
# Run the example and capture output
$timeout_cmd = "timeout 30s java -cp '.;../../../maven-artifacts/*' $example_name"
$output_file = "../../../test-results/${{ matrix.category }}/${example_name}.output"
try {
& cmd /c "$timeout_cmd > `"$output_file`" 2>&1"
if ($LASTEXITCODE -eq 0) {
# Validate output using pattern matching
$content = Get-Content $output_file -Raw
if (($content -match "(?i)(dataset|datatype|group|success|created|written|read)") -and
($content -notmatch "(?i)(error|exception|failed|cannot)")) {
Write-Host "✓ Execution and validation successful for $example_name"
$PASSED_EXAMPLES++
} else {
Write-Host "✗ Output validation failed for $example_name"
$FAILED_EXAMPLES += $example_name
Write-Host "Output:"
Get-Content $output_file
}
} else {
Write-Host "✗ Execution failed for $example_name"
$FAILED_EXAMPLES += $example_name
}
} catch {
Write-Host "✗ Execution failed for $example_name"
$FAILED_EXAMPLES += $example_name
}
} else {
Write-Host "✗ Compilation failed for $example_name"
$FAILED_EXAMPLES += $example_name
}
Write-Host ""
}
# Summary
Write-Host "=== ${{ matrix.category }} Summary ==="
Write-Host "Total examples: $TOTAL_EXAMPLES"
Write-Host "Passed: $PASSED_EXAMPLES"
Write-Host "Failed: $($TOTAL_EXAMPLES - $PASSED_EXAMPLES)"
if ($FAILED_EXAMPLES.Count -gt 0) {
Write-Host "Failed examples: $($FAILED_EXAMPLES -join ' ')"
echo "failed-examples=$($FAILED_EXAMPLES -join ' ')" >> $env:GITHUB_OUTPUT
echo "test-status=FAILED" >> $env:GITHUB_OUTPUT
} else {
Write-Host "All examples passed!"
echo "test-status=PASSED" >> $env:GITHUB_OUTPUT
}
echo "total-examples=$TOTAL_EXAMPLES" >> $env:GITHUB_OUTPUT
echo "passed-examples=$PASSED_EXAMPLES" >> $env:GITHUB_OUTPUT
- name: Upload failure artifacts (Windows ${{ matrix.category }})
if: steps.test-examples.outputs.test-status == 'FAILED'
uses: actions/upload-artifact@v5
with:
name: java-examples-failure-windows-${{ matrix.category }}-${{ github.run_id }}
path: |
test-results/${{ matrix.category }}/
HDF5Examples/JAVA/${{ matrix.category }}/*.class
HDF5Examples/JAVA/${{ matrix.category }}/*.h5
test-examples-macos:
name: "Test Examples macOS (${{ matrix.category }})"
runs-on: macos-latest
continue-on-error: true
strategy:
fail-fast: false
matrix:
category: [H5D, H5T, H5G, TUTR]
steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
- name: Download Maven artifacts (macOS aarch64)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-macos-aarch64
path: ./maven-artifacts
continue-on-error: true
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-examples-${{ hashFiles('**/pom-examples.xml*') }}
- name: Test Examples Category ${{ matrix.category }}
id: test-examples
run: |
cd HDF5Examples/JAVA/${{ matrix.category }}
echo "=== Testing ${{ matrix.category }} Examples ==="
# Create test results directory
mkdir -p ../../../test-results/${{ matrix.category }}
FAILED_EXAMPLES=""
TOTAL_EXAMPLES=0
PASSED_EXAMPLES=0
# Test each Java example in the category
for java_file in *.java; do
if [ -f "$java_file" ]; then
TOTAL_EXAMPLES=$((TOTAL_EXAMPLES + 1))
example_name=$(basename "$java_file" .java)
echo "--- Testing $example_name ---"
# Build classpath (use platform-specific artifacts)
MAVEN_ARTIFACTS_DIR="../../../maven-artifacts"
HDF5_JAR=$(find "$MAVEN_ARTIFACTS_DIR" -name "*hdf5*.jar" -o -name "jarhdf5*.jar" | head -1)
DEP_JARS=$(find "$MAVEN_ARTIFACTS_DIR" -name "slf4j-api*.jar" -o -name "slf4j-simple*.jar")
if [ -z "$HDF5_JAR" ]; then
echo "❌ No HDF5 JAR found"
find "$MAVEN_ARTIFACTS_DIR" -name "*.jar" | head -10
continue
fi
CLASSPATH="$HDF5_JAR"
for dep_jar in $DEP_JARS; do
CLASSPATH="$CLASSPATH:$dep_jar"
done
# Compile the example
if javac -cp "$CLASSPATH" "$java_file"; then
echo "✓ Compilation successful for $example_name"
# Run the example and capture output
if timeout 30s java -cp ".:$CLASSPATH" "$example_name" > "../../../test-results/${{ matrix.category }}/${example_name}.output" 2>&1; then
# Validate output using pattern matching
output_file="../../../test-results/${{ matrix.category }}/${example_name}.output"
# Check for common success patterns
if grep -q -i -E "(dataset|datatype|group|success|created|written|read)" "$output_file" && \
! grep -q -i -E "(error|exception|failed|cannot)" "$output_file"; then
echo "✓ Execution and validation successful for $example_name"
PASSED_EXAMPLES=$((PASSED_EXAMPLES + 1))
else
echo "✗ Output validation failed for $example_name"
FAILED_EXAMPLES="$FAILED_EXAMPLES $example_name"
fi
else
echo "✗ Execution failed for $example_name"
FAILED_EXAMPLES="$FAILED_EXAMPLES $example_name"
fi
else
echo "✗ Compilation failed for $example_name"
FAILED_EXAMPLES="$FAILED_EXAMPLES $example_name"
fi
echo ""
fi
done
# Summary
echo "=== ${{ matrix.category }} Summary ==="
echo "Total examples: $TOTAL_EXAMPLES"
echo "Passed: $PASSED_EXAMPLES"
echo "Failed: $((TOTAL_EXAMPLES - PASSED_EXAMPLES))"
if [ -n "$FAILED_EXAMPLES" ]; then
echo "Failed examples:$FAILED_EXAMPLES"
echo "failed-examples=$FAILED_EXAMPLES" >> $GITHUB_OUTPUT
echo "test-status=FAILED" >> $GITHUB_OUTPUT
else
echo "All examples passed!"
echo "test-status=PASSED" >> $GITHUB_OUTPUT
fi
echo "total-examples=$TOTAL_EXAMPLES" >> $GITHUB_OUTPUT
echo "passed-examples=$PASSED_EXAMPLES" >> $GITHUB_OUTPUT
- name: Upload failure artifacts (macOS ${{ matrix.category }})
if: steps.test-examples.outputs.test-status == 'FAILED'
uses: actions/upload-artifact@v5
with:
name: java-examples-failure-macos-${{ matrix.category }}-${{ github.run_id }}
path: |
test-results/${{ matrix.category }}/
HDF5Examples/JAVA/${{ matrix.category }}/*.class
HDF5Examples/JAVA/${{ matrix.category }}/*.h5
analyze-cross-platform-failures:
name: "Analyze Cross-Platform Failures"
runs-on: ubuntu-latest
needs: [test-examples-linux, test-examples-windows, test-examples-macos]
if: always()
steps:
- name: Collect Test Results
run: |
echo "=== Java Examples Testing Summary ==="
# Collect results from matrix outputs (this would need to be enhanced
# to actually collect the outputs from the matrix jobs)
echo "Cross-platform failure analysis:"
echo "- Examples failing on multiple platforms require attention"
echo "- Single-platform failures may be platform-specific issues"
# This step would analyze patterns in failures across platforms
# and generate appropriate alerts/issues for multi-platform failures
- name: Generate Test Summary Report
run: |
cat > java-examples-test-summary.md << 'EOF'
# Java Examples Maven Testing Summary
**Build Mode**: ${{ inputs.build_mode }}
**Maven Version**: ${{ inputs.maven_artifacts_version }}
**Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
## Platform Results
- **Linux**: See individual category results
- **Windows**: See individual category results
- **macOS**: See individual category results
## Cross-Platform Analysis
Examples failing on multiple platforms require investigation.
EOF
echo "Test summary report generated"
- name: Upload Test Summary
uses: actions/upload-artifact@v5
with:
name: java-examples-test-summary-${{ github.run_id }}
path: java-examples-test-summary.md
retention-days: 30
@@ -0,0 +1,318 @@
name: Java Implementation Testing (FFM vs JNI)
# Test both FFM and JNI implementations across multiple Java versions
on:
pull_request:
branches: [ develop, main ]
paths:
- 'java/**'
- 'CMakeBuildOptions.cmake'
- 'CMakePresets.json'
- 'config/cmake-presets/hidden-presets.json'
- '.github/workflows/java-implementation-test.yml'
- '.github/scripts/test-java-implementations.sh'
workflow_call:
inputs:
java_versions:
description: 'Java versions to test (comma-separated)'
type: string
required: false
default: '11,17,21,24'
test_mode:
description: 'Test mode (build, maven, full)'
type: string
required: false
default: 'build'
platforms:
description: 'Platforms to test'
type: string
required: false
default: 'ubuntu-latest'
workflow_dispatch:
inputs:
java_versions:
description: 'Java versions to test'
type: string
required: false
default: '11,17,21,24'
test_mode:
description: 'Test mode'
type: choice
required: false
default: 'build'
options:
- 'build'
- 'maven'
- 'full'
platforms:
description: 'Platforms to test'
type: choice
required: false
default: 'ubuntu-latest'
options:
- 'ubuntu-latest'
- 'windows-latest'
- 'macos-latest'
- 'all-platforms'
env:
CMAKE_GENERATOR: Ninja
jobs:
setup-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.generate-matrix.outputs.matrix }}
steps:
- name: Generate test matrix
id: generate-matrix
run: |
# Parse inputs
JAVA_VERSIONS="${{ inputs.java_versions || '11,17,21,25' }}"
PLATFORMS="${{ inputs.platforms || 'ubuntu-latest' }}"
# Expand platforms if needed
if [[ "$PLATFORMS" == "all-platforms" ]]; then
PLATFORMS="ubuntu-latest,windows-latest,macos-latest"
fi
# Generate matrix
matrix_json="["
first_entry=true
for platform in $(echo "$PLATFORMS" | tr ',' ' '); do
for java_version in $(echo "$JAVA_VERSIONS" | tr ',' ' '); do
# Determine available implementations
if [[ $java_version -ge 25 ]]; then
implementations="ffm jni"
else
implementations="jni"
fi
for impl in $implementations; do
if [ "$first_entry" = true ]; then
first_entry=false
else
matrix_json="$matrix_json,"
fi
matrix_json="$matrix_json{\"os\":\"$platform\",\"java-version\":\"$java_version\",\"implementation\":\"$impl\"}"
done
done
done
matrix_json="$matrix_json]"
echo "Generated matrix:"
echo "$matrix_json" | jq '.'
echo "matrix=$matrix_json" >> $GITHUB_OUTPUT
test-implementations:
needs: setup-matrix
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}
name: Test Java ${{ matrix.java-version }} ${{ matrix.implementation }} on ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v5.0.0
with:
submodules: recursive
- name: Set up Java ${{ matrix.java-version }} (${{ matrix.implementation }})
uses: actions/setup-java@v5
with:
distribution: ${{ matrix.implementation == 'ffm' && 'oracle' || 'temurin' }}
java-version: ${{ matrix.implementation == 'ffm' && '25' || matrix.java-version }}
- name: Setup jextract (FFM builds only)
if: ${{ matrix.implementation == 'ffm' }}
uses: ./.github/actions/setup-jextract
with:
java-version: '25'
- name: Setup Build Environment (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y ninja-build libaec-dev zlib1g-dev
- name: Setup Build Environment (macOS)
if: runner.os == 'macOS'
run: |
brew install ninja libaec
- name: Setup Build Environment (Windows)
if: runner.os == 'Windows'
run: |
choco install ninja
- name: Cache CMake build
uses: actions/cache@v4
with:
path: |
build-test-*
key: ${{ runner.os }}-java${{ matrix.java-version }}-${{ matrix.implementation }}-${{ hashFiles('**/CMakeLists.txt', 'CMakePresets.json') }}
restore-keys: |
${{ runner.os }}-java${{ matrix.java-version }}-${{ matrix.implementation }}-
${{ runner.os }}-java${{ matrix.java-version }}-
- name: Verify Java version and implementation compatibility
run: |
java -version
echo "Testing Java ${{ matrix.java-version }} with ${{ matrix.implementation }} implementation"
# Additional validation for FFM
if [[ "${{ matrix.implementation }}" == "ffm" ]]; then
if [[ ${{ matrix.java-version }} -lt 25 ]]; then
echo "::error::FFM implementation requires Java 25, got Java ${{ matrix.java-version }}"
exit 1
fi
echo "FFM implementation validated for Java ${{ matrix.java-version }}"
fi
- name: Run implementation tests
shell: bash
run: |
chmod +x .github/scripts/test-java-implementations.sh
.github/scripts/test-java-implementations.sh \
${{ matrix.java-version }} \
${{ matrix.implementation }} \
${{ inputs.test_mode || 'build' }}
- name: Upload build artifacts on failure
if: failure()
uses: actions/upload-artifact@v5
with:
name: build-logs-${{ matrix.os }}-java${{ matrix.java-version }}-${{ matrix.implementation }}
path: |
build-test-*/CMakeCache.txt
build-test-*/CMakeFiles/CMakeError.log
build-test-*/CMakeFiles/CMakeOutput.log
retention-days: 7
- name: Upload Maven artifacts (if generated)
if: inputs.test_mode == 'maven' || inputs.test_mode == 'full'
uses: actions/upload-artifact@v5
with:
name: maven-artifacts-${{ matrix.os }}-java${{ matrix.java-version }}-${{ matrix.implementation }}
path: |
build-test-*/java/**/target/*.jar
build-test-*/java/**/pom.xml
retention-days: 3
validate-artifacts:
needs: [setup-matrix, test-implementations]
runs-on: ubuntu-latest
if: inputs.test_mode == 'maven' || inputs.test_mode == 'full'
steps:
- name: Checkout repository
uses: actions/checkout@v5.0.0
- name: Download all Maven artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: maven-artifacts-*
path: artifacts/
- name: Validate artifact differentiation
run: |
echo "Validating Maven artifact differentiation..."
# Check for FFM artifacts
ffm_artifacts=$(find artifacts/ -name "*hdf5-java-ffm*" | wc -l)
jni_artifacts=$(find artifacts/ -name "*hdf5-java-jni*" | wc -l)
echo "Found $ffm_artifacts FFM artifacts and $jni_artifacts JNI artifacts"
if [[ $ffm_artifacts -eq 0 && $jni_artifacts -eq 0 ]]; then
echo "::error::No Maven artifacts found!"
exit 1
fi
# Verify no mixed artifacts
mixed_artifacts=$(find artifacts/ -name "*hdf5-java-*" | grep -v -E "(ffm|jni)" | wc -l)
if [[ $mixed_artifacts -gt 0 ]]; then
echo "::error::Found artifacts without proper FFM/JNI differentiation"
find artifacts/ -name "*hdf5-java-*" | grep -v -E "(ffm|jni)"
exit 1
fi
echo "✅ Artifact differentiation validation passed"
- name: Validate POM files
run: |
echo "Validating POM file contents..."
for pom in $(find artifacts/ -name "pom.xml"); do
echo "Checking POM: $pom"
# Extract artifact ID
artifact_id=$(grep -o '<artifactId>hdf5-java-[^<]*</artifactId>' "$pom" | sed 's/<[^>]*>//g')
echo "Artifact ID: $artifact_id"
# Validate implementation metadata
if grep -q "hdf5-java-ffm" "$pom"; then
if ! grep -q "FFM" "$pom"; then
echo "::error::FFM POM missing implementation metadata"
exit 1
fi
echo "✅ FFM POM validation passed"
elif grep -q "hdf5-java-jni" "$pom"; then
if ! grep -q "JNI" "$pom"; then
echo "::error::JNI POM missing implementation metadata"
exit 1
fi
echo "✅ JNI POM validation passed"
else
echo "::error::POM has unrecognized artifact ID: $artifact_id"
exit 1
fi
done
report-results:
needs: [setup-matrix, test-implementations, validate-artifacts]
runs-on: ubuntu-latest
if: always()
steps:
- name: Generate test report
run: |
echo "## Java Implementation Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Test Configuration" >> $GITHUB_STEP_SUMMARY
echo "- **Java Versions**: ${{ inputs.java_versions || '11,17,21,25' }}" >> $GITHUB_STEP_SUMMARY
echo "- **Test Mode**: ${{ inputs.test_mode || 'build' }}" >> $GITHUB_STEP_SUMMARY
echo "- **Platforms**: ${{ inputs.platforms || 'ubuntu-latest' }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Report job statuses
if [[ "${{ needs.test-implementations.result }}" == "success" ]]; then
echo "✅ **Implementation Tests**: PASSED" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Implementation Tests**: FAILED" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.validate-artifacts.result }}" == "success" ]]; then
echo "✅ **Artifact Validation**: PASSED" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.validate-artifacts.result }}" == "skipped" ]]; then
echo "⏭️ **Artifact Validation**: SKIPPED" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Artifact Validation**: FAILED" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Implementation Matrix" >> $GITHUB_STEP_SUMMARY
echo "| Java Version | FFM Support | JNI Support |" >> $GITHUB_STEP_SUMMARY
echo "|--------------|-------------|-------------|" >> $GITHUB_STEP_SUMMARY
echo "| 11 | ❌ | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "| 17 | ❌ | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "| 21 | ❌ | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "| 24+ | ✅ (optional) | ✅ (default) |" >> $GITHUB_STEP_SUMMARY
+206
View File
@@ -0,0 +1,206 @@
name: hdf5 dev CI
# Triggers the workflow on a call from another workflow
on:
workflow_call:
inputs:
cmake_version:
description: "3.26.0 or later, latest"
required: true
type: string
thread_safety:
description: "TS or empty"
required: true
type: string
concurrent:
description: "CC or empty"
required: true
type: string
build_mode:
description: "release vs. debug build"
required: true
type: string
save_binary:
description: "binary-ext-name or missing"
required: false
default: "skip"
type: string
permissions:
contents: read
jobs:
# A workflow that builds the library and runs all the tests
Static_build_and_test:
strategy:
# The current matrix has one dimensions:
#
# * config name
#
# Most configuration information is added via the 'include' mechanism,
# which will append the key-value pairs in the configuration where the
# names match.
matrix:
name:
- "Windows Static MSVC"
- "Ubuntu Static gcc"
- "MacOS Static Clang"
# This is where we list the bulk of the options for each configuration.
# The key-value pair values are usually appropriate for being CMake
# configure values, so be aware of that.
include:
- name: "Windows Static MSVC"
ostype: windows
os: windows-latest
shared: OFF
cpp: ON
fortran: OFF
java: OFF
docs: OFF
libaecfc: ON
localaec: OFF
zlibfc: ON
localzlib: OFF
parallel: OFF
mirror_vfd: OFF
direct_vfd: OFF
ros3_vfd: OFF
generator: "-G \"Visual Studio 17 2022\" -A x64"
run_tests: true
- name: "Ubuntu Static gcc"
ostype: ubuntu
os: ubuntu-latest
shared: OFF
cpp: ON
fortran: ON
java: OFF
docs: OFF
libaecfc: ON
localaec: OFF
zlibfc: ON
localzlib: OFF
parallel: OFF
mirror_vfd: ON
direct_vfd: ON
ros3_vfd: OFF
generator: "-G Ninja"
run_tests: true
- name: "MacOS Static Clang"
ostype: macos
os: macos-latest
shared: OFF
cpp: ON
fortran: OFF
java: OFF
docs: OFF
libaecfc: ON
localaec: OFF
zlibfc: ON
localzlib: OFF
parallel: OFF
mirror_vfd: ON
direct_vfd: OFF
ros3_vfd: OFF
generator: "-G Ninja"
run_tests: true
if: ${{ inputs.thread_safety != 'TS' && inputs.concurrent != 'CC'}}
# Sets the job's name from the properties
name: "${{ matrix.name }}-${{ inputs.build_mode }}-${{ inputs.thread_safety }}-${{ inputs.concurrent }}"
# The type of runner that the job will run on
runs-on: ${{ matrix.os }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
#Useful for debugging
- name: Dump matrix context
run: echo '${{ toJSON(matrix) }}'
- name: Install Dependencies (Linux)
run: |
sudo apt-get update
sudo apt-get install ninja-build graphviz
sudo apt install libssl3 libssl-dev libcurl4 libcurl4-openssl-dev
if: matrix.ostype == 'ubuntu'
# CMake gets libaec from fetchcontent
- name: Install Dependencies (macOS)
run: brew install ninja curl
if: ${{ matrix.ostype == 'macos' }}
- name: Install Dependencies
uses: ssciwr/doxygen-install@v1
with:
version: "1.13.2"
- name: Install CMake
uses: lukka/get-cmake@latest
with:
cmakeVersion: ${{ inputs.cmake_version }}
ninjaVersion: latest
- name: Check CMake Version
shell: bash
run: |
which cmake
cmake --version
- name: Set environment for MSVC (Windows)
run: |
# Set these environment variables so CMake picks the correct compiler
echo "CXX=cl.exe" >> $GITHUB_ENV
echo "CC=cl.exe" >> $GITHUB_ENV
if: matrix.ostype == 'windows'
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Get Sources
uses: actions/checkout@v5.0.0
# CONFIGURE
- name: Configure
run: |
mkdir "${{ runner.workspace }}/build"
cd "${{ runner.workspace }}/build"
cmake -C $GITHUB_WORKSPACE/config/cmake/cacheinit.cmake \
${{ matrix.generator }} \
--log-level=VERBOSE \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DBUILD_SHARED_LIBS:BOOL=OFF \
-DBUILD_STATIC_LIBS:BOOL=ON \
-DHDF5_ENABLE_ALL_WARNINGS:BOOL=ON \
-DHDF5_ENABLE_PARALLEL:BOOL=${{ matrix.parallel }} \
-DHDF5_BUILD_CPP_LIB:BOOL=${{ matrix.cpp }} \
-DHDF5_BUILD_FORTRAN:BOOL=${{ matrix.fortran }} \
-DHDF5_BUILD_JAVA:BOOL=OFF \
-DHDF5_BUILD_DOC:BOOL=OFF \
-DHDF5_ENABLE_ZLIB_SUPPORT:BOOL=${{ matrix.zlibfc }} \
-DHDF5_ENABLE_SZIP_SUPPORT:BOOL=${{ matrix.libaecfc }} \
-DLIBAEC_USE_LOCALCONTENT:BOOL=${{ matrix.localaec }} \
-DZLIB_USE_LOCALCONTENT:BOOL=${{ matrix.localzlib }} \
-DHDF5_ENABLE_MIRROR_VFD:BOOL=${{ matrix.mirror_vfd }} \
-DHDF5_ENABLE_DIRECT_VFD:BOOL=${{ matrix.direct_vfd }} \
-DHDF5_ENABLE_ROS3_VFD:BOOL=${{ matrix.ros3_vfd }} \
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_PACKAGE_EXTLIBS:BOOL=ON \
-DHDF5_PACK_MACOSX_DMG:BOOL=OFF \
$GITHUB_WORKSPACE
shell: bash
# BUILD
- name: Build
run: cmake --build . --parallel 3 --config ${{ inputs.build_mode }}
working-directory: ${{ runner.workspace }}/build
# RUN TESTS
- name: Run Tests
run: ctest . --parallel 2 -C ${{ inputs.build_mode }} -V
working-directory: ${{ runner.workspace }}/build
if: ${{ matrix.run_tests }}
+39 -179
View File
@@ -25,6 +25,16 @@ on:
required: false
default: "skip"
type: string
java_version:
description: "Java version for testing (11, 17, 21, 24, latest, auto)"
required: false
default: "auto"
type: string
force_java_implementation:
description: "Force specific Java implementation (auto, ffm, jni)"
required: false
default: "jni"
type: string
permissions:
contents: read
@@ -159,6 +169,25 @@ jobs:
which cmake
cmake --version
- name: Set up Java (if specified or FFM required)
if: inputs.java_version != 'auto' || inputs.force_java_implementation == 'ffm'
uses: actions/setup-java@v5
with:
distribution: ${{ inputs.force_java_implementation == 'ffm' && 'oracle' || 'temurin' }}
java-version: |
${{
inputs.force_java_implementation == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
- name: Verify Java Setup
if: inputs.java_version != 'auto' || inputs.force_java_implementation == 'ffm'
run: |
java -version
echo "JAVA_HOME=$JAVA_HOME"
echo "Selected Java implementation: ${{ inputs.force_java_implementation }}"
- name: Set environment for MSVC (Windows)
run: |
# Set these environment variables so CMake picks the correct compiler
@@ -170,6 +199,12 @@ jobs:
- name: Get Sources
uses: actions/checkout@v5.0.0
- name: Setup jextract (FFM builds only)
if: ${{ inputs.force_java_implementation == 'ffm' }}
uses: ./.github/actions/setup-jextract
with:
java-version: '25'
# CONFIGURE
- name: Configure
run: |
@@ -199,6 +234,7 @@ jobs:
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_PACKAGE_EXTLIBS:BOOL=ON \
-DHDF5_PACK_MACOSX_DMG:BOOL=OFF \
-DHDF5_ENABLE_JNI:BOOL=${{ inputs.force_java_implementation == 'jni' }} \
$GITHUB_WORKSPACE
shell: bash
if: ${{ inputs.thread_safety != 'TS' && inputs.concurrent != 'CC'}}
@@ -288,7 +324,7 @@ jobs:
- name: Save published binary (Windows)
uses: actions/upload-artifact@v5
with:
name: zip-vs2022_cl-${{ inputs.build_mode }}-binary
name: zip-vs2022_cl-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ runner.workspace }}/build/HDF5-*-win64.zip
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
if: ${{ (matrix.ostype == 'windows') && ( inputs.save_binary != 'skip') }}
@@ -296,7 +332,7 @@ jobs:
- name: Save published binary (linux)
uses: actions/upload-artifact@v5
with:
name: tgz-ubuntu-2404_gcc-${{ inputs.build_mode }}-binary
name: tgz-ubuntu-2404_gcc-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ runner.workspace }}/build/HDF5-*-Linux.tar.gz
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
if: ${{ (matrix.ostype == 'ubuntu') && ( inputs.save_binary != 'skip') }}
@@ -304,183 +340,7 @@ jobs:
- name: Save published binary (Mac_latest)
uses: actions/upload-artifact@v5
with:
name: tgz-macos14_clang-${{ inputs.build_mode }}-binary
name: tgz-macos14_clang-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ runner.workspace }}/build/HDF5-*-Darwin.tar.gz
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
if: ${{ (matrix.ostype == 'macos') && ( inputs.save_binary != 'skip') }}
# A workflow that builds the library and runs all the tests
Static_build_and_test:
strategy:
# The current matrix has one dimensions:
#
# * config name
#
# Most configuration information is added via the 'include' mechanism,
# which will append the key-value pairs in the configuration where the
# names match.
matrix:
name:
- "Windows Static MSVC"
- "Ubuntu Static gcc"
- "MacOS Static Clang"
# This is where we list the bulk of the options for each configuration.
# The key-value pair values are usually appropriate for being CMake
# configure values, so be aware of that.
include:
- name: "Windows Static MSVC"
ostype: windows
os: windows-latest
shared: OFF
cpp: ON
fortran: OFF
java: OFF
docs: OFF
libaecfc: ON
localaec: OFF
zlibfc: ON
localzlib: OFF
parallel: OFF
mirror_vfd: OFF
direct_vfd: OFF
ros3_vfd: OFF
generator: "-G \"Visual Studio 17 2022\" -A x64"
run_tests: true
- name: "Ubuntu Static gcc"
ostype: ubuntu
os: ubuntu-latest
shared: OFF
cpp: ON
fortran: ON
java: OFF
docs: OFF
libaecfc: ON
localaec: OFF
zlibfc: ON
localzlib: OFF
parallel: OFF
mirror_vfd: ON
direct_vfd: ON
ros3_vfd: OFF
generator: "-G Ninja"
run_tests: true
- name: "MacOS Static Clang"
ostype: macos
os: macos-latest
shared: OFF
cpp: ON
fortran: OFF
java: OFF
docs: OFF
libaecfc: ON
localaec: OFF
zlibfc: ON
localzlib: OFF
parallel: OFF
mirror_vfd: ON
direct_vfd: OFF
ros3_vfd: OFF
generator: "-G Ninja"
run_tests: true
if: ${{ inputs.thread_safety != 'TS' && inputs.concurrent != 'CC'}}
# Sets the job's name from the properties
name: "${{ matrix.name }}-${{ inputs.build_mode }}-${{ inputs.thread_safety }}-${{ inputs.concurrent }}"
# The type of runner that the job will run on
runs-on: ${{ matrix.os }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
#Useful for debugging
- name: Dump matrix context
run: echo '${{ toJSON(matrix) }}'
- name: Install Dependencies (Linux)
run: |
sudo apt-get update
sudo apt-get install ninja-build graphviz
sudo apt install libssl3 libssl-dev libcurl4 libcurl4-openssl-dev
if: matrix.ostype == 'ubuntu'
# CMake gets libaec from fetchcontent
- name: Install Dependencies (macOS)
run: brew install ninja curl
if: ${{ matrix.ostype == 'macos' }}
- name: Install Dependencies
uses: ssciwr/doxygen-install@v1
with:
version: "1.13.2"
- name: Install CMake
uses: lukka/get-cmake@latest
with:
cmakeVersion: ${{ inputs.cmake_version }}
ninjaVersion: latest
- name: Check CMake Version
shell: bash
run: |
which cmake
cmake --version
- name: Set environment for MSVC (Windows)
run: |
# Set these environment variables so CMake picks the correct compiler
echo "CXX=cl.exe" >> $GITHUB_ENV
echo "CC=cl.exe" >> $GITHUB_ENV
if: matrix.ostype == 'windows'
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Get Sources
uses: actions/checkout@v5.0.0
# CONFIGURE
- name: Configure
run: |
mkdir "${{ runner.workspace }}/build"
cd "${{ runner.workspace }}/build"
cmake -C $GITHUB_WORKSPACE/config/cmake/cacheinit.cmake \
${{ matrix.generator }} \
--log-level=VERBOSE \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DBUILD_SHARED_LIBS:BOOL=OFF \
-DBUILD_STATIC_LIBS:BOOL=ON \
-DHDF5_ENABLE_ALL_WARNINGS:BOOL=ON \
-DHDF5_ENABLE_PARALLEL:BOOL=${{ matrix.parallel }} \
-DHDF5_BUILD_CPP_LIB:BOOL=${{ matrix.cpp }} \
-DHDF5_BUILD_FORTRAN:BOOL=${{ matrix.fortran }} \
-DHDF5_BUILD_JAVA:BOOL=OFF \
-DHDF5_BUILD_DOC:BOOL=OFF \
-DHDF5_ENABLE_ZLIB_SUPPORT:BOOL=${{ matrix.zlibfc }} \
-DHDF5_ENABLE_SZIP_SUPPORT:BOOL=${{ matrix.libaecfc }} \
-DLIBAEC_USE_LOCALCONTENT:BOOL=${{ matrix.localaec }} \
-DZLIB_USE_LOCALCONTENT:BOOL=${{ matrix.localzlib }} \
-DHDF5_ENABLE_MIRROR_VFD:BOOL=${{ matrix.mirror_vfd }} \
-DHDF5_ENABLE_DIRECT_VFD:BOOL=${{ matrix.direct_vfd }} \
-DHDF5_ENABLE_ROS3_VFD:BOOL=${{ matrix.ros3_vfd }} \
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_PACKAGE_EXTLIBS:BOOL=ON \
-DHDF5_PACK_MACOSX_DMG:BOOL=OFF \
$GITHUB_WORKSPACE
shell: bash
# BUILD
- name: Build
run: cmake --build . --parallel 3 --config ${{ inputs.build_mode }}
working-directory: ${{ runner.workspace }}/build
# RUN TESTS
- name: Run Tests
run: ctest . --parallel 2 -C ${{ inputs.build_mode }} -V
working-directory: ${{ runner.workspace }}/build
if: ${{ matrix.run_tests }}
+518
View File
@@ -0,0 +1,518 @@
name: Maven Repository Deployment
# Triggers the workflow on a call from another workflow
on:
workflow_call:
inputs:
file_base:
description: "The common base name of the source tarballs"
required: true
type: string
preset_name:
description: "The preset configuration name used for build"
required: true
type: string
repository_url:
description: 'Maven repository URL (GitHub Packages or Maven Central)'
required: false
type: string
default: 'https://maven.pkg.github.com/HDFGroup/hdf5'
repository_id:
description: 'Maven repository ID for server configuration'
required: false
type: string
default: 'github'
deploy_snapshots:
description: 'Deploy snapshot versions (-SNAPSHOT suffix)'
required: false
type: boolean
default: false
dry_run:
description: 'Perform validation without actual deployment'
required: false
type: boolean
default: false
secrets:
MAVEN_USERNAME:
description: 'Maven repository username'
required: true
MAVEN_PASSWORD:
description: 'Maven repository password/token'
required: true
GPG_PRIVATE_KEY:
description: 'GPG private key for signing (Maven Central)'
required: false
GPG_PASSPHRASE:
description: 'GPG passphrase for signing'
required: false
permissions:
contents: read
packages: write
jobs:
check-secret:
name: Check Secrets exists
runs-on: ubuntu-latest
outputs:
gpg-state: ${{ steps.set-gpg-state.outputs.HAVEGPG }}
steps:
- name: Identify GPG Status
id: set-gpg-state
env:
gpg_secret: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
if [[ '${{ env.gpg_secret }}' == '' ]]
then
GPG_VAL=$(echo 'notexists')
else
GPG_VAL=$(echo 'exists')
fi
echo "HAVEGPG=$GPG_VAL" >> $GITHUB_OUTPUT
shell: bash
- run: echo "gpg key is ${{ steps.set-gpg-state.outputs.HAVEGPG }}."
validate-artifacts:
name: Validate Build Artifacts
runs-on: ubuntu-latest
outputs:
hdf5-version: ${{ steps.extract-version.outputs.hdf5-version }}
jar-files: ${{ steps.find-jars.outputs.jar-files }}
pom-file: ${{ steps.find-pom.outputs.pom-file }}
platform-classifier: ${{ steps.platform-info.outputs.classifier }}
steps:
- name: Download artifacts (Linux)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-linux-x86_64
path: ./artifacts/linux
continue-on-error: true
- name: Download artifacts (Windows)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-windows-x86_64
path: ./artifacts/windows
continue-on-error: true
- name: Download artifacts (macOS x86_64)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-macos-x86_64
path: ./artifacts/macos-x86_64
continue-on-error: true
- name: Download artifacts (macOS aarch64)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-macos-aarch64
path: ./artifacts/macos-aarch64
continue-on-error: true
- name: Find JAR files
id: find-jars
run: |
# Find only main HDF5 JAR files across all platform directories
JAR_FILES=""
echo "=== Scanning for main HDF5 JAR files ==="
for platform_dir in ./artifacts/*/; do
if [ -d "$platform_dir" ]; then
platform_name=$(basename "$platform_dir")
echo "Scanning platform: $platform_name"
# Find main HDF5 JAR files (jarhdf5-*.jar) and examples JAR files (hdf5-java-examples-*.jar)
# Find both main HDF5 JARs and examples JARs
platform_jars=$(find "$platform_dir" \( -name "jarhdf5-*.jar" -o -name "hdf5-java-examples-*.jar" \) 2>/dev/null || true)
if [ -n "$platform_jars" ]; then
echo "Found HDF5 JARs in $platform_name:"
echo "$platform_jars" | while read jar; do echo " - $(basename "$jar")"; done
if [ -z "$JAR_FILES" ]; then
JAR_FILES="$platform_jars"
else
JAR_FILES="$JAR_FILES,$platform_jars"
fi
else
echo "No HDF5 JARs found in $platform_name"
fi
fi
done
# Remove trailing comma and convert newlines to commas
JAR_FILES=$(echo "$JAR_FILES" | tr '\n' ',' | sed 's/,$//' | sed 's/^,//')
echo "jar-files=${JAR_FILES}" >> $GITHUB_OUTPUT
echo "=== Final JAR list for deployment ==="
echo "$JAR_FILES" | tr ',' '\n' | while read jar; do
if [ -n "$jar" ]; then
echo " - $jar"
fi
done
if [ -z "${JAR_FILES}" ]; then
echo "ERROR: No main HDF5 JAR files found in artifacts"
echo "Available files:"
find ./artifacts -name "*.jar" -o -name "*.xml" 2>/dev/null | head -20
exit 1
fi
- name: Find POM file
id: find-pom
run: |
POM_FILE=$(find ./artifacts -name "pom.xml" | head -1)
echo "pom-file=${POM_FILE}" >> $GITHUB_OUTPUT
echo "Found POM file: ${POM_FILE}"
if [ -z "${POM_FILE}" ]; then
echo "ERROR: No POM file found in artifacts"
exit 1
fi
- name: Extract version information
id: extract-version
run: |
# Extract version from POM file
VERSION=$(grep -o '<version>[^<]*</version>' "${{ steps.find-pom.outputs.pom-file }}" | head -1 | sed 's/<[^>]*>//g')
echo "hdf5-version=${VERSION}" >> $GITHUB_OUTPUT
echo "Extracted HDF5 version: ${VERSION}"
- name: Determine platform classifier
id: platform-info
run: |
# Extract platform classifier from JAR filename
JAR_FILE=$(echo "${{ steps.find-jars.outputs.jar-files }}" | cut -d',' -f1)
CLASSIFIER=""
if [[ "${JAR_FILE}" == *"linux"* ]]; then
CLASSIFIER="linux-x86_64"
elif [[ "${JAR_FILE}" == *"windows"* ]]; then
CLASSIFIER="windows-x86_64"
elif [[ "${JAR_FILE}" == *"macos"* ]]; then
if [[ "${JAR_FILE}" == *"aarch64"* ]]; then
CLASSIFIER="macos-aarch64"
else
CLASSIFIER="macos-x86_64"
fi
fi
echo "classifier=${CLASSIFIER}" >> $GITHUB_OUTPUT
echo "Platform classifier: ${CLASSIFIER}"
- name: Quick artifact validation
run: |
echo "=== Quick Artifact Validation ==="
# Count artifacts
jar_count=$(echo "${{ steps.find-jars.outputs.jar-files }}" | tr ',' '\n' | wc -l)
echo "Found ${jar_count} JAR file(s) for deployment"
# Basic validation (artifacts should already be validated by staging workflow)
for jar_file in $(echo "${{ steps.find-jars.outputs.jar-files }}" | tr ',' ' '); do
if [ ! -f "${jar_file}" ]; then
echo "ERROR: JAR file not found: ${jar_file}"
exit 1
fi
platform=$(dirname "${jar_file}" | sed 's|./artifacts/||')
jar_name=$(basename "${jar_file}")
echo "✓ [$platform] ${jar_name}"
done
# Quick POM validation
if [ -f "${{ steps.find-pom.outputs.pom-file }}" ]; then
echo "✓ POM file found: $(basename "${{ steps.find-pom.outputs.pom-file }}")"
else
echo "ERROR: POM file not found"
exit 1
fi
echo "✓ Quick validation passed - artifacts ready for deployment"
deploy-maven:
name: Deploy to Maven Repository
runs-on: ubuntu-latest
needs: [check-secret, validate-artifacts]
if: ${{ !inputs.dry_run }}
steps:
- name: Download artifacts (Linux)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-linux-x86_64
path: ./artifacts/linux
continue-on-error: true
- name: Download artifacts (Windows)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-windows-x86_64
path: ./artifacts/windows
continue-on-error: true
- name: Download artifacts (macOS x86_64)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-macos-x86_64
path: ./artifacts/macos-x86_64
continue-on-error: true
- name: Download artifacts (macOS aarch64)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-macos-aarch64
path: ./artifacts/macos-aarch64
continue-on-error: true
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: '11'
distribution: 'temurin'
- name: Create Maven settings.xml
run: |
mkdir -p ~/.m2
cat > ~/.m2/settings.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>${{ inputs.repository_id }}</id>
<username>${{ secrets.MAVEN_USERNAME }}</username>
<password>${{ secrets.MAVEN_PASSWORD }}</password>
</server>
</servers>
</settings>
EOF
- name: Import GPG key (if provided)
if: ${{ needs.check-secret.outputs.gpg-state == 'exists' }}
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
echo "GPG key imported for artifact signing"
- name: Deploy JAR artifacts
env:
HDF5_VERSION: ${{ needs.validate-artifacts.outputs.hdf5-version }}
PLATFORM_CLASSIFIER: ${{ needs.validate-artifacts.outputs.platform-classifier }}
run: |
echo "=== Maven Deployment Debug Info ==="
echo "Version: ${HDF5_VERSION}"
echo "Repository: ${{ inputs.repository_url }}"
echo "Repository ID: ${{ inputs.repository_id }}"
echo "Platform Classifier: ${PLATFORM_CLASSIFIER}"
echo "Dry Run: ${{ inputs.dry_run }}"
echo "Deploy Snapshots: ${{ inputs.deploy_snapshots }}"
echo "Username: ${{ secrets.MAVEN_USERNAME }}"
echo "Password length: ${#MAVEN_PASSWORD} chars"
echo "GPG Private Key available: ${{ secrets.GPG_PRIVATE_KEY != '' }}"
# Check Maven configuration
echo "=== Maven Configuration ==="
mvn --version
cat ~/.m2/settings.xml
# Set GPG options if available
GPG_OPTS=""
if [ -n "${{ secrets.GPG_PRIVATE_KEY }}" ]; then
GPG_OPTS="-Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }}"
echo "GPG signing enabled"
else
echo "GPG signing disabled (no private key)"
fi
# Deploy each JAR file with auto-detected platform classifier
success_count=0
total_count=0
echo "=== Starting JAR Deployment ==="
for jar_file in $(echo "${{ needs.validate-artifacts.outputs.jar-files }}" | tr ',' ' '); do
total_count=$((total_count + 1))
jar_basename=$(basename "${jar_file}")
platform_dir=$(dirname "${jar_file}")
echo "--- Processing JAR $total_count: $jar_basename ---"
echo "Full path: $jar_file"
echo "Platform dir: $platform_dir"
# Verify file exists
if [ ! -f "$jar_file" ]; then
echo "❌ ERROR: JAR file does not exist: $jar_file"
continue
fi
# Show file details
echo "File size: $(du -h "$jar_file" | cut -f1)"
echo "File permissions: $(ls -l "$jar_file")"
# Determine artifact type and settings
if [[ "${jar_basename}" == *"hdf5-java-examples"* ]]; then
# Java Examples artifact
ARTIFACT_ID="hdf5-java-examples"
CURRENT_CLASSIFIER="" # Examples JAR has no platform classifier
classifier_opts=""
echo "Artifact type: Java Examples (no classifier)"
else
# Main HDF5 Java library
ARTIFACT_ID="hdf5-java"
# Auto-detect platform classifier from directory structure
CURRENT_CLASSIFIER=""
if [[ "${platform_dir}" == *"/linux"* ]]; then
CURRENT_CLASSIFIER="linux-x86_64"
elif [[ "${platform_dir}" == *"/windows"* ]]; then
CURRENT_CLASSIFIER="windows-x86_64"
elif [[ "${platform_dir}" == *"/macos-x86_64"* ]]; then
CURRENT_CLASSIFIER="macos-x86_64"
elif [[ "${platform_dir}" == *"/macos-aarch64"* ]]; then
CURRENT_CLASSIFIER="macos-aarch64"
fi
# Determine classifier options for main library
classifier_opts=""
if [ -n "${CURRENT_CLASSIFIER}" ] && [[ "${jar_basename}" != *"sources"* ]] && [[ "${jar_basename}" != *"javadoc"* ]]; then
classifier_opts="-Dclassifier=${CURRENT_CLASSIFIER}"
echo "Artifact type: HDF5 Java Library, classifier: ${CURRENT_CLASSIFIER}"
else
echo "Artifact type: HDF5 Java Library (no classifier)"
fi
fi
# Check if this is a dry run
if [ "${{ inputs.dry_run }}" == "true" ]; then
echo "🧪 DRY RUN: Would deploy ${jar_basename} as ${ARTIFACT_ID} with classifier ${CURRENT_CLASSIFIER:-none}"
echo "Command would be: mvn deploy:deploy-file -DgroupId=org.hdfgroup -DartifactId=${ARTIFACT_ID} -Dversion=${HDF5_VERSION} -Dfile=${jar_file} ${classifier_opts}"
success_count=$((success_count + 1))
else
echo "🚀 Deploying ${jar_basename}..."
# Deploy with Maven (with verbose output for debugging)
deploy_cmd="mvn deploy:deploy-file \
-DgroupId=org.hdfgroup \
-DartifactId=\"${ARTIFACT_ID}\" \
-Dversion=\"${HDF5_VERSION}\" \
-Dfile=\"${jar_file}\" \
-DpomFile=\"${{ needs.validate-artifacts.outputs.pom-file }}\" \
-DrepositoryId=\"${{ inputs.repository_id }}\" \
-Durl=\"${{ inputs.repository_url }}\" \
${classifier_opts} \
${GPG_OPTS} \
-B -X"
echo "Command: $deploy_cmd"
if eval $deploy_cmd; then
echo "✓ Successfully deployed: ${jar_basename}"
success_count=$((success_count + 1))
else
deploy_exit_code=$?
echo "✗ Failed to deploy: ${jar_basename} (exit code: $deploy_exit_code)"
# Try to get more specific error information
echo "=== Debugging deployment failure ==="
echo "Testing repository connectivity..."
curl -I "${{ inputs.repository_url }}" || echo "Repository not accessible via curl"
echo "Testing authentication..."
curl -u "${{ secrets.MAVEN_USERNAME }}:${{ secrets.MAVEN_PASSWORD }}" \
-I "${{ inputs.repository_url }}" || echo "Authentication test failed"
fi
fi
done
echo "=== Deployment Summary ==="
echo "Successful deployments: ${success_count}/${total_count}"
if [ ${success_count} -eq ${total_count} ]; then
echo "🎉 All artifacts deployed successfully!"
else
echo "❌ Some deployments failed"
exit 1
fi
- name: Verify deployment
env:
HDF5_VERSION: ${{ needs.validate-artifacts.outputs.hdf5-version }}
run: |
echo "=== Deployment Verification ==="
# Wait for repository to process
sleep 10
# For GitHub Packages, we can verify using the API
if [[ "${{ inputs.repository_url }}" == *"maven.pkg.github.com"* ]]; then
echo "Verifying GitHub Packages deployment..."
# Extract owner/repo from URL
REPO_PATH=$(echo "${{ inputs.repository_url }}" | sed 's|.*maven.pkg.github.com/||')
curl -s -H "Authorization: token ${{ secrets.MAVEN_PASSWORD }}" \
"https://api.github.com/users/HDFGroup/packages?package_type=maven" | \
grep -q "hdf5-java" && echo "✓ Package verified in GitHub Packages" || echo "⚠ Package verification pending"
fi
echo "Deployment verification completed"
create-release-notes:
name: Create Maven Release Notes
runs-on: ubuntu-latest
needs: [validate-artifacts, deploy-maven]
if: ${{ always() && needs.validate-artifacts.result == 'success' }}
steps:
- name: Generate deployment summary
run: |
cat > maven-deployment-summary.md << 'EOF'
# Maven Deployment Summary
**Version**: ${{ needs.validate-artifacts.outputs.hdf5-version }}
**Repository**: ${{ inputs.repository_url }}
**Deployment Status**: ${{ needs.deploy-maven.result || 'skipped (dry-run)' }}
## HDF5 Java Library
```xml
<dependency>
<groupId>org.hdfgroup</groupId>
<artifactId>hdf5-java</artifactId>
<version>${{ needs.validate-artifacts.outputs.hdf5-version }}</version>
<classifier>linux-x86_64</classifier> <!-- or windows-x86_64, macos-x86_64, macos-aarch64 -->
</dependency>
```
## HDF5 Java Examples
```xml
<dependency>
<groupId>org.hdfgroup</groupId>
<artifactId>hdf5-java-examples</artifactId>
<version>${{ needs.validate-artifacts.outputs.hdf5-version }}</version>
</dependency>
```
## Gradle Dependencies
```kotlin
// HDF5 Java Library
implementation("org.hdfgroup:hdf5-java:${{ needs.validate-artifacts.outputs.hdf5-version }}:linux-x86_64")
// HDF5 Java Examples (62 examples)
implementation("org.hdfgroup:hdf5-java-examples:${{ needs.validate-artifacts.outputs.hdf5-version }}")
```
## Available Packages
- **hdf5-java**: Platform-specific HDF5 Java bindings (4 platform variants)
- **hdf5-java-examples**: 62 Java examples (platform-independent)
EOF
echo "Maven deployment summary created"
- name: Upload deployment summary
uses: actions/upload-artifact@v5
with:
name: maven-deployment-summary
path: maven-deployment-summary.md
retention-days: 30
+1175
View File
@@ -0,0 +1,1175 @@
name: Maven Staging Repository Test
# Triggers on pull requests that modify Maven-related files
on:
pull_request:
branches: [ develop, main ]
paths:
- 'java/src/hdf/hdf5lib/**'
- 'HDF5Examples/JAVA/**'
- '.github/workflows/maven-*.yml'
- '.github/workflows/java-examples-*.yml'
- 'CMakePresets.json'
- '**/CMakeLists.txt'
- 'java/src/hdf/hdf5lib/pom.xml.in'
- 'HDF5Examples/JAVA/pom-examples.xml.in'
workflow_call:
inputs:
test_maven_deployment:
description: 'Test Maven deployment to staging'
type: boolean
required: false
default: true
use_snapshot_version:
description: 'Use snapshot version (-SNAPSHOT suffix)'
type: boolean
required: false
default: true
platforms:
description: 'Build platforms for Maven artifacts'
type: string
required: false
default: 'all-platforms'
java_implementation:
description: 'Java implementation to test'
type: string
required: false
default: 'auto'
workflow_dispatch:
inputs:
test_maven_deployment:
description: 'Test Maven deployment to staging'
type: boolean
required: false
default: true
use_snapshot_version:
description: 'Use snapshot version (-SNAPSHOT suffix)'
type: boolean
required: false
default: true
platforms:
description: 'Build platforms for Maven artifacts'
type: choice
required: false
default: 'all-platforms'
options:
- 'linux-only'
- 'linux-windows'
- 'linux-macos'
- 'all-platforms'
java_implementation:
description: 'Java implementation to test'
type: choice
required: false
default: 'auto'
options:
- 'auto'
- 'ffm'
- 'jni'
- 'both'
permissions:
contents: read
packages: write
pull-requests: write
jobs:
detect-changes:
name: Detect Maven-related Changes
runs-on: ubuntu-latest
outputs:
maven-changes: ${{ steps.changes.outputs.maven }}
should-test: ${{ steps.should-test.outputs.result }}
steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
with:
fetch-depth: 0
- name: Detect changes in Maven-related files
id: changes
run: |
# Check if this is a manual trigger
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "maven=true" >> $GITHUB_OUTPUT
echo "Manual workflow dispatch - Maven testing enabled"
exit 0
fi
# For push events, check the last commit
if [ "${{ github.event_name }}" == "push" ]; then
echo "maven=true" >> $GITHUB_OUTPUT
echo "Push event - Maven testing enabled"
exit 0
fi
# For pull requests, check changed files
if [ -n "${{ github.base_ref }}" ]; then
git fetch origin ${{ github.base_ref }}
MAVEN_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -E "(java/src/hdf/hdf5lib/|HDF5Examples/JAVA/|maven|pom\.xml|CMakePresets\.json)" || true)
else
# Fallback: assume changes if base_ref not available
MAVEN_FILES="true"
fi
if [ -n "$MAVEN_FILES" ]; then
echo "maven=true" >> $GITHUB_OUTPUT
echo "Maven-related changes detected"
else
echo "maven=false" >> $GITHUB_OUTPUT
echo "No Maven-related changes detected"
fi
- name: Determine if Maven testing should run
id: should-test
run: |
if [ "${{ steps.changes.outputs.maven }}" == "true" ] || [ "${{ inputs.test_maven_deployment }}" == "true" ]; then
echo "result=true" >> $GITHUB_OUTPUT
echo "Maven testing will be performed"
else
echo "result=false" >> $GITHUB_OUTPUT
echo "Maven testing will be skipped"
fi
determine-matrix:
name: Determine Build Matrix
needs: detect-changes
if: ${{ needs.detect-changes.outputs.should-test == 'true' }}
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Determine build matrix
id: set-matrix
run: |
JAVA_IMPL="${{ inputs.java_implementation || 'auto' }}"
PLATFORMS="${{ inputs.platforms || 'all-platforms' }}"
# Determine which implementations to build
case "$JAVA_IMPL" in
"ffm")
IMPLEMENTATIONS='["ffm"]'
;;
"jni")
IMPLEMENTATIONS='["jni"]'
;;
"both")
IMPLEMENTATIONS='["ffm", "jni"]'
;;
"auto"|*)
# Auto means build based on Java version (defaults handled by presets)
# We'll build once with auto setting
IMPLEMENTATIONS='["auto"]'
;;
esac
# Determine which platforms to build
case "$PLATFORMS" in
"linux-only")
PLATFORM_LIST='[{"name": "Linux", "os": "ubuntu-latest", "compiler": "GNUC", "arch": "x86_64"}]'
;;
"linux-windows")
PLATFORM_LIST='[{"name": "Linux", "os": "ubuntu-latest", "compiler": "GNUC", "arch": "x86_64"}, {"name": "Windows", "os": "windows-latest", "compiler": "MSVC", "arch": "x86_64"}]'
;;
"linux-macos")
PLATFORM_LIST='[{"name": "Linux", "os": "ubuntu-latest", "compiler": "GNUC", "arch": "x86_64"}, {"name": "macOS-x86_64", "os": "macos-13", "compiler": "Clang", "arch": "x86_64"}, {"name": "macOS-aarch64", "os": "macos-latest", "compiler": "Clang", "arch": "aarch64"}]'
;;
"all-platforms"|*)
PLATFORM_LIST='[{"name": "Linux", "os": "ubuntu-latest", "compiler": "GNUC", "arch": "x86_64"}, {"name": "Windows", "os": "windows-latest", "compiler": "MSVC", "arch": "x86_64"}, {"name": "macOS-x86_64", "os": "macos-13", "compiler": "Clang", "arch": "x86_64"}, {"name": "macOS-aarch64", "os": "macos-latest", "compiler": "Clang", "arch": "aarch64"}]'
;;
esac
# Create the full matrix combining platforms and implementations
MATRIX="{\"include\":["
FIRST=true
for platform in $(echo "$PLATFORM_LIST" | jq -c '.[]'); do
for impl in $(echo "$IMPLEMENTATIONS" | jq -r '.[]'); do
if [ "$FIRST" = true ]; then
FIRST=false
else
MATRIX+=","
fi
# Extract platform details
PLATFORM_NAME=$(echo "$platform" | jq -r '.name')
PLATFORM_OS=$(echo "$platform" | jq -r '.os')
PLATFORM_COMPILER=$(echo "$platform" | jq -r '.compiler')
PLATFORM_ARCH=$(echo "$platform" | jq -r '.arch')
# Create artifact name suffix
# Platform name already includes arch for macOS (e.g., macOS-x86_64)
PLATFORM_LOWER="${PLATFORM_NAME,,}"
if [[ "$PLATFORM_LOWER" == *"-"* ]]; then
# Platform name already has arch suffix (macOS case)
BASE_NAME="$PLATFORM_LOWER"
else
# Add arch suffix (Linux, Windows case)
BASE_NAME="${PLATFORM_LOWER}-${PLATFORM_ARCH}"
fi
if [ "$impl" = "auto" ]; then
ARTIFACT_SUFFIX="$BASE_NAME"
else
ARTIFACT_SUFFIX="${BASE_NAME}-${impl}"
fi
MATRIX+="{\"platform\":\"$PLATFORM_NAME\",\"os\":\"$PLATFORM_OS\",\"compiler\":\"$PLATFORM_COMPILER\",\"arch\":\"$PLATFORM_ARCH\",\"implementation\":\"$impl\",\"artifact-suffix\":\"$ARTIFACT_SUFFIX\"}"
done
done
MATRIX+="]}"
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
echo "Generated matrix:"
echo "$MATRIX" | jq '.'
build-maven-artifacts:
name: "Build Maven Artifacts (${{ matrix.platform }} - ${{ matrix.implementation }})"
needs: [detect-changes, determine-matrix]
if: ${{ needs.detect-changes.outputs.should-test == 'true' }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.determine-matrix.outputs.matrix) }}
steps:
- name: Install Dependencies (Linux)
if: ${{ runner.os == 'Linux' }}
run: |
sudo apt-get update
sudo apt-get install ninja-build doxygen graphviz
- name: Install Dependencies (macOS)
if: ${{ runner.os == 'macOS' }}
run: |
brew install ninja doxygen graphviz
- name: Install Dependencies (Windows)
if: ${{ runner.os == 'Windows' }}
run: |
choco install ninja
choco install doxygen.install
choco install graphviz
- name: Enable Developer Command Prompt (Windows)
if: ${{ runner.os == 'Windows' }}
uses: ilammy/msvc-dev-cmd@v1.13.0
- name: Set up JDK (Java 25 for FFM builds)
uses: actions/setup-java@v5
with:
java-version: ${{ matrix.implementation == 'ffm' && '25' || '21' }}
distribution: ${{ matrix.implementation == 'ffm' && 'oracle' || 'temurin' }}
- name: Checkout code
uses: actions/checkout@v5.0.0
- name: Setup jextract (FFM builds only)
if: ${{ matrix.implementation == 'ffm' }}
uses: ./.github/actions/setup-jextract
with:
java-version: '25'
- name: Set preset name
id: set-preset
shell: bash
run: |
# Determine implementation suffix for preset based on matrix
JAVA_IMPL="${{ matrix.implementation }}"
case "$JAVA_IMPL" in
"ffm")
IMPL_SUFFIX="-FFM"
;;
"jni"|"auto"|*)
# JNI and auto use default Maven presets (JNI is default as of HDF5 2.0)
IMPL_SUFFIX=""
;;
esac
# Determine snapshot setting
SNAPSHOT_SUFFIX=""
if [ "${{ inputs.use_snapshot_version }}" == "true" ] || [ "${{ github.event_name }}" == "pull_request" ]; then
SNAPSHOT_SUFFIX="-Snapshot"
fi
# Build preset name: ci-MinShar-{COMPILER}-Maven{-FFM}{-Snapshot}
# Note: Generic Maven presets default to JNI (no suffix needed)
PRESET_NAME="ci-MinShar-${{ matrix.compiler }}-Maven${IMPL_SUFFIX}${SNAPSHOT_SUFFIX}"
echo "preset=$PRESET_NAME" >> $GITHUB_OUTPUT
echo "Using preset: $PRESET_NAME"
echo "Platform: ${{ matrix.platform }}, Compiler: ${{ matrix.compiler }}, Implementation: $JAVA_IMPL"
- name: Build HDF5 with Maven support
id: buildhdf5
shell: bash
run: |
cd "${{ github.workspace }}"
cmake --workflow --preset="${{ steps.set-preset.outputs.preset }}" --fresh
- name: Extract version information
id: version-info
shell: bash
run: |
# Find the generated POM file across all possible locations
BUILD_ROOT="${{ runner.workspace }}/build/${{ steps.set-preset.outputs.preset }}"
echo "Looking for POM file in: $BUILD_ROOT"
# Try multiple search patterns for cross-platform compatibility
POM_FILE=""
# Search patterns in order of preference
if [ -z "$POM_FILE" ]; then
POM_FILE=$(find "$BUILD_ROOT" -name "pom.xml" -path "*/java/*" 2>/dev/null | head -1)
fi
if [ -z "$POM_FILE" ]; then
POM_FILE=$(find "$BUILD_ROOT" -name "pom.xml" 2>/dev/null | head -1)
fi
# Try Maven artifacts directory if build structure differs
if [ -z "$POM_FILE" ] && [ -d "${{ runner.workspace }}/maven-artifacts" ]; then
POM_FILE=$(find "${{ runner.workspace }}/maven-artifacts" -name "pom.xml" 2>/dev/null | head -1)
fi
if [ -n "$POM_FILE" ] && [ -f "$POM_FILE" ]; then
# Extract version using robust pattern that works across platforms
VERSION=$(grep -o '<version>[^<]*</version>' "$POM_FILE" | head -1 | sed 's/<[^>]*>//g' | tr -d '\r\n')
# Validate version format
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "✓ Detected version: $VERSION"
echo "✓ POM file: $POM_FILE"
else
echo "version=unknown" >> $GITHUB_OUTPUT
echo "❌ Invalid version format detected: $VERSION"
exit 1
fi
else
echo "version=unknown" >> $GITHUB_OUTPUT
echo "❌ Could not find POM file"
echo "Available files in build root:"
find "$BUILD_ROOT" -name "*.xml" -o -name "pom*" 2>/dev/null | head -10 || echo "No XML files found"
exit 1
fi
- name: Collect Maven artifacts
shell: bash
run: |
echo "Collecting Maven artifacts for testing..."
mkdir -p "${{ runner.workspace }}/maven-artifacts"
BUILD_ROOT="${{ runner.workspace }}/build/${{ steps.set-preset.outputs.preset }}"
echo "Looking for Maven artifacts in build root: $BUILD_ROOT"
if [ ! -d "$BUILD_ROOT" ]; then
echo "ERROR: Build root directory does not exist: $BUILD_ROOT"
exit 1
fi
# Debug: Show what's in the build directory
echo "Build directory contents:"
find "$BUILD_ROOT" -maxdepth 3 -type d 2>/dev/null | head -20 || echo "Directory listing completed"
# Find build directory (try multiple patterns)
BUILD_DIR=$(find "$BUILD_ROOT" -name "*Maven*" -type d 2>/dev/null | head -1)
if [ -z "$BUILD_DIR" ]; then
# Try looking for java directory as fallback (more specific patterns)
BUILD_DIR=$(find "$BUILD_ROOT" -path "*/java/*" -type d 2>/dev/null | head -1)
if [ -z "$BUILD_DIR" ]; then
BUILD_DIR=$(find "$BUILD_ROOT" -name "java" -type d 2>/dev/null | head -1)
fi
fi
if [ -z "$BUILD_DIR" ]; then
# Try looking for any directory with JAR files
JAR_FILE=$(find "$BUILD_ROOT" -name "*.jar" -type f 2>/dev/null | head -1)
if [ -n "$JAR_FILE" ]; then
BUILD_DIR=$(dirname "$JAR_FILE")
echo "Found JAR file in: $BUILD_DIR"
fi
fi
if [ -z "$BUILD_DIR" ]; then
# Last resort: look for the build directory itself if it contains artifacts
if find "$BUILD_ROOT" -name "*.jar" -o -name "pom.xml" | grep -q .; then
BUILD_DIR="$BUILD_ROOT"
echo "Using build root as artifacts directory"
fi
fi
if [ -z "$BUILD_DIR" ]; then
echo "ERROR: Could not find Maven build directory with any of the patterns"
echo "Available directories:"
find "$BUILD_ROOT" -maxdepth 2 -type d
exit 1
fi
echo "Looking for artifacts in: $BUILD_DIR"
# Debug: Show all JAR files in build directory
echo "All JAR files in build directory:"
find "$BUILD_DIR" -name "*.jar" -type f 2>/dev/null | head -20 || true
# Debug: Show specifically what we're looking for
echo "SLF4J JAR files in build directory:"
find "$BUILD_DIR" -name "*slf4j*.jar" -type f
# Copy JAR files (excluding test and H5Ex_ example JARs)
find "$BUILD_DIR" -name "*.jar" -not -name "*test*" -not -name "*H5Ex_*" -exec cp {} "${{ runner.workspace }}/maven-artifacts/" \;
# Also look for Maven dependencies in common locations
echo "Looking for Maven dependencies in additional locations..."
# Check if there's a Maven repository in the build area
if [ -d "$BUILD_ROOT" ]; then
find "$BUILD_ROOT" -name "*slf4j*.jar" -type f -exec cp {} "${{ runner.workspace }}/maven-artifacts/" \;
fi
# Check common Maven local repository locations
MAVEN_REPO_PATHS=(
"$HOME/.m2/repository"
"$BUILD_ROOT/.m2/repository"
"${{ runner.workspace }}/.m2/repository"
)
for repo_path in "${MAVEN_REPO_PATHS[@]}"; do
if [ -d "$repo_path" ]; then
echo "Checking Maven repository: $repo_path"
find "$repo_path" -name "slf4j-api*.jar" -o -name "slf4j-simple*.jar" 2>/dev/null | head -2 | while read jar_file; do
if [ -f "$jar_file" ]; then
echo "Found dependency: $jar_file"
cp "$jar_file" "${{ runner.workspace }}/maven-artifacts/"
fi
done
fi
done
# Copy POM files
find "$BUILD_DIR" -name "pom.xml" -exec cp {} "${{ runner.workspace }}/maven-artifacts/" \;
# List collected artifacts
echo "Collected Maven artifacts:"
ls -la "${{ runner.workspace }}/maven-artifacts/"
- name: Validate artifacts
id: artifacts-check
shell: bash
run: |
ARTIFACT_COUNT=$(find "${{ runner.workspace }}/maven-artifacts" -name "*.jar" | wc -l)
POM_COUNT=$(find "${{ runner.workspace }}/maven-artifacts" -name "pom.xml" | wc -l)
echo "Found $ARTIFACT_COUNT JAR files and $POM_COUNT POM files"
if [ $ARTIFACT_COUNT -gt 0 ] && [ $POM_COUNT -gt 0 ]; then
echo "created=true" >> $GITHUB_OUTPUT
echo "✅ Artifacts successfully created"
else
echo "created=false" >> $GITHUB_OUTPUT
echo "❌ Artifact creation failed"
exit 1
fi
- name: Run validation script
shell: bash
run: |
if [ -f .github/scripts/validate-maven-artifacts.sh ]; then
echo "Running Maven artifact validation..."
.github/scripts/validate-maven-artifacts.sh "${{ runner.workspace }}/maven-artifacts"
else
echo "Validation script not found - skipping validation"
fi
- name: Upload Maven artifacts
uses: actions/upload-artifact@v5
with:
name: maven-staging-artifacts-${{ matrix.artifact-suffix }}
path: ${{ runner.workspace }}/maven-artifacts
retention-days: 7
test-maven-deployment:
name: Test Maven Deployment
runs-on: ubuntu-latest
needs: [detect-changes, determine-matrix, build-maven-artifacts]
if: ${{ always() && needs.detect-changes.outputs.should-test == 'true' }}
steps:
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Download all Maven artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: maven-staging-artifacts-*
path: ./artifacts
merge-multiple: false
- name: Test Maven deployment (dry run)
run: |
echo "=== Maven Deployment Test (Dry Run) ==="
# Extract version from first available POM file
POM_FILE=$(find ./artifacts -name "pom.xml" 2>/dev/null | head -1)
if [ -n "$POM_FILE" ]; then
VERSION=$(grep -o '<version>[^<]*</version>' "$POM_FILE" | head -1 | sed 's/<[^>]*>//g')
echo "Version: $VERSION"
else
echo "Version: (detecting from artifacts)"
fi
echo "Repository: GitHub Packages (staging)"
# List artifacts to be deployed by platform
echo "Artifacts ready for deployment:"
for platform_dir in ./artifacts/*/; do
if [ -d "$platform_dir" ]; then
platform_name=$(basename "$platform_dir")
echo "Platform: $platform_name"
find "$platform_dir" -name "*.jar" -exec basename {} \; | sed 's/^/ - /'
fi
done
# Create test Maven settings
mkdir -p ~/.m2
cat > ~/.m2/settings.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
</servers>
</settings>
EOF
# Simulate deployment validation for each platform
total_jars=0
valid_jars=0
for jar_file in $(find ./artifacts -name "*.jar"); do
jar_name=$(basename "$jar_file")
platform=$(dirname "$jar_file" | sed 's|./artifacts/||')
total_jars=$((total_jars + 1))
echo "[$platform] Testing: $jar_name"
# Test JAR integrity
if jar tf "$jar_file" > /dev/null 2>&1; then
echo " ✓ JAR integrity verified"
valid_jars=$((valid_jars + 1))
else
echo " ❌ JAR integrity check failed"
fi
done
echo "Validation summary: $valid_jars/$total_jars JARs passed integrity check"
if [ $valid_jars -ne $total_jars ]; then
echo "❌ Some artifacts failed validation"
exit 1
fi
echo "🎉 Dry run deployment test passed!"
test-java-examples-maven:
name: "Test Java Examples with Maven Artifacts (${{ matrix.platform }} - ${{ matrix.implementation }})"
runs-on: ${{ matrix.os }}
needs: [detect-changes, determine-matrix, build-maven-artifacts]
if: ${{ always() && needs.detect-changes.outputs.should-test == 'true' && needs.build-maven-artifacts.result == 'success' }}
continue-on-error: true # Non-blocking failures
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.determine-matrix.outputs.matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
- name: Set up JDK (Java 25 for FFM builds)
uses: actions/setup-java@v5
with:
java-version: ${{ matrix.implementation == 'ffm' && '25' || '21' }}
distribution: ${{ matrix.implementation == 'ffm' && 'oracle' || 'temurin' }}
- name: Install timeout command on macOS
if: ${{ startsWith(matrix.platform, 'macOS') }}
run: |
# Install GNU coreutils which includes gtimeout
brew install coreutils
echo "Installed gtimeout: $(which gtimeout)"
- name: Download Maven artifacts (${{ matrix.platform }} - ${{ matrix.implementation }})
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: maven-staging-artifacts-${{ matrix.artifact-suffix }}
path: ./maven-artifacts/${{ matrix.platform }}
continue-on-error: true
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-examples-${{ hashFiles('**/pom-examples.xml*') }}
restore-keys: |
${{ runner.os }}-maven-examples-
${{ runner.os }}-maven-
- name: Test Java Examples (Unix)
if: ${{ matrix.platform != 'Windows' }}
id: test-examples-unix
shell: bash
run: |
echo "=== Java Examples Maven Integration Test (${{ matrix.platform }}) ==="
# Test one representative example from each category
cd HDF5Examples/JAVA
# Get absolute path to maven artifacts for this platform
MAVEN_ARTIFACTS_DIR="$(realpath ../../maven-artifacts/${{ matrix.platform }})"
echo "Maven artifacts directory (${{ matrix.platform }}): $MAVEN_ARTIFACTS_DIR"
# Find HDF5 JAR files (not dependencies like slf4j) - use platform-specific artifacts
HDF5_JAR=$(find "$MAVEN_ARTIFACTS_DIR" -name "*hdf5*.jar" -o -name "jarhdf5*.jar" 2>/dev/null | head -1)
if [ -z "$HDF5_JAR" ]; then
echo "❌ No HDF5 JAR files found for testing"
echo "Available JAR files:"
find "$MAVEN_ARTIFACTS_DIR" -name "*.jar"
exit 1
fi
echo "Using HDF5 JAR file: $HDF5_JAR"
# Detect JAR type by checking for FFM-specific classes
# FFM JARs contain org.hdfgroup.javahdf5 package, JNI JARs contain hdf.hdf5lib
if jar tf "$HDF5_JAR" | grep -q "org/hdfgroup/javahdf5/hdf5_h.class"; then
JAR_TYPE="ffm"
echo "Detected FFM JAR (contains org.hdfgroup.javahdf5 package)"
else
JAR_TYPE="jni"
echo "Detected JNI JAR (contains hdf.hdf5lib package)"
fi
# Determine which examples directory to use based on detected JAR type
# This ensures we test with examples that match the JAR's implementation
if [ "$JAR_TYPE" = "jni" ]; then
EXAMPLES_DIR="compat"
echo "Using JNI-compatible examples from compat/ directory"
else
EXAMPLES_DIR="."
echo "Using FFM examples from root directory"
fi
# Also find any dependency JARs - only include slf4j-api and slf4j-simple, exclude slf4j-nop to avoid conflicts
DEP_JARS=$(find "$MAVEN_ARTIFACTS_DIR" -name "slf4j-api*.jar" -o -name "slf4j-simple*.jar")
if [ -n "$DEP_JARS" ]; then
echo "Found dependency JARs:"
echo "$DEP_JARS"
else
echo "No SLF4J dependency JARs found in artifacts, downloading them directly..."
# Download SLF4J dependencies directly using Maven
SLF4J_VERSION="2.0.16"
TEMP_POM="$MAVEN_ARTIFACTS_DIR/temp-pom.xml"
# Create a minimal POM to download dependencies using echo
echo '<?xml version="1.0" encoding="UTF-8"?>' > "$TEMP_POM"
echo '<project xmlns="http://maven.apache.org/POM/4.0.0"' >> "$TEMP_POM"
echo ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' >> "$TEMP_POM"
echo ' xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">' >> "$TEMP_POM"
echo ' <modelVersion>4.0.0</modelVersion>' >> "$TEMP_POM"
echo ' <groupId>temp</groupId>' >> "$TEMP_POM"
echo ' <artifactId>temp</artifactId>' >> "$TEMP_POM"
echo ' <version>1.0</version>' >> "$TEMP_POM"
echo ' <dependencies>' >> "$TEMP_POM"
echo ' <dependency>' >> "$TEMP_POM"
echo ' <groupId>org.slf4j</groupId>' >> "$TEMP_POM"
echo ' <artifactId>slf4j-api</artifactId>' >> "$TEMP_POM"
echo ' <version>2.0.16</version>' >> "$TEMP_POM"
echo ' </dependency>' >> "$TEMP_POM"
echo ' <dependency>' >> "$TEMP_POM"
echo ' <groupId>org.slf4j</groupId>' >> "$TEMP_POM"
echo ' <artifactId>slf4j-simple</artifactId>' >> "$TEMP_POM"
echo ' <version>2.0.16</version>' >> "$TEMP_POM"
echo ' </dependency>' >> "$TEMP_POM"
echo ' </dependencies>' >> "$TEMP_POM"
echo '</project>' >> "$TEMP_POM"
# Download dependencies
if (cd "$MAVEN_ARTIFACTS_DIR" && mvn -f temp-pom.xml dependency:copy-dependencies -DoutputDirectory=. -DincludeScope=runtime -q); then
# Clean up temporary POM
rm -f "$TEMP_POM"
# Re-scan for dependency JARs
DEP_JARS=$(find "$MAVEN_ARTIFACTS_DIR" -name "slf4j-api*.jar" -o -name "slf4j-simple*.jar")
if [ -n "$DEP_JARS" ]; then
echo "Successfully downloaded SLF4J dependencies:"
echo "$DEP_JARS"
else
echo "Failed to download SLF4J dependencies"
fi
else
echo "Error downloading dependencies with Maven"
rm -f "$TEMP_POM"
fi
fi
FAILED_EXAMPLES=""
TOTAL_EXAMPLES=0
PASSED_EXAMPLES=0
# Save current directory (HDF5Examples/JAVA)
JAVA_DIR="$(pwd)"
# Test representative examples from each category
for category in H5D H5T H5G TUTR; do
if [ -d "$EXAMPLES_DIR/$category" ]; then
cd "$JAVA_DIR/$EXAMPLES_DIR/$category"
# Find first .java file in category
EXAMPLE_FILE=$(ls *.java | head -1)
if [ -f "$EXAMPLE_FILE" ]; then
TOTAL_EXAMPLES=$((TOTAL_EXAMPLES + 1))
example_name=$(basename "$EXAMPLE_FILE" .java)
echo "--- Testing $category/$example_name ---"
# Build classpath with HDF5 JAR and dependencies (already absolute paths)
CLASSPATH="$HDF5_JAR"
if [ -n "$DEP_JARS" ]; then
for dep_jar in $DEP_JARS; do
CLASSPATH="$CLASSPATH:$dep_jar"
done
fi
echo "Using classpath: $CLASSPATH"
# Set compilation flags based on detected JAR type
# This ensures we use correct flags for the actual JAR implementation
if [ "$JAR_TYPE" = "ffm" ]; then
# FFM requires preview features (Java 25)
JAVAC_FLAGS="--enable-preview --release 25"
JAVA_FLAGS="--enable-preview"
else
# JNI uses standard Java
JAVAC_FLAGS=""
JAVA_FLAGS=""
fi
# Test compilation
COMPILE_OUTPUT=$(javac $JAVAC_FLAGS -cp "$CLASSPATH" "$EXAMPLE_FILE" 2>&1)
if [ $? -eq 0 ]; then
echo "✓ Compilation successful for $category/$example_name"
# Test execution (with cross-platform timeout)
if command -v gtimeout >/dev/null 2>&1; then
# macOS with GNU coreutils timeout
EXEC_RESULT=$(gtimeout 10s java $JAVA_FLAGS -cp ".:$CLASSPATH" "$example_name" >/tmp/${example_name}.out 2>&1; echo $?)
elif command -v timeout >/dev/null 2>&1; then
# Linux/Windows with timeout command
EXEC_RESULT=$(timeout 10s java $JAVA_FLAGS -cp ".:$CLASSPATH" "$example_name" >/tmp/${example_name}.out 2>&1; echo $?)
else
# Fallback - run without timeout (Java examples should complete quickly)
echo "Note: Running without timeout"
java $JAVA_FLAGS -cp ".:$CLASSPATH" "$example_name" >/tmp/${example_name}.out 2>&1
EXEC_RESULT=$?
fi
if [ "$EXEC_RESULT" -eq 0 ]; then
# Basic output validation
if grep -q -i -E "(dataset|datatype|group|success|created|written|read)" /tmp/${example_name}.out && \
! grep -q -i -E "(error|exception|failed|cannot)" /tmp/${example_name}.out; then
echo "✓ Execution and validation successful for $category/$example_name"
PASSED_EXAMPLES=$((PASSED_EXAMPLES + 1))
else
echo "✗ Output validation failed for $category/$example_name"
echo "Output:"
cat /tmp/${example_name}.out
FAILED_EXAMPLES="$FAILED_EXAMPLES $category/$example_name"
fi
else
# Check if failure is due to expected native library issue (acceptable for Maven-only testing)
if grep -q "UnsatisfiedLinkError.*hdf5_java.*java.library.path" /tmp/${example_name}.out; then
echo "✓ Expected native library error for Maven-only testing: $category/$example_name"
echo " (This confirms JAR structure is correct)"
PASSED_EXAMPLES=$((PASSED_EXAMPLES + 1))
else
echo "✗ Unexpected execution failure for $category/$example_name"
echo "Output:"
cat /tmp/${example_name}.out
FAILED_EXAMPLES="$FAILED_EXAMPLES $category/$example_name"
fi
fi
else
echo "✗ Compilation failed for $category/$example_name"
echo "Compilation error output:"
echo "$COMPILE_OUTPUT"
FAILED_EXAMPLES="$FAILED_EXAMPLES $category/$example_name"
fi
fi
fi
done
echo "=== Java Examples Test Summary (${{ matrix.platform }}) ==="
echo "Total representative examples tested: $TOTAL_EXAMPLES"
echo "Passed: $PASSED_EXAMPLES"
echo "Failed: $((TOTAL_EXAMPLES - PASSED_EXAMPLES))"
if [ -n "$FAILED_EXAMPLES" ]; then
echo "Failed examples:$FAILED_EXAMPLES"
echo "❌ Some Java examples failed - but continuing (non-blocking)"
echo "test-status=FAILED" >> $GITHUB_OUTPUT
else
echo "✅ All representative Java examples passed!"
echo "test-status=PASSED" >> $GITHUB_OUTPUT
fi
echo "total-examples=$TOTAL_EXAMPLES" >> $GITHUB_OUTPUT
echo "passed-examples=$PASSED_EXAMPLES" >> $GITHUB_OUTPUT
- name: Test Java Examples (Windows)
if: ${{ matrix.platform == 'Windows' }}
id: test-examples-windows
shell: pwsh
run: |
Write-Host "=== Java Examples Maven Integration Test (Windows) ==="
# Test one representative example from each category
Set-Location HDF5Examples/JAVA
# Get absolute path to maven artifacts for this platform
$MAVEN_ARTIFACTS_DIR = Resolve-Path "../../maven-artifacts/${{ matrix.platform }}"
Write-Host "Maven artifacts directory (Windows): $MAVEN_ARTIFACTS_DIR"
# Find HDF5 JAR files (not dependencies like slf4j)
$HDF5_JAR = Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "*hdf5*.jar" -Recurse | Select-Object -First 1
if (-not $HDF5_JAR) {
$HDF5_JAR = Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "jarhdf5*.jar" -Recurse | Select-Object -First 1
}
if (-not $HDF5_JAR) {
Write-Host "❌ No HDF5 JAR files found for testing"
Write-Host "Available JAR files:"
Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "*.jar" -Recurse
exit 1
}
Write-Host "Using HDF5 JAR file: $($HDF5_JAR.FullName)"
# Detect JAR type by checking for FFM-specific classes
# FFM JARs contain org.hdfgroup.javahdf5 package, JNI JARs contain hdf.hdf5lib
$jar_contents = & jar tf $HDF5_JAR.FullName
if ($jar_contents -match "org/hdfgroup/javahdf5/hdf5_h.class") {
$JAR_TYPE = "ffm"
Write-Host "Detected FFM JAR (contains org.hdfgroup.javahdf5 package)"
} else {
$JAR_TYPE = "jni"
Write-Host "Detected JNI JAR (contains hdf.hdf5lib package)"
}
# Determine which examples directory to use based on detected JAR type
# This ensures we test with examples that match the JAR's implementation
if ($JAR_TYPE -eq "jni") {
$EXAMPLES_DIR = "compat"
Write-Host "Using JNI-compatible examples from compat/ directory"
} else {
$EXAMPLES_DIR = "."
Write-Host "Using FFM examples from root directory"
}
# Find dependency JARs - only include slf4j-api and slf4j-simple
$DEP_JARS = @()
$DEP_JARS += Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "slf4j-api*.jar" -Recurse
$DEP_JARS += Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "slf4j-simple*.jar" -Recurse
if ($DEP_JARS.Count -gt 0) {
Write-Host "Found dependency JARs:"
$DEP_JARS | ForEach-Object { Write-Host " $($_.FullName)" }
} else {
Write-Host "No SLF4J dependency JARs found in artifacts, downloading them directly..."
# Download SLF4J dependencies directly using Maven
$SLF4J_VERSION = "2.0.16"
$TEMP_POM = "$MAVEN_ARTIFACTS_DIR\temp-pom.xml"
# Create a minimal POM to download dependencies using PowerShell strings
Write-Host "Creating temporary POM at: $TEMP_POM"
'<?xml version="1.0" encoding="UTF-8"?>' | Out-File $TEMP_POM -Encoding UTF8
'<project xmlns="http://maven.apache.org/POM/4.0.0"' | Out-File $TEMP_POM -Append -Encoding UTF8
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' | Out-File $TEMP_POM -Append -Encoding UTF8
' xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">' | Out-File $TEMP_POM -Append -Encoding UTF8
' <modelVersion>4.0.0</modelVersion>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <groupId>temp</groupId>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <artifactId>temp</artifactId>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <version>1.0</version>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <dependencies>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <dependency>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <groupId>org.slf4j</groupId>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <artifactId>slf4j-api</artifactId>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <version>2.0.16</version>' | Out-File $TEMP_POM -Append -Encoding UTF8
' </dependency>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <dependency>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <groupId>org.slf4j</groupId>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <artifactId>slf4j-simple</artifactId>' | Out-File $TEMP_POM -Append -Encoding UTF8
' <version>2.0.16</version>' | Out-File $TEMP_POM -Append -Encoding UTF8
' </dependency>' | Out-File $TEMP_POM -Append -Encoding UTF8
' </dependencies>' | Out-File $TEMP_POM -Append -Encoding UTF8
'</project>' | Out-File $TEMP_POM -Append -Encoding UTF8
# Download dependencies
try {
Write-Host "Running Maven command: mvn -f $TEMP_POM dependency:copy-dependencies -DoutputDirectory=$MAVEN_ARTIFACTS_DIR -DincludeScope=runtime -q"
$mvn_result = & mvn -f $TEMP_POM dependency:copy-dependencies "-DoutputDirectory=$MAVEN_ARTIFACTS_DIR" -DincludeScope=runtime -q
$mvn_exit_code = $LASTEXITCODE
# Clean up temporary POM
Remove-Item $TEMP_POM -Force -ErrorAction SilentlyContinue
if ($mvn_exit_code -eq 0) {
# Re-scan for dependency JARs
$DEP_JARS = @()
$DEP_JARS += Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "slf4j-api*.jar" -Recurse
$DEP_JARS += Get-ChildItem -Path $MAVEN_ARTIFACTS_DIR -Filter "slf4j-simple*.jar" -Recurse
if ($DEP_JARS.Count -gt 0) {
Write-Host "Successfully downloaded SLF4J dependencies:"
$DEP_JARS | ForEach-Object { Write-Host " $($_.FullName)" }
} else {
Write-Host "Maven succeeded but no SLF4J JARs found"
}
} else {
Write-Host "Maven command failed with exit code: $mvn_exit_code"
Write-Host "Maven output: $mvn_result"
}
} catch {
Write-Host "Error downloading dependencies: $($_.Exception.Message)"
}
}
$FAILED_EXAMPLES = @()
$TOTAL_EXAMPLES = 0
$PASSED_EXAMPLES = 0
# Save current directory (HDF5Examples/JAVA)
$JAVA_DIR = Get-Location
# Test representative examples from each category
foreach ($category in @("H5D", "H5T", "H5G", "TUTR")) {
$category_path = Join-Path $EXAMPLES_DIR $category
$full_category_path = Join-Path $JAVA_DIR $category_path
if (Test-Path $full_category_path) {
Set-Location $full_category_path
# Find first .java file in category
$EXAMPLE_FILE = Get-ChildItem -Filter "*.java" | Select-Object -First 1
if ($EXAMPLE_FILE) {
$TOTAL_EXAMPLES++
$example_name = $EXAMPLE_FILE.BaseName
Write-Host "--- Testing $category/$example_name ---"
# Build classpath with HDF5 JAR and dependencies
$CLASSPATH = $HDF5_JAR.FullName
foreach ($dep_jar in $DEP_JARS) {
$CLASSPATH += ";$($dep_jar.FullName)"
}
Write-Host "Using classpath: $CLASSPATH"
# Set compilation flags based on detected JAR type
# This ensures we use correct flags for the actual JAR implementation
if ($JAR_TYPE -eq "ffm") {
# FFM requires preview features (Java 25)
$JAVAC_FLAGS = @("--enable-preview", "--release", "25")
$JAVA_FLAGS = @("--enable-preview")
} else {
# JNI uses standard Java
$JAVAC_FLAGS = @()
$JAVA_FLAGS = @()
}
# Test compilation
$javac_args = $JAVAC_FLAGS + @("-cp", $CLASSPATH, $EXAMPLE_FILE.Name)
$compileResult = & javac $javac_args 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ Compilation successful for $category/$example_name"
# Test execution (with PowerShell timeout)
$output_file = "../../../$example_name.out"
# Use PowerShell's Start-Process with timeout for Windows
try {
# Create temporary files for stdout and stderr
$stdout_file = "$output_file.stdout"
$stderr_file = "$output_file.stderr"
# Build java arguments with optional FFM flags
$java_args = $JAVA_FLAGS + @("-cp", ".;$CLASSPATH", $example_name)
$process = Start-Process -FilePath "java" -ArgumentList $java_args -RedirectStandardOutput $stdout_file -RedirectStandardError $stderr_file -NoNewWindow -PassThru
# Wait for the process with timeout
if ($process.WaitForExit(10000)) { # 10 seconds in milliseconds
$execResult = $process.ExitCode
# Combine stdout and stderr into single output file
$stdout_content = if (Test-Path $stdout_file) {
try { Get-Content $stdout_file -Raw -ErrorAction SilentlyContinue } catch { "" }
} else { "" }
$stderr_content = if (Test-Path $stderr_file) {
try { Get-Content $stderr_file -Raw -ErrorAction SilentlyContinue } catch { "" }
} else { "" }
$combined_content = "$stdout_content$stderr_content"
if ([string]::IsNullOrWhiteSpace($combined_content)) {
$combined_content = "No output generated"
}
$combined_content | Out-File $output_file -Encoding UTF8
# Clean up temporary files
if (Test-Path $stdout_file) { Remove-Item $stdout_file -Force }
if (Test-Path $stderr_file) { Remove-Item $stderr_file -Force }
} else {
# Process timed out
try { $process.Kill() } catch { }
$execResult = 1
"Process timed out after 10 seconds" | Out-File $output_file -Encoding UTF8
# Clean up temporary files
if (Test-Path $stdout_file) { Remove-Item $stdout_file -Force }
if (Test-Path $stderr_file) { Remove-Item $stderr_file -Force }
}
} catch {
$execResult = 1
"Execution error: $($_.Exception.Message)" | Out-File $output_file -Encoding UTF8
}
if ($execResult -eq 0) {
# Basic output validation
$content = Get-Content $output_file -Raw
if (($content -match "(?i)(dataset|datatype|group|success|created|written|read)") -and
($content -notmatch "(?i)(error|exception|failed|cannot)")) {
Write-Host "✓ Execution and validation successful for $category/$example_name"
$PASSED_EXAMPLES++
} else {
Write-Host "✗ Output validation failed for $category/$example_name"
Write-Host "Output:"
Get-Content $output_file
$FAILED_EXAMPLES += "$category/$example_name"
}
} else {
# Check if failure is due to expected native library issue
$content = Get-Content $output_file -Raw
if ($content -match "UnsatisfiedLinkError.*hdf5_java.*java.library.path") {
Write-Host "✓ Expected native library error for Maven-only testing: $category/$example_name"
Write-Host " (This confirms JAR structure is correct)"
$PASSED_EXAMPLES++
} else {
Write-Host "✗ Unexpected execution failure for $category/$example_name"
Write-Host "Output:"
Get-Content $output_file
$FAILED_EXAMPLES += "$category/$example_name"
}
}
} else {
Write-Host "✗ Compilation failed for $category/$example_name"
Write-Host "Compilation error output:"
Write-Host $compileResult
$FAILED_EXAMPLES += "$category/$example_name"
}
}
}
}
Write-Host "=== Java Examples Test Summary (Windows) ==="
Write-Host "Total representative examples tested: $TOTAL_EXAMPLES"
Write-Host "Passed: $PASSED_EXAMPLES"
Write-Host "Failed: $($TOTAL_EXAMPLES - $PASSED_EXAMPLES)"
if ($FAILED_EXAMPLES.Count -gt 0) {
Write-Host "Failed examples: $($FAILED_EXAMPLES -join ' ')"
Write-Host "❌ Some Java examples failed - but continuing (non-blocking)"
echo "test-status=FAILED" >> $env:GITHUB_OUTPUT
} else {
Write-Host "✅ All representative Java examples passed!"
echo "test-status=PASSED" >> $env:GITHUB_OUTPUT
}
echo "total-examples=$TOTAL_EXAMPLES" >> $env:GITHUB_OUTPUT
echo "passed-examples=$PASSED_EXAMPLES" >> $env:GITHUB_OUTPUT
- name: Upload failure artifacts (Java Examples)
if: steps.test-examples-unix.outputs.test-status == 'FAILED' || steps.test-examples-windows.outputs.test-status == 'FAILED'
uses: actions/upload-artifact@v5
with:
name: java-examples-staging-failure-${{ matrix.platform }}-${{ github.run_id }}
path: |
/tmp/*.out
*.out
HDF5Examples/JAVA/*/*.class
HDF5Examples/JAVA/*/*.h5
retention-days: 7
comment-pr:
name: Comment on Pull Request
runs-on: ubuntu-latest
needs: [detect-changes, determine-matrix, build-maven-artifacts, test-maven-deployment]
if: ${{ github.event_name == 'pull_request' && needs.detect-changes.outputs.should-test == 'true' && needs.build-maven-artifacts.result == 'success' && needs.test-maven-deployment.result == 'success' }}
steps:
- name: Generate comment body
id: comment
run: |
COMMENT="## ✅ Maven Staging Tests Passed
Maven artifacts successfully generated and validated.
Ready for Maven deployment to GitHub Packages."
echo "comment<<EOF" >> $GITHUB_OUTPUT
echo "$COMMENT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Comment on PR
# Skip commenting if running from a fork due to permission restrictions
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
try {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.COMMENT_BODY
});
console.log('✅ Comment posted successfully');
} catch (error) {
console.log('❌ Failed to post comment:', error.message);
console.log('This may be due to insufficient permissions or fork restrictions');
// Don't fail the workflow if commenting fails
}
env:
COMMENT_BODY: ${{ steps.comment.outputs.comment }}
- name: Output test results (fallback)
if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
run: |
echo "==========================================="
echo "✅ Maven Staging Tests Passed"
echo "Maven artifacts successfully generated and validated"
echo "Ready for Maven deployment to GitHub Packages"
echo "==========================================="
echo "Note: Running from fork - PR comment skipped due to permission restrictions"
cleanup:
name: Cleanup Staging Artifacts
runs-on: ubuntu-latest
needs: [detect-changes, determine-matrix, build-maven-artifacts, test-maven-deployment]
if: ${{ always() && needs.detect-changes.outputs.should-test == 'true' }}
steps:
- name: Cleanup summary
run: |
echo "=== Maven Staging Cleanup ==="
echo "Artifacts will be automatically cleaned up after 7 days"
echo "Build artifacts are stored in GitHub Actions artifacts"
echo "No persistent staging repository cleanup needed"
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v5.0.0
- name: Build and test on OpenBSD
uses: vmactions/openbsd-vm@v1
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Get Sources
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.7
uses: actions/checkout@v5.0.0
with:
fetch-depth: 0
ref: '${{ github.head_ref || github.ref_name }}'
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Get Sources
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.7
uses: actions/checkout@v5.0.0
with:
fetch-depth: 0
ref: '${{ github.head_ref || github.ref_name }}'
+119 -4
View File
@@ -9,6 +9,19 @@ on:
type: string
required: false
default: snapshot
deploy_maven:
description: 'Deploy artifacts to Maven repository'
type: boolean
required: false
default: false
maven_repository:
description: 'Maven repository type'
type: choice
options:
- github-packages
- maven-central-staging
required: false
default: github-packages
permissions:
contents: read
@@ -35,13 +48,11 @@ jobs:
call-aws-c-s3-build:
needs: call-workflow-tarball
name: "Build aws-c-s3 library"
uses: ./.github/workflows/vfd-ros3.yml
uses: ./.github/workflows/build-aws-c-s3.yml
with:
build_mode: "Release"
build_aws_c_s3_only: true
aws_c_s3_build_type: "source"
# Use latest release for building from source on Ubuntu
# until a package is available to install
# until a package is available to install
aws_c_s3_tag: "v0.8.0"
call-workflow-ctest:
@@ -85,3 +96,107 @@ jobs:
use_tag: ${{ needs.log-the-inputs.outputs.rel_tag }}
use_environ: release
call-workflow-maven-staging:
needs: [log-the-inputs, call-workflow-tarball]
if: ${{ inputs.deploy_maven == true }}
permissions:
contents: read
packages: write
pull-requests: write
uses: ./.github/workflows/maven-staging.yml
with:
test_maven_deployment: true
use_snapshot_version: ${{ needs.log-the-inputs.outputs.rel_tag == 'snapshot' }}
platforms: 'all-platforms'
java_implementation: 'both' # Build both FFM and JNI implementations
deploy-maven-artifacts:
name: Deploy Maven Artifacts (FFM & JNI)
needs: [log-the-inputs, call-workflow-tarball, call-workflow-ctest, call-workflow-abi, call-workflow-maven-staging]
if: ${{ inputs.deploy_maven == true }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # For GitHub Packages deployment
strategy:
fail-fast: false
matrix:
include:
# Linux artifacts
- implementation: ffm
artifact-name: maven-staging-artifacts-linux-x86_64-ffm
- implementation: jni
artifact-name: maven-staging-artifacts-linux-x86_64-jni
# Windows artifacts
- implementation: ffm
artifact-name: maven-staging-artifacts-windows-x86_64-ffm
- implementation: jni
artifact-name: maven-staging-artifacts-windows-x86_64-jni
# macOS x86_64 artifacts
- implementation: ffm
artifact-name: maven-staging-artifacts-macos-x86_64-ffm
- implementation: jni
artifact-name: maven-staging-artifacts-macos-x86_64-jni
# macOS aarch64 artifacts
- implementation: ffm
artifact-name: maven-staging-artifacts-macos-aarch64-ffm
- implementation: jni
artifact-name: maven-staging-artifacts-macos-aarch64-jni
steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
server-id: ${{ inputs.maven_repository == 'github-packages' && 'github' || 'ossrh' }}
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg-passphrase: GPG_PASSPHRASE
- name: Download Maven artifacts (${{ matrix.artifact-name }})
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: ${{ matrix.artifact-name }}
path: ./maven-artifacts
continue-on-error: true
- name: Deploy to Maven repository
if: hashFiles('maven-artifacts/**') != ''
env:
MAVEN_USERNAME: ${{ inputs.maven_repository == 'github-packages' && github.actor || secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_PASSWORD: ${{ inputs.maven_repository == 'github-packages' && secrets.GITHUB_TOKEN || secrets.MAVEN_CENTRAL_PASSWORD }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
REPOSITORY_URL: ${{ inputs.maven_repository == 'github-packages' && format('https://maven.pkg.github.com/{0}', github.repository) || 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/' }}
REPOSITORY_ID: ${{ inputs.maven_repository == 'github-packages' && 'github' || 'ossrh' }}
run: |
# Find POM and JAR files
POM_FILE=$(find ./maven-artifacts -name "pom.xml" | head -1)
JAR_FILE=$(find ./maven-artifacts -name "*.jar" -not -name "*sources*" -not -name "*javadoc*" | head -1)
if [ -z "$POM_FILE" ] || [ -z "$JAR_FILE" ]; then
echo "No artifacts found for ${{ matrix.platform }} - ${{ matrix.implementation }}"
exit 0
fi
# Extract Maven coordinates from POM
GROUP_ID=$(grep -o '<groupId>[^<]*</groupId>' "$POM_FILE" | head -1 | sed 's/<[^>]*>//g')
ARTIFACT_ID=$(grep -o '<artifactId>[^<]*</artifactId>' "$POM_FILE" | head -1 | sed 's/<[^>]*>//g')
VERSION=$(grep -o '<version>[^<]*</version>' "$POM_FILE" | head -1 | sed 's/<[^>]*>//g')
echo "Deploying: $GROUP_ID:$ARTIFACT_ID:$VERSION"
echo "Platform: ${{ matrix.platform }}, Implementation: ${{ matrix.implementation }}"
echo "Repository: $REPOSITORY_URL"
# Deploy to Maven repository
mvn deploy:deploy-file \
-Dfile="$JAR_FILE" \
-DpomFile="$POM_FILE" \
-DrepositoryId="$REPOSITORY_ID" \
-Durl="$REPOSITORY_URL" \
-DgeneratePom=false \
-DuniqueVersion=false
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.7
uses: actions/checkout@v5.0.0
with:
persist-credentials: false
+210
View File
@@ -0,0 +1,210 @@
name: Test Maven Deployment
# Manual workflow for testing Maven deployment to HDFGroup packages
on:
workflow_dispatch:
inputs:
test_mode:
description: 'Test mode'
type: choice
options:
- dry-run
- live-deployment
required: true
default: dry-run
target_repository:
description: 'Maven repository target'
type: choice
options:
- github-packages
- maven-central-staging
required: false
default: github-packages
permissions:
contents: read
packages: write
jobs:
generate-test-artifacts:
name: Generate Test Artifacts
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5.0.0
- name: Display test configuration
run: |
echo "=== Maven Deployment Test Configuration ==="
echo "Test Mode: ${{ inputs.test_mode }}"
echo "Target Repository: ${{ inputs.target_repository }}"
echo "GitHub Actor: ${{ github.actor }}"
echo "Repository: ${{ github.repository }}"
echo "Expected packages URL: https://github.com/${{ github.repository }}/packages"
echo ""
- name: Check repository permissions
run: |
echo "=== Repository Permission Check ==="
# Check repository context
if [[ "${{ github.repository }}" == "HDFGroup/hdf5" ]]; then
echo "✓ Running on canonical repository (${{ github.repository }})"
echo " Packages will be published to HDFGroup/hdf5"
else
echo "✓ Running on fork/test repository (${{ github.repository }})"
echo " Packages will be published to ${{ github.repository }} for validation"
echo " This allows full testing before merging to canonical repository"
fi
# Check if we have packages permission
echo "Checking packages permission..."
if [[ "${{ github.token }}" != "" ]]; then
echo "✓ GITHUB_TOKEN is available"
else
echo "❌ GITHUB_TOKEN not available"
fi
- name: Test GitHub Packages API access
run: |
echo "=== Testing GitHub Packages API Access ==="
# Test basic API access
echo "Testing GitHub API access..."
curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/user" | jq '.login // "API_ERROR"'
# Test packages API access
echo "Testing GitHub Packages API access..."
curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/packages?package_type=maven" \
| jq 'length // "API_ERROR"' || echo "No packages found yet"
- name: Generate test Maven artifacts
run: |
echo "=== Generating Test Maven Artifacts ==="
# Create test directory structure
mkdir -p test-artifacts/maven-staging-artifacts-linux-x86_64
# Create a minimal test JAR file
mkdir -p temp-jar/org/hdfgroup/test
echo 'package org.hdfgroup.test; public class TestClass { }' > temp-jar/org/hdfgroup/test/TestClass.java
# Compile and create JAR
cd temp-jar
javac org/hdfgroup/test/TestClass.java
jar cf ../test-artifacts/maven-staging-artifacts-linux-x86_64/jarhdf5-2.0.0-test.jar org/hdfgroup/test/TestClass.class
cd ..
# Create a test POM file
cat > test-artifacts/maven-staging-artifacts-linux-x86_64/pom.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hdfgroup</groupId>
<artifactId>hdf5-java</artifactId>
<version>2.0.0-test</version>
<name>HDF5 Java Test</name>
<description>Test artifact for HDF5 Java Maven deployment</description>
</project>
EOF
# Upload as artifact for the deployment workflow
echo "Test artifacts created:"
find test-artifacts -type f -exec ls -la {} \;
- name: Upload test artifacts
uses: actions/upload-artifact@v5
with:
name: maven-staging-artifacts-linux-x86_64
path: test-artifacts/maven-staging-artifacts-linux-x86_64/
test-maven-deployment:
name: Test Maven Deployment to HDFGroup Packages
needs: generate-test-artifacts
uses: ./.github/workflows/maven-deploy.yml
with:
file_base: "hdf5-test"
preset_name: "test"
repository_url: ${{ inputs.target_repository == 'github-packages' && format('https://maven.pkg.github.com/{0}', github.repository) || 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/' }}
repository_id: ${{ inputs.target_repository == 'github-packages' && 'github' || 'ossrh' }}
deploy_snapshots: false
dry_run: ${{ inputs.test_mode == 'dry-run' }}
secrets:
MAVEN_USERNAME: ${{ inputs.target_repository == 'github-packages' && github.actor || secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_PASSWORD: ${{ inputs.target_repository == 'github-packages' && secrets.GITHUB_TOKEN || secrets.MAVEN_CENTRAL_PASSWORD }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
validate-results:
name: Validate Deployment Results
needs: test-maven-deployment
if: ${{ always() && inputs.test_mode == 'live-deployment' }}
runs-on: ubuntu-latest
steps:
- name: Validate deployment results
run: |
echo "=== Validating Deployment Results ==="
# Wait for packages to be processed
echo "Waiting 30 seconds for packages to be processed..."
sleep 30
# Check GitHub Packages for the deployed artifact
if [[ "${{ inputs.target_repository }}" == "github-packages" ]]; then
echo "Checking GitHub Packages..."
packages=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/packages?package_type=maven")
echo "Available packages:"
echo "$packages" | jq '.[] | {name: .name, html_url: .html_url}' || echo "No packages or jq not available"
# Check for our test package
if echo "$packages" | jq -r '.[].name' | grep -q "hdf5-java"; then
echo "✓ hdf5-java package found in GitHub Packages"
else
echo "⚠️ hdf5-java package not found in GitHub Packages"
fi
fi
display-results:
name: Display Test Results
needs: [generate-test-artifacts, test-maven-deployment]
if: always()
runs-on: ubuntu-latest
steps:
- name: Display next steps
run: |
echo "=== Test Results and Next Steps ==="
echo "Generation Status: ${{ needs.generate-test-artifacts.result }}"
echo "Deployment Status: ${{ needs.test-maven-deployment.result }}"
if [[ "${{ inputs.test_mode }}" == "dry-run" ]]; then
echo "🧪 DRY RUN COMPLETED"
echo ""
echo "✓ Permission configuration tested"
echo "✓ Workflow logic validated"
echo "✓ No actual artifacts deployed"
echo ""
echo "Next steps:"
echo "1. If no errors above, run with 'live-deployment' mode"
echo "2. Check https://github.com/${{ github.repository }}/packages for deployed artifacts"
echo "3. Test consuming the artifacts in a sample Maven project"
else
echo "🚀 LIVE DEPLOYMENT COMPLETED"
echo ""
echo "Check deployment results at:"
echo "- GitHub Packages: https://github.com/${{ github.repository }}/packages"
echo "- Workflow logs above for any deployment errors"
echo ""
echo "Next steps:"
echo "1. Run full release workflow with deploy_maven=true"
echo "2. Test end-to-end user experience with deployed artifacts"
fi
+8 -2
View File
@@ -36,14 +36,20 @@ jobs:
# with:
# build_mode: "${{ inputs.build_mode }}"
# Build aws-c-s3 library for ROS3 VFD testing
build_aws_c_s3:
uses: ./.github/workflows/build-aws-c-s3.yml
with:
build_mode: "${{ inputs.build_mode }}"
aws_c_s3_tag: "main"
# Test HDF5 ROS3 VFD
hdf5_vfd_ros3:
needs: build_aws_c_s3
uses: ./.github/workflows/vfd-ros3.yml
with:
build_mode: "${{ inputs.build_mode }}"
build_aws_c_s3_only: false
aws_c_s3_build_type: "source"
aws_c_s3_tag: "main"
# Test HDF5 HDFS VFD
#hdf5_vfd_hdfs:
+188 -243
View File
@@ -7,248 +7,39 @@ on:
description: "Build type (CMAKE_BUILD_TYPE)"
required: true
type: string
build_aws_c_s3_only:
description: "Only build the aws-c-s3 library without performing other actions"
required: true
type: boolean
aws_c_s3_build_type:
description: "Install aws-c-s3 from a package manager ('package') or build from source ('source')"
required: true
type: string
aws_c_s3_tag:
description: "Tag of aws-c-s3 to use when building from source"
save_binary:
description: "binary-ext-name or missing"
required: false
default: "skip"
type: string
java_version:
description: "Java version for testing (11, 17, 21, 24, latest, auto)"
required: false
default: "auto"
type: string
force_java_implementation:
description: "Force specific Java implementation (auto, ffm, jni)"
required: false
default: "jni"
type: string
permissions:
contents: read
jobs:
# Build the aws-c-s3 library from source using the specified tag
# and cache the results, currently only on Ubuntu. The result is
# compressed into a 'libaws-c-s3.tar' archive to preserve permissions
# and then is uploaded as the artifact 'libaws-c-s3' which can later
# be downloaded with 'actions/download-artifact' and then uncompressed
# with 'tar xvf libaws-c-s3.tar -C <directory>'. The uncompressed build
# directory will be called 'aws-c-s3-build'.
build_aws_c_s3:
# Ubuntu doesn't have a package for aws-c-s3 yet
# if: ${{ inputs.aws_c_s3_build_type == 'source' }}
name: "Build aws-c-s3 library"
runs-on: ubuntu-latest
steps:
- name: Get aws-c-s3 sources (main)
if: inputs.aws_c_s3_tag == ''
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-s3
path: aws-c-s3
- name: Get aws-c-s3 sources (tag)
if: inputs.aws_c_s3_tag != ''
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-s3
path: aws-c-s3
ref: ${{ inputs.aws_c_s3_tag }}
- name: Get aws-c-s3 commit hash
shell: bash
id: get-sha
run: |
cd $GITHUB_WORKSPACE/aws-c-s3
export AWSCS3_SHA=$(git rev-parse HEAD)
echo "AWSCS3_SHA=$AWSCS3_SHA" >> $GITHUB_ENV
echo "sha=$AWSCS3_SHA" >> $GITHUB_OUTPUT
# Output SHA for debugging
echo "AWSCS3_SHA=$AWSCS3_SHA"
- name: Cache/Restore aws-c-s3 (GCC) installation
id: cache-aws-c-s3-ubuntu-gcc
uses: actions/cache@v4
with:
path: ${{ runner.workspace }}/aws-c-s3-build
key: ${{ runner.os }}-${{ runner.arch }}-gcc-aws-c-s3-${{ steps.get-sha.outputs.sha }}-${{ inputs.build_mode }}
- name: Get aws-lc sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: aws/aws-lc
path: aws-lc
- name: Get s2n-tls sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: aws/s2n-tls
path: s2n-tls
- name: Get aws-c-common sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-common
path: aws-c-common
- name: Get aws-checksums sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-checksums
path: aws-checksums
- name: Get aws-c-cal sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-cal
path: aws-c-cal
- name: Get aws-c-io sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-io
path: aws-c-io
- name: Get aws-c-compression sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-compression
path: aws-c-compression
- name: Get aws-c-http sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-http
path: aws-c-http
- name: Get aws-c-sdkutils sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-sdkutils
path: aws-c-sdkutils
- name: Get aws-c-auth sources
if: ${{ steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true' }}
uses: actions/checkout@v5.0.0
with:
repository: awslabs/aws-c-auth
path: aws-c-auth
- name: Build aws-c-s3 from source
if: ${{ (steps.cache-aws-c-s3-ubuntu-gcc.outputs.cache-hit != 'true') }}
run: |
# Build aws-lc
echo "Building aws-lc"
cmake -S aws-lc -B aws-lc/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-lc/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build s2n-tls
echo "Building s2n-tls"
cmake -S s2n-tls -B s2n-tls/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build s2n-tls/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-common
echo "Building aws-c-common"
cmake -S aws-c-common -B aws-c-common/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-common/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-checksums
echo "Building aws-checksums"
cmake -S aws-checksums -B aws-checksums/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-checksums/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-cal
echo "Building aws-c-cal"
cmake -S aws-c-cal -B aws-c-cal/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-cal/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-io
echo "Building aws-c-io"
cmake -S aws-c-io -B aws-c-io/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-io/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-compression
echo "Building aws-c-compression"
cmake -S aws-c-compression -B aws-c-compression/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-compression/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-http
echo "Building aws-c-http"
cmake -S aws-c-http -B aws-c-http/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-http/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-sdkutils
echo "Building aws-c-sdkutils"
cmake -S aws-c-sdkutils -B aws-c-sdkutils/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-sdkutils/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-auth
echo "Building aws-c-auth"
cmake -S aws-c-auth -B aws-c-auth/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-auth/build --parallel 3 --config ${{ inputs.build_mode }} --target install
# Build aws-c-s3
echo "Building aws-c-s3"
cmake -S aws-c-s3 -B aws-c-s3/build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/aws-c-s3-build \
-DCMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build \
-DBUILD_SHARED_LIBS=1
cmake --build aws-c-s3/build --parallel 3 --config ${{ inputs.build_mode }} --target install
- name: Tar aws-c-s3 installation to preserve permissions for artifact
run: tar -cvf libaws-c-s3.tar -C ${{ runner.workspace }} aws-c-s3-build
- name: Save aws-c-s3 installation artifact
uses: actions/upload-artifact@v5
with:
name: libaws-c-s3-${{ inputs.build_mode }}
path: libaws-c-s3.tar
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
# NOTE: The aws-c-s3 library build is now handled by the parent workflow
# that calls this workflow. The parent must call build-aws-c-s3.yml before
# calling vfd-ros3.yml to ensure the libaws-c-s3 artifact is available.
build_from_package_managers:
if: ${{ inputs.aws_c_s3_build_type == 'package' && ! inputs.build_aws_c_s3_only }}
if: ${{ inputs.aws_c_s3_build_type == 'package' }}
# Ubuntu doesn't have a package for aws-c-s3 yet, so use a
# built from source version until then
needs: build_aws_c_s3
strategy:
# Let jobs run to completion even if one fails
@@ -266,10 +57,8 @@ jobs:
os: macos-latest
test_ros3: OFF
name: "Build and test the ROS3 VFD (${{ matrix.os_name }} ${{ inputs.build_mode }})"
name: "ROS3 VFD (${{ matrix.os_name }} ${{ inputs.build_mode }}-${{ inputs.force_java_implementation }})"
runs-on: ${{ matrix.os }}
steps:
- name: Install aws-c-s3 (Windows)
if: ${{ matrix.os_name == 'Windows MSVC' }}
@@ -310,6 +99,25 @@ jobs:
if: ${{ matrix.os_name == 'MacOS Clang' }}
run: brew install aws-c-s3
- name: Set up Java (if specified or FFM required)
if: inputs.java_version != 'auto' || inputs.force_java_implementation == 'ffm'
uses: actions/setup-java@v5
with:
distribution: ${{ inputs.force_java_implementation == 'ffm' && 'oracle' || 'temurin' }}
java-version: |
${{
inputs.force_java_implementation == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
- name: Verify Java Setup
if: inputs.java_version != 'auto' || inputs.force_java_implementation == 'ffm'
run: |
java -version
echo "JAVA_HOME=$JAVA_HOME"
echo "Selected Java implementation: ${{ inputs.force_java_implementation }}"
- name: Set environment for MSVC (Windows)
if: ${{ matrix.os_name == 'Windows MSVC' }}
run: |
@@ -320,6 +128,12 @@ jobs:
- name: Get HDF5 sources
uses: actions/checkout@v5.0.0
- name: Setup jextract (FFM builds only)
if: ${{ inputs.force_java_implementation == 'ffm' }}
uses: ./.github/actions/setup-jextract
with:
java-version: '25'
# For Windows, use vcpkg toolchain file to allow find_package() calls to resolve
- name: "Configure (vcpkg; ROS3 testing: ${{ matrix.test_ros3 }})"
if: ${{ matrix.os_name == 'Windows MSVC' }}
@@ -344,6 +158,8 @@ jobs:
-DZLIB_USE_LOCALCONTENT=OFF \
-DHDF5_ENABLE_ROS3_VFD:BOOL=ON \
-DHDF5_ENABLE_ROS3_VFD_DOCKER_PROXY=${{ matrix.test_ros3 }} \
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_ENABLE_JNI:BOOL=${{ inputs.force_java_implementation == 'jni' }} \
$GITHUB_WORKSPACE
shell: bash
@@ -369,6 +185,8 @@ jobs:
-DZLIB_USE_LOCALCONTENT=OFF \
-DHDF5_ENABLE_ROS3_VFD:BOOL=ON \
-DHDF5_ENABLE_ROS3_VFD_DOCKER_PROXY=${{ matrix.test_ros3 }} \
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_ENABLE_JNI:BOOL=${{ inputs.force_java_implementation == 'jni' }} \
$GITHUB_WORKSPACE
shell: bash
@@ -383,41 +201,132 @@ jobs:
ctest . -C ${{ inputs.build_mode }} -R "S3TEST" -V
working-directory: ${{ runner.workspace }}/build
# Build and test the ROS3 VFD using aws-c-s3 built from source,
# currently only on Ubuntu.
# Build and test the ROS3 VFD using aws-c-s3 from source (Linux) or package managers (Windows/macOS)
build_and_test_vfd:
if: ${{ inputs.aws_c_s3_build_type == 'source' && ! inputs.build_aws_c_s3_only }}
if: ${{ inputs.aws_c_s3_build_type == 'source' }}
needs: build_aws_c_s3
name: "Build and test the ROS3 VFD (Ubuntu ${{ inputs.build_mode }})"
runs-on: ubuntu-latest
strategy:
# Let jobs run to completion even if one fails
fail-fast: false
matrix:
os_name: ["Windows MSVC", "Ubuntu GCC", "MacOS Clang"]
include:
- os_name: "Windows MSVC"
os: windows-latest
ostype: windows
test_ros3: OFF
- os_name: "Ubuntu GCC"
os: ubuntu-latest
ostype: ubuntu
test_ros3: ON
- os_name: "MacOS Clang"
os: macos-latest
ostype: macos
test_ros3: OFF
name: "ROS3 VFD Source (${{ matrix.os_name }} ${{ inputs.build_mode }})"
runs-on: ${{ matrix.os }}
steps:
- name: Install libaws-c-s3 (Cached installation)
# Linux: Download aws-c-s3 artifact from build-aws-c-s3 workflow
- name: Install libaws-c-s3 (Ubuntu) (Cached installation)
if: ${{ matrix.os_name == 'Ubuntu GCC' }}
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: libaws-c-s3-${{ inputs.build_mode }}
- name: Untar libaws-c-s3 installation
- name: Untar libaws-c-s3 installation (Ubuntu)
if: ${{ matrix.os_name == 'Ubuntu GCC' }}
run: |
tar xvf libaws-c-s3.tar -C ${{ runner.workspace }}
- name: List contents of libaws-c-s3 installation
- name: List contents of libaws-c-s3 installation (Ubuntu)
if: ${{ matrix.os_name == 'Ubuntu GCC' }}
run: |
ls -lR ${{ runner.workspace }}/aws-c-s3-build
- name: Setup environment
- name: Setup environment (Ubuntu)
if: ${{ matrix.os_name == 'Ubuntu GCC' }}
shell: bash
run: |
echo "LD_LIBRARY_PATH=${{ runner.workspace }}/aws-c-s3-build/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV
echo "CMAKE_PREFIX_PATH=${{ runner.workspace }}/aws-c-s3-build" >> $GITHUB_ENV
# Windows: Install aws-c-s3 via vcpkg
- name: Install aws-c-s3 (Windows)
if: ${{ matrix.os_name == 'Windows MSVC' }}
run: vcpkg install aws-c-s3
# macOS: Install aws-c-s3 via Homebrew
- name: Install aws-c-s3 (MacOS)
if: ${{ matrix.os_name == 'MacOS Clang' }}
run: brew install aws-c-s3
- name: Set up Java (if specified or FFM required)
if: inputs.java_version != 'auto' || inputs.force_java_implementation == 'ffm'
uses: actions/setup-java@v5
with:
distribution: ${{ inputs.force_java_implementation == 'ffm' && 'oracle' || 'temurin' }}
java-version: |
${{
inputs.force_java_implementation == 'ffm' && '25' ||
inputs.java_version == 'latest' && '24' ||
inputs.java_version
}}
- name: Verify Java Setup
if: inputs.java_version != 'auto' || inputs.force_java_implementation == 'ffm'
run: |
java -version
echo "JAVA_HOME=$JAVA_HOME"
echo "Selected Java implementation: ${{ inputs.force_java_implementation }}"
- name: Set environment for MSVC (Windows)
if: ${{ matrix.os_name == 'Windows MSVC' }}
run: |
# Set these environment variables so CMake picks the correct compiler
echo "CXX=cl.exe" >> $GITHUB_ENV
echo "CC=cl.exe" >> $GITHUB_ENV
- name: Get HDF5 sources
uses: actions/checkout@v5.0.0
- name: Configure
- name: Setup jextract (FFM builds only)
if: ${{ inputs.force_java_implementation == 'ffm' }}
uses: ./.github/actions/setup-jextract
with:
java-version: '25'
# For Windows, use vcpkg toolchain file to allow find_package() calls to resolve
- name: "Configure (vcpkg; ROS3 testing: ${{ matrix.test_ros3 }})"
if: ${{ matrix.os_name == 'Windows MSVC' }}
run: |
mkdir "${{ runner.workspace }}/build"
cd "${{ runner.workspace }}/build"
cmake -C $GITHUB_WORKSPACE/config/cmake/cacheinit.cmake \
--log-level=VERBOSE \
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_BUILD_TYPE=${{ inputs.build_mode }} \
-DBUILD_SHARED_LIBS=ON \
-DHDF5_ENABLE_ALL_WARNINGS=ON \
-DHDF5_ENABLE_WARNINGS_AS_ERRORS=ON \
-DHDF5_ENABLE_PARALLEL:BOOL=OFF \
-DHDF5_BUILD_FORTRAN:BOOL=OFF \
-DHDF5_BUILD_CPP_LIB:BOOL=ON \
-DHDF5_ENABLE_ZLIB_SUPPORT:BOOL=ON \
-DHDF5_ENABLE_SZIP_SUPPORT:BOOL=ON \
-DHDF5_ENABLE_SZIP_ENCODING:BOOL=ON \
-DHDF5_ENABLE_PLUGIN_SUPPORT:BOOL=ON \
-DLIBAEC_USE_LOCALCONTENT=OFF \
-DZLIB_USE_LOCALCONTENT=OFF \
-DHDF5_ENABLE_ROS3_VFD:BOOL=ON \
-DHDF5_ENABLE_ROS3_VFD_DOCKER_PROXY=${{ matrix.test_ros3 }} \
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_ENABLE_JNI:BOOL=${{ inputs.force_java_implementation == 'jni' }} \
$GITHUB_WORKSPACE
shell: bash
- name: "Configure (ROS3 testing: ${{ matrix.test_ros3 }})"
if: ${{ matrix.os_name != 'Windows MSVC' }}
run: |
mkdir "${{ runner.workspace }}/build"
cd "${{ runner.workspace }}/build"
@@ -437,7 +346,9 @@ jobs:
-DLIBAEC_USE_LOCALCONTENT=OFF \
-DZLIB_USE_LOCALCONTENT=OFF \
-DHDF5_ENABLE_ROS3_VFD:BOOL=ON \
-DHDF5_ENABLE_ROS3_VFD_DOCKER_PROXY=ON \
-DHDF5_ENABLE_ROS3_VFD_DOCKER_PROXY=${{ matrix.test_ros3 }} \
-DHDF5_PACK_EXAMPLES:BOOL=ON \
-DHDF5_ENABLE_JNI:BOOL=${{ inputs.force_java_implementation == 'jni' }} \
$GITHUB_WORKSPACE
shell: bash
@@ -446,7 +357,41 @@ jobs:
working-directory: ${{ runner.workspace }}/build
- name: Run Tests
if: matrix.test_ros3 == 'ON'
run: |
# For now, just run S3 tests
ctest . -C ${{ inputs.build_mode }} -R "S3TEST" -V
working-directory: ${{ runner.workspace }}/build
- name: Run Package
run: cpack -C ${{ inputs.build_mode }} -V
working-directory: ${{ runner.workspace }}/build
- name: List files in the space
run: |
ls -l ${{ runner.workspace }}/build
# Save files created by CTest script
- name: Save published binary (Windows)
uses: actions/upload-artifact@v5
with:
name: zip-vs2022_cl-S3-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ runner.workspace }}/build/HDF5-*-win64.zip
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
if: ${{ (matrix.ostype == 'windows') && ( inputs.save_binary != 'skip') }}
- name: Save published binary (linux)
uses: actions/upload-artifact@v5
with:
name: tgz-ubuntu-2404_gcc-S3-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ runner.workspace }}/build/HDF5-*-Linux.tar.gz
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
if: ${{ (matrix.ostype == 'ubuntu') && ( inputs.save_binary != 'skip') }}
- name: Save published binary (Mac_latest)
uses: actions/upload-artifact@v5
with:
name: tgz-macos14_clang-S3-${{ inputs.build_mode }}-${{ inputs.save_binary }}-binary
path: ${{ runner.workspace }}/build/HDF5-*-Darwin.tar.gz
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
if: ${{ (matrix.ostype == 'macos') && ( inputs.save_binary != 'skip') }}