diff --git a/build/jenkins/GDriveUpload b/build/jenkins/GDriveUpload index 994e256..91230c3 100644 --- a/build/jenkins/GDriveUpload +++ b/build/jenkins/GDriveUpload @@ -1,135 +1,167 @@ -// This pipeline job is triggered by the main AzaionSuite build pipeline. -// It copies build artifacts, zips them, and then triggers the Google Drive upload pipeline. pipeline { - agent { label 'Win10-BuildMachine' } tools { - // Git tool might be needed if this Jenkinsfile is in SCM git 'Default' - // dotnetsdk is not needed here as we only process artifacts + } + + parameters { + string(name: 'buildPath', defaultValue: 'C:/Jenkins/workspace/Azaion/suite', description: 'Path to folder containing zip builds.') } environment { - // 7-Zip path (assuming default installation) - SEVEN_ZIP_PATH = "C:/Program Files/7-Zip" // Adjust if 7-Zip is installed elsewhere - - // Set the PATH environment variable including 7-Zip - PATH = "${SEVEN_ZIP_PATH};${env.PATH}" // Add 7-Zip to PATH - - // Define the name of your existing Google Drive upload pipeline job - // ** IMPORTANT: Replace 'YourGoogleDriveUploadPipelineName' with the actual name ** - GOOGLE_DRIVE_UPLOAD_JOB_NAME = 'YourGoogleDriveUploadPipelineName' // <<== UPDATE THIS + GOOGLE_DRIVE_FOLDER = 'AzaionSuiteBuilds' // Hardcoded folder on Google Drive + RCLONE_CONFIG = 'C:/Program Files/rclone/rclone.conf' } stages { - stage('Copy Build Artifacts') { + stage('Initialize Workspace') { + steps { + echo 'Initializing workspace on Windows agent...' + powershell ''' + $uploadDir = "temp_upload" + if (-Not (Test-Path $uploadDir)) { + New-Item -ItemType Directory -Path $uploadDir | Out-Null + } + ''' + } + } + + stage('Find Latest Zip') { steps { script { - echo "Starting 'Copy Build Artifacts' stage." - // Copy artifacts from the upstream build job - // Replace 'AzaionSuite' with the actual name of your main build pipeline job - copyArtifacts( - projectName: 'AzaionSuite', // <<== UPDATE THIS if your main build job name is different - selector: lastSuccessful(), // Copy from the last successful build - // Specify which files to copy. These should match the files produced by the build. - // Assuming artifacts are in the 'suite' directory relative to the upstream workspace root. - filter: 'suite/AzaionSuite*.exe, suite/AzaionSuite*.bin' - // By default, artifacts are copied to the current job's workspace root. - ) - echo "Artifacts copied successfully." + echo "Using build path: ${params.buildPath}" // Debug output for build path + echo "Finding latest zip file in: ${params.buildPath}" + def latestZipFilename = '' + dir("${params.buildPath}") { + def output = powershell(returnStdout: true, script: ''' + $pattern = "AzaionSuite*.zip" + $zipFiles = Get-ChildItem -Filter $pattern | Sort-Object Name -Descending + if ($zipFiles.Count -gt 0) { + $latestZip = $zipFiles[0].Name + Write-Output "::SET-ENV::LATEST_ZIP_FILENAME=$latestZip" + } else { + Write-Output "::SET-ENV::LATEST_ZIP_FILENAME=" + } + ''').trim() + + // Debug output to verify the response from the powershell script + echo "PowerShell output: ${output}" + + def match = output =~ /::SET-ENV::LATEST_ZIP_FILENAME=(.+)/ + if (!match || !match[0][1]?.trim()) { + echo "⚠️ No ZIP files matching the pattern were found. Skipping upload and cleanup stages." + } else { + latestZipFilename = match[0][1] + echo "✅ Latest zip file selected: ${latestZipFilename}" + } + } + + // Pass the filename to the next stages directly + env.LATEST_ZIP_FILENAME = latestZipFilename + echo "LATEST_ZIP_FILENAME after processing: ${env.LATEST_ZIP_FILENAME}" } } } - stage('Archive Copied Artifacts (7-Zip)') { + stage('Upload If Not Exists & Always Remove Local') { + when { + expression { + echo "LATEST_ZIP_FILENAME is: '${env.LATEST_ZIP_FILENAME}'" // Debug output + return env.LATEST_ZIP_FILENAME?.trim() + } + } steps { - script { - echo "Starting 'Archive Copied Artifacts (7-Zip)' stage." - // The copied artifacts are now in the root of this job's workspace. - def artifactsDirectory = '.' // Artifacts are in the current workspace root - def version = '1.0.0' // Default version - def filesToArchive = [] - def exeFound = false + echo "Checking Google Drive for existing ZIP and uploading if needed..." + powershell """ + \$fileName = "${env.LATEST_ZIP_FILENAME}" + \$folder = "${GOOGLE_DRIVE_FOLDER}" + \$rcloneRemote = "AzaionGoogleDrive:\$folder" + \$localFilePath = "${params.buildPath}/\$fileName" - // Find all relevant files in the current workspace root - def foundFiles = findFiles(glob: 'AzaionSuite*.exe') + findFiles(glob: 'AzaionSuite*.bin') - filesToArchive = foundFiles.collect { it.path } // Get list of paths relative to the workspace root + Write-Output "Checking for existing files in: \$rcloneRemote" + \$existingFiles = rclone lsf --files-only \$rcloneRemote + Write-Output "Existing files:" + Write-Output \$existingFiles - // --- Version Extraction (only from .exe if present) --- - def exeFiles = findFiles(glob: 'AzaionSuite*.exe') - if (exeFiles.size() > 0) { - exeFound = true - def exeFilePath = exeFiles[0].path // Use path from the first found exe - // Regex to find version like 1.2.3 or 1.2.3-4 followed by .exe - // Match against the full path (which is relative to workspace root here) - def matcher = (exeFilePath =~ /AzaionSuite(\d+\.\d+\.\d+(-\d+)?)\.exe/) - if (matcher.find()) { - version = matcher.group(1) - echo "Found version for archive: ${version}" + if (\$existingFiles -match "^\$fileName\$") { + Write-Output "File '\$fileName' already exists on Google Drive. Skipping upload." + } else { + Write-Output "Uploading '\$fileName' to Google Drive..." + rclone copy "\$localFilePath" \$rcloneRemote --progress --drive-chunk-size 64M + Write-Output "Upload complete." + } + + if (Test-Path \$localFilePath) { + Remove-Item -Force \$localFilePath + Write-Output "Local file deleted: \$localFilePath" + } else { + Write-Output "Local file already deleted or not found." + } + """ + } + } + + stage('Cleanup Older Files on Google Drive') { + when { + expression { + echo "LATEST_ZIP_FILENAME is: '${env.LATEST_ZIP_FILENAME}'" // Debug output + return env.LATEST_ZIP_FILENAME?.trim() + } + } + steps { + echo "Cleaning up older files on Google Drive..." + powershell """ + Write-Output "Listing all files in the folder ${GOOGLE_DRIVE_FOLDER} on Google Drive..." + \$files = rclone lsf --files-only AzaionGoogleDrive:${GOOGLE_DRIVE_FOLDER} + Write-Output "Files found on Google Drive:" + Write-Output \$files + + \$filesArray = \$files -split "`n" | Where-Object { \$_ -ne "" } + if (\$filesArray.Count -gt 3) { + \$filesSorted = \$filesArray | Sort-Object -Descending + \$filesToDelete = \$filesSorted | Select-Object -Skip 3 + + Write-Output "Files to delete (older than 3 latest):" + Write-Output \$filesToDelete + + if (\$filesToDelete.Count -gt 0) { + \$tempFile = [System.IO.Path]::GetTempFileName() + \$filesToDelete | Set-Content -Path \$tempFile -Encoding utf8 + + Write-Output "Contents of temporary delete list file (\$tempFile):" + Get-Content \$tempFile + + foreach (\$file in \$filesToDelete) { + Write-Output "Deleting \$file..." + rclone deletefile AzaionGoogleDrive:${GOOGLE_DRIVE_FOLDER}/\$file + } + + Remove-Item -Path \$tempFile } else { - echo "Warning: Could not extract version from '${exeFiles[0].name}'. Using default: ${version}" + Write-Output "No files to delete." } } else { - echo "Warning: No executable found to extract version for archive. Using default: ${version}" + Write-Output "No files found on Google Drive to clean up." } - - // --- Zipping Logic --- - if (filesToArchive.size() > 0) { - // Get current date and time in YYYYMMdd-HHMMSS format using PowerShell - // Using a separate bat call to ensure output is captured cleanly - def timestamp = bat( - script: 'powershell -Command "Get-Date -Format YYYYMMdd-HHmmss"', - returnStdout: true - ).trim() // Trim to remove potential newline characters - - def zipFilename = "AzaionSuite.${version}-${timestamp}.zip" - // 7-Zip command requires quoting paths with spaces. - // We provide full paths relative to the workspace root. - def filesListString = filesToArchive.collect { "\"${it}\"" }.join(' ') // Quote each file path and join - - echo "Creating zip archive: ${zipFilename} using 7-Zip." - echo "Files to include (full paths): ${filesListString}" - - // Construct the full 7z command string in Groovy - def sevenZipCommand = "7z a -tzip \"${zipFilename}\" ${filesListString}" - - // Execute the constructed command string using a single bat step - bat """ - @echo off - echo Zipping files with 7-Zip... - ${sevenZipCommand} - if %errorlevel% neq 0 ( - echo Error creating zip archive with 7-Zip. 7z exit code: %errorlevel% - exit /b %errorlevel% - ) - echo Zip archive created successfully by 7-Zip. - """ - - // Archive the created zip file using Jenkins built-in step - // This makes the zip available for the downstream Google Drive upload job - archiveArtifacts artifacts: "${zipFilename}", fingerprint: true - echo "Archive step completed." - - } else { - error "No files (.exe or .bin) found in the copied artifacts to archive. Cannot create zip." - } - } - } - } - - stage('Trigger Google Drive Upload') { - steps { - script { - echo "Triggering Google Drive Upload pipeline: ${env.GOOGLE_DRIVE_UPLOAD_JOB_NAME}" - // Trigger the Google Drive upload pipeline - // This assumes the Google Drive job is configured to copy artifacts - // from THIS job (the one creating the zip). - build job: env.GOOGLE_DRIVE_UPLOAD_JOB_NAME - } + """ } } } - // No post section needed for this job, post actions will be handled by the triggered job + + post { + always { + echo 'Executing post-build cleanup...' + powershell ''' + $uploadDir = "temp_upload" + if (Test-Path $uploadDir) { + Remove-Item -Recurse -Force $uploadDir + } + ''' + } + + failure { + echo 'Pipeline failed. Check logs for details.' + } + } } -//test \ No newline at end of file diff --git a/build/jenkins/zip b/build/jenkins/zip new file mode 100644 index 0000000..4ffed6b --- /dev/null +++ b/build/jenkins/zip @@ -0,0 +1,133 @@ +pipeline { + agent { label 'Win10-BuildMachine' } + + parameters { + string(name: 'buildPath', defaultValue: 'C:/Jenkins/workspace/Azaion/suite', description: 'Build directory to zip from') + } + + tools { + git 'Default' + } + + environment { + SEVEN_ZIP_PATH = "C:/Program Files/7-Zip" + PATH = "${SEVEN_ZIP_PATH};${env.PATH}" + GOOGLE_DRIVE_UPLOAD_JOB_NAME = 'GDrive Upload' + } + + stages { + stage('Detect or Create Zip') { + steps { + script { + echo "Starting 'Detect or Create Zip' stage." + echo "Using build path: ${params.buildPath}" + dir("${params.buildPath}") { + powershell ''' + $ErrorActionPreference = "Stop" + $sevenZipExe = "$env:SEVEN_ZIP_PATH\\7z.exe" + $exePattern = "AzaionSuite*.exe" + $binPattern = "AzaionSuite*.bin" + $zipPattern = "AzaionSuite*.zip" + + if (-not (Test-Path $sevenZipExe)) { + Write-Error "7-Zip not found at $sevenZipExe" + exit 1 + } + + $existingZips = Get-ChildItem -Path . -Filter $zipPattern | Sort-Object LastWriteTime -Descending + $zipFilename = "" + + if ($existingZips.Count -gt 0) { + $zipFilename = $existingZips[0].Name + Write-Host "Using existing zip file: $zipFilename" + $wasCreated = $false + } else { + $exeFile = Get-ChildItem -Recurse -Filter $exePattern | Select-Object -First 1 + if (-not $exeFile) { + Write-Error "No EXE file found to create zip" + exit 1 + } + + $zipBaseFilename = $exeFile.BaseName + $timestamp = (Get-Date -Format "yyyyMMdd-HHmmss") + $zipFilename = "$zipBaseFilename-$timestamp.zip" + + $filesToZip = Get-ChildItem -Recurse -Include $exePattern, $binPattern | Select-Object -ExpandProperty FullName + if ($filesToZip.Count -eq 0) { + Write-Error "No files found to zip." + exit 1 + } + + $args = @("a", "-tzip", "$zipFilename") + ($filesToZip | ForEach-Object { "`"$_`"" }) + $process = Start-Process -FilePath $sevenZipExe -ArgumentList $args -Wait -NoNewWindow -PassThru + if ($process.ExitCode -ne 0) { + Write-Error "7-Zip failed with code $($process.ExitCode)" + exit $process.ExitCode + } + + $wasCreated = $true + Write-Host "Created new zip file: $zipFilename" + } + + Set-Content -Path "zipfilename.txt" -Value $zipFilename -Encoding ASCII + Set-Content -Path "zip_was_created.txt" -Value $wasCreated -Encoding ASCII + ''' + + def zipFilename = readFile('zipfilename.txt').trim() + def zipCreated = readFile('zip_was_created.txt').trim().toBoolean() + + echo "Zip filename: ${zipFilename}" + echo "Was zip created this run? ${zipCreated}" + + writeFile file: 'created_zip.txt', text: zipFilename + writeFile file: 'zip_was_created.txt', text: zipCreated.toString() + } + } + } + } + + stage('Archive Zip File (if new)') { + when { + expression { + def zipCreated = readFile("${params.buildPath}/zip_was_created.txt").trim().toBoolean() + return zipCreated + } + } + steps { + script { + echo "Archiving newly created zip file..." + dir("${params.buildPath}") { + def zipFilename = readFile('created_zip.txt').trim() + if (!fileExists(zipFilename)) { + error "Zip file '${zipFilename}' not found!" + } + archiveArtifacts artifacts: "${zipFilename}", fingerprint: true + } + } + } + } + + stage('Trigger Google Drive Upload') { + steps { + script { + echo "Triggering Google Drive Upload pipeline: ${env.GOOGLE_DRIVE_UPLOAD_JOB_NAME}" + build job: env.GOOGLE_DRIVE_UPLOAD_JOB_NAME, parameters: [ + string(name: 'buildPath', value: params.buildPath) + ] + } + } + } + } + + post { + success { + script { + def zipFilename = readFile("${params.buildPath}/created_zip.txt").trim() + echo "Pipeline completed successfully. Final zip: ${zipFilename}" + } + } + failure { + echo "Pipeline failed." + } + } +} diff --git a/build/zip.bat b/build/zip.bat new file mode 100644 index 0000000..d98756a --- /dev/null +++ b/build/zip.bat @@ -0,0 +1,105 @@ +@echo off +setlocal enabledelayedexpansion + +:: Move one level up +cd /d .. +echo [INFO] Changed working directory to: %CD% + +:: Get timestamp +for /f %%a in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMdd-HHmmss"') do set "timestamp=%%a" + +set "fullZipCreated=0" +set "iterZipCreated=0" + +:: ===== FULL BUILD ===== +set "fullExe=" +for %%F in (AzaionSuite.Full.*.exe) do ( + set "fullExe=%%F" + goto :FullExeFound +) +echo [WARNING] No Full build EXE found [AzaionSuite.Full.*.exe] +goto :AfterFullBuild + +:FullExeFound +echo [INFO] Found Full build EXE: [%fullExe%] +set "baseFull=%fullExe:.exe=%" + +:: Collect BIN files for Full build +set "fullBinList=" +for %%B in (%baseFull%-*.bin) do ( + echo [INFO] Found BIN file: [%%B] + if defined fullBinList ( + set "fullBinList=!fullBinList!,\"%%B\"" + ) else ( + set "fullBinList=\"%%B\"" + ) +) + +echo [INFO] BIN files list: %fullBinList% + +:: Compose PowerShell command for Full +if "%fullBinList%"=="" ( + set "fullPsCmd=Compress-Archive -Force -Path \"%fullExe%\" -DestinationPath \"%baseFull%-%timestamp%.zip\"" +) else ( + set "fullPsCmd=Compress-Archive -Force -Path \"%fullExe%\",%fullBinList% -DestinationPath \"%baseFull%-%timestamp%.zip\"" +) + +echo [INFO] Creating ZIP: [%baseFull%-%timestamp%.zip] +echo [INFO] Using PowerShell command to compress: +echo powershell -Command "%fullPsCmd%" + +powershell -Command "%fullPsCmd%" +if errorlevel 1 ( + echo [ERROR] Failed to create Full archive: [%baseFull%-%timestamp%.zip] +) else ( + echo [SUCCESS] Full archive created: [%baseFull%-%timestamp%.zip] + set "fullZipCreated=1" +) + +:AfterFullBuild + +:: ===== ITERATIVE BUILD ===== +set "iterExe=" +for %%I in (AzaionSuite.Iterative.*.exe) do ( + set "iterExe=%%I" + goto :IterExeFound +) +echo [WARNING] No Iterative build EXE found [AzaionSuite.Iterative.*.exe] +goto :AfterIterBuild + +:IterExeFound +echo [INFO] Found Iterative build EXE: [%iterExe%] +set "baseIter=%iterExe:.exe=%" + +:: Iterative pack (exe only) +set "iterPsCmd=Compress-Archive -Force -Path \"%iterExe%\" -DestinationPath \"%baseIter%-%timestamp%.zip\"" + +echo [INFO] Creating ZIP: [%baseIter%-%timestamp%.zip] +echo [INFO] Using PowerShell command to compress: +echo powershell -Command "%iterPsCmd%" + +powershell -Command "%iterPsCmd%" +if errorlevel 1 ( + echo [ERROR] Failed to create Iterative archive: [%baseIter%-%timestamp%.zip] +) else ( + echo [SUCCESS] Iterative archive created: [%baseIter%-%timestamp%.zip] + set "iterZipCreated=1" +) + +:AfterIterBuild + +echo. + +if "%fullZipCreated%"=="1" ( + if "%iterZipCreated%"=="1" ( + echo [DONE] Both Full and Iterative packaging complete. + ) else ( + echo [DONE] Full packaging complete. No Iterative package created. + ) +) else ( + if "%iterZipCreated%"=="1" ( + echo [DONE] Iterative packaging complete. No Full package created. + ) else ( + echo [INFO] No packages were created. + ) +) \ No newline at end of file