add distributable app archive to ci release gradle task

This commit is contained in:
AmirHossein Abdolmotallebi 2024-08-13 03:43:04 +03:30
parent 761908f579
commit 556a696a63
2 changed files with 188 additions and 29 deletions

View File

@ -6,36 +6,146 @@ import org.jetbrains.compose.desktop.application.dsl.JvmApplicationDistributions
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import java.io.File
object CiUtils {
fun moveAndCreateSignature(
fun getTargetFileName(
packageName: String,
appVersion: Version,
nativeDistributions: JvmApplicationDistributions,
target: TargetFormat,
path: File,
output: File,
) {
require(!output.isFile) {
"$output is a file"
): String {
val fileExtension = when (target) {
// we use archived for app image distribution
TargetFormat.AppImage -> {
when (Platform.getCurrentPlatform()) {
Platform.Desktop.Linux -> "tar.gz"
Platform.Desktop.MacOS -> "tar.gz"
Platform.Desktop.Windows -> "zip"
Platform.Android -> error("Android not available for now")
}
}
else -> target.fileExtensionWithoutDot()
}
output.mkdirs()
require(output.isDirectory) {
"$output is not directory"
}
val folder = path.resolve(target.outputDirName)
val exeFile = folder.walk().first {
it.name.endsWith(target.fileExt)
}
val appName = requireNotNull(nativeDistributions.packageName){
"package name must not null"
}
val fileExtension = exeFile.extension
val platformName = requireNotNull(Platform.fromExecutableFileExtension(fileExtension)){
"can't find platform name with this file extension :${fileExtension}"
val platformName = when (target) {
TargetFormat.AppImage -> Platform.getCurrentPlatform()
else -> {
val packageFileExt = target.fileExtensionWithoutDot()
requireNotNull(Platform.fromExecutableFileExtension(packageFileExt)) {
"can't find platform name with this file extension: ${packageFileExt}"
}
}
}.name.lowercase()
val newName = "${appName}_${appVersion}_${platformName}.${fileExtension}"
val destinationExeFile = output.resolve(newName)
val md5File = output.resolve("$newName.md5")
exeFile.copyTo(destinationExeFile, true)
md5File.writeText(HashUtils.md5(exeFile))
return "${packageName}_${appVersion}_${platformName}.${fileExtension}"
}
}
fun getFileOfPackagedTarget(
baseOutputDir: File,
target: TargetFormat,
): File {
val folder = baseOutputDir.resolve(target.outputDirName)
val exeFile = kotlin.runCatching {
folder.walk().first {
it.name.endsWith(target.fileExt)
}
}.onFailure {
println("error when finding packaged app for $target in: $baseOutputDir")
}
return exeFile.getOrThrow()
}
fun getFileOfDistributedArchivedTarget(
baseOutputDir: File,
): File {
val folder = baseOutputDir
val extension = when (Platform.getCurrentPlatform()) {
Platform.Desktop.Linux,
Platform.Desktop.MacOS -> "tar.gz"
Platform.Android,
Platform.Desktop.Windows -> "zip"
}
val archiveFile = kotlin.runCatching {
folder.walk().first {
it.name.endsWith(extension)
}
}.onFailure {
println("error when finding archive of unpackaged app in: $baseOutputDir")
}
return archiveFile.getOrThrow()
}
fun copyAndHashToDestination(
src: File,
destinationFolder: File,
name: String,
) {
val destinationExeFile = destinationFolder.resolve(name)
src.copyTo(destinationExeFile)
val md5File = destinationFolder.resolve("$name.md5")
md5File.writeText(HashUtils.md5(src))
}
fun movePackagedAndCreateSignature(
appVersion: Version,
packageName: String,
target: TargetFormat,
basePackagedAppsDir: File,
outputDir: File,
) {
require(!outputDir.isFile) {
"$outputDir is a file"
}
outputDir.mkdirs()
require(outputDir.isDirectory) {
"$outputDir is not directory"
}
val exeFile = getFileOfPackagedTarget(
baseOutputDir = basePackagedAppsDir,
target = target
)
val newName = getTargetFileName(packageName, appVersion, target)
copyAndHashToDestination(
src = exeFile,
destinationFolder = outputDir,
name = newName,
)
}
/*
fun moveAndCreateSignature(
appVersion: Version,
nativeDistributions: JvmApplicationDistributions,
target: TargetFormat,
path: File,
output: File,
) {
require(!output.isFile) {
"$output is a file"
}
output.mkdirs()
require(output.isDirectory) {
"$output is not directory"
}
val folder = path.resolve(target.outputDirName)
val exeFile = folder.walk().first {
it.name.endsWith(target.fileExt)
}
val appName = requireNotNull(nativeDistributions.packageName){
"package name must not null"
}
val fileExtension = exeFile.extension
val platformName = requireNotNull(Platform.fromExecutableFileExtension(fileExtension)){
"can't find platform name with this file extension :${fileExtension}"
}.name.lowercase()
val newName = "${appName}_${appVersion}_${platformName}.${fileExtension}"
val destinationExeFile = output.resolve(newName)
val md5File = output.resolve("$newName.md5")
exeFile.copyTo(destinationExeFile, true)
md5File.writeText(HashUtils.md5(exeFile))
}
*/
}
private fun TargetFormat.fileExtensionWithoutDot() = fileExt.substring(".".length)

View File

@ -2,6 +2,7 @@ import buildlogic.*
import buildlogic.versioning.*
import org.jetbrains.changelog.Changelog
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import ir.amirab.util.platform.Platform
plugins {
id(MyPlugins.kotlin)
@ -192,27 +193,75 @@ changelog {
// ======= begin of GitHub action stuff
val ciDir = CiDirs(rootProject.layout.buildDirectory)
val appPackageNameByComposePlugin
get() = requireNotNull(compose.desktop.application.nativeDistributions.packageName) {
"compose.desktop.application.nativeDistributions.packageName must not be null!"
}
val distributableAppArchiveDir: Provider<Directory> = project.layout.buildDirectory.dir("dist/archives")
fun AbstractArchiveTask.fromAppImagePath() {
from(tasks.named("createReleaseDistributable"))
destinationDirectory.set(distributableAppArchiveDir)
}
val createDistributableAppArchiveTar by tasks.registering(Tar::class) {
archiveFileName.set("app.tar.gz")
compression = Compression.GZIP
fromAppImagePath()
}
val createDistributableAppArchiveZip by tasks.registering(Zip::class) {
archiveFileName.set("app.zip")
fromAppImagePath()
}
val createDistributableAppArchive by tasks.registering {
when (Platform.getCurrentPlatform()) {
Platform.Desktop.Linux,
Platform.Desktop.MacOS -> dependsOn(createDistributableAppArchiveTar)
Platform.Desktop.Windows -> dependsOn(createDistributableAppArchiveZip)
Platform.Android -> error("this task is used for desktop only")
}
}
val createBinariesForCi by tasks.registering {
val nativeDistributions = compose.desktop.application.nativeDistributions
val mainRelease = nativeDistributions.outputBaseDir.dir("main-release")
dependsOn("packageReleaseDistributionForCurrentOS")
dependsOn(createDistributableAppArchive)
inputs.property("appVersion", getAppVersionString())
inputs.dir(mainRelease)
inputs.dir(distributableAppArchiveDir)
outputs.dir(ciDir.binariesDir)
doLast {
val output = ciDir.binariesDir.get().asFile
val packageName = appPackageNameByComposePlugin
output.deleteRecursively()
val allowedTarget = nativeDistributions.targetFormats.filter { it.isCompatibleWithCurrentOS }
for (target in allowedTarget) {
CiUtils.moveAndCreateSignature(
CiUtils.movePackagedAndCreateSignature(
getAppVersion(),
nativeDistributions,
packageName,
target,
mainRelease.get().asFile,
output,
)
}
logger.lifecycle("app packages for '${allowedTarget.joinToString(", ") { it.name }}' written in $output")
val appArchiveDistributableDir = distributableAppArchiveDir.get().asFile
CiUtils.copyAndHashToDestination(
distributableAppArchiveDir.get().asFile.resolve(
CiUtils.getFileOfDistributedArchivedTarget(
appArchiveDistributableDir,
)
),
output,
CiUtils.getTargetFileName(
packageName,
getAppVersion(),
TargetFormat.AppImage,
)
)
logger.lifecycle("distributable app archive written in ${output}")
}
}