Skip to content

Commit e5a0bd9

Browse files
committed
gradle
1 parent cf9d863 commit e5a0bd9

2 files changed

Lines changed: 118 additions & 93 deletions

File tree

apps/faf-legacy-deployment/scripts/deploy-coop.main.kts renamed to apps/faf-legacy-deployment/scripts/CoopDeployer.kt

Lines changed: 92 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
#!/usr/bin/env kotlin
2-
3-
@file:DependsOn("com.mysql:mysql-connector-j:9.5.0")
4-
@file:DependsOn("org.eclipse.jgit:org.eclipse.jgit:7.4.0.202509020913-r")
5-
@file:DependsOn("com.squareup.okio:okio:3.16.4")
6-
71
import org.eclipse.jgit.api.Git
2+
import org.slf4j.LoggerFactory
83
import java.io.IOException
94
import java.net.HttpURLConnection
10-
import java.net.URL
5+
import java.net.URI
116
import java.nio.file.Files
127
import java.nio.file.Path
138
import java.nio.file.Paths
@@ -20,6 +15,9 @@ import java.util.zip.ZipEntry
2015
import java.util.zip.ZipOutputStream
2116
import kotlin.io.path.inputStream
2217

18+
private val log = LoggerFactory.getLogger("CoopDeployer")
19+
20+
2321
// --------------------------- CONFIG ---------------------------
2422

2523
val PATCH_VERSION = System.getenv("PATCH_VERSION") ?: error("PATCH_VERSION required")
@@ -68,7 +66,7 @@ fun setPerm664(path: Path) {
6866
}
6967
Files.setPosixFilePermissions(path, perms)
7068
} catch (e: Exception) {
71-
println("Warning: couldn't set perms on $path: ${e.message}")
69+
log.warn("Warning: couldn't set perms on {}", path, e)
7270
}
7371
}
7472

