From 696ca38efeed66c22f4f41de9602cd16b6f3fb1e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Jun 2022 14:18:44 +0300 Subject: [PATCH] Another attempt on deploy --- .space.kts | 45 ++++----------- build.gradle.kts | 30 +++++++++- buildSrc/build.gradle.kts | 12 ++++ buildSrc/settings.gradle.kts | 7 +++ buildSrc/src/main/kotlin/execute.kt | 42 ++++++++++++++ buildSrc/src/main/kotlin/uploads.kt | 80 ++++++++++++++++++++++++++ src/main/kotlin/ru/mipt/spc/spcHome.kt | 1 - 7 files changed, 181 insertions(+), 36 deletions(-) create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/settings.gradle.kts create mode 100644 buildSrc/src/main/kotlin/execute.kt create mode 100644 buildSrc/src/main/kotlin/uploads.kt diff --git a/.space.kts b/.space.kts index 22d1d5b..ba5feda 100644 --- a/.space.kts +++ b/.space.kts @@ -1,29 +1,15 @@ -import circlet.pipelines.script.put - job("Deploy") { startOn { gitPush { enabled = false } } - container(image = "openjdk:11") { + container(image = "mipt-npm.registry.jetbrains.space/p/mipt-npm/containers/kotlin-ci:1.0.2") { + env["SPC_HOST"] = Params("spc-host") + env["SPC_USER"] = Secrets("spc-webmaster.key-user") + env["SPC_ID"] = Secrets("spc-webmaster.key-id") kotlinScript { api -> - api.gradlew("installDist") - api.fileShare().put(java.io.File("build/install")) - } - } - - container(image = "openjdk:11") { - env["HOST"] = Params("spc-host") - env["USER"] = Secrets("spc-webmaster-user") - env["ID"] = Secrets("spc-webmaster-id") - - shellScript { - interpreter = "/bin/bash" - content = """ - echo ${'$'}ID > id.key - chmod 400 id.key - scp -r -i id.key /mnt/space/share/spc-site/ "${'$'}USER@${'$'}HOST:/opt" - """.trimIndent() + api.gradlew("uploadDistribution") + api.gradlew("reloadDistribution") } } } @@ -32,20 +18,13 @@ job("Restart service"){ startOn { gitPush { enabled = false } } - - container(image = "openjdk:11") { - env["HOST"] = Params("spc-host") - env["USER"] = Secrets("spc-webmaster-user") - env["ID"] = Secrets("spc-webmaster-id") - shellScript { - interpreter = "/bin/bash" - content = """ - echo ${'$'}ID > id_ed25519 - chmod 400 id_ed25519 - echo "$(cat id_ed25519)" - ssh -i id_ed25519 -o StrictHostKeyChecking=no -o HostKeyAlgorithms=ssh-ed25519 -t "${'$'}USER@${'$'}HOST" "systemctl restart sciprog-site" - """.trimIndent() + container(image = "mipt-npm.registry.jetbrains.space/p/mipt-npm/containers/kotlin-ci:1.0.2") { + env["SPC_HOST"] = Params("spc-host") + env["SPC_USER"] = Secrets("spc-webmaster.key-user") + env["SPC_ID"] = Secrets("spc-webmaster.key-id") + kotlinScript { api -> + api.gradlew("reloadDistribution") } } } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index f92dced..f917281 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,6 +68,32 @@ val writeBuildDate: Task by tasks.creating { outputs.upToDateWhen { false } } - //write build time in build to check outdated external data directory -tasks.getByName("processResources").dependsOn(writeBuildDate) \ No newline at end of file +tasks.getByName("processResources").dependsOn(writeBuildDate) + +/* Upload with JSch */ + +val host = System.getProperty("SPC_HOST") +val user = System.getProperty("SPC_USER") +val identity = System.getProperty("SPC_ID") + +if (host != null && user != null && identity != null) { + val uploadDistribution by tasks.creating { + group = "distribution" + dependsOn("installDist") + doLast { + sshUploadDirectory(buildDir.resolve("install"), host, user, "/opt") { + addIdentity("spc-webmaster.key", identity.encodeToByteArray(), null, null) + } + } + } + + val reloadDistribution by tasks.creating { + group = "distribution" + doLast { + sshExecute(host, user, "sudo systemctl restart sciprog-site") { + addIdentity("spc-webmaster", identity.encodeToByteArray(), null, null) + } + } + } +} \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..48b2cf5 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,12 @@ +plugins{ + `kotlin-dsl` +} + +repositories{ + mavenCentral() + gradlePluginPortal() +} + +dependencies{ + implementation("com.github.mwiede:jsch:0.2.1") +} \ No newline at end of file diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000..10374ea --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + repositories { + maven("https://repo.kotlin.link") + mavenCentral() + gradlePluginPortal() + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/execute.kt b/buildSrc/src/main/kotlin/execute.kt new file mode 100644 index 0000000..2d5eb36 --- /dev/null +++ b/buildSrc/src/main/kotlin/execute.kt @@ -0,0 +1,42 @@ +import com.jcraft.jsch.ChannelExec +import com.jcraft.jsch.JSch +import com.jcraft.jsch.Session +import java.util.* + + +fun JSch.execute( + host: String, + user: String, + command: String, + port: Int = 22, +): String { + var session: Session? = null + var channel: ChannelExec? = null + try { + session = getSession(user, host, port) + + val config = Properties() + config["StrictHostKeyChecking"] = "no" + session.setConfig(config) + session.connect() + channel = session.openChannel("exec") as ChannelExec + channel.setCommand(command) + channel.inputStream = null + channel.setErrStream(System.err) + val input = channel.inputStream + channel.connect() + return input.use { it.readAllBytes().decodeToString() } + } finally { + channel?.disconnect() + session?.disconnect() + } +} + + +fun sshExecute( + host: String, + user: String, + command: String, + port: Int = 22, + shellConfig: JSch.() -> Unit, +): String = JSch().apply(shellConfig).execute(host, user, command, port) \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/uploads.kt b/buildSrc/src/main/kotlin/uploads.kt new file mode 100644 index 0000000..6e703ea --- /dev/null +++ b/buildSrc/src/main/kotlin/uploads.kt @@ -0,0 +1,80 @@ +import com.jcraft.jsch.ChannelSftp +import com.jcraft.jsch.JSch +import com.jcraft.jsch.Session +import com.jcraft.jsch.SftpATTRS +import java.io.File +import java.io.FileInputStream +import java.util.* + + +/** + * https://kodehelp.com/java-program-uploading-folder-content-recursively-from-local-to-sftp-server/ + */ +private fun ChannelSftp.recursiveFolderUpload(sourceFile: File, destinationPath: String) { + if (sourceFile.isFile) { + // copy if it is a file + cd(destinationPath) + if (!sourceFile.name.startsWith(".")) put( + FileInputStream(sourceFile), + sourceFile.getName(), + ChannelSftp.OVERWRITE + ) + } else { + val files = sourceFile.listFiles() + if (files != null && !sourceFile.getName().startsWith(".")) { + cd(destinationPath) + var attrs: SftpATTRS? = null + // check if the directory is already existing + try { + attrs = stat(destinationPath + "/" + sourceFile.getName()) + } catch (e: Exception) { + println(destinationPath + "/" + sourceFile.getName() + " not found") + } + // else create a directory + if (attrs != null) { + println("Directory exists IsDir=" + attrs.isDir()) + } else { + println("Creating dir " + sourceFile.getName()) + mkdir(sourceFile.getName()) + } + for (f in files) { + recursiveFolderUpload(f, destinationPath + "/" + sourceFile.getName()) + } + } + } +} + +fun JSch.uploadDirectory( + file: File, + host: String, + user: String, + targetDirectory: String, + port: Int = 22, +) { + var session: Session? = null + var channel: ChannelSftp? = null + try { + session = getSession(user, host, port) + + val config = Properties() + config["StrictHostKeyChecking"] = "no" + session.setConfig(config) + session.connect() // Create SFTP Session + channel = session.openChannel("sftp") as ChannelSftp // Open SFTP Channel + channel.connect() + channel.cd(targetDirectory) // Change Directory on SFTP Server + channel.recursiveFolderUpload(file, targetDirectory) + } finally { + channel?.disconnect() + session?.disconnect() + } +} + +fun sshUploadDirectory( + file: File, + host: String, + user: String, + targetDirectory: String, + port: Int = 22, + shellConfig: JSch.() -> Unit, +) = JSch().apply(shellConfig).uploadDirectory(file, host, user, targetDirectory, port) diff --git a/src/main/kotlin/ru/mipt/spc/spcHome.kt b/src/main/kotlin/ru/mipt/spc/spcHome.kt index 16c169d..670078d 100644 --- a/src/main/kotlin/ru/mipt/spc/spcHome.kt +++ b/src/main/kotlin/ru/mipt/spc/spcHome.kt @@ -300,7 +300,6 @@ context(PageContext) private fun HTML.spcHome() { } - internal fun Application.spcHome(context: Context, rootPath: Path, prefix: String = "") { val snark = context.fetch(SnarkPlugin)