initial: Kotlin/Gradle skeleton for cloud-installer
CI / build (push) Failing after 24s
CI / release (push) Has been skipped

Compiles to a 3.4 MB fat jar via shadow plugin.
Entrypoint with CLI dispatch (pull/push subcommands) + FlatLaf init.
Real sync logic stubbed; lands in subsequent commits per task plan.

Build via containerized gradle (8.10.2 + jdk21) to sidestep the
Kotlin 2.1 + JDK 26 compiler crash. Documented in README.

CI workflow tags-only release artifact upload prepared (needs
RELEASE_TOKEN secret in repo settings before first tag).
This commit is contained in:
2026-06-02 20:16:40 +02:00
commit 6ab43a168e
16 changed files with 817 additions and 0 deletions
@@ -0,0 +1,20 @@
package center.timemachine.cloud
/**
* Subcommand dispatchers. Skeleton — real arg parsing + sync logic lands
* in subsequent tasks. For now these print intent and exit cleanly so the
* fat jar can be smoke-tested end-to-end through Prism / frazclient.
*/
object Cli {
fun runPull(args: Array<String>): Int {
println("cloud-installer pull: ${args.joinToString(" ")}")
println("(not yet implemented; skeleton commit only)")
return 0
}
fun runPush(args: Array<String>): Int {
println("cloud-installer push: ${args.joinToString(" ")}")
println("(not yet implemented; skeleton commit only)")
return 0
}
}
@@ -0,0 +1,74 @@
package center.timemachine.cloud
import com.formdev.flatlaf.themes.FlatMacDarkLaf
import javax.swing.UIManager
/**
* cloud-installer entrypoint.
*
* Invoked twice in the launcher hooks:
* PreLaunch: java -jar cloud-installer.jar pull --url=... --pack-folder=...
* PostExit: java -jar cloud-installer.jar push --url=... --pack-folder=...
*
* Exit codes:
* 0 ok
* 1 user cancelled
* 2 error
*/
fun main(args: Array<String>) {
if (args.isEmpty() || args[0] in listOf("-h", "--help", "help")) {
printHelp()
return
}
if (args[0] in listOf("--version", "-V")) {
println("cloud-installer 0.1.0")
return
}
// Install FlatLaf theme as early as possible so any Swing window
// we open later picks it up. Falls back to system L&F on failure.
try {
UIManager.setLookAndFeel(FlatMacDarkLaf())
} catch (e: Exception) {
System.err.println("note: FlatLaf init failed (${e.message}); using system L&F")
}
val subcommand = args[0]
val rest = args.drop(1).toTypedArray()
val rc = when (subcommand) {
"pull" -> Cli.runPull(rest)
"push" -> Cli.runPush(rest)
else -> {
System.err.println("unknown subcommand: $subcommand")
printHelp()
2
}
}
kotlin.system.exitProcess(rc)
}
private fun printHelp() {
println("""
cloud-installer — per-user state sync for Minecraft clients
Usage:
java -jar cloud-installer.jar <subcommand> [flags]
Subcommands:
pull Fetch user's cloud state, apply conflict resolution, write to instance.
push Walk instance, build snapshot, upload changed files.
Flags:
--url <URL> cloud-svc base URL (required)
--pack-folder <DIR> instance dir to sync into/from (default: ".")
--token <STR> bearer token (or use --token-file)
--token-file <PATH> read token from this file (default: <pack-folder>/.cloud-token)
-g, --no-gui headless mode; conflicts auto-resolve to remote-wins
-V, --version print version
-h, --help print this help
Environment:
CLOUD_TOKEN fallback token source if no flag and no file
""".trimIndent())
}
@@ -0,0 +1,16 @@
package center.timemachine.cloud
import kotlin.test.Test
import kotlin.test.assertEquals
class SmokeTest {
@Test
fun `cli pull returns 0 in skeleton`() {
assertEquals(0, Cli.runPull(arrayOf("--url=http://localhost:9091")))
}
@Test
fun `cli push returns 0 in skeleton`() {
assertEquals(0, Cli.runPush(arrayOf("--url=http://localhost:9091")))
}
}