@@ -111,13 +109,13 @@ fun zipPreserveStructure(sources: List<Path>, outputFile: Path, base: Path) {
111109
fun prepareRepo(): Path {
112110
val dir = Paths.get(WORKDIR)
113111
if (Files.exists(dir.resolve(".git"))) {
114-
println("Repo exists — fetching and checking out $GIT_REF...")
112+
log.info("Repo exists — fetching and checking out $GIT_REF...")
115113
Git.open(dir.toFile()).use { git ->
116114
git.fetch().call()
117115
git.checkout().setName(GIT_REF).call()
118116
}
119117
} else {
120-
println("Cloning $REPO_URL -> $dir ...")
118+
log.info("Cloning $REPO_URL -> $dir ...")
121119
Git.cloneRepository()
122120
.setURI(REPO_URL)
123121
.setDirectory(dir.toFile())
@@ -132,7 +130,7 @@ fun prepareRepo(): Path {
132130
// --------------------------- GITHUB RELEASE ASSET DOWNLOAD ---------------------------
133131

134132
fun httpGet(url: String): String {
135-
val conn = URL(url).openConnection() as HttpURLConnection
133+
val conn = URI.create(url).toURL().openConnection() as HttpURLConnection
136134
conn.requestMethod = "GET"
137135
conn.setRequestProperty("Accept", "application/vnd.github.v3+json")
138136
conn.connectTimeout = 15000
@@ -143,7 +141,7 @@ fun httpGet(url: String): String {
143141
}
144142

145143
fun downloadFile(url: String, dest: Path) {
146-
val u = URL(url)
144+
val u = URI.create(url).toURL()
147145
val conn = u.openConnection() as HttpURLConnection
148146
conn.requestMethod = "GET"
149147
conn.connectTimeout = 20000
@@ -168,36 +166,36 @@ fun findNx2UrlsFromReleaseJson(json: String): List<String> {
168166
}
169167

170168
fun downloadVoAssets(version: String, targetDir: Path): List<Path> {
171-
println("Downloading VO assets for version $version from GitHub releases...")
169+
log.info("Downloading VO assets for version $version from GitHub releases...")
172170
Files.createDirectories(VO_DOWNLOAD_TMP)
173171
val apiUrl = "https://api.github.com/repos/FAForever/fa-coop/releases/tags/v$version"
174172
val json = try {
175173
httpGet(apiUrl)
176174
} catch (e: Exception) {
177-
println("Warning: failed to fetch release JSON: ${e.message}")
175+
log.warn("Warning: failed to fetch release JSON", e)
178176
return emptyList()
179177
}
180178

181179
val urls = findNx2UrlsFromReleaseJson(json)
182180
if (urls.isEmpty()) {
183-
println("No .nx2 assets found in release v$version")
181+
log.info("No .nx2 assets found in release v{}", version)
184182
return emptyList()
185183
}
186184

187185
val downloaded = mutableListOf<Path>()
188186
for (u in urls) {
189-
val filename = Paths.get(URL(u).path).fileName.toString()
187+
val filename = Paths.get(URI.create(u).toURL().path).fileName.toString()
190188
val dst = VO_DOWNLOAD_TMP.resolve(filename)
191189
try {
192-
println("Downloading $u -> $dst")
190+
log.info("Downloading {} -> {}",u, dst)
193191
downloadFile(u, dst)
194192
// rename to include .v{version}.nx2 before .nx2
195193
val newName = filename.replace(Regex("\\.nx2$"), ".v$version.nx2")
196194
val newPath = VO_DOWNLOAD_TMP.resolve(newName)
197195
Files.move(dst, newPath, StandardCopyOption.REPLACE_EXISTING)
198196
downloaded.add(newPath)
199197
} catch (e: Exception) {
200-
println("Warning: failed to download $u: ${e.message}")
198+
log.warn("Warning: failed to download {}", u, e)
201199
}
202200
}
203201

@@ -206,16 +204,16 @@ fun downloadVoAssets(version: String, targetDir: Path): List<Path> {
206204
Files.createDirectories(outDir)
207205
for (p in downloaded) {
208206
val dest = outDir.resolve(p.fileName.toString())
209-
println("Copying VO $p -> $dest")
207+
log.info("Copying VO {} -> {}", p, dest)
210208
try {
211209
if (!DRYRUN) {
212210
Files.copy(p, dest, StandardCopyOption.REPLACE_EXISTING)
213211
setPerm664(dest)
214212
} else {
215-
println("[DRYRUN] Would copy $p -> $dest")
213+
log.info("[DRYRUN] Would copy {} -> {}", p, dest)
216214
}
217215
} catch (e: Exception) {
218-
println("Warning: copying failed: ${e.message}")
216+
log.warn("Warning: copying failed", e)
219217
}
220218
}
221219

@@ -225,7 +223,7 @@ fun downloadVoAssets(version: String, targetDir: Path): List<Path> {
225223
// --------------------------- DATABASE ---------------------------
226224

227225
fun dbConnection() =
228-
DriverManager.getConnection("jdbc:mysql://$DB_HOST/$DB_NAME?useSSL=false&serverTimezone=UTC", DB_USER, DB_PASS)
226+
DriverManager.getConnection("jdbc:mariadb://$DB_HOST/$DB_NAME?useSSL=false&serverTimezone=UTC", DB_USER, DB_PASS)
229227

230228
fun readExisting(conn: java.sql.Connection, mod: String): Map<Int, Pair<String?, String?>> {
231229
val sql = """
@@ -248,9 +246,9 @@ fun readExisting(conn: java.sql.Connection, mod: String): Map<Int, Pair<String?,
248246
}
249247

250248
fun updateDb(conn: java.sql.Connection, mod: String, fileId: Int, version: Int, name: String, md5: String) {
251-
println("Updating DB: $name (fileId=$fileId, version=$version) md5=$md5")
249+
log.info("Updating DB: {} (fileId={}, version={}) md5={}", name, fileId, version, md5)
252250
if (DRYRUN) {
253-
println("[DRYRUN] DB: would delete/insert for $fileId,$version")
251+
log.info("[DRYRUN] DB: would delete/insert for {},{}", fileId, version)
254252
return
255253
}
256254
val del = "DELETE FROM updates_${mod}_files WHERE fileId=? AND version=?"
@@ -285,49 +283,49 @@ fun processItem(
285283
Files.createDirectories(outDir)
286284
val target = outDir.resolve(name)
287285

288-
println("Processing $name (fileId $fileId)")
286+
log.info("Processing {} (fileId {})", name, fileId)
289287

290288
if (sources == null) {
291289
// VO file: look for downloaded file in target dir (name formatted)
292290
val expectedName = name // matches nameFmt.format(version)
293291
val candidate = outDir.resolve(expectedName)
294292
if (!Files.exists(candidate)) {
295-
println("Warning: VO file $expectedName not found in $outDir, skipping")
293+
log.info("Warning: VO file {} not found in {}, skipping", expectedName, outDir)
296294
return
297295
}
298296
val newMd5 = md5(candidate)
299297
val oldMd5 = readExisting(conn, mod)[fileId]?.second
300298
if (newMd5 != oldMd5) {
301299
updateDb(conn, mod, fileId, version, expectedName, newMd5)
302300
} else {
303-
println("VO $expectedName unchanged")
301+
log.info("VO {} unchanged", expectedName)
304302
}
305303
return
306304
}
307305

308306
// sources present -> create zip or copy single file
309307
val existing = sources.filter { p -> Files.exists(p) }
310308
if (existing.isEmpty()) {
311-
println("Warning: no existing sources for $name, skipping")
309+
log.info("Warning: no existing sources for {}, skipping", name)
312310
return
313311
}
314312

315313
// if single source and it's a file, copy it directly (like init_coop.lua)
316314
if (existing.size == 1 && Files.isRegularFile(existing[0])) {
317315
val src = existing[0]
318-
println("Single file source for $name: copying $src -> $target")
316+
log.info("Single file source for {}: copying {} -> {}", name, src, target)
319317
if (!DRYRUN) {
320318
Files.copy(src, target, StandardCopyOption.REPLACE_EXISTING)
321319
setPerm664(target)
322320
} else {
323-
println("[DRYRUN] Would copy $src -> $target")
321+
log.info("[DRYRUN] Would copy {} -> {}", src, target)
324322
}
325323
val newMd5 = md5(target)
326324
val oldMd5 = readExisting(conn, mod)[fileId]?.second
327325
if (newMd5 != oldMd5) {
328326
updateDb(conn, mod, fileId, version, name, newMd5)
329327
} else {
330-
println("$name unchanged")
328+
log.info("{} unchanged", name)
331329
}
332330
return
333331
}
@@ -340,85 +338,86 @@ fun processItem(
340338
}
341339

342340
val tmp = Files.createTempFile("coop", ".zip")
343-
println("Zipping sources with base=$base -> $tmp")
341+
log.info("Zipping sources with base={} -> {}", base, tmp)
344342
zipPreserveStructure(existing, tmp, base)
345-
println("Moving zip to $target")
343+
log.info("Moving zip to {}", target)
346344
if (!DRYRUN) {
347345
Files.move(tmp, target, StandardCopyOption.REPLACE_EXISTING)
348346
setPerm664(target)
349347
} else {
350-
println("[DRYRUN] Would move $tmp -> $target")
348+
log.info("[DRYRUN] Would move {} -> {}", tmp, target)
351349
}
352350

353351
val newMd5 = md5(target)
354352
val oldMd5 = readExisting(conn, mod)[fileId]?.second
355353
if (newMd5 != oldMd5) {
356354
updateDb(conn, mod, fileId, version, name, newMd5)
357355
} else {
358-
println("$name unchanged")
356+
log.info("{} unchanged", name)
359357
}
360358
}
361359

362360
// --------------------------- MAIN ---------------------------
363-
364-
println("=== Kotlin Coop Deployer v$PATCH_VERSION ===")
365-
val repo = prepareRepo()
366-
println("Repo ready at $repo")
361+
fun main() {
362+
log.info("=== Kotlin Coop Deployer v{} ===", PATCH_VERSION)
363+
val repo = prepareRepo()
364+
log.info("Repo ready at {}", repo)
367365

368366
// Download VO assets first
369-
val voFiles = downloadVoAssets(PATCH_VERSION, TARGET_DIR) // returns list of paths in target dir
370-
val voMap = voFiles.associateBy { it.fileName.toString() } // name -> Path
371-
372-
val conn = dbConnection()
373-
try {
374-
val existing = readExisting(conn, "coop")
375-
376-
data class PatchFile(val id: Int, val fileTemplate: String, val includes: List<Path>?)
377-
378-
val filesList = listOf(
379-
PatchFile(1, "init_coop.v%d.lua", listOf(repo.resolve("init_coop.lua"))),
380-
PatchFile(
381-
2, "lobby_coop_v%d.cop", listOf(
382-
repo.resolve("mods"),
383-
repo.resolve("units"),
384-
repo.resolve("mod_info.lua"),
385-
repo.resolve("readme.md"),
386-
repo.resolve("changelog.md")
387-
)
388-
),
389-
390-
// all VO files (no sources → already downloaded externally)
391-
PatchFile(3, "A01_VO.v%d.nx2", null),
392-
PatchFile(4, "A02_VO.v%d.nx2", null),
393-
PatchFile(5, "A03_VO.v%d.nx2", null),
394-
PatchFile(6, "A04_VO.v%d.nx2", null),
395-
PatchFile(7, "A05_VO.v%d.nx2", null),
396-
PatchFile(8, "A06_VO.v%d.nx2", null),
397-
PatchFile(9, "C01_VO.v%d.nx2", null),
398-
PatchFile(10, "C02_VO.v%d.nx2", null),
399-
PatchFile(11, "C03_VO.v%d.nx2", null),
400-
PatchFile(12, "C04_VO.v%d.nx2", null),
401-
PatchFile(13, "C05_VO.v%d.nx2", null),
402-
PatchFile(14, "C06_VO.v%d.nx2", null),
403-
PatchFile(15, "E01_VO.v%d.nx2", null),
404-
PatchFile(16, "E02_VO.v%d.nx2", null),
405-
PatchFile(17, "E03_VO.v%d.nx2", null),
406-
PatchFile(18, "E04_VO.v%d.nx2", null),
407-
PatchFile(19, "E05_VO.v%d.nx2", null),
408-
PatchFile(20, "E06_VO.v%d.nx2", null),
409-
PatchFile(21, "Prothyon16_VO.v%d.nx2", null),
410-
PatchFile(22, "A03_VO.v%d.nx2", null),
411-
PatchFile(23, "A03_VO.v%d.nx2", null),
412-
PatchFile(24, "A03_VO.v%d.nx2", null),
413-
PatchFile(25, "A03_VO.v%d.nx2", null),
414-
// … add the rest
415-
)
416-
417-
for ((fileId, fmt, srcs) in filesList) {
418-
processItem(conn, "coop", PATCH_VERSION.toInt(), fileId, fmt, srcs?.map { it }, voMap)
367+
val voFiles = downloadVoAssets(PATCH_VERSION, TARGET_DIR) // returns list of paths in target dir
368+
val voMap = voFiles.associateBy { it.fileName.toString() } // name -> Path
369+
370+
val conn = dbConnection()
371+
try {
372+
val existing = readExisting(conn, "coop")
373+
374+
data class PatchFile(val id: Int, val fileTemplate: String, val includes: List<Path>?)
375+
376+
val filesList = listOf(
377+
PatchFile(1, "init_coop.v%d.lua", listOf(repo.resolve("init_coop.lua"))),
378+
PatchFile(
379+
2, "lobby_coop_v%d.cop", listOf(
380+
repo.resolve("mods"),
381+
repo.resolve("units"),
382+
repo.resolve("mod_info.lua"),
383+
repo.resolve("readme.md"),
384+
repo.resolve("changelog.md")
385+
)
386+
),
387+
388+
// all VO files (no sources → already downloaded externally)
389+
PatchFile(3, "A01_VO.v%d.nx2", null),
390+
PatchFile(4, "A02_VO.v%d.nx2", null),
391+
PatchFile(5, "A03_VO.v%d.nx2", null),
392+
PatchFile(6, "A04_VO.v%d.nx2", null),
393+
PatchFile(7, "A05_VO.v%d.nx2", null),
394+
PatchFile(8, "A06_VO.v%d.nx2", null),
395+
PatchFile(9, "C01_VO.v%d.nx2", null),
396+
PatchFile(10, "C02_VO.v%d.nx2", null),
397+
PatchFile(11, "C03_VO.v%d.nx2", null),
398+
PatchFile(12, "C04_VO.v%d.nx2", null),
399+
PatchFile(13, "C05_VO.v%d.nx2", null),
400+
PatchFile(14, "C06_VO.v%d.nx2", null),
401+
PatchFile(15, "E01_VO.v%d.nx2", null),
402+
PatchFile(16, "E02_VO.v%d.nx2", null),
403+
PatchFile(17, "E03_VO.v%d.nx2", null),
404+
PatchFile(18, "E04_VO.v%d.nx2", null),
405+
PatchFile(19, "E05_VO.v%d.nx2", null),
406+
PatchFile(20, "E06_VO.v%d.nx2", null),
407+
PatchFile(21, "Prothyon16_VO.v%d.nx2", null),
408+
PatchFile(22, "A03_VO.v%d.nx2", null),
409+
PatchFile(23, "A03_VO.v%d.nx2", null),
410+
PatchFile(24, "A03_VO.v%d.nx2", null),
411+
PatchFile(25, "A03_VO.v%d.nx2", null),
412+
// … add the rest
413+
)
414+
415+
for ((fileId, fmt, srcs) in filesList) {
416+
processItem(conn, "coop", PATCH_VERSION.toInt(), fileId, fmt, srcs?.map { it }, voMap)
417+
}
418+
} finally {
419+
conn.close()
419420
}
420-
} finally {
421-
conn.close()
422-
}
423421

424-
println("=== Done ===")
422+
log.info("=== Done ===")
423+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
plugins {
2+
kotlin("jvm") version "1.9.24"
3+
application
4+
}
5+
6+
repositories {
7+
mavenCentral()
8+
}
9+
10+
dependencies {
11+
implementation("org.mariadb.jdbc:mariadb-java-client:3.5.7")
12+
implementation("org.eclipse.jgit:org.eclipse.jgit:7.5.0.202512021534-r")
13+
implementation("org.slf4j:slf4j-api:2.0.13")
14+
runtimeOnly("ch.qos.logback:logback-classic:1.5.23")
15+
}
16+
17+
application {
18+
mainClass.set("CoopDeployerKt") // filename + Kt
19+
}
20+
21+
// Use the root level for files
22+
sourceSets {
23+
main {
24+
kotlin.srcDirs(".")
25+
}
26+
}

0 commit comments

Comments
 (0)