Read init's effective configuration from the repository root
`init --systemd` resolved the configuration through `Paths.get(".")` while
every other file it touches — the two generated config layers, an applied
fragment, the units, the .htaccess — goes through the git top level. The two
agree only when the process happens to run in the repository root; from a
subdirectory the command silently read a different repository's configuration
or none at all, so `--apply`'s promise that the fragment's port reaches the
generated unit did not hold, and the host integration was skipped as if no
publicBaseUrl were configured.
The root is passed down instead, matching every other caller of
`ConfigLoader.load`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7fd473b88b
commit
2cddd76c88
@@ -297,20 +297,25 @@ class InitCommand(
|
||||
* already loadable (re-running `init --systemd` on an installed instance); during
|
||||
* the very first bootstrap they stay unset and the defaults (no directives) apply.
|
||||
*/
|
||||
private fun loadedSystemdConfig(): de.hoennig.werkator.config.SystemdConfig = loadedServerConfig().systemd
|
||||
private fun loadedSystemdConfig(root: Path): de.hoennig.werkator.config.SystemdConfig = loadedServerConfig(root).systemd
|
||||
|
||||
/** Loaded once per run, so a broken configuration is reported once and not per caller. */
|
||||
private var cachedServerConfig: de.hoennig.werkator.config.ServerConfig? = null
|
||||
|
||||
/**
|
||||
* Read from the repository root like every other file this command touches — the
|
||||
* layers sit there, not in whatever directory the process happens to run in, and
|
||||
* an applied fragment must reach the generated unit even when `init` is invoked
|
||||
* from a subdirectory.
|
||||
*
|
||||
* A configuration error here is not fatal — the units are still generated with defaults —
|
||||
* but it must not pass for "nothing configured": without the warning a broken `.werkator.yml`
|
||||
* looks exactly like an unset `publicBaseUrl` and the host integration is skipped silently.
|
||||
*/
|
||||
private fun loadedServerConfig(): de.hoennig.werkator.config.ServerConfig =
|
||||
private fun loadedServerConfig(root: Path): de.hoennig.werkator.config.ServerConfig =
|
||||
cachedServerConfig ?: run {
|
||||
try {
|
||||
configLoader.load(Paths.get(".")).server
|
||||
configLoader.load(root).server
|
||||
} catch (e: Exception) {
|
||||
println("Warning: the effective configuration could not be loaded (${e.message})")
|
||||
println(" continuing with default server settings — check the generated unit and host files")
|
||||
@@ -340,8 +345,8 @@ class InitCommand(
|
||||
javaExecutable = javaExecutableResolver(),
|
||||
jarPath = jarPath,
|
||||
envFile = envFile,
|
||||
memoryMax = loadedSystemdConfig().memoryMax,
|
||||
tasksMax = loadedSystemdConfig().tasksMax,
|
||||
memoryMax = loadedSystemdConfig(root).memoryMax,
|
||||
tasksMax = loadedSystemdConfig(root).tasksMax,
|
||||
),
|
||||
)
|
||||
println("created ${unitFile.toFile().relativeTo(normalizedWorkingDir.toFile())}")
|
||||
@@ -364,7 +369,7 @@ class InitCommand(
|
||||
|
||||
// generated host integration like the units: only meaningful behind a web
|
||||
// frontend, so it needs a public base URL; unused elsewhere and harmless
|
||||
val server = loadedServerConfig()
|
||||
val server = loadedServerConfig(root)
|
||||
if (server.publicBaseUrl.isNotBlank()) {
|
||||
val htaccessFile = werkatorDir.resolve(SystemdServiceFiles.HTACCESS_NAME)
|
||||
htaccessFile.toFile().writeText(SystemdServiceFiles.htaccessContent(server.port))
|
||||
|
||||
@@ -253,6 +253,29 @@ class InitCommandTest : FunSpec() {
|
||||
initCommand.run()
|
||||
}
|
||||
|
||||
test("--systemd reads the configuration from the repository root, not the current directory") {
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
// written before the run, so `init` keeps it instead of creating a template
|
||||
tempDir.resolve(".werkator.yml").toFile().writeText(
|
||||
"server:\n publicBaseUrl: \"https://werkator.example.org/\"\n port: 18099\n",
|
||||
)
|
||||
initCommand.workingDir = tempDir
|
||||
initCommand.systemd = true
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/werkator.jar") }
|
||||
initCommand.javaExecutableResolver = { Paths.get("/usr/bin/java") }
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
every { gitService.getOriginUrl(tempDir) } returns "https://git.example.org/my-org/my-repo.git"
|
||||
|
||||
initCommand.run()
|
||||
|
||||
// the host integration is generated only when the root's config has a public base URL
|
||||
val htaccess = tempDir.resolve(".git/werkator/${SystemdServiceFiles.HTACCESS_NAME}")
|
||||
htaccess.toFile().shouldExist()
|
||||
htaccess.toFile().readText() shouldContain "18099"
|
||||
tempDir.resolve(".git/werkator/${SystemdServiceFiles.MAINTENANCE_PAGE_NAME}").toFile().shouldExist()
|
||||
}
|
||||
|
||||
test("--systemd warns once when the effective configuration cannot be loaded") {
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
val brokenLoader = mockk<de.hoennig.werkator.config.ConfigLoader>()
|
||||
|
||||
Reference in New Issue
Block a user