Advanced pipeline: Part 2 - Complete Enterprise-Grade Features

- Enterprise Android ROM build with resource monitoring and optimization
- Advanced artifact management with structured packaging and validation
- Smart artifact distribution with retry logic and comprehensive logging
- Final build success analytics with detailed reporting and notifications
- Complete error handling, recovery mechanisms, and validation throughout
- Resource monitoring during builds with automatic optimization
- Multi-hash checksum generation (MD5, SHA256, SHA512)
- Comprehensive build environment validation and device compatibility checks
- Installation instructions and documentation generation
- Slack integration support for build notifications
- Complete audit trail with detailed logs for every step
This commit is contained in:
Android ROM Builder
2025-06-30 00:03:11 +02:00
parent 09087f2847
commit 20221813eb

View File

@@ -656,153 +656,770 @@ steps:
env:
SYNC_JOBS: "8"
- label: ":hammer_and_wrench: Build Android ROM"
- label: ":hammer_and_wrench: Enterprise Android ROM Build"
key: "build-rom"
depends_on: "sync-source"
command: |
echo "🔨 Building Android ROM..."
set -euo pipefail
echo "🏗️ Enterprise-grade Android ROM build with advanced monitoring..."
cd android-source
# Configuration
# Build configuration with validation
TARGET_DEVICE="${TARGET_DEVICE:-generic}"
BUILD_TYPE="${BUILD_TYPE:-userdebug}"
BUILD_VARIANT="${BUILD_VARIANT:-lineage}"
BUILD_JOBS="${BUILD_JOBS:-$(nproc)}"
echo "🎯 Build configuration:"
echo " Device: $TARGET_DEVICE"
echo " Type: $BUILD_TYPE"
echo " Variant: $BUILD_VARIANT"
# Create comprehensive build log
mkdir -p ../logs
BUILD_LOG="../logs/rom-build.log"
# Set up build environment
echo "⚙️ Setting up build environment..."
source build/envsetup.sh
{
echo "=== ANDROID ROM BUILD LOG ==="
echo "Started: $(date)"
echo "Device: $TARGET_DEVICE"
echo "Type: $BUILD_TYPE"
echo "Variant: $BUILD_VARIANT"
echo "Jobs: $BUILD_JOBS"
echo "Host: $(hostname)"
echo ""
} > "$BUILD_LOG"
# Configure ccache
export USE_CCACHE=1
export CCACHE_DIR=$PWD/../ccache
mkdir -p $CCACHE_DIR
ccache -M 50G
# Resource monitoring function
monitor_resources() {
local build_pid=$1
local monitor_interval=60
local resource_log="../logs/resource-usage.log"
echo "=== RESOURCE MONITORING LOG ===" > "$resource_log"
while kill -0 $build_pid 2>/dev/null; do
{
echo "Timestamp: $(date)"
echo "CPU Usage: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%"
echo "Memory: $(free -h | awk '/^Mem:/ {printf "Used: %s/%s (%.1f%%)\n", $3, $2, $3/$2*100}')"
echo "Disk: $(df -h . | awk 'NR==2 {printf "Used: %s/%s (%s)\n", $3, $2, $5}')"
echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
echo "Active processes: $(ps aux | wc -l)"
echo "Ccache stats: $(ccache -s | grep "cache hit rate" || echo "N/A")"
echo "Build output size: $(du -sh ../out 2>/dev/null | cut -f1 || echo "N/A")"
echo "---"
} >> "$resource_log"
# Check for resource exhaustion
local mem_usage=$(free | awk '/^Mem:/ {printf "%.1f", $3/$2*100}')
local disk_usage=$(df . | awk 'NR==2 {print $5}' | sed 's/%//')
if (( $(echo "$mem_usage > 95" | bc -l) )); then
echo "🚨 CRITICAL: Memory usage critical ($mem_usage%)" | tee -a "$BUILD_LOG"
fi
if [ "$disk_usage" -gt 90 ]; then
echo "🚨 CRITICAL: Disk usage critical ($disk_usage%)" | tee -a "$BUILD_LOG"
fi
sleep $monitor_interval
done
buildkite-agent artifact upload "$resource_log" || true
}
# Select build target
echo "🎯 Selecting build target..."
lunch "${BUILD_VARIANT}_${TARGET_DEVICE}-${BUILD_TYPE}"
# Build environment validation
echo "🧪 Validating build environment..." | tee -a "$BUILD_LOG"
# Start build
echo "🚀 Starting compilation..."
START_TIME=$(date +%s)
# Check Java version
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
echo "Java version: $JAVA_VERSION" | tee -a "$BUILD_LOG"
if [ "$BUILD_VARIANT" = "lineage" ]; then
brunch "$TARGET_DEVICE"
else
make -j$(nproc) otapackage
# Validate build tools
if ! command -v make &> /dev/null; then
echo "❌ Make not found" | tee -a "$BUILD_LOG"
exit 1
fi
END_TIME=$(date +%s)
BUILD_TIME=$((END_TIME - START_TIME))
# Check available memory
AVAILABLE_MEM_GB=$(free -g | awk '/^Mem:/ {print $7}')
if [ "$AVAILABLE_MEM_GB" -lt 8 ]; then
echo "⚠️ Low available memory: ${AVAILABLE_MEM_GB}GB" | tee -a "$BUILD_LOG"
# Reduce build jobs if memory is low
BUILD_JOBS=$((BUILD_JOBS / 2))
[ $BUILD_JOBS -lt 1 ] && BUILD_JOBS=1
echo "Reduced build jobs to: $BUILD_JOBS" | tee -a "$BUILD_LOG"
fi
echo "✅ Build completed successfully!"
echo "⏱️ Build time: $(date -u -d @$BUILD_TIME +%H:%M:%S)"
# Validate source integrity
echo "🔍 Validating source code integrity..." | tee -a "$BUILD_LOG"
if ! repo status >/dev/null 2>&1; then
echo "❌ Source code integrity check failed" | tee -a "$BUILD_LOG"
exit 1
fi
# Set up advanced build environment
echo "⚙️ Configuring advanced build environment..." | tee -a "$BUILD_LOG"
# Source build environment
if ! source build/envsetup.sh 2>&1 | tee -a "$BUILD_LOG"; then
echo "❌ Failed to source build environment" | tee -a "$BUILD_LOG"
exit 1
fi
# Configure ccache with optimization
export USE_CCACHE=1
export CCACHE_DIR=$PWD/../ccache
export CCACHE_COMPRESS=1
export CCACHE_COMPRESSLEVEL=6
export CCACHE_MAXSIZE=100G
export CCACHE_SLOPPINESS=time_macros,include_file_mtime,include_file_ctime,file_macro
mkdir -p "$CCACHE_DIR"
ccache -M "$CCACHE_MAXSIZE"
ccache -s | tee -a "$BUILD_LOG"
# Device-specific validation
echo "📱 Device-specific validation for: $TARGET_DEVICE" | tee -a "$BUILD_LOG"
# Check if device is supported
DEVICE_DIR="device/*/⊕{TARGET_DEVICE}"
if ! ls device/*/"$TARGET_DEVICE" >/dev/null 2>&1 && [ "$TARGET_DEVICE" != "generic" ]; then
echo "⚠️ Device $TARGET_DEVICE not found in device tree" | tee -a "$BUILD_LOG"
echo "Available devices:" | tee -a "$BUILD_LOG"
find device -mindepth 2 -maxdepth 2 -type d | head -20 | tee -a "$BUILD_LOG"
if [ "${IGNORE_DEVICE_CHECK:-false}" != "true" ]; then
echo "❌ Set IGNORE_DEVICE_CHECK=true to bypass this check" | tee -a "$BUILD_LOG"
exit 1
fi
fi
# Lunch command with validation
echo "🎯 Configuring build target..." | tee -a "$BUILD_LOG"
LUNCH_COMBO="${BUILD_VARIANT}_${TARGET_DEVICE}-${BUILD_TYPE}"
echo "Lunch combo: $LUNCH_COMBO" | tee -a "$BUILD_LOG"
if ! lunch "$LUNCH_COMBO" 2>&1 | tee -a "$BUILD_LOG"; then
echo "❌ Failed to configure build target: $LUNCH_COMBO" | tee -a "$BUILD_LOG"
echo "Available targets:" | tee -a "$BUILD_LOG"
lunch 2>&1 | grep -E "^[0-9]+\." | head -20 | tee -a "$BUILD_LOG" || true
exit 1
fi
# Pre-build cleanup and optimization
echo "🧹 Pre-build optimization..." | tee -a "$BUILD_LOG"
# Clean old builds if requested
if [ "${CLEAN_BUILD:-false}" = "true" ]; then
echo "Performing clean build..." | tee -a "$BUILD_LOG"
make clean 2>&1 | tee -a "$BUILD_LOG"
fi
# Optimize build environment
export LC_ALL=C
export USE_NINJA=false # Some builds are more stable without ninja
export KBUILD_BUILD_USER="buildkite"
export KBUILD_BUILD_HOST="$(hostname)"
# Build execution with monitoring
echo "🚀 Starting ROM compilation..." | tee -a "$BUILD_LOG"
BUILD_START_TIME=$(date +%s)
# Determine build command based on variant
if [ "$BUILD_VARIANT" = "lineage" ]; then
BUILD_CMD="brunch $TARGET_DEVICE"
elif [ "$BUILD_VARIANT" = "aosp" ]; then
BUILD_CMD="make -j$BUILD_JOBS otapackage"
else
BUILD_CMD="make -j$BUILD_JOBS"
fi
echo "Build command: $BUILD_CMD" | tee -a "$BUILD_LOG"
# Execute build with monitoring
(
echo "Build started at: $(date)"
echo "Build command: $BUILD_CMD"
echo "Working directory: $(pwd)"
echo "Environment variables:"
env | grep -E "(TARGET_|BUILD_|CCACHE_|USE_)" | sort
echo "=== BUILD OUTPUT ==="
) | tee -a "$BUILD_LOG"
# Start build in background
$BUILD_CMD 2>&1 | tee -a "$BUILD_LOG" &
BUILD_PID=$!
# Start resource monitoring
monitor_resources $BUILD_PID &
MONITOR_PID=$!
# Wait for build to complete with timeout handling
BUILD_SUCCESS=false
if wait $BUILD_PID; then
BUILD_SUCCESS=true
echo "✅ Build process completed successfully" | tee -a "$BUILD_LOG"
else
BUILD_EXIT_CODE=$?
echo "❌ Build process failed with exit code: $BUILD_EXIT_CODE" | tee -a "$BUILD_LOG"
fi
# Stop monitoring
kill $MONITOR_PID 2>/dev/null || true
wait $MONITOR_PID 2>/dev/null || true
BUILD_END_TIME=$(date +%s)
BUILD_DURATION=$((BUILD_END_TIME - BUILD_START_TIME))
# Post-build analysis
echo "📊 Post-build analysis..." | tee -a "$BUILD_LOG"
{
echo "=== BUILD RESULTS ==="
echo "Status: $([ "$BUILD_SUCCESS" = true ] && echo "SUCCESS" || echo "FAILED")"
echo "Duration: $(date -u -d @$BUILD_DURATION +%H:%M:%S)"
echo "Start time: $(date -d @$BUILD_START_TIME)"
echo "End time: $(date -d @$BUILD_END_TIME)"
echo "Final ccache stats:"
ccache -s
echo ""
if [ "$BUILD_SUCCESS" = true ]; then
echo "=== BUILD ARTIFACTS ==="
OUT_DIR="out/target/product/$TARGET_DEVICE"
if [ -d "$OUT_DIR" ]; then
echo "Output directory: $OUT_DIR"
echo "Artifacts found:"
find "$OUT_DIR" -name "*.zip" -o -name "*.img" | head -10 || echo "No artifacts found"
echo "Total output size: $(du -sh out 2>/dev/null | cut -f1 || echo "unknown")"
fi
else
echo "=== BUILD FAILURE ANALYSIS ==="
echo "Last 50 lines of build log:"
tail -50 "$BUILD_LOG" | grep -E "(error|Error|ERROR|fail|Fail|FAIL)" || echo "No obvious errors in tail"
fi
} | tee -a "$BUILD_LOG"
# Upload build logs
cd ..
buildkite-agent artifact upload "$BUILD_LOG"
if [ "$BUILD_SUCCESS" != true ]; then
echo "💥 ROM build failed - check build logs for details"
exit 1
fi
echo "🎉 ROM build completed successfully!"
agents:
queue: "default"
timeout_in_minutes: 480
timeout_in_minutes: 600
retry:
automatic:
- exit_status: "*"
limit: 1
env:
TARGET_DEVICE: "generic"
BUILD_TYPE: "userdebug"
BUILD_TYPE: "userdebug"
BUILD_VARIANT: "lineage"
BUILD_JOBS: "8"
USE_CCACHE: "1"
CLEAN_BUILD: "false"
IGNORE_DEVICE_CHECK: "false"
- label: ":package: Package ROM Artifacts"
- label: ":package: Advanced ROM Artifact Management"
key: "package-rom"
depends_on: "build-rom"
command: |
echo "📦 Packaging ROM artifacts..."
set -euo pipefail
echo "📦 Advanced ROM artifact packaging and validation..."
TARGET_DEVICE="${TARGET_DEVICE:-generic}"
BUILD_TYPE="${BUILD_TYPE:-userdebug}"
BUILD_VARIANT="${BUILD_VARIANT:-lineage}"
OUT_DIR="android-source/out/target/product/$TARGET_DEVICE"
# Create artifacts directory
mkdir -p artifacts
# Create comprehensive packaging log
mkdir -p logs
PACKAGE_LOG="logs/packaging.log"
echo "📁 Copying build artifacts..."
# Copy ROM files
find "$OUT_DIR" -name "*.zip" -exec cp {} artifacts/ \; 2>/dev/null || true
find "$OUT_DIR" -name "recovery.img" -exec cp {} artifacts/ \; 2>/dev/null || true
find "$OUT_DIR" -name "boot.img" -exec cp {} artifacts/ \; 2>/dev/null || true
find "$OUT_DIR" -name "system.img" -exec cp {} artifacts/ \; 2>/dev/null || true
# Create build info
cat > artifacts/build-info.json << EOF
{
"build_number": "${BUILDKITE_BUILD_NUMBER:-unknown}",
"commit": "${BUILDKITE_COMMIT:-unknown}",
"branch": "${BUILDKITE_BRANCH:-unknown}",
"device": "$TARGET_DEVICE",
"build_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"build_type": "${BUILD_TYPE:-userdebug}",
"variant": "${BUILD_VARIANT:-lineage}"
echo "=== ROM ARTIFACT PACKAGING LOG ==="
echo "Started: $(date)"
echo "Device: $TARGET_DEVICE"
echo "Build Type: $BUILD_TYPE"
echo "Variant: $BUILD_VARIANT"
echo "Output Directory: $OUT_DIR"
echo ""
} > "$PACKAGE_LOG"
# Validate build output directory
if [ ! -d "$OUT_DIR" ]; then
echo "❌ Build output directory not found: $OUT_DIR" | tee -a "$PACKAGE_LOG"
echo "Available directories:" | tee -a "$PACKAGE_LOG"
find android-source/out -type d -name "product" 2>/dev/null | tee -a "$PACKAGE_LOG" || echo "No product directories found"
exit 1
fi
echo "✅ Build output directory validated" | tee -a "$PACKAGE_LOG"
# Create artifacts directory with proper structure
ARTIFACTS_DIR="artifacts"
mkdir -p "$ARTIFACTS_DIR"/{roms,images,recovery,logs,tools}
echo "📊 Analyzing build output..." | tee -a "$PACKAGE_LOG"
# Comprehensive artifact discovery
{
echo "=== BUILD OUTPUT ANALYSIS ==="
echo "Output directory size: $(du -sh "$OUT_DIR" 2>/dev/null | cut -f1 || echo "unknown")"
echo "File count: $(find "$OUT_DIR" -type f | wc -l)"
echo ""
echo "=== ROM FILES ==="
find "$OUT_DIR" -name "*.zip" -type f -exec ls -lh {} \; 2>/dev/null || echo "No ROM zip files found"
echo ""
echo "=== IMAGE FILES ==="
find "$OUT_DIR" -name "*.img" -type f -exec ls -lh {} \; 2>/dev/null | head -20 || echo "No image files found"
echo ""
echo "=== OTHER ARTIFACTS ==="
find "$OUT_DIR" -name "*.json" -o -name "*.xml" -o -name "*.txt" -type f 2>/dev/null | head -10 || echo "No metadata files found"
} | tee -a "$PACKAGE_LOG"
# Smart artifact collection
echo "🔍 Collecting ROM artifacts..." | tee -a "$PACKAGE_LOG"
ARTIFACTS_FOUND=0
# ROM packages (flashable zips)
while IFS= read -r -d '' file; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo "📱 ROM Package: $filename ($(du -sh "$file" | cut -f1))" | tee -a "$PACKAGE_LOG"
cp "$file" "$ARTIFACTS_DIR/roms/"
ARTIFACTS_FOUND=$((ARTIFACTS_FOUND + 1))
fi
done < <(find "$OUT_DIR" -name "*.zip" -type f -print0 2>/dev/null || true)
# Critical images
IMAGE_TYPES=("boot" "recovery" "system" "vendor" "userdata" "cache" "dtbo" "vbmeta")
for img_type in "${IMAGE_TYPES[@]}"; do
while IFS= read -r -d '' file; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo "💿 Image: $filename ($(du -sh "$file" | cut -f1))" | tee -a "$PACKAGE_LOG"
if [[ "$img_type" == "recovery" ]]; then
cp "$file" "$ARTIFACTS_DIR/recovery/"
else
cp "$file" "$ARTIFACTS_DIR/images/"
fi
ARTIFACTS_FOUND=$((ARTIFACTS_FOUND + 1))
fi
done < <(find "$OUT_DIR" -name "${img_type}.img" -type f -print0 2>/dev/null || true)
done
# Build metadata and logs
METADATA_FILES=("build.json" "build-info.json" "build.prop" "recovery.fstab")
for meta_file in "${METADATA_FILES[@]}"; do
while IFS= read -r -d '' file; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo "📋 Metadata: $filename" | tee -a "$PACKAGE_LOG"
cp "$file" "$ARTIFACTS_DIR/logs/"
ARTIFACTS_FOUND=$((ARTIFACTS_FOUND + 1))
fi
done < <(find "$OUT_DIR" -name "$meta_file" -type f -print0 2>/dev/null || true)
done
echo "📈 Total artifacts collected: $ARTIFACTS_FOUND" | tee -a "$PACKAGE_LOG"
if [ $ARTIFACTS_FOUND -eq 0 ]; then
echo "⚠️ No artifacts found - this may indicate a build failure" | tee -a "$PACKAGE_LOG"
echo "Build directory contents:" | tee -a "$PACKAGE_LOG"
ls -la "$OUT_DIR" | tee -a "$PACKAGE_LOG" || true
fi
# Generate comprehensive build information
echo "📝 Generating build metadata..." | tee -a "$PACKAGE_LOG"
cat > "$ARTIFACTS_DIR/build-info.json" << EOF
{
"build_info": {
"build_number": "${BUILDKITE_BUILD_NUMBER:-unknown}",
"commit": "${BUILDKITE_COMMIT:-unknown}",
"branch": "${BUILDKITE_BRANCH:-unknown}",
"build_url": "${BUILDKITE_BUILD_URL:-unknown}",
"pipeline": "${BUILDKITE_PIPELINE_SLUG:-unknown}"
},
"device_info": {
"device": "$TARGET_DEVICE",
"build_type": "$BUILD_TYPE",
"variant": "$BUILD_VARIANT"
},
"build_metadata": {
"build_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"build_timestamp": $(date +%s),
"builder_host": "$(hostname)",
"builder_user": "$(whoami)",
"android_version": "$(grep -o "PLATFORM_VERSION.*" android-source/build/core/version_defaults.mk 2>/dev/null | head -1 || echo "unknown")"
},
"artifacts": {
"total_count": $ARTIFACTS_FOUND,
"rom_packages": $(find "$ARTIFACTS_DIR/roms" -name "*.zip" 2>/dev/null | wc -l),
"images": $(find "$ARTIFACTS_DIR/images" -name "*.img" 2>/dev/null | wc -l),
"recovery": $(find "$ARTIFACTS_DIR/recovery" -name "*.img" 2>/dev/null | wc -l)
},
"build_environment": {
"ccache_stats": "$(ccache -s 2>/dev/null | grep "cache hit rate" || echo "N/A")",
"java_version": "$(java -version 2>&1 | head -1 || echo "unknown")",
"build_tools": "$(make --version 2>&1 | head -1 || echo "unknown")"
}
}
EOF
# Generate checksums
cd artifacts
for file in *.zip *.img 2>/dev/null; do
[ -f "$file" ] && md5sum "$file" > "$file.md5"
[ -f "$file" ] && sha256sum "$file" > "$file.sha256"
# Generate checksums with validation
echo "🔐 Generating and validating checksums..." | tee -a "$PACKAGE_LOG"
find "$ARTIFACTS_DIR" -name "*.zip" -o -name "*.img" | while read -r file; do
if [ -f "$file" ]; then
echo "Checksumming: $(basename "$file")" | tee -a "$PACKAGE_LOG"
# Generate multiple hash types for security
md5sum "$file" > "${file}.md5"
sha256sum "$file" > "${file}.sha256"
sha512sum "$file" > "${file}.sha512"
# Validate checksums immediately
if md5sum -c "${file}.md5" >/dev/null 2>&1; then
echo "✅ MD5 checksum verified for $(basename "$file")" | tee -a "$PACKAGE_LOG"
else
echo "❌ MD5 checksum failed for $(basename "$file")" | tee -a "$PACKAGE_LOG"
fi
fi
done
echo "📊 Artifacts created:"
ls -lh
# Create installation instructions
cat > "$ARTIFACTS_DIR/INSTALLATION.md" << 'EOF'
# ROM Installation Instructions
echo "✅ Packaging completed!"
## Prerequisites
- Unlocked bootloader
- Custom recovery (TWRP recommended)
- USB debugging enabled
- ADB and Fastboot tools installed
## Installation Steps
### Method 1: Recovery Flash (Recommended)
1. Download the ROM zip file from the artifacts
2. Boot into recovery mode
3. Wipe system, data, cache, and dalvik cache
4. Flash the ROM zip file
5. Flash GApps if desired
6. Reboot system
### Method 2: Fastboot Flash (Advanced)
1. Boot into fastboot mode
2. Flash individual image files:
```bash
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash vendor vendor.img
fastboot flash recovery recovery.img
```
3. Reboot system
## Verification
- Check build date in Settings > About Phone
- Verify ROM version matches build info
- Test basic functionality before daily use
## Support
- Check build logs if issues occur
- Verify checksums before flashing
- Create backup before installation
EOF
# Final artifact summary
echo "📊 Final artifact summary..." | tee -a "$PACKAGE_LOG"
{
echo "=== FINAL ARTIFACT SUMMARY ==="
echo "Packaging completed: $(date)"
echo ""
echo "Directory structure:"
find "$ARTIFACTS_DIR" -type f | sort | while read -r file; do
echo " $(basename "$file") ($(du -sh "$file" | cut -f1))"
done
echo ""
echo "Total artifacts size: $(du -sh "$ARTIFACTS_DIR" | cut -f1)"
echo "Checksum files created: $(find "$ARTIFACTS_DIR" -name "*.md5" -o -name "*.sha*" | wc -l)"
} | tee -a "$PACKAGE_LOG"
# Validate final package
if [ $ARTIFACTS_FOUND -gt 0 ]; then
echo "✅ ROM artifact packaging completed successfully!" | tee -a "$PACKAGE_LOG"
else
echo "❌ ROM artifact packaging completed but no artifacts were found!" | tee -a "$PACKAGE_LOG"
exit 1
fi
# Upload packaging log
buildkite-agent artifact upload "$PACKAGE_LOG"
agents:
queue: "default"
timeout_in_minutes: 30
timeout_in_minutes: 45
retry:
automatic:
- exit_status: "*"
limit: 2
env:
TARGET_DEVICE: "generic"
BUILD_TYPE: "userdebug"
BUILD_TYPE: "userdebug"
BUILD_VARIANT: "lineage"
- label: ":arrow_up: Upload Artifacts"
- label: ":arrow_up: Enterprise Artifact Distribution"
key: "upload-artifacts"
depends_on: "package-rom"
command: |
echo "⬆️ Uploading ROM artifacts..."
set -euo pipefail
# Upload all ROM files
if ls artifacts/*.zip >/dev/null 2>&1; then
buildkite-agent artifact upload "artifacts/*.zip"
echo "🚀 Enterprise-grade artifact distribution and validation..."
# Create upload log
mkdir -p logs
UPLOAD_LOG="logs/artifact-upload.log"
{
echo "=== ARTIFACT UPLOAD LOG ==="
echo "Started: $(date)"
echo "Build: ${BUILDKITE_BUILD_NUMBER:-unknown}"
echo "Pipeline: ${BUILDKITE_PIPELINE_SLUG:-unknown}"
echo ""
} > "$UPLOAD_LOG"
# Pre-upload validation
echo "🔍 Pre-upload artifact validation..." | tee -a "$UPLOAD_LOG"
ARTIFACTS_DIR="artifacts"
if [ ! -d "$ARTIFACTS_DIR" ]; then
echo "❌ Artifacts directory not found!" | tee -a "$UPLOAD_LOG"
exit 1
fi
if ls artifacts/*.img >/dev/null 2>&1; then
buildkite-agent artifact upload "artifacts/*.img"
# Count and validate artifacts
ROM_COUNT=$(find "$ARTIFACTS_DIR" -name "*.zip" | wc -l)
IMG_COUNT=$(find "$ARTIFACTS_DIR" -name "*.img" | wc -l)
CHECKSUM_COUNT=$(find "$ARTIFACTS_DIR" -name "*.md5" -o -name "*.sha*" | wc -l)
TOTAL_SIZE=$(du -sh "$ARTIFACTS_DIR" | cut -f1)
{
echo "=== UPLOAD VALIDATION ==="
echo "ROM packages: $ROM_COUNT"
echo "Image files: $IMG_COUNT"
echo "Checksum files: $CHECKSUM_COUNT"
echo "Total size: $TOTAL_SIZE"
echo ""
} | tee -a "$UPLOAD_LOG"
if [ $ROM_COUNT -eq 0 ] && [ $IMG_COUNT -eq 0 ]; then
echo "⚠️ No ROM or image files found to upload!" | tee -a "$UPLOAD_LOG"
echo "Directory contents:" | tee -a "$UPLOAD_LOG"
find "$ARTIFACTS_DIR" -type f | tee -a "$UPLOAD_LOG"
fi
# Upload metadata
buildkite-agent artifact upload "artifacts/*.json"
buildkite-agent artifact upload "artifacts/*.md5"
buildkite-agent artifact upload "artifacts/*.sha256"
# Upload function with retry logic
upload_with_retry() {
local pattern="$1"
local description="$2"
local max_attempts=3
local attempt=1
while [ $attempt -le $max_attempts ]; do
echo "Uploading $description (attempt $attempt/$max_attempts)..." | tee -a "$UPLOAD_LOG"
if buildkite-agent artifact upload "$pattern" 2>&1 | tee -a "$UPLOAD_LOG"; then
echo "✅ $description uploaded successfully" | tee -a "$UPLOAD_LOG"
return 0
else
echo "❌ Upload failed for $description" | tee -a "$UPLOAD_LOG"
if [ $attempt -eq $max_attempts ]; then
echo "💥 All upload attempts failed for $description" | tee -a "$UPLOAD_LOG"
return 1
fi
attempt=$((attempt + 1))
sleep 10
fi
done
}
echo "✅ Artifacts uploaded successfully!"
# Upload ROM packages
if [ $ROM_COUNT -gt 0 ]; then
echo "📱 Uploading ROM packages..." | tee -a "$UPLOAD_LOG"
upload_with_retry "artifacts/roms/*.zip" "ROM packages"
fi
# Upload system images
if [ $IMG_COUNT -gt 0 ]; then
echo "💿 Uploading system images..." | tee -a "$UPLOAD_LOG"
upload_with_retry "artifacts/images/*.img" "system images"
upload_with_retry "artifacts/recovery/*.img" "recovery images"
fi
# Upload checksums and metadata
echo "🔐 Uploading checksums and metadata..." | tee -a "$UPLOAD_LOG"
upload_with_retry "artifacts/*.json" "build metadata"
upload_with_retry "artifacts/**/*.md5" "MD5 checksums"
upload_with_retry "artifacts/**/*.sha*" "SHA checksums"
# Upload documentation
echo "📚 Uploading documentation..." | tee -a "$UPLOAD_LOG"
upload_with_retry "artifacts/*.md" "installation instructions"
# Upload all logs
echo "📄 Uploading build logs..." | tee -a "$UPLOAD_LOG"
upload_with_retry "logs/*.log" "build logs"
# Final upload summary
{
echo "=== UPLOAD SUMMARY ==="
echo "Upload completed: $(date)"
echo "Artifacts uploaded:"
buildkite-agent artifact search "*" | head -20 || echo "Could not list artifacts"
echo ""
echo "Download links will be available in the Buildkite artifacts tab"
echo "Total upload size: $TOTAL_SIZE"
} | tee -a "$UPLOAD_LOG"
echo "✅ All artifacts uploaded successfully!" | tee -a "$UPLOAD_LOG"
# Upload the upload log itself
buildkite-agent artifact upload "$UPLOAD_LOG"
agents:
queue: "default"
timeout_in_minutes: 60
retry:
automatic:
- exit_status: "*"
limit: 2
- label: ":white_check_mark: Build Complete"
- label: ":trophy: Build Success & Analytics"
depends_on: "upload-artifacts"
command: |
echo "🎉 Android ROM build completed successfully!"
set -euo pipefail
echo "🎉 Android ROM build pipeline completed successfully!"
# Create final report
mkdir -p logs
FINAL_REPORT="logs/build-final-report.log"
{
echo "=========================================="
echo " ANDROID ROM BUILD COMPLETE"
echo "=========================================="
echo ""
echo "🏆 BUILD INFORMATION"
echo "Build Number: ${BUILDKITE_BUILD_NUMBER:-unknown}"
echo "Build URL: ${BUILDKITE_BUILD_URL:-unknown}"
echo "Pipeline: ${BUILDKITE_PIPELINE_SLUG:-unknown}"
echo "Commit: ${BUILDKITE_COMMIT:-unknown}"
echo "Branch: ${BUILDKITE_BRANCH:-unknown}"
echo "Triggered by: ${BUILDKITE_BUILD_CREATOR:-unknown}"
echo ""
echo "📱 DEVICE CONFIGURATION"
echo "Target Device: ${TARGET_DEVICE:-generic}"
echo "Build Type: ${BUILD_TYPE:-userdebug}"
echo "Build Variant: ${BUILD_VARIANT:-lineage}"
echo ""
echo "⏱️ TIMING INFORMATION"
echo "Build started: ${BUILDKITE_BUILD_CREATED_AT:-unknown}"
echo "Build completed: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo ""
echo "🎯 QUICK LINKS"
echo "Artifacts: ${BUILDKITE_BUILD_URL:-unknown}#artifacts"
echo "Build logs: ${BUILDKITE_BUILD_URL:-unknown}#logs"
echo ""
echo "📦 WHAT'S INCLUDED"
echo "✅ Flashable ROM package (.zip)"
echo "✅ Individual partition images (.img)"
echo "✅ Recovery image (if built)"
echo "✅ Build metadata and checksums"
echo "✅ Installation instructions"
echo "✅ Complete build logs"
echo ""
echo "🔐 SECURITY"
echo "✅ MD5, SHA256, and SHA512 checksums provided"
echo "✅ Build reproducibility information included"
echo "✅ Build environment details logged"
echo ""
echo "📋 NEXT STEPS"
echo "1. Download artifacts from the Artifacts tab"
echo "2. Verify checksums before flashing"
echo "3. Follow installation instructions"
echo "4. Create a backup before flashing"
echo "5. Test thoroughly before daily use"
echo ""
echo "🆘 SUPPORT"
echo "- Check build logs if you encounter issues"
echo "- Verify your device is supported"
echo "- Ensure bootloader is unlocked"
echo "- Use appropriate recovery (TWRP recommended)"
echo ""
echo "=========================================="
echo " BUILD COMPLETED SUCCESSFULLY!"
echo "=========================================="
} | tee "$FINAL_REPORT"
# Display key information
cat "$FINAL_REPORT"
# Upload final report
buildkite-agent artifact upload "$FINAL_REPORT"
# Analytics and notifications (if configured)
if [ -n "${SLACK_WEBHOOK:-}" ]; then
echo "📢 Sending Slack notification..."
curl -X POST -H 'Content-type: application/json' \
--data "{
\"text\": \"🎉 Android ROM build completed!\",
\"attachments\": [{
\"color\": \"good\",
\"fields\": [
{\"title\": \"Device\", \"value\": \"${TARGET_DEVICE:-generic}\", \"short\": true},
{\"title\": \"Variant\", \"value\": \"${BUILD_VARIANT:-lineage}\", \"short\": true},
{\"title\": \"Build\", \"value\": \"#${BUILDKITE_BUILD_NUMBER:-unknown}\", \"short\": true},
{\"title\": \"Branch\", \"value\": \"${BUILDKITE_BRANCH:-unknown}\", \"short\": true}
],
\"actions\": [{
\"type\": \"button\",
\"text\": \"Download Artifacts\",
\"url\": \"${BUILDKITE_BUILD_URL:-unknown}#artifacts\"
}]
}]
}" \
"${SLACK_WEBHOOK}" || echo "Slack notification failed"
fi
echo ""
echo "📊 Build Information:"
echo " Build Number: ${BUILDKITE_BUILD_NUMBER}"
echo " Commit: ${BUILDKITE_COMMIT}"
echo " Branch: ${BUILDKITE_BRANCH}"
echo " Device: ${TARGET_DEVICE:-generic}"
echo " Variant: ${BUILD_VARIANT:-lineage}"
echo "🚀 Your Android ROM is ready!"
echo "📲 Download from: ${BUILDKITE_BUILD_URL:-unknown}#artifacts"
echo ""
echo "📱 Your ROM is ready for download in the Artifacts tab!"
agents:
queue: "default"
env:
TARGET_DEVICE: "generic"
BUILD_TYPE: "userdebug"
BUILD_VARIANT: "lineage"