renaming from gitTally to Werkator
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally
|
||||
package de.hoennig.werkator
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.file.Files
|
||||
@@ -8,7 +8,7 @@ import java.nio.file.attribute.PosixFilePermissions
|
||||
|
||||
/**
|
||||
* Creation of files and directories that hold secrets — the Gitea token in
|
||||
* `.git/gittally/.gittally.yml` and the control token.
|
||||
* `.git/werkator/.werkator.yml` and the control token.
|
||||
*
|
||||
* The permissions are set *at creation*, never with a `chmod` after the write:
|
||||
* writing at the umask default first (typically `0644`) would leave a window in
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally
|
||||
package de.hoennig.werkator
|
||||
|
||||
import de.hoennig.gittally.config.ConfigException
|
||||
import de.hoennig.werkator.config.ConfigException
|
||||
import org.springframework.boot.CommandLineRunner
|
||||
import org.springframework.boot.ExitCodeGenerator
|
||||
import org.springframework.boot.SpringApplication
|
||||
@@ -13,14 +13,14 @@ import picocli.CommandLine.IFactory
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@SpringBootApplication
|
||||
class GitTallyApplication
|
||||
class WerkatorApplication
|
||||
|
||||
/** Not in the `server` profile: the second context started by `ServerCommand` must not run picocli again. */
|
||||
@Component
|
||||
@Profile("!server")
|
||||
class CliRunner(
|
||||
private val factory: IFactory,
|
||||
private val rootCommand: GitTallyCommand,
|
||||
private val rootCommand: werkatorCommand,
|
||||
) : CommandLineRunner,
|
||||
ExitCodeGenerator {
|
||||
private var exitCode = 0
|
||||
@@ -29,7 +29,7 @@ class CliRunner(
|
||||
exitCode =
|
||||
CommandLine(rootCommand, factory)
|
||||
.setExecutionExceptionHandler { exception, commandLine, _ ->
|
||||
// a config GitTally must not read is a stated fact, not a crash: the message
|
||||
// a config werkator must not read is a stated fact, not a crash: the message
|
||||
// names the file, the versions, and the way out — a stack trace would bury it
|
||||
if (exception is ConfigException) {
|
||||
commandLine.err.println("Error: ${exception.message}")
|
||||
@@ -49,5 +49,5 @@ class CliRunner(
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
exitProcess(SpringApplication.exit(runApplication<GitTallyApplication>(*args)))
|
||||
exitProcess(SpringApplication.exit(runApplication<WerkatorApplication>(*args)))
|
||||
}
|
||||
+10
-10
@@ -1,11 +1,11 @@
|
||||
package de.hoennig.gittally
|
||||
package de.hoennig.werkator
|
||||
|
||||
import de.hoennig.gittally.commands.BuildCommand
|
||||
import de.hoennig.gittally.commands.ConfigPrintCommand
|
||||
import de.hoennig.gittally.commands.InitCommand
|
||||
import de.hoennig.gittally.commands.RetryCommand
|
||||
import de.hoennig.gittally.commands.ServerCommand
|
||||
import de.hoennig.gittally.commands.StatusCommand
|
||||
import de.hoennig.werkator.commands.BuildCommand
|
||||
import de.hoennig.werkator.commands.ConfigPrintCommand
|
||||
import de.hoennig.werkator.commands.InitCommand
|
||||
import de.hoennig.werkator.commands.RetryCommand
|
||||
import de.hoennig.werkator.commands.ServerCommand
|
||||
import de.hoennig.werkator.commands.StatusCommand
|
||||
import org.springframework.beans.factory.ObjectProvider
|
||||
import org.springframework.boot.info.BuildProperties
|
||||
import org.springframework.stereotype.Component
|
||||
@@ -14,7 +14,7 @@ import picocli.CommandLine.Command
|
||||
|
||||
@Component
|
||||
@Command(
|
||||
name = "gittally",
|
||||
name = "werkator",
|
||||
subcommands = [
|
||||
InitCommand::class,
|
||||
ServerCommand::class,
|
||||
@@ -27,7 +27,7 @@ import picocli.CommandLine.Command
|
||||
versionProvider = BuildPropertiesVersionProvider::class,
|
||||
description = ["Lightweight, declarative CI/CD system"],
|
||||
)
|
||||
class GitTallyCommand : Runnable {
|
||||
class werkatorCommand : Runnable {
|
||||
override fun run(): Unit = throw CommandLine.ParameterException(CommandLine(this), "Specify a subcommand")
|
||||
}
|
||||
|
||||
@@ -41,5 +41,5 @@ class GitTallyCommand : Runnable {
|
||||
class BuildPropertiesVersionProvider(
|
||||
private val buildProperties: ObjectProvider<BuildProperties>,
|
||||
) : CommandLine.IVersionProvider {
|
||||
override fun getVersion(): Array<String> = arrayOf("GitTally v${buildProperties.getIfAvailable()?.version ?: "dev"}")
|
||||
override fun getVersion(): Array<String> = arrayOf("werkator v${buildProperties.getIfAvailable()?.version ?: "dev"}")
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.artifacts
|
||||
package de.hoennig.werkator.artifacts
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package de.hoennig.gittally.artifacts
|
||||
package de.hoennig.werkator.artifacts
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactKeys
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.config.BranchConfig
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.werkator.build.ArtifactKeys
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.config.BranchConfig
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.IOException
|
||||
import java.nio.file.FileVisitResult
|
||||
@@ -22,7 +22,7 @@ import kotlin.concurrent.write
|
||||
/**
|
||||
* Stores build artifacts on the filesystem under `<root>/branches/<artifactKey>/`.
|
||||
* The root is `artifacts.rootDir` from the config, or the platform default
|
||||
* `XDG_STATE_HOME` (falling back to `~/.local/state`) plus `/gittally/artifacts/<repo-key>` when unset —
|
||||
* `XDG_STATE_HOME` (falling back to `~/.local/state`) plus `/werkator/artifacts/<repo-key>` when unset —
|
||||
* deliberately not `/tmp` like legacy, where artifacts vanished on reboot.
|
||||
*
|
||||
* Each build is assembled in a temporary directory next to its target and moved
|
||||
@@ -115,7 +115,7 @@ class FileArtifactStore(
|
||||
env("XDG_STATE_HOME")?.takeIf { it.isNotBlank() }?.let { Paths.get(it) }
|
||||
?: Paths.get(System.getProperty("user.home"), ".local", "state")
|
||||
return stateHome
|
||||
.resolve("gittally")
|
||||
.resolve("werkator")
|
||||
.resolve("artifacts")
|
||||
.resolve(ArtifactKeys.repoKey(workingDir))
|
||||
.toAbsolutePath()
|
||||
@@ -160,9 +160,9 @@ class FileArtifactStore(
|
||||
}
|
||||
|
||||
/**
|
||||
* The settings [build] ran with, from the build [workspace]'s `.gittally.yml` layered
|
||||
* The settings [build] ran with, from the build [workspace]'s `.werkator.yml` layered
|
||||
* on top of the primary config (see [ConfigLoader.loadForWorktree]) — resolved through
|
||||
* [GitTallyConfig.buildSettings], so a job's own `artifactDirs` are archived and not
|
||||
* [werkatorConfig.buildSettings], so a job's own `artifactDirs` are archived and not
|
||||
* only the ones its branch would have used.
|
||||
*/
|
||||
private fun buildSettings(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.security.MessageDigest
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* Persists the artifacts of finished builds (logs plus configured report directories)
|
||||
* and prunes them together with the result retention.
|
||||
* Implemented by `de.hoennig.gittally.artifacts.FileArtifactStore`.
|
||||
* Implemented by `de.hoennig.werkator.artifacts.FileArtifactStore`.
|
||||
*/
|
||||
interface ArtifactStore {
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Files
|
||||
@@ -20,7 +20,7 @@ fun interface BranchWorkspaces {
|
||||
}
|
||||
|
||||
/**
|
||||
* One reusable git worktree per branch under `.git/gittally/worktrees/<branchKey>`,
|
||||
* One reusable git worktree per branch under `.git/werkator/worktrees/<branchKey>`,
|
||||
* checked out detached at the requested commit. Reuse keeps incremental build
|
||||
* caches; the branch's `cleanCommand` decides how much of them survives.
|
||||
*/
|
||||
@@ -50,6 +50,6 @@ class GitWorktreeWorkspaces(
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val WORKTREES_DIR = ".git/gittally/worktrees"
|
||||
const val WORKTREES_DIR = ".git/werkator/worktrees"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
@@ -8,9 +8,9 @@ import java.nio.file.Paths
|
||||
class BuildConfiguration {
|
||||
/**
|
||||
* Results file relative to the working directory, matching how `ConfigLoader`
|
||||
* resolves the `.git/gittally/` override file. Nothing is touched until the
|
||||
* resolves the `.git/werkator/` override file. Nothing is touched until the
|
||||
* first build runs, so the bean is safe outside a git repository.
|
||||
*/
|
||||
@Bean
|
||||
fun buildResultRepository(): BuildResultRepository = FileBuildResultRepository(Paths.get(".git/gittally/build-results.json"))
|
||||
fun buildResultRepository(): BuildResultRepository = FileBuildResultRepository(Paths.get(".git/werkator/build-results.json"))
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BranchConfig
|
||||
import de.hoennig.gittally.config.BuildDefinition
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.gitea.GiteaClient
|
||||
import de.hoennig.werkator.config.BranchConfig
|
||||
import de.hoennig.werkator.config.BuildDefinition
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.gitea.GiteaClient
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
import org.springframework.context.event.ContextClosedEvent
|
||||
@@ -93,7 +93,7 @@ class BuildExecutor(
|
||||
return duplicate.runningBuild
|
||||
}
|
||||
val startedAt = Instant.now()
|
||||
val stagingDir = Files.createTempDirectory("gittally-build-")
|
||||
val stagingDir = Files.createTempDirectory("werkator-build-")
|
||||
val runningBuild =
|
||||
RunningBuild(
|
||||
branch = branch,
|
||||
@@ -249,7 +249,7 @@ class BuildExecutor(
|
||||
|
||||
private fun serialWorker(branch: String): ExecutorService =
|
||||
Executors.newSingleThreadExecutor { runnable ->
|
||||
Thread(runnable, "gittally-build-${ArtifactKeys.branchKey(branch)}").apply { isDaemon = true }
|
||||
Thread(runnable, "werkator-build-${ArtifactKeys.branchKey(branch)}").apply { isDaemon = true }
|
||||
}
|
||||
|
||||
private fun runBuildCommands(
|
||||
@@ -324,7 +324,7 @@ class BuildExecutor(
|
||||
input: InputStream,
|
||||
vararg sinks: OutputStream,
|
||||
): Thread =
|
||||
thread(isDaemon = true, name = "gittally-build-log") {
|
||||
thread(isDaemon = true, name = "werkator-build-log") {
|
||||
val buffer = ByteArray(8192)
|
||||
try {
|
||||
while (true) {
|
||||
@@ -480,7 +480,7 @@ class BuildExecutor(
|
||||
|
||||
/**
|
||||
* The effective settings of this run: the branch config with the build [worktree]'s
|
||||
* `.gittally.yml` layered on top (see [ConfigLoader.loadForWorktree]), then the
|
||||
* `.werkator.yml` layered on top (see [ConfigLoader.loadForWorktree]), then the
|
||||
* build definition's overrides applied last — the job wins, and it always comes
|
||||
* from the primary config (`builds` is a pinned section). An unknown build name
|
||||
* (a stale result whose job was removed) falls back to the plain branch settings.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BuildDefinition
|
||||
import de.hoennig.werkator.config.BuildDefinition
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BranchConfig
|
||||
import de.hoennig.werkator.config.BranchConfig
|
||||
import org.springframework.context.annotation.Primary
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Path
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
enum class BuildStatus {
|
||||
PENDING,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BranchConfig
|
||||
import de.hoennig.gittally.config.DockerConfig
|
||||
import de.hoennig.gittally.git.GitCommandRunner
|
||||
import de.hoennig.werkator.config.BranchConfig
|
||||
import de.hoennig.werkator.config.DockerConfig
|
||||
import de.hoennig.werkator.git.GitCommandRunner
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Files
|
||||
@@ -23,7 +23,7 @@ import java.nio.file.Path
|
||||
* same container run; under a rootless daemon the container runs as root, which
|
||||
* already is the host user, so the repair chown degenerates to `0:0`.
|
||||
* Git works inside the container: the primary `.git` is mounted read-only with
|
||||
* `.git/gittally/` masked, see [gitMetadataMounts].
|
||||
* `.git/werkator/` masked, see [gitMetadataMounts].
|
||||
*/
|
||||
@Component
|
||||
class DockerBuildRunner(
|
||||
@@ -114,11 +114,11 @@ class DockerBuildRunner(
|
||||
"docker",
|
||||
"build",
|
||||
"--label",
|
||||
"org.gittally.dockerfile=${docker.dockerfile}",
|
||||
"org.werkator.dockerfile=${docker.dockerfile}",
|
||||
"--label",
|
||||
"org.gittally.dockerfile-sha256=$dockerfileHash",
|
||||
"org.werkator.dockerfile-sha256=$dockerfileHash",
|
||||
"--label",
|
||||
"org.gittally.build-context=${docker.context}",
|
||||
"org.werkator.build-context=${docker.context}",
|
||||
"--label",
|
||||
"${DockerImageInputs.INPUTS_LABEL}=$inputsHash",
|
||||
"-t",
|
||||
@@ -194,11 +194,11 @@ class DockerBuildRunner(
|
||||
"ps",
|
||||
"-aq",
|
||||
"--filter",
|
||||
"label=$GITTALLY_LABEL=true",
|
||||
"label=$werkator_LABEL=true",
|
||||
"--filter",
|
||||
"label=$GITTALLY_LABEL.repository=$repoKey",
|
||||
"label=$werkator_LABEL.repository=$repoKey",
|
||||
"--filter",
|
||||
"label=$GITTALLY_LABEL.role=build",
|
||||
"label=$werkator_LABEL.role=build",
|
||||
),
|
||||
repoDir,
|
||||
)
|
||||
@@ -238,11 +238,11 @@ class DockerBuildRunner(
|
||||
args +=
|
||||
listOf(
|
||||
"--label",
|
||||
"$GITTALLY_LABEL=true",
|
||||
"$werkator_LABEL=true",
|
||||
"--label",
|
||||
"$GITTALLY_LABEL.repository=$repoKey",
|
||||
"$werkator_LABEL.repository=$repoKey",
|
||||
"--label",
|
||||
"$GITTALLY_LABEL.role=build",
|
||||
"$werkator_LABEL.role=build",
|
||||
)
|
||||
args += listOf("--workdir", "$workspace", "--volume", "$workspace:$workspace")
|
||||
args += gitMetadataMounts(workspace, repoDir)
|
||||
@@ -279,12 +279,12 @@ class DockerBuildRunner(
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes git work inside the build container without exposing GitTally's secrets.
|
||||
* Makes git work inside the build container without exposing werkator's secrets.
|
||||
*
|
||||
* The workspace is a git worktree whose `.git` file points into the primary
|
||||
* repository's `.git`, which is not part of the workspace mount — so any git call
|
||||
* in the build would fail. Three layered mounts fix that (Docker nests mounts by
|
||||
* target path): the primary `.git` read-only, an empty tmpfs masking `.git/gittally/`
|
||||
* target path): the primary `.git` read-only, an empty tmpfs masking `.git/werkator/`
|
||||
* (machine config with `git.token`, control token, build state — the workspace bind
|
||||
* resurfaces only this build's own worktree inside it), and this worktree's admin
|
||||
* directory read-write, so index-refreshing commands like `git status` keep working.
|
||||
@@ -312,9 +312,9 @@ class DockerBuildRunner(
|
||||
return emptyList()
|
||||
}
|
||||
val args = mutableListOf("--volume", "$gitDir:$gitDir:ro")
|
||||
val gittallyDir = gitDir.resolve("gittally")
|
||||
if (Files.isDirectory(gittallyDir)) {
|
||||
args += listOf("--tmpfs", "$gittallyDir")
|
||||
val werkatorDir = gitDir.resolve("werkator")
|
||||
if (Files.isDirectory(werkatorDir)) {
|
||||
args += listOf("--tmpfs", "$werkatorDir")
|
||||
}
|
||||
args += listOf("--volume", "$adminDir:$adminDir")
|
||||
return args
|
||||
@@ -326,15 +326,15 @@ class DockerBuildRunner(
|
||||
): String = commandRunner.runOrThrow(listOf("id", flag), repoDir).stdout.trim()
|
||||
|
||||
companion object {
|
||||
/** Container label namespace; legacy used `org.hostsharing.gittally`. */
|
||||
const val GITTALLY_LABEL = "org.hoennig.gittally"
|
||||
/** Container label namespace; legacy used `org.hostsharing.werkator`. */
|
||||
const val werkator_LABEL = "org.hoennig.werkator"
|
||||
|
||||
fun gradleVolumeName(repoKey: String): String = "gittally-gradle-$repoKey"
|
||||
fun gradleVolumeName(repoKey: String): String = "werkator-gradle-$repoKey"
|
||||
|
||||
fun containerName(
|
||||
repoKey: String,
|
||||
branch: String?,
|
||||
): String = "gittally-build-$repoKey" + (branch?.let { "-${ArtifactKeys.branchKey(it)}" } ?: "")
|
||||
): String = "werkator-build-$repoKey" + (branch?.let { "-${ArtifactKeys.branchKey(it)}" } ?: "")
|
||||
|
||||
private val INSPECT_INPUTS_LABEL_FORMAT = """{{ index .Config.Labels "${DockerImageInputs.INPUTS_LABEL}" }}"""
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
@@ -10,7 +10,7 @@ import java.security.MessageDigest
|
||||
* with the configured Dockerfile and context paths, stored as an image label.
|
||||
*/
|
||||
object DockerImageInputs {
|
||||
const val INPUTS_LABEL = "org.gittally.build-inputs-sha256"
|
||||
const val INPUTS_LABEL = "org.werkator.build-inputs-sha256"
|
||||
|
||||
fun dockerfileSha256(dockerfile: Path): String = sha256Hex(Files.readAllBytes(dockerfile))
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Files
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
@@ -13,7 +13,7 @@ import java.nio.file.StandardCopyOption
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* Stores build results as a JSON file, e.g. `.git/gittally/build-results.json`.
|
||||
* Stores build results as a JSON file, e.g. `.git/werkator/build-results.json`.
|
||||
* Writes are atomic (temp file + atomic move) so readers never see partial content.
|
||||
*/
|
||||
class FileBuildResultRepository(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BuildDefinition
|
||||
import de.hoennig.werkator.config.BuildDefinition
|
||||
import java.nio.file.Path
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
/**
|
||||
* Port of the legacy `resolve_branch_name` partial-name matching: a branch-name
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.springframework.stereotype.Component
|
||||
import picocli.CommandLine.Command
|
||||
import picocli.CommandLine.ExitCode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import org.springframework.stereotype.Component
|
||||
import picocli.CommandLine.Command
|
||||
import picocli.CommandLine.Option
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.build.BuildExecutor
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.build.RunningBuild
|
||||
import de.hoennig.gittally.config.BuildDefinition
|
||||
import de.hoennig.gittally.server.UiFormats
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.BuildExecutor
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.build.RunningBuild
|
||||
import de.hoennig.werkator.config.BuildDefinition
|
||||
import de.hoennig.werkator.server.UiFormats
|
||||
import org.springframework.stereotype.Component
|
||||
import java.io.IOException
|
||||
import java.nio.channels.Channels
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.SecretFiles
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.SecretFiles
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.springframework.beans.factory.ObjectProvider
|
||||
import org.springframework.boot.info.BuildProperties
|
||||
import org.springframework.stereotype.Component
|
||||
@@ -13,19 +13,19 @@ import java.nio.file.Paths
|
||||
@Component
|
||||
@Command(
|
||||
name = "init",
|
||||
description = ["Initialize GitTally for the current repository"],
|
||||
description = ["Initialize werkator for the current repository"],
|
||||
mixinStandardHelpOptions = true,
|
||||
)
|
||||
class InitCommand(
|
||||
private val gitService: GitService,
|
||||
/** The version written into the generated config as `gitTally.version.since`. */
|
||||
/** The version written into the generated config as `werkator.version.since`. */
|
||||
private val buildProperties: ObjectProvider<BuildProperties>? = null,
|
||||
) : Runnable {
|
||||
var workingDir: Path = Paths.get(".")
|
||||
|
||||
@Option(
|
||||
names = ["--systemd"],
|
||||
description = ["also generate a systemd user unit that runs `gittally server` for this repository"],
|
||||
description = ["also generate a systemd user unit that runs `werkator server` for this repository"],
|
||||
)
|
||||
var systemd: Boolean = false
|
||||
|
||||
@@ -56,7 +56,7 @@ class InitCommand(
|
||||
}
|
||||
|
||||
/**
|
||||
* The running version for `gitTally.version.since`; outside a built jar (IDE, tests)
|
||||
* The running version for `werkator.version.since`; outside a built jar (IDE, tests)
|
||||
* there is none, and `0.0.0` then declares no floor at all rather than a wrong one.
|
||||
*/
|
||||
private fun runningVersion(): String = buildProperties?.getIfAvailable()?.version ?: "0.0.0"
|
||||
@@ -99,7 +99,7 @@ class InitCommand(
|
||||
detected: DetectedValues,
|
||||
normalizedWorkingDir: Path,
|
||||
) {
|
||||
val file = root.resolve(".git/gittally/.gittally.yml")
|
||||
val file = root.resolve(".git/werkator/.werkator.yml")
|
||||
if (file.toFile().exists()) {
|
||||
println("${file.toFile().relativeTo(normalizedWorkingDir.toFile())} already exists — not overwritten")
|
||||
return
|
||||
@@ -107,7 +107,7 @@ class InitCommand(
|
||||
SecretFiles.createDirectoriesOwnerOnly(file.parent)
|
||||
val content =
|
||||
"""
|
||||
# Machine- or user-specific overrides and secrets. Keys here win over .gittally.yml.
|
||||
# Machine- or user-specific overrides and secrets. Keys here win over .werkator.yml.
|
||||
git:
|
||||
account: "${detected.account}" # technical username for git HTTPS authentication
|
||||
token: "" # Gitea API token — never commit this
|
||||
@@ -123,31 +123,31 @@ class InitCommand(
|
||||
detected: DetectedValues,
|
||||
normalizedWorkingDir: Path,
|
||||
) {
|
||||
val file = root.resolve(".gittally.yml")
|
||||
val file = root.resolve(".werkator.yml")
|
||||
if (file.toFile().exists()) {
|
||||
println("${file.toFile().relativeTo(normalizedWorkingDir.toFile())} already exists — not overwritten")
|
||||
return
|
||||
}
|
||||
val content =
|
||||
"""
|
||||
# The GitTally this file is written for.
|
||||
# since: enforced — an older GitTally refuses to read this file instead of
|
||||
# The werkator this file is written for.
|
||||
# since: enforced — an older werkator refuses to read this file instead of
|
||||
# silently ignoring the keys it does not know yet.
|
||||
# below: your release marker for a coming major; GitTally decides how strictly
|
||||
# below: your release marker for a coming major; werkator decides how strictly
|
||||
# to take it, and warns rather than blocks unless the format really broke.
|
||||
gitTally:
|
||||
werkator:
|
||||
version:
|
||||
since: "${runningVersion()}"
|
||||
# below: "2.0"
|
||||
|
||||
server:
|
||||
# Public base URL of this GitTally installation — used for all links posted to Gitea.
|
||||
# Public base URL of this werkator installation — used for all links posted to Gitea.
|
||||
publicBaseUrl: ""
|
||||
# HTTP port of the `server` subcommand
|
||||
port: 18080
|
||||
# bind address of the `server` subcommand; loopback only, because the UI and the
|
||||
# API are unauthenticated — use 0.0.0.0 only without a reverse proxy in front
|
||||
# (and with the managed nginx below, which reaches GitTally from its container)
|
||||
# (and with the managed nginx below, which reaches werkator from its container)
|
||||
bindAddress: 127.0.0.1
|
||||
# optional Impressum (legal disclosure) link in the web UI footer; empty hides the link
|
||||
impressumUrl: ""
|
||||
@@ -159,8 +159,8 @@ class InitCommand(
|
||||
httpPort: 8080 # host port published as nginx port 80
|
||||
httpsPort: 8443 # host port published as nginx port 443
|
||||
upstreamHost: "" # host nginx proxies to; empty = serverName
|
||||
containerName: "" # empty = gittally-nginx-<repo-name>
|
||||
stateDir: "" # empty = XDG_STATE_HOME (or ~/.local/state) + /gittally/nginx/<repo-key>
|
||||
containerName: "" # empty = werkator-nginx-<repo-name>
|
||||
stateDir: "" # empty = XDG_STATE_HOME (or ~/.local/state) + /werkator/nginx/<repo-key>
|
||||
letsencryptEmail: "" # e-mail for the Let's Encrypt account; empty registers without one
|
||||
|
||||
# Gitea integration for fetching commits and posting build statuses.
|
||||
@@ -168,7 +168,7 @@ class InitCommand(
|
||||
baseUrl: ${detected.baseUrl} # base URL of the Gitea instance
|
||||
owner: ${detected.owner} # repository owner (user or organisation) for Gitea API (e.g. status checks)
|
||||
repo: ${detected.repo} # repository name
|
||||
statusContext: GitTally # label shown on Gitea commit status checks (default: GitTally)
|
||||
statusContext: werkator # label shown on Gitea commit status checks (default: werkator)
|
||||
|
||||
# Build execution settings, enforced for all builds regardless of their trigger.
|
||||
executor:
|
||||
@@ -178,7 +178,7 @@ class InitCommand(
|
||||
# Named build definitions (jobs); every key names a build.
|
||||
# "default" is the base every other definition inherits its settings from — never
|
||||
# its trigger — and is itself the build of every branch as long as it has one.
|
||||
# A branch may add or override definitions in its own committed .gittally.yml;
|
||||
# A branch may add or override definitions in its own committed .werkator.yml;
|
||||
# they apply to that branch alone, so a new job can be tried out on one branch.
|
||||
builds:
|
||||
default:
|
||||
@@ -218,11 +218,11 @@ class InitCommand(
|
||||
# atTimes: ["01:00"]
|
||||
# branches: ["master"]
|
||||
# buildCommand: ./gradlew pitestFull
|
||||
# statusContext: GitTally/pitest
|
||||
# statusContext: werkator/pitest
|
||||
|
||||
# Build artifact storage and retention.
|
||||
artifacts:
|
||||
# root directory for stored artifacts; empty = XDG_STATE_HOME (or ~/.local/state) + /gittally/artifacts/<repo-key>
|
||||
# root directory for stored artifacts; empty = XDG_STATE_HOME (or ~/.local/state) + /werkator/artifacts/<repo-key>
|
||||
rootDir: ""
|
||||
# number of builds to keep per branch
|
||||
retentionPerBranch: 3
|
||||
@@ -256,14 +256,14 @@ class InitCommand(
|
||||
) {
|
||||
val jarPath = jarPathResolver()
|
||||
if (jarPath == null) {
|
||||
println("Error: cannot determine the GitTally jar path — run `init --systemd` via `java -jar <path-to>/gittally.jar`")
|
||||
println("Error: cannot determine the werkator jar path — run `init --systemd` via `java -jar <path-to>/werkator.jar`")
|
||||
return
|
||||
}
|
||||
val gittallyDir = root.resolve(".git/gittally")
|
||||
SecretFiles.createDirectoriesOwnerOnly(gittallyDir)
|
||||
val werkatorDir = root.resolve(".git/werkator")
|
||||
SecretFiles.createDirectoriesOwnerOnly(werkatorDir)
|
||||
val unitName = SystemdServiceFiles.unitName(root)
|
||||
val unitFile = gittallyDir.resolve(unitName)
|
||||
val envFile = gittallyDir.resolve(SystemdServiceFiles.ENV_FILE_NAME)
|
||||
val unitFile = werkatorDir.resolve(unitName)
|
||||
val envFile = werkatorDir.resolve(SystemdServiceFiles.ENV_FILE_NAME)
|
||||
|
||||
unitFile.toFile().writeText(
|
||||
SystemdServiceFiles.unitFileContent(
|
||||
@@ -283,9 +283,9 @@ class InitCommand(
|
||||
}
|
||||
|
||||
// the nightly Docker cleanup is host-global: every repository generates the same
|
||||
// units, so with several GitTally instances the symlinks simply coincide
|
||||
val pruneServiceFile = gittallyDir.resolve(SystemdServiceFiles.PRUNE_SERVICE_NAME)
|
||||
val pruneTimerFile = gittallyDir.resolve(SystemdServiceFiles.PRUNE_TIMER_NAME)
|
||||
// units, so with several werkator instances the symlinks simply coincide
|
||||
val pruneServiceFile = werkatorDir.resolve(SystemdServiceFiles.PRUNE_SERVICE_NAME)
|
||||
val pruneTimerFile = werkatorDir.resolve(SystemdServiceFiles.PRUNE_TIMER_NAME)
|
||||
pruneServiceFile.toFile().writeText(SystemdServiceFiles.pruneServiceContent())
|
||||
println("created ${pruneServiceFile.toFile().relativeTo(normalizedWorkingDir.toFile())}")
|
||||
pruneTimerFile.toFile().writeText(SystemdServiceFiles.pruneTimerContent())
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.springframework.stereotype.Component
|
||||
import picocli.CommandLine.Command
|
||||
import picocli.CommandLine.ExitCode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.GitTallyApplication
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.werkator.WerkatorApplication
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import org.springframework.boot.WebApplicationType
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder
|
||||
import org.springframework.context.ApplicationListener
|
||||
@@ -24,7 +24,7 @@ import java.util.concurrent.CountDownLatch
|
||||
@Component
|
||||
@Command(
|
||||
name = "server",
|
||||
description = ["Start the GitTally server"],
|
||||
description = ["Start the werkator server"],
|
||||
mixinStandardHelpOptions = true,
|
||||
)
|
||||
class ServerCommand(
|
||||
@@ -35,7 +35,7 @@ class ServerCommand(
|
||||
override fun run() {
|
||||
val config = configLoader.load(workingDir)
|
||||
val context =
|
||||
SpringApplicationBuilder(GitTallyApplication::class.java)
|
||||
SpringApplicationBuilder(WerkatorApplication::class.java)
|
||||
.web(WebApplicationType.SERVLET)
|
||||
.profiles(SERVER_PROFILE)
|
||||
.properties(
|
||||
@@ -43,7 +43,7 @@ class ServerCommand(
|
||||
"server.address=${config.server.bindAddress}",
|
||||
).run()
|
||||
val port = context.environment.getProperty("local.server.port", config.server.port.toString())
|
||||
println("GitTally server listening on http://${config.server.bindAddress}:$port/ — Ctrl-C to stop")
|
||||
println("werkator server listening on http://${config.server.bindAddress}:$port/ — Ctrl-C to stop")
|
||||
awaitShutdown(context)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.server.UiFormats
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.server.UiFormats
|
||||
import org.springframework.stereotype.Component
|
||||
import picocli.CommandLine.Command
|
||||
import picocli.CommandLine.ExitCode
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* Generates the content of the systemd user unit and its `EnvironmentFile` for running
|
||||
* `gittally server` as a service — the shape of the legacy `generate_systemd_config`,
|
||||
* `werkator server` as a service — the shape of the legacy `generate_systemd_config`,
|
||||
* without the self-copy/self-update machinery (the unit points at the jar in place).
|
||||
*/
|
||||
object SystemdServiceFiles {
|
||||
const val ENV_FILE_NAME = "gittally.env"
|
||||
const val ENV_FILE_NAME = "werkator.env"
|
||||
|
||||
/** Host-global unit names of the nightly Docker cleanup — shared by all GitTally repositories on the host. */
|
||||
const val PRUNE_SERVICE_NAME = "gittally-docker-prune.service"
|
||||
const val PRUNE_TIMER_NAME = "gittally-docker-prune.timer"
|
||||
/** Host-global unit names of the nightly Docker cleanup — shared by all werkator repositories on the host. */
|
||||
const val PRUNE_SERVICE_NAME = "werkator-docker-prune.service"
|
||||
const val PRUNE_TIMER_NAME = "werkator-docker-prune.timer"
|
||||
|
||||
/** Per-repository unit name, because one GitTally instance serves exactly one repository. */
|
||||
fun unitName(repoRoot: Path): String = "gittally-${sanitize(repoRoot.fileName.toString())}.service"
|
||||
/** Per-repository unit name, because one werkator instance serves exactly one repository. */
|
||||
fun unitName(repoRoot: Path): String = "werkator-${sanitize(repoRoot.fileName.toString())}.service"
|
||||
|
||||
fun unitFileContent(
|
||||
repoRoot: Path,
|
||||
@@ -25,7 +25,7 @@ object SystemdServiceFiles {
|
||||
): String =
|
||||
"""
|
||||
[Unit]
|
||||
Description=GitTally CI for ${repoRoot.fileName}
|
||||
Description=werkator CI for ${repoRoot.fileName}
|
||||
Wants=network-online.target
|
||||
After=network-online.target docker.service
|
||||
|
||||
@@ -49,7 +49,7 @@ object SystemdServiceFiles {
|
||||
fun pruneServiceContent(): String =
|
||||
"""
|
||||
[Unit]
|
||||
Description=Clean up unused Docker containers and images (GitTally)
|
||||
Description=Clean up unused Docker containers and images (werkator)
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
@@ -62,7 +62,7 @@ object SystemdServiceFiles {
|
||||
fun pruneTimerContent(): String =
|
||||
"""
|
||||
[Unit]
|
||||
Description=Nightly Docker cleanup before the auto builds (GitTally)
|
||||
Description=Nightly Docker cleanup before the auto builds (werkator)
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* 02:00:00
|
||||
@@ -74,8 +74,8 @@ object SystemdServiceFiles {
|
||||
|
||||
fun envFileContent(): String =
|
||||
"""
|
||||
# EnvironmentFile for the GitTally systemd service.
|
||||
# GitTally itself is configured via .gittally.yml and .git/gittally/.gittally.yml,
|
||||
# EnvironmentFile for the werkator systemd service.
|
||||
# werkator itself is configured via .werkator.yml and .git/werkator/.werkator.yml,
|
||||
# not via environment variables; this file only tunes the JVM process.
|
||||
#JAVA_OPTS=-Xmx256m
|
||||
""".trimIndent() + "\n"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
@@ -17,7 +17,7 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Service
|
||||
class ConfigLoader(
|
||||
/** The running version, for the `gitTally.version` check; absent outside a built jar (IDE, tests). */
|
||||
/** The running version, for the `werkator.version` check; absent outside a built jar (IDE, tests). */
|
||||
private val buildProperties: ObjectProvider<BuildProperties>? = null,
|
||||
) {
|
||||
private val log = LoggerFactory.getLogger(ConfigLoader::class.java)
|
||||
@@ -37,21 +37,21 @@ class ConfigLoader(
|
||||
/** Section-level warnings already reported, keyed by a fixed slug; the config is loaded on every poll cycle. */
|
||||
private val warnedSections = ConcurrentHashMap.newKeySet<String>()
|
||||
|
||||
fun load(workingDir: Path = Paths.get(".")): GitTallyConfig = toConfig(loadRaw(workingDir))
|
||||
fun load(workingDir: Path = Paths.get(".")): WerkatorConfig = toConfig(loadRaw(workingDir))
|
||||
|
||||
/**
|
||||
* Config for building a branch in [worktreeDir]: the worktree's `.gittally.yml`
|
||||
* Config for building a branch in [worktreeDir]: the worktree's `.werkator.yml`
|
||||
* (the committed config of the branch being built) is applied as the branch layer,
|
||||
* see [loadWithBranchLayer]. With no worktree `.gittally.yml` this is identical
|
||||
* see [loadWithBranchLayer]. With no worktree `.werkator.yml` this is identical
|
||||
* to [load].
|
||||
*/
|
||||
fun loadForWorktree(
|
||||
workingDir: Path,
|
||||
worktreeDir: Path,
|
||||
): GitTallyConfig = withBranchLayer(workingDir, loadFile(worktreeDir.resolve(".gittally.yml").toFile()))
|
||||
): WerkatorConfig = withBranchLayer(workingDir, loadFile(worktreeDir.resolve(".werkator.yml").toFile()))
|
||||
|
||||
/**
|
||||
* The primary/`.git` config with the committed `.gittally.yml` of one branch
|
||||
* The primary/`.git` config with the committed `.werkator.yml` of one branch
|
||||
* ([branchConfigYaml], null or blank for a branch without one) merged on top:
|
||||
* precedence branch > `.git` > project. A branch describes its own CI — build
|
||||
* settings (`buildCommand`, `cleanCommand`, `artifactDirs`, `docker.image`/`env`, …)
|
||||
@@ -70,25 +70,25 @@ class ConfigLoader(
|
||||
fun loadWithBranchLayer(
|
||||
workingDir: Path,
|
||||
branchConfigYaml: String?,
|
||||
): GitTallyConfig = withBranchLayer(workingDir, parseYaml(branchConfigYaml))
|
||||
): WerkatorConfig = withBranchLayer(workingDir, parseYaml(branchConfigYaml))
|
||||
|
||||
private fun withBranchLayer(
|
||||
workingDir: Path,
|
||||
branchLayer: Map<String, Any?>,
|
||||
): GitTallyConfig {
|
||||
): WerkatorConfig {
|
||||
// scoped to this branch: an incompatible branch config fails its own builds and
|
||||
// must never stop the server or hold up the branches that are fine
|
||||
checkVersion(branchLayer, "the committed .gittally.yml of this branch", BRANCH_HINT)
|
||||
checkTriggerBlocks(branchLayer, "the committed .gittally.yml of this branch", BRANCH_HINT)
|
||||
checkVersion(branchLayer, "the committed .werkator.yml of this branch", BRANCH_HINT)
|
||||
checkTriggerBlocks(branchLayer, "the committed .werkator.yml of this branch", BRANCH_HINT)
|
||||
return toConfig(deepMerge(loadRaw(workingDir), stripPinned(branchLayer)))
|
||||
}
|
||||
|
||||
private fun toConfig(raw: Map<String, Any?>): GitTallyConfig {
|
||||
private fun toConfig(raw: Map<String, Any?>): WerkatorConfig {
|
||||
val config =
|
||||
if (raw.isEmpty()) {
|
||||
GitTallyConfig()
|
||||
WerkatorConfig()
|
||||
} else {
|
||||
yaml.convertValue(resolveBuildSections(dropNonDefinitionBuilds(raw)), GitTallyConfig::class.java)
|
||||
yaml.convertValue(resolveBuildSections(dropNonDefinitionBuilds(raw)), WerkatorConfig::class.java)
|
||||
}
|
||||
return defaultPublicBaseUrl(config)
|
||||
}
|
||||
@@ -265,7 +265,7 @@ class ConfigLoader(
|
||||
}
|
||||
|
||||
/** Legacy default: an empty `server.publicBaseUrl` becomes `https://<nginx.serverName>/`. */
|
||||
private fun defaultPublicBaseUrl(config: GitTallyConfig): GitTallyConfig {
|
||||
private fun defaultPublicBaseUrl(config: WerkatorConfig): WerkatorConfig {
|
||||
if (config.server.publicBaseUrl.isNotBlank() ||
|
||||
config.server.nginx.serverName
|
||||
.isBlank()
|
||||
@@ -276,18 +276,18 @@ class ConfigLoader(
|
||||
}
|
||||
|
||||
fun loadRaw(workingDir: Path = Paths.get(".")): Map<String, Any?> {
|
||||
val repoInstall = loadFile(workingDir.resolve(".git/gittally/.gittally.yml").toFile())
|
||||
val project = loadFile(workingDir.resolve(".gittally.yml").toFile())
|
||||
val repoInstall = loadFile(workingDir.resolve(".git/werkator/.werkator.yml").toFile())
|
||||
val project = loadFile(workingDir.resolve(".werkator.yml").toFile())
|
||||
// per file, so the message names the file to fix — the merged map has no provenance
|
||||
checkVersion(project, ".gittally.yml", ROLLBACK_HINT)
|
||||
checkVersion(repoInstall, ".git/gittally/.gittally.yml", ROLLBACK_HINT)
|
||||
checkTriggerBlocks(project, ".gittally.yml", ROLLBACK_HINT)
|
||||
checkTriggerBlocks(repoInstall, ".git/gittally/.gittally.yml", ROLLBACK_HINT)
|
||||
checkVersion(project, ".werkator.yml", ROLLBACK_HINT)
|
||||
checkVersion(repoInstall, ".git/werkator/.werkator.yml", ROLLBACK_HINT)
|
||||
checkTriggerBlocks(project, ".werkator.yml", ROLLBACK_HINT)
|
||||
checkTriggerBlocks(repoInstall, ".git/werkator/.werkator.yml", ROLLBACK_HINT)
|
||||
return deepMerge(project, repoInstall)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces the `gitTally.version` declaration of one configuration file.
|
||||
* Enforces the `werkator.version` declaration of one configuration file.
|
||||
* An incompatible file throws — reading it would mean honoring keys that mean
|
||||
* something else now, which is worse than not building. A file that merely exceeds
|
||||
* its own `below` marker is a warning, logged once: an unmaintained marker must
|
||||
@@ -314,7 +314,7 @@ class ConfigLoader(
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun requirementOf(raw: Map<String, Any?>): VersionRequirement {
|
||||
val version = (raw["gitTally"] as? Map<String, Any?>)?.get("version") as? Map<String, Any?> ?: return VersionRequirement()
|
||||
val version = (raw["werkator"] as? Map<String, Any?>)?.get("version") as? Map<String, Any?> ?: return VersionRequirement()
|
||||
return VersionRequirement(
|
||||
since = version["since"]?.toString()?.trim().orEmpty(),
|
||||
below = version["below"]?.toString()?.trim().orEmpty(),
|
||||
@@ -329,7 +329,7 @@ class ConfigLoader(
|
||||
return yaml.readValue(file, Map::class.java) as Map<String, Any?>
|
||||
}
|
||||
|
||||
/** Parses a `.gittally.yml` read from git (not from disk); blank or null yields no layer. */
|
||||
/** Parses a `.werkator.yml` read from git (not from disk); blank or null yields no layer. */
|
||||
private fun parseYaml(text: String?): Map<String, Any?> {
|
||||
if (text.isNullOrBlank()) return emptyMap()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -411,7 +411,7 @@ class ConfigLoader(
|
||||
private const val NO_TRIGGER_WARNING = "no-build-triggered"
|
||||
|
||||
private const val ROLLBACK_HINT =
|
||||
"Migrate the file, or roll back to the GitTally version it was written for."
|
||||
"Migrate the file, or roll back to the werkator version it was written for."
|
||||
|
||||
private const val BRANCH_HINT =
|
||||
"Migrate the file on this branch; the other branches keep building."
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
/**
|
||||
* The GitTally version a configuration file declares itself for, the `gitTally.version`
|
||||
* The werkator version a configuration file declares itself for, the `werkator.version`
|
||||
* section:
|
||||
*
|
||||
* ```yaml
|
||||
* gitTally:
|
||||
* werkator:
|
||||
* version:
|
||||
* since: "0.9.16" # always hard: an older GitTally refuses this file
|
||||
* below: "2.0" # GitTally decides how hard, see ConfigVersions.verdict
|
||||
* since: "0.9.16" # always hard: an older werkator refuses this file
|
||||
* below: "2.0" # werkator decides how hard, see ConfigVersions.verdict
|
||||
* ```
|
||||
*
|
||||
* There is deliberately no version of the file format itself (no `apiVersion`): no API is
|
||||
* involved — GitTally reads its own configuration — and only one configuration generation
|
||||
* involved — werkator reads its own configuration — and only one configuration generation
|
||||
* is ever supported. The declared version exists to make an incompatibility nameable,
|
||||
* never to run two parsers.
|
||||
*/
|
||||
data class VersionRequirement(
|
||||
/** Oldest GitTally that understands this file; empty means the file does not say. */
|
||||
/** Oldest werkator that understands this file; empty means the file does not say. */
|
||||
val since: String = "",
|
||||
/** First GitTally this file was not released for; empty means no ceiling. */
|
||||
/** First werkator this file was not released for; empty means no ceiling. */
|
||||
val below: String = "",
|
||||
)
|
||||
|
||||
data class GitTallyMeta(
|
||||
data class werkatorMeta(
|
||||
val version: VersionRequirement = VersionRequirement(),
|
||||
)
|
||||
|
||||
/** What a [VersionRequirement] means for the GitTally that reads the file. */
|
||||
/** What a [VersionRequirement] means for the werkator that reads the file. */
|
||||
sealed interface VersionVerdict {
|
||||
/** The running version is covered by the declaration. */
|
||||
data object Compatible : VersionVerdict
|
||||
@@ -37,24 +37,24 @@ sealed interface VersionVerdict {
|
||||
val message: String,
|
||||
) : VersionVerdict
|
||||
|
||||
/** Not usable: the file predates a change that GitTally cannot bridge. */
|
||||
/** Not usable: the file predates a change that werkator cannot bridge. */
|
||||
data class Incompatible(
|
||||
val message: String,
|
||||
) : VersionVerdict
|
||||
}
|
||||
|
||||
/** A configuration file this GitTally must not read; carries the file's name in its message. */
|
||||
/** A configuration file this werkator must not read; carries the file's name in its message. */
|
||||
open class ConfigException(
|
||||
message: String,
|
||||
) : RuntimeException(message)
|
||||
|
||||
/** The file declares a GitTally that cannot read it, see [ConfigVersions]. */
|
||||
/** The file declares a werkator that cannot read it, see [ConfigVersions]. */
|
||||
class ConfigVersionException(
|
||||
message: String,
|
||||
) : ConfigException(message)
|
||||
|
||||
/**
|
||||
* The file is written in a shape this GitTally no longer reads. Refusing it is the point:
|
||||
* The file is written in a shape this werkator no longer reads. Refusing it is the point:
|
||||
* a key that moved and is silently ignored means a build that quietly stops happening.
|
||||
*/
|
||||
class ConfigFormatException(
|
||||
@@ -64,7 +64,7 @@ class ConfigFormatException(
|
||||
object ConfigVersions {
|
||||
/**
|
||||
* The version in which the configuration format last changed incompatibly — a file
|
||||
* written before it cannot be read by this GitTally. Empty while no such change has
|
||||
* written before it cannot be read by this werkator. Empty while no such change has
|
||||
* happened; set it to the release that introduces one, together with the migration
|
||||
* note the message points at.
|
||||
*/
|
||||
@@ -76,13 +76,13 @@ object ConfigVersions {
|
||||
/**
|
||||
* Decides what [requirement] means for [running].
|
||||
*
|
||||
* `since` is always hard — a file that needs a newer GitTally cannot be honored, and
|
||||
* `since` is always hard — a file that needs a newer werkator cannot be honored, and
|
||||
* silently ignoring its unknown keys is exactly the failure mode this section exists
|
||||
* to prevent.
|
||||
*
|
||||
* `below` alone only warns: it is the team's release marker, and an unmaintained
|
||||
* marker must never stop a CI. Whether the running version really broke the file is
|
||||
* GitTally's own knowledge ([FORMAT_BROKE_IN]) — a file written before that change
|
||||
* werkator's own knowledge ([FORMAT_BROKE_IN]) — a file written before that change
|
||||
* and read after it is incompatible regardless of what it declares as its ceiling.
|
||||
*/
|
||||
fun verdict(
|
||||
@@ -95,13 +95,13 @@ object ConfigVersions {
|
||||
val since = parse(requirement.since)
|
||||
if (since != null && version < since) {
|
||||
return VersionVerdict.Incompatible(
|
||||
"needs GitTally ${requirement.since} or newer (gitTally.version.since), this is $running",
|
||||
"needs werkator ${requirement.since} or newer (werkator.version.since), this is $running",
|
||||
)
|
||||
}
|
||||
val broke = parse(brokeIn)
|
||||
if (since != null && broke != null && since < broke && version >= broke) {
|
||||
return VersionVerdict.Incompatible(
|
||||
"is written for GitTally ${requirement.since} (gitTally.version.since), " +
|
||||
"is written for werkator ${requirement.since} (werkator.version.since), " +
|
||||
"but the configuration format changed incompatibly in $brokeIn" +
|
||||
brokeDescription.takeIf { it.isNotBlank() }?.let { ": $it" }.orEmpty(),
|
||||
)
|
||||
@@ -109,7 +109,7 @@ object ConfigVersions {
|
||||
val below = parse(requirement.below)
|
||||
if (below != null && version >= below) {
|
||||
return VersionVerdict.Warn(
|
||||
"was released for GitTally below ${requirement.below} (gitTally.version.below), this is $running",
|
||||
"was released for werkator below ${requirement.below} (werkator.version.below), this is $running",
|
||||
)
|
||||
}
|
||||
return VersionVerdict.Compatible
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import java.time.Duration
|
||||
|
||||
|
||||
+10
-10
@@ -1,10 +1,10 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
|
||||
data class GitTallyConfig(
|
||||
/** What this file declares about the GitTally that reads it; see [VersionRequirement]. */
|
||||
val gitTally: GitTallyMeta = GitTallyMeta(),
|
||||
data class WerkatorConfig(
|
||||
/** What this file declares about the werkator that reads it; see [VersionRequirement]. */
|
||||
val werkator: werkatorMeta = werkatorMeta(),
|
||||
val server: ServerConfig = ServerConfig(),
|
||||
val git: GitConfig = GitConfig(),
|
||||
val gitea: GiteaConfig = GiteaConfig(),
|
||||
@@ -61,7 +61,7 @@ data class ServerConfig(
|
||||
)
|
||||
|
||||
/**
|
||||
* Opt-in managed nginx+certbot Docker container serving GitTally over HTTPS,
|
||||
* Opt-in managed nginx+certbot Docker container serving werkator over HTTPS,
|
||||
* for hosts without a usable reverse proxy (ADR 0005). Off by default; the
|
||||
* reverse-proxy deployment from `docs/deployment.md` stays the recommended setup.
|
||||
*/
|
||||
@@ -76,11 +76,11 @@ data class NginxConfig(
|
||||
val httpsPort: Int = 8443,
|
||||
/** Host nginx proxies to; empty uses [serverName] (the container cannot reach `localhost`). */
|
||||
val upstreamHost: String = "",
|
||||
/** Name of the managed container; empty means `gittally-nginx-<repo-name>`. */
|
||||
/** Name of the managed container; empty means `werkator-nginx-<repo-name>`. */
|
||||
val containerName: String = "",
|
||||
/**
|
||||
* Directory for nginx config, certificates, and logs; empty means the platform
|
||||
* default `XDG_STATE_HOME` (or `~/.local/state`) + `/gittally/nginx/<repo-key>`.
|
||||
* default `XDG_STATE_HOME` (or `~/.local/state`) + `/werkator/nginx/<repo-key>`.
|
||||
*/
|
||||
val stateDir: String = "",
|
||||
/** E-mail for the Let's Encrypt account; empty registers without one. */
|
||||
@@ -96,7 +96,7 @@ data class GiteaConfig(
|
||||
val baseUrl: String = "",
|
||||
val owner: String = "",
|
||||
val repo: String = "",
|
||||
val statusContext: String = "GitTally",
|
||||
val statusContext: String = "werkator",
|
||||
)
|
||||
|
||||
data class ArtifactsConfig(
|
||||
@@ -117,7 +117,7 @@ data class ArtifactsConfig(
|
||||
val keepLatestGreen: Boolean = true,
|
||||
/**
|
||||
* Root directory for stored build artifacts; empty means the platform default
|
||||
* `XDG_STATE_HOME` (or `~/.local/state`) + `/gittally/artifacts/<repo-key>`.
|
||||
* `XDG_STATE_HOME` (or `~/.local/state`) + `/werkator/artifacts/<repo-key>`.
|
||||
*/
|
||||
val rootDir: String = "",
|
||||
)
|
||||
@@ -130,7 +130,7 @@ data class WatcherConfig(
|
||||
* Honor the `branches.<name>.requirePullRequest` gates. Set false for a plain git
|
||||
* origin without pull-request refs (no Gitea/GitHub) — gated branches then build
|
||||
* on new commits like any other branch. Typically overridden per machine in
|
||||
* `.git/gittally/.gittally.yml` when the committed config enables the gates.
|
||||
* `.git/werkator/.werkator.yml` when the committed config enables the gates.
|
||||
*/
|
||||
val pullRequestGate: Boolean = true,
|
||||
/**
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.git
|
||||
package de.hoennig.werkator.git
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.attribute.PosixFilePermissions
|
||||
@@ -15,10 +15,10 @@ object GitAskPass {
|
||||
#!/bin/sh
|
||||
case "${'$'}1" in
|
||||
*[Uu]sername*)
|
||||
printf '%s\n' "${'$'}GITTALLY_GIT_ACCOUNT"
|
||||
printf '%s\n' "${'$'}werkator_GIT_ACCOUNT"
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "${'$'}GITTALLY_GIT_TOKEN"
|
||||
printf '%s\n' "${'$'}werkator_GIT_TOKEN"
|
||||
;;
|
||||
esac
|
||||
""".trimIndent() + "\n"
|
||||
@@ -30,7 +30,7 @@ object GitAskPass {
|
||||
): T {
|
||||
val script =
|
||||
Files.createTempFile(
|
||||
"gittally-askpass",
|
||||
"werkator-askpass",
|
||||
".sh",
|
||||
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")),
|
||||
)
|
||||
@@ -40,8 +40,8 @@ object GitAskPass {
|
||||
mapOf(
|
||||
"GIT_ASKPASS" to script.toAbsolutePath().toString(),
|
||||
"GIT_TERMINAL_PROMPT" to "0",
|
||||
"GITTALLY_GIT_ACCOUNT" to account,
|
||||
"GITTALLY_GIT_TOKEN" to token,
|
||||
"werkator_GIT_ACCOUNT" to account,
|
||||
"werkator_GIT_TOKEN" to token,
|
||||
),
|
||||
)
|
||||
} finally {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.git
|
||||
package de.hoennig.werkator.git
|
||||
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Path
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.git
|
||||
package de.hoennig.werkator.git
|
||||
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Service
|
||||
import java.nio.file.Path
|
||||
@@ -260,7 +260,7 @@ class GitService(
|
||||
|
||||
/**
|
||||
* The content of [path] as committed in [commit], or null when that commit has no
|
||||
* such file — used to read a branch's committed `.gittally.yml` without a worktree.
|
||||
* such file — used to read a branch's committed `.werkator.yml` without a worktree.
|
||||
*/
|
||||
fun showFileAtCommit(
|
||||
commit: String,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package de.hoennig.gittally.gitea
|
||||
package de.hoennig.werkator.gitea
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.config.GitTallyConfig
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.config.WerkatorConfig
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.client.JdkClientHttpRequestFactory
|
||||
@@ -170,7 +170,7 @@ class GiteaClient(
|
||||
}
|
||||
}
|
||||
|
||||
private fun isEnabled(config: GitTallyConfig): Boolean =
|
||||
private fun isEnabled(config: WerkatorConfig): Boolean =
|
||||
config.gitea.baseUrl.isNotBlank() &&
|
||||
config.gitea.owner.isNotBlank() &&
|
||||
config.gitea.repo.isNotBlank() &&
|
||||
@@ -182,7 +182,7 @@ class GiteaClient(
|
||||
HttpClient.newBuilder().connectTimeout(REQUEST_TIMEOUT).build(),
|
||||
).apply { setReadTimeout(REQUEST_TIMEOUT) }
|
||||
|
||||
private fun restClient(config: GitTallyConfig): RestClient =
|
||||
private fun restClient(config: WerkatorConfig): RestClient =
|
||||
RestClient
|
||||
.builder()
|
||||
.requestFactory(requestFactory)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.gitea
|
||||
package de.hoennig.werkator.gitea
|
||||
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
|
||||
/**
|
||||
* Gitea commit-status state published for this build status.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.metrics
|
||||
package de.hoennig.werkator.metrics
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import java.time.Clock
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.metrics
|
||||
package de.hoennig.werkator.metrics
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.metrics
|
||||
package de.hoennig.werkator.metrics
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
@@ -30,7 +30,7 @@ data class PersistedMetricsState(
|
||||
* repository size every 60 seconds and keeps running min/max/avg per metric.
|
||||
* The aggregation state is persisted, so restarts continue the series.
|
||||
* Every source degrades gracefully: an unreadable source makes its metric null
|
||||
* (shown as `n/a`), never fails a sample. Like the [de.hoennig.gittally.watcher.Watcher],
|
||||
* (shown as `n/a`), never fails a sample. Like the [de.hoennig.werkator.watcher.Watcher],
|
||||
* nothing is scheduled until [start] is called (server mode only).
|
||||
*/
|
||||
class SystemMetricsCollector(
|
||||
@@ -83,7 +83,7 @@ class SystemMetricsCollector(
|
||||
scheduler =
|
||||
Executors
|
||||
.newSingleThreadScheduledExecutor { runnable ->
|
||||
Thread(runnable, "gittally-metrics").apply { isDaemon = true }
|
||||
Thread(runnable, "werkator-metrics").apply { isDaemon = true }
|
||||
}.also {
|
||||
it.scheduleWithFixedDelay(::sampleSafely, 0, SAMPLE_INTERVAL_SECONDS, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import java.time.Instant
|
||||
|
||||
/** JSON statuses are lowercase like the legacy TSV/HTML statuses. */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.core.io.FileSystemResource
|
||||
import org.springframework.core.io.Resource
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactKeys
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.ArtifactKeys
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.server.ResponseStatusException
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.build.BuildExecutor
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.config.BuildDefinition
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.BuildExecutor
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.config.BuildDefinition
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.DeleteMapping
|
||||
@@ -192,7 +192,7 @@ class BuildsApiController(
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TOKEN_HEADER = "X-GitTally-Token"
|
||||
const val TOKEN_HEADER = "X-werkator-Token"
|
||||
private const val MAX_LOG_CHUNK = 1024L * 1024L
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.SecretFiles
|
||||
import de.hoennig.werkator.SecretFiles
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.security.MessageDigest
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
/**
|
||||
* Generates the nginx configuration for the managed proxy container, ported from
|
||||
@@ -12,7 +12,7 @@ object NginxConfigFiles {
|
||||
* The `nginx.conf` content. Without [full] it is the init config for the
|
||||
* two-phase startup: HTTP only, serving the ACME webroot challenge and
|
||||
* redirecting everything else to HTTPS. With [full] an HTTPS server block
|
||||
* with the Let's Encrypt certificate and the proxy to GitTally is added.
|
||||
* with the Let's Encrypt certificate and the proxy to werkator is added.
|
||||
*/
|
||||
fun nginxConf(
|
||||
serverName: String,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactKeys
|
||||
import de.hoennig.gittally.build.DockerBuildRunner.Companion.GITTALLY_LABEL
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.git.GitCommandRunner
|
||||
import de.hoennig.werkator.build.ArtifactKeys
|
||||
import de.hoennig.werkator.build.DockerBuildRunner.Companion.werkator_LABEL
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.git.GitCommandRunner
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
import java.nio.file.Files
|
||||
@@ -11,10 +11,10 @@ import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* Manages the opt-in nginx+certbot Docker container that serves GitTally over
|
||||
* Manages the opt-in nginx+certbot Docker container that serves werkator over
|
||||
* HTTPS on hosts without a reverse proxy (ADR 0005), ported from the legacy
|
||||
* `start_artifact_nginx` subsystem. Shells out to the `docker` CLI via the
|
||||
* generic [GitCommandRunner] process wrapper, like [de.hoennig.gittally.build.DockerBuildRunner].
|
||||
* generic [GitCommandRunner] process wrapper, like [de.hoennig.werkator.build.DockerBuildRunner].
|
||||
*
|
||||
* Startup is two-phase: an HTTP-only init config serves the ACME webroot
|
||||
* challenge, the certificate is obtained via a certbot container, then nginx is
|
||||
@@ -197,7 +197,7 @@ class NginxProxyManager(
|
||||
/**
|
||||
* Legacy `cleanup_stale_artifact_nginx_containers`: remove the container by
|
||||
* name, all nginx-role containers of this repository by label, and any
|
||||
* GitTally container still occupying the configured ports.
|
||||
* werkator container still occupying the configured ports.
|
||||
*/
|
||||
private fun cleanupStaleContainers(settings: NginxSettings) {
|
||||
commandRunner.run(listOf("docker", "rm", "-f", settings.containerName), workingDir)
|
||||
@@ -208,11 +208,11 @@ class NginxProxyManager(
|
||||
"ps",
|
||||
"-aq",
|
||||
"--filter",
|
||||
"label=$GITTALLY_LABEL=true",
|
||||
"label=$werkator_LABEL=true",
|
||||
"--filter",
|
||||
"label=$GITTALLY_LABEL.repository=${settings.repoKey}",
|
||||
"label=$werkator_LABEL.repository=${settings.repoKey}",
|
||||
"--filter",
|
||||
"label=$GITTALLY_LABEL.role=nginx",
|
||||
"label=$werkator_LABEL.role=nginx",
|
||||
),
|
||||
workingDir,
|
||||
)
|
||||
@@ -220,11 +220,11 @@ class NginxProxyManager(
|
||||
commandRunner.run(listOf("docker", "rm", "-f") + labelled.lines(), workingDir)
|
||||
}
|
||||
for (container in listContainersUsingPorts(settings)) {
|
||||
if (container.labels.contains("$GITTALLY_LABEL=true") ||
|
||||
container.name.startsWith("gittally-") ||
|
||||
if (container.labels.contains("$werkator_LABEL=true") ||
|
||||
container.name.startsWith("werkator-") ||
|
||||
container.name.startsWith("git-watch-origin-and-test-nginx-")
|
||||
) {
|
||||
log.info("removing stale GitTally container using an nginx port: {}", container.name)
|
||||
log.info("removing stale werkator container using an nginx port: {}", container.name)
|
||||
commandRunner.run(listOf("docker", "rm", "-f", container.id), workingDir)
|
||||
}
|
||||
}
|
||||
@@ -303,11 +303,11 @@ class NginxProxyManager(
|
||||
"--volume",
|
||||
"${settings.nginxConf}:/etc/nginx/nginx.conf:ro",
|
||||
"--label",
|
||||
"$GITTALLY_LABEL=true",
|
||||
"$werkator_LABEL=true",
|
||||
"--label",
|
||||
"$GITTALLY_LABEL.repository=${settings.repoKey}",
|
||||
"$werkator_LABEL.repository=${settings.repoKey}",
|
||||
"--label",
|
||||
"$GITTALLY_LABEL.role=nginx",
|
||||
"$werkator_LABEL.role=nginx",
|
||||
"nginx",
|
||||
)
|
||||
|
||||
@@ -405,16 +405,16 @@ class NginxProxyManager(
|
||||
System.getenv("XDG_STATE_HOME")?.takeIf { it.isNotBlank() }?.let { Paths.get(it) }
|
||||
?: Paths.get(System.getProperty("user.home"), ".local", "state")
|
||||
return stateHome
|
||||
.resolve("gittally")
|
||||
.resolve("werkator")
|
||||
.resolve("nginx")
|
||||
.resolve(ArtifactKeys.repoKey(repoDir))
|
||||
.toAbsolutePath()
|
||||
.normalize()
|
||||
}
|
||||
|
||||
/** Legacy default `gittally-nginx-<repo-name>` with unsafe characters replaced. */
|
||||
/** Legacy default `werkator-nginx-<repo-name>` with unsafe characters replaced. */
|
||||
fun defaultContainerName(repoDir: Path): String =
|
||||
"gittally-nginx-" + repoDir.fileName.toString().replace(Regex("[^A-Za-z0-9_.-]"), "-")
|
||||
"werkator-nginx-" + repoDir.fileName.toString().replace(Regex("[^A-Za-z0-9_.-]"), "-")
|
||||
|
||||
/**
|
||||
* Certbot's pinned DH parameters (RFC 7919 ffdhe2048), bundled as a resource:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
@@ -12,5 +12,5 @@ class ServerConfiguration {
|
||||
* until the first guarded request, so the bean is safe outside a git repository.
|
||||
*/
|
||||
@Bean
|
||||
fun controlTokenService(): ControlTokenService = ControlTokenService(Paths.get(".git/gittally/control-token"))
|
||||
fun controlTokenService(): ControlTokenService = ControlTokenService(Paths.get(".git/werkator/control-token"))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.metrics.SystemMetricsCollector
|
||||
import de.hoennig.werkator.metrics.SystemMetricsCollector
|
||||
import jakarta.annotation.PreDestroy
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||
import org.springframework.context.annotation.Profile
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import jakarta.annotation.PreDestroy
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||
@@ -26,7 +26,7 @@ class ServerNginxLifecycle(
|
||||
/** Replaceable for tests: the scheduler running startup and renewal checks. */
|
||||
internal var schedulerFactory: () -> ScheduledExecutorService = {
|
||||
Executors.newSingleThreadScheduledExecutor { runnable ->
|
||||
Thread(runnable, "gittally-nginx").apply { isDaemon = true }
|
||||
Thread(runnable, "werkator-nginx").apply { isDaemon = true }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.watcher.Watcher
|
||||
import de.hoennig.werkator.watcher.Watcher
|
||||
import jakarta.annotation.PreDestroy
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||
import org.springframework.context.annotation.Profile
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.gitea.GiteaClient
|
||||
import de.hoennig.gittally.gitea.GiteaStatusResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.gitea.GiteaClient
|
||||
import de.hoennig.werkator.gitea.GiteaStatusResult
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.metrics.SystemMetrics
|
||||
import de.hoennig.gittally.metrics.SystemMetricsCollector
|
||||
import de.hoennig.werkator.metrics.SystemMetrics
|
||||
import de.hoennig.werkator.metrics.SystemMetricsCollector
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.build.BuildExecutor
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.gittally.metrics.SystemMetricsCollector
|
||||
import de.hoennig.gittally.watcher.Watcher
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.BuildExecutor
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import de.hoennig.werkator.metrics.SystemMetricsCollector
|
||||
import de.hoennig.werkator.watcher.Watcher
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.beans.factory.ObjectProvider
|
||||
import org.springframework.boot.info.BuildProperties
|
||||
@@ -28,7 +28,7 @@ import kotlin.streams.asSequence
|
||||
|
||||
/**
|
||||
* Server-rendered Thymeleaf views over the JSON API. The pages render the full
|
||||
* state server-side (usable without JavaScript); `gittally.js` then polls the
|
||||
* state server-side (usable without JavaScript); `werkator.js` then polls the
|
||||
* `/api/…` endpoints and re-renders the table bodies — pages are never re-fetched
|
||||
* and diffed like legacy, so the UI cannot get stuck on a loading animation.
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.config.GiteaConfig
|
||||
import de.hoennig.gittally.metrics.MetricAggregate
|
||||
import de.hoennig.gittally.metrics.SystemMetrics
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.config.GiteaConfig
|
||||
import de.hoennig.werkator.metrics.MetricAggregate
|
||||
import de.hoennig.werkator.metrics.SystemMetrics
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.time.Duration
|
||||
@@ -32,7 +32,7 @@ class GiteaWebLinks(
|
||||
.joinToString("/") { URLEncoder.encode(it, StandardCharsets.UTF_8).replace("+", "%20") }
|
||||
}
|
||||
|
||||
/** Display formatting shared by the server-rendered views; `gittally.js` renders the same formats. */
|
||||
/** Display formatting shared by the server-rendered views; `werkator.js` renders the same formats. */
|
||||
object UiFormats {
|
||||
private val timestampFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneId.systemDefault())
|
||||
|
||||
@@ -69,7 +69,7 @@ object UiFormats {
|
||||
/**
|
||||
* CSS class highlighting a critical utilization: `metric-warn` from 80% of [total],
|
||||
* `metric-crit` from 90%, empty below or when either value is unavailable.
|
||||
* `gittally.js` (`utilizationClass`) must apply the same thresholds.
|
||||
* `werkator.js` (`utilizationClass`) must apply the same thresholds.
|
||||
*/
|
||||
fun utilizationClass(
|
||||
used: Double?,
|
||||
@@ -176,7 +176,7 @@ data class LogFileView(
|
||||
val failed: Boolean,
|
||||
)
|
||||
|
||||
/** One card of the current-builds view; the live log is fetched by `gittally.js`. */
|
||||
/** One card of the current-builds view; the live log is fetched by `werkator.js`. */
|
||||
data class CurrentBuildView(
|
||||
val branch: String,
|
||||
/** The displayed build name; = [branch] unless a named auto-build slot triggered the build. */
|
||||
@@ -194,7 +194,7 @@ data class CurrentBuildView(
|
||||
|
||||
/**
|
||||
* One row of the system-metrics table. The [key] matches the JSON field of
|
||||
* `GET /api/system`, so `gittally.js` can update the cells in place.
|
||||
* `GET /api/system`, so `werkator.js` can update the cells in place.
|
||||
*/
|
||||
data class MetricRowView(
|
||||
val key: String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.server
|
||||
package de.hoennig.werkator.server
|
||||
|
||||
import de.hoennig.gittally.watcher.Watcher
|
||||
import de.hoennig.gittally.watcher.WatcherState
|
||||
import de.hoennig.werkator.watcher.Watcher
|
||||
import de.hoennig.werkator.watcher.WatcherState
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.watcher
|
||||
package de.hoennig.werkator.watcher
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
@@ -74,7 +74,7 @@ object AutoBuildSlots {
|
||||
|
||||
/**
|
||||
* Persists which auto-build slots already triggered as a JSON file,
|
||||
* e.g. `.git/gittally/auto-builds.json` (replaces the legacy `auto-builds.tsv`).
|
||||
* e.g. `.git/werkator/auto-builds.json` (replaces the legacy `auto-builds.tsv`).
|
||||
* Entries of past days are dropped on write, so the file never grows unbounded.
|
||||
*/
|
||||
class FileAutoBuildState(
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package de.hoennig.gittally.watcher
|
||||
package de.hoennig.werkator.watcher
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactKeys
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.build.BuildExecutor
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.build.GitWorktreeWorkspaces
|
||||
import de.hoennig.gittally.config.BuildDefinition
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.config.DurationParser
|
||||
import de.hoennig.gittally.config.GitTallyConfig
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.ArtifactKeys
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.BuildExecutor
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.build.GitWorktreeWorkspaces
|
||||
import de.hoennig.werkator.config.BuildDefinition
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.config.DurationParser
|
||||
import de.hoennig.werkator.config.WerkatorConfig
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Service
|
||||
import java.nio.file.Files
|
||||
@@ -80,7 +80,7 @@ class Watcher(
|
||||
scheduler =
|
||||
Executors
|
||||
.newSingleThreadScheduledExecutor { runnable ->
|
||||
Thread(runnable, "gittally-watcher").apply { isDaemon = true }
|
||||
Thread(runnable, "werkator-watcher").apply { isDaemon = true }
|
||||
}.also {
|
||||
it.scheduleWithFixedDelay({ pollSafely(workingDir) }, 0, interval.toMillis(), TimeUnit.MILLISECONDS)
|
||||
}
|
||||
@@ -207,7 +207,7 @@ class Watcher(
|
||||
}
|
||||
|
||||
private fun enqueueDueBranches(
|
||||
config: GitTallyConfig,
|
||||
config: WerkatorConfig,
|
||||
originBranches: Set<String>,
|
||||
workingDir: Path,
|
||||
) {
|
||||
@@ -238,7 +238,7 @@ class Watcher(
|
||||
|
||||
/**
|
||||
* The build definitions that apply to [branch]: the primary configuration with the
|
||||
* branch's own committed `.gittally.yml` merged on top (the pinned keys stripped),
|
||||
* branch's own committed `.werkator.yml` merged on top (the pinned keys stripped),
|
||||
* so a new `builds` configuration can be tried out on a branch without touching any
|
||||
* other branch's builds. A branch's definitions only ever apply to that branch —
|
||||
* their selectors are evaluated for it alone, so a definition committed on one branch
|
||||
@@ -254,7 +254,7 @@ class Watcher(
|
||||
branch: String,
|
||||
headCommit: String?,
|
||||
workingDir: Path,
|
||||
primary: GitTallyConfig,
|
||||
primary: WerkatorConfig,
|
||||
): Map<String, BuildDefinition> {
|
||||
val commit = headCommit ?: return primary.effectiveBuildDefinitions()
|
||||
branchDefinitions[branch]?.takeIf { it.commit == commit && it.primary == primary }?.let { return it.definitions }
|
||||
@@ -279,7 +279,7 @@ class Watcher(
|
||||
|
||||
private class CachedDefinitions(
|
||||
val commit: String,
|
||||
val primary: GitTallyConfig,
|
||||
val primary: WerkatorConfig,
|
||||
val definitions: Map<String, BuildDefinition>,
|
||||
)
|
||||
|
||||
@@ -304,7 +304,7 @@ class Watcher(
|
||||
private fun startBuildIfDue(
|
||||
branch: String,
|
||||
allowSameCommit: Boolean,
|
||||
config: GitTallyConfig,
|
||||
config: WerkatorConfig,
|
||||
pullRequestHeads: Lazy<Set<String>>,
|
||||
workingDir: Path,
|
||||
build: String = BuildDefinition.DEFAULT,
|
||||
@@ -335,7 +335,7 @@ class Watcher(
|
||||
* the point of a scheduled build.
|
||||
*/
|
||||
private fun enqueueScheduledBuilds(
|
||||
config: GitTallyConfig,
|
||||
config: WerkatorConfig,
|
||||
originBranches: Set<String>,
|
||||
heads: Map<String, String>,
|
||||
pullRequestHeads: Lazy<Set<String>>,
|
||||
@@ -373,7 +373,7 @@ class Watcher(
|
||||
* `builds` entry with `atTimes` and a single-branch selector would do.
|
||||
*/
|
||||
private fun enqueueDeprecatedAutoBuilds(
|
||||
config: GitTallyConfig,
|
||||
config: WerkatorConfig,
|
||||
originBranches: Set<String>,
|
||||
pullRequestHeads: Lazy<Set<String>>,
|
||||
workingDir: Path,
|
||||
@@ -413,7 +413,7 @@ class Watcher(
|
||||
|
||||
/** Results first, then artifacts of dropped results, then worktrees of branches gone from origin. */
|
||||
private fun prune(
|
||||
config: GitTallyConfig,
|
||||
config: WerkatorConfig,
|
||||
originBranches: List<String>,
|
||||
workingDir: Path,
|
||||
) {
|
||||
@@ -463,9 +463,9 @@ class Watcher(
|
||||
|
||||
companion object {
|
||||
/** Auto-build trigger state next to the build results (replaces legacy `auto-builds.tsv`). */
|
||||
const val AUTO_BUILDS_FILE = ".git/gittally/auto-builds.json"
|
||||
const val AUTO_BUILDS_FILE = ".git/werkator/auto-builds.json"
|
||||
|
||||
/** The committed config read per branch for its build definitions. */
|
||||
const val CONFIG_FILE = ".gittally.yml"
|
||||
const val CONFIG_FILE = ".werkator.yml"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.watcher
|
||||
package de.hoennig.werkator.watcher
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.watcher
|
||||
package de.hoennig.werkator.watcher
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
@@ -7,4 +7,4 @@ spring:
|
||||
|
||||
logging:
|
||||
level:
|
||||
de.hoennig.gittally: INFO
|
||||
de.hoennig.werkator: INFO
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="GitTally">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="werkator">
|
||||
<rect width="64" height="64" rx="14" fill="#155eef"/>
|
||||
<path d="M17 47V18m0 14h13c7 0 10-4 10-11" fill="none" stroke="#f9fafb" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="17" cy="18" r="5" fill="#DD4901"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 564 B |
@@ -1,4 +1,4 @@
|
||||
/* GitTally web UI — loosely ported from the legacy generated pages. */
|
||||
/* werkator web UI — loosely ported from the legacy generated pages. */
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// GitTally web UI — polls the JSON API and re-renders table bodies from data.
|
||||
// werkator web UI — polls the JSON API and re-renders table bodies from data.
|
||||
// Every fetch has a timeout and failures render an explicit error badge, so the
|
||||
// UI can never get stuck on a loading animation (the legacy defect).
|
||||
"use strict";
|
||||
@@ -97,13 +97,13 @@ function metaContent(name) {
|
||||
return element ? element.content : "";
|
||||
}
|
||||
|
||||
const giteaRepoUrl = metaContent("gittally-gitea-repo-url");
|
||||
const giteaRepoUrl = metaContent("werkator-gitea-repo-url");
|
||||
|
||||
// The control token is deliberately NOT embedded in the pages: reading them is
|
||||
// unauthenticated, so anyone could have read it out of the HTML. The operator
|
||||
// pastes it once per browser from `.git/gittally/control-token` on the server;
|
||||
// pastes it once per browser from `.git/werkator/control-token` on the server;
|
||||
// it is kept in localStorage and only ever sent as a request header.
|
||||
const CONTROL_TOKEN_KEY = "gittally.controlToken";
|
||||
const CONTROL_TOKEN_KEY = "werkator.controlToken";
|
||||
|
||||
function storedControlToken() {
|
||||
try {
|
||||
@@ -131,7 +131,7 @@ function forgetControlToken() {
|
||||
|
||||
function askForControlToken() {
|
||||
const answer = window.prompt(
|
||||
"Control token — the content of .git/gittally/control-token on the GitTally host:",
|
||||
"Control token — the content of .git/werkator/control-token on the werkator host:",
|
||||
"",
|
||||
);
|
||||
return answer ? answer.trim() : "";
|
||||
@@ -169,7 +169,7 @@ async function sendAction(url, method) {
|
||||
function sendWithToken(url, method, token) {
|
||||
return fetch(url, {
|
||||
method,
|
||||
headers: { "X-GitTally-Token": token },
|
||||
headers: { "X-werkator-Token": token },
|
||||
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,6 +76,6 @@
|
||||
</article>
|
||||
</main>
|
||||
<footer th:replace="~{fragments :: footer}"></footer>
|
||||
<script src="/gittally.js"></script>
|
||||
<script src="/werkator.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -78,6 +78,6 @@
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="~{fragments :: footer}"></footer>
|
||||
<script src="/gittally.js"></script>
|
||||
<script src="/werkator.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -35,6 +35,6 @@
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="~{fragments :: footer}"></footer>
|
||||
<script src="/gittally.js"></script>
|
||||
<script src="/werkator.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<head th:fragment="head(title)">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title th:text="${#strings.isEmpty(repoName)} ? ${title} + ' — GitTally' : ${title} + ' — ' + ${repoName} + ' — GitTally'">GitTally</title>
|
||||
<title th:text="${#strings.isEmpty(repoName)} ? ${title} + ' — werkator' : ${title} + ' — ' + ${repoName} + ' — werkator'">werkator</title>
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||||
<link rel="stylesheet" href="/gittally.css">
|
||||
<meta name="gittally-gitea-repo-url" th:content="${giteaRepoUrl}">
|
||||
<link rel="stylesheet" href="/werkator.css">
|
||||
<meta name="werkator-gitea-repo-url" th:content="${giteaRepoUrl}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
<button id="reload-button" class="reload-button" type="button" title="Reload view" aria-label="Reload view">⟳</button>
|
||||
</span>
|
||||
</div>
|
||||
<!-- Filled by gittally.js from /api/watcher: while the watcher cannot reach origin, every
|
||||
<!-- Filled by werkator.js from /api/watcher: while the watcher cannot reach origin, every
|
||||
row below is as old as its last successful poll, and a calm list would imply otherwise. -->
|
||||
<div id="watcher-banner" class="watcher-banner" role="status" hidden></div>
|
||||
</th:block>
|
||||
|
||||
<footer th:fragment="footer" class="site-footer">
|
||||
<strong><a href="/releases" title="Release notes"><em th:text="'GitTally v' + ${version}">GitTally</em></a></strong>
|
||||
<strong><a href="/releases" title="Release notes"><em th:text="'werkator v' + ${version}">werkator</em></a></strong>
|
||||
— © <a href="https://michael.hoennig.de" target="_blank" rel="noopener noreferrer">Michael Hönnig</a>, 2026
|
||||
<th:block th:unless="${#strings.isEmpty(impressumUrl)}">
|
||||
— <a th:href="${impressumUrl}" target="_blank" rel="noopener noreferrer">Impressum (Legal Disclosure)</a>
|
||||
|
||||
@@ -39,6 +39,6 @@
|
||||
</p>
|
||||
</main>
|
||||
<footer th:replace="~{fragments :: footer}"></footer>
|
||||
<script src="/gittally.js"></script>
|
||||
<script src="/werkator.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally
|
||||
package de.hoennig.werkator
|
||||
|
||||
import de.hoennig.gittally.commands.ConfigPrintCommand
|
||||
import de.hoennig.gittally.commands.InitCommand
|
||||
import de.hoennig.gittally.commands.ServerCommand
|
||||
import de.hoennig.werkator.commands.ConfigPrintCommand
|
||||
import de.hoennig.werkator.commands.InitCommand
|
||||
import de.hoennig.werkator.commands.ServerCommand
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
@@ -11,7 +11,7 @@ import org.springframework.boot.test.context.SpringBootTest
|
||||
@SpringBootTest
|
||||
class ApplicationContextTest : FunSpec() {
|
||||
@Autowired
|
||||
lateinit var rootCommand: GitTallyCommand
|
||||
lateinit var rootCommand: werkatorCommand
|
||||
|
||||
@Autowired
|
||||
lateinit var initCommand: InitCommand
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally
|
||||
package de.hoennig.werkator
|
||||
|
||||
import com.ninjasquad.springmockk.MockkBean
|
||||
import de.hoennig.gittally.metrics.SystemMetricsCollector
|
||||
import de.hoennig.gittally.watcher.Watcher
|
||||
import de.hoennig.werkator.metrics.SystemMetricsCollector
|
||||
import de.hoennig.werkator.watcher.Watcher
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.booleans.shouldBeTrue
|
||||
import io.mockk.verify
|
||||
|
||||
+9
-9
@@ -1,11 +1,11 @@
|
||||
package de.hoennig.gittally.artifacts
|
||||
package de.hoennig.werkator.artifacts
|
||||
|
||||
import de.hoennig.gittally.build.BranchWorkspaces
|
||||
import de.hoennig.gittally.build.BuildExecutor
|
||||
import de.hoennig.gittally.build.FileBuildResultRepository
|
||||
import de.hoennig.gittally.build.ProcessBuildRunner
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.gitea.GiteaClient
|
||||
import de.hoennig.werkator.build.BranchWorkspaces
|
||||
import de.hoennig.werkator.build.BuildExecutor
|
||||
import de.hoennig.werkator.build.FileBuildResultRepository
|
||||
import de.hoennig.werkator.build.ProcessBuildRunner
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.gitea.GiteaClient
|
||||
import io.kotest.assertions.nondeterministic.eventually
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
@@ -20,10 +20,10 @@ import kotlin.time.Duration.Companion.seconds
|
||||
class BuildExecutorArtifactIntegrationTest : FunSpec() {
|
||||
init {
|
||||
test("the executor persists a successful build's logs and reports through the real store") {
|
||||
val workingDir = Files.createTempDirectory("gittally-artifact-integration-test")
|
||||
val workingDir = Files.createTempDirectory("werkator-artifact-integration-test")
|
||||
val root = workingDir.resolve("artifact-root")
|
||||
Files.writeString(
|
||||
workingDir.resolve(".gittally.yml"),
|
||||
workingDir.resolve(".werkator.yml"),
|
||||
"""
|
||||
artifacts:
|
||||
rootDir: "$root"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.artifacts
|
||||
package de.hoennig.werkator.artifacts
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactKeys
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.werkator.build.ArtifactKeys
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.collections.shouldContainExactly
|
||||
@@ -22,13 +22,13 @@ class FileArtifactStoreTest : FunSpec() {
|
||||
private val startedAt = Instant.parse("2026-07-07T10:00:00Z")
|
||||
|
||||
private class Harness {
|
||||
val workingDir: Path = Files.createTempDirectory("gittally-store-test")
|
||||
val workingDir: Path = Files.createTempDirectory("werkator-store-test")
|
||||
val root: Path = workingDir.resolve("artifact-root")
|
||||
val store = FileArtifactStore(ConfigLoader(), workingDir)
|
||||
|
||||
init {
|
||||
Files.writeString(
|
||||
workingDir.resolve(".gittally.yml"),
|
||||
workingDir.resolve(".werkator.yml"),
|
||||
"""
|
||||
artifacts:
|
||||
rootDir: "$root"
|
||||
@@ -57,7 +57,7 @@ class FileArtifactStoreTest : FunSpec() {
|
||||
)
|
||||
|
||||
private fun stagingDir(): Path {
|
||||
val dir = Files.createTempDirectory("gittally-staging-test")
|
||||
val dir = Files.createTempDirectory("werkator-staging-test")
|
||||
Files.writeString(dir.resolve("build.stdout.log"), "out")
|
||||
Files.writeString(dir.resolve("build.stderr.log"), "err")
|
||||
Files.writeString(dir.resolve("build.log"), "live")
|
||||
@@ -133,8 +133,8 @@ class FileArtifactStoreTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("the artifact root defaults to XDG_STATE_HOME plus the repo key") {
|
||||
val workingDir = Files.createTempDirectory("gittally-store-test")
|
||||
val stateHome = Files.createTempDirectory("gittally-state-home-test")
|
||||
val workingDir = Files.createTempDirectory("werkator-store-test")
|
||||
val stateHome = Files.createTempDirectory("werkator-state-home-test")
|
||||
val store =
|
||||
FileArtifactStore(ConfigLoader(), workingDir) { name ->
|
||||
if (name == "XDG_STATE_HOME") stateHome.toString() else null
|
||||
@@ -145,7 +145,7 @@ class FileArtifactStoreTest : FunSpec() {
|
||||
|
||||
val expectedDir =
|
||||
stateHome
|
||||
.resolve("gittally/artifacts")
|
||||
.resolve("werkator/artifacts")
|
||||
.resolve(ArtifactKeys.repoKey(workingDir))
|
||||
.resolve("branches")
|
||||
.resolve(build.artifactKey)
|
||||
@@ -183,7 +183,7 @@ class FileArtifactStoreTest : FunSpec() {
|
||||
|
||||
test("prune deletes a symlink without touching its target outside the root") {
|
||||
val h = Harness()
|
||||
val outside = Files.createTempDirectory("gittally-outside-test")
|
||||
val outside = Files.createTempDirectory("werkator-outside-test")
|
||||
Files.writeString(outside.resolve("keep-me.txt"), "precious")
|
||||
Files.createDirectories(h.branchesDir())
|
||||
val link = h.branchesDir().resolve("evil-link")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.gitea.GiteaClient
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.gitea.GiteaClient
|
||||
import io.kotest.assertions.nondeterministic.eventually
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.booleans.shouldBeFalse
|
||||
@@ -33,7 +33,7 @@ class BuildExecutorTest : FunSpec() {
|
||||
workspaceSubdir: String? = null,
|
||||
val buildRunner: BuildRunner = ProcessBuildRunner(),
|
||||
) {
|
||||
val workingDir: Path = Files.createTempDirectory("gittally-executor-test")
|
||||
val workingDir: Path = Files.createTempDirectory("werkator-executor-test")
|
||||
val repository = FileBuildResultRepository(workingDir.resolve("build-results.json"))
|
||||
val giteaClient = mockk<GiteaClient>(relaxed = true)
|
||||
val artifactStore = mockk<ArtifactStore>(relaxed = true)
|
||||
@@ -65,7 +65,7 @@ class BuildExecutorTest : FunSpec() {
|
||||
)
|
||||
|
||||
init {
|
||||
Files.writeString(workingDir.resolve(".gittally.yml"), configYaml)
|
||||
Files.writeString(workingDir.resolve(".werkator.yml"), configYaml)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ class BuildExecutorTest : FunSpec() {
|
||||
workingDir: java.nio.file.Path,
|
||||
environment: Map<String, String>,
|
||||
repoDir: java.nio.file.Path,
|
||||
branchConfig: de.hoennig.gittally.config.BranchConfig,
|
||||
branchConfig: de.hoennig.werkator.config.BranchConfig,
|
||||
onAuxProcess: (Process) -> Unit,
|
||||
): Process {
|
||||
val aux = ProcessBuilder("bash", "-c", "sleep 60").directory(workingDir.toFile()).start()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BranchConfig
|
||||
import de.hoennig.gittally.config.DockerConfig
|
||||
import de.hoennig.werkator.config.BranchConfig
|
||||
import de.hoennig.werkator.config.DockerConfig
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.Called
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.BranchConfig
|
||||
import de.hoennig.gittally.config.DockerConfig
|
||||
import de.hoennig.gittally.git.GitCommandResult
|
||||
import de.hoennig.gittally.git.GitCommandRunner
|
||||
import de.hoennig.werkator.config.BranchConfig
|
||||
import de.hoennig.werkator.config.DockerConfig
|
||||
import de.hoennig.werkator.git.GitCommandResult
|
||||
import de.hoennig.werkator.git.GitCommandRunner
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.collections.shouldContain
|
||||
@@ -47,7 +47,7 @@ class DockerBuildRunnerTest : FunSpec() {
|
||||
beforeEach {
|
||||
clearMocks(commandRunner, socketLocator)
|
||||
captured.clear()
|
||||
repoDir = Files.createTempDirectory("gittally-docker-runner")
|
||||
repoDir = Files.createTempDirectory("werkator-docker-runner")
|
||||
workspace = repoDir.resolve("workspace")
|
||||
every { commandRunner.run(any(), any(), any(), any()) } returns GitCommandResult(0, "", "")
|
||||
every { commandRunner.runOrThrow(any(), any(), any(), any()) } returns GitCommandResult(0, "", "")
|
||||
@@ -77,19 +77,19 @@ class DockerBuildRunnerTest : FunSpec() {
|
||||
"--rm",
|
||||
"--init",
|
||||
"--name",
|
||||
"gittally-build-$repoKey-${ArtifactKeys.branchKey("main")}",
|
||||
"werkator-build-$repoKey-${ArtifactKeys.branchKey("main")}",
|
||||
"--label",
|
||||
"org.hoennig.gittally=true",
|
||||
"org.hoennig.werkator=true",
|
||||
"--label",
|
||||
"org.hoennig.gittally.repository=$repoKey",
|
||||
"org.hoennig.werkator.repository=$repoKey",
|
||||
"--label",
|
||||
"org.hoennig.gittally.role=build",
|
||||
"org.hoennig.werkator.role=build",
|
||||
"--workdir",
|
||||
"$workspace",
|
||||
"--volume",
|
||||
"$workspace:$workspace",
|
||||
"--volume",
|
||||
"gittally-gradle-$repoKey:/gradle-user-home",
|
||||
"werkator-gradle-$repoKey:/gradle-user-home",
|
||||
"--env",
|
||||
"HOME=/tmp/docker-home",
|
||||
"--env",
|
||||
@@ -150,11 +150,11 @@ class DockerBuildRunnerTest : FunSpec() {
|
||||
}
|
||||
}
|
||||
|
||||
test("exposes git metadata read-only with the gittally dir masked for a worktree workspace") {
|
||||
test("exposes git metadata read-only with the werkator dir masked for a worktree workspace") {
|
||||
val gitDir = repoDir.resolve(".git")
|
||||
val adminDir = gitDir.resolve("worktrees/workspace")
|
||||
Files.createDirectories(adminDir)
|
||||
Files.createDirectories(gitDir.resolve("gittally"))
|
||||
Files.createDirectories(gitDir.resolve("werkator"))
|
||||
Files.createDirectories(workspace)
|
||||
Files.writeString(workspace.resolve(".git"), "gitdir: $adminDir\n")
|
||||
|
||||
@@ -162,7 +162,7 @@ class DockerBuildRunnerTest : FunSpec() {
|
||||
|
||||
val args = captured.single()
|
||||
args shouldContain "$gitDir:$gitDir:ro"
|
||||
args[args.indexOf("--tmpfs") + 1] shouldBe "${gitDir.resolve("gittally")}"
|
||||
args[args.indexOf("--tmpfs") + 1] shouldBe "${gitDir.resolve("werkator")}"
|
||||
args shouldContain "$adminDir:$adminDir"
|
||||
}
|
||||
|
||||
@@ -209,13 +209,13 @@ class DockerBuildRunnerTest : FunSpec() {
|
||||
"docker",
|
||||
"build",
|
||||
"--label",
|
||||
"org.gittally.dockerfile=Dockerfile",
|
||||
"org.werkator.dockerfile=Dockerfile",
|
||||
"--label",
|
||||
"org.gittally.dockerfile-sha256=$dockerfileHash",
|
||||
"org.werkator.dockerfile-sha256=$dockerfileHash",
|
||||
"--label",
|
||||
"org.gittally.build-context=.",
|
||||
"org.werkator.build-context=.",
|
||||
"--label",
|
||||
"org.gittally.build-inputs-sha256=$inputsHash",
|
||||
"org.werkator.build-inputs-sha256=$inputsHash",
|
||||
"-t",
|
||||
"build-env:latest",
|
||||
"-f",
|
||||
@@ -251,11 +251,11 @@ class DockerBuildRunnerTest : FunSpec() {
|
||||
|
||||
val repoKey = ArtifactKeys.repoKey(repoDir)
|
||||
verify(exactly = 1) {
|
||||
commandRunner.runOrThrow(listOf("docker", "volume", "create", "gittally-gradle-$repoKey"), repoDir, any(), any())
|
||||
commandRunner.runOrThrow(listOf("docker", "volume", "create", "werkator-gradle-$repoKey"), repoDir, any(), any())
|
||||
}
|
||||
verify(exactly = 2) {
|
||||
commandRunner.run(
|
||||
listOf("docker", "rm", "-f", "gittally-build-$repoKey-${ArtifactKeys.branchKey("main")}"),
|
||||
listOf("docker", "rm", "-f", "werkator-build-$repoKey-${ArtifactKeys.branchKey("main")}"),
|
||||
repoDir,
|
||||
any(),
|
||||
any(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -9,7 +9,7 @@ import java.nio.file.Files
|
||||
class DockerImageInputsTest : FunSpec() {
|
||||
init {
|
||||
test("dockerfileSha256 is a stable hex checksum of the file contents") {
|
||||
val dir = Files.createTempDirectory("gittally-docker-inputs")
|
||||
val dir = Files.createTempDirectory("werkator-docker-inputs")
|
||||
val dockerfile = dir.resolve("Dockerfile")
|
||||
Files.writeString(dockerfile, "FROM eclipse-temurin:21\n")
|
||||
|
||||
@@ -20,7 +20,7 @@ class DockerImageInputsTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("inputs checksum changes when the Dockerfile contents change") {
|
||||
val dir = Files.createTempDirectory("gittally-docker-inputs")
|
||||
val dir = Files.createTempDirectory("werkator-docker-inputs")
|
||||
val dockerfile = dir.resolve("Dockerfile")
|
||||
Files.writeString(dockerfile, "FROM eclipse-temurin:21\n")
|
||||
val before =
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.booleans.shouldBeFalse
|
||||
@@ -16,7 +16,7 @@ import java.time.Instant
|
||||
class FileBuildResultRepositoryTest : FunSpec() {
|
||||
private val baseTime = Instant.parse("2026-07-07T10:00:00Z")
|
||||
|
||||
private fun newFile(): Path = Files.createTempDirectory("gittally-results-test").resolve("build-results.json")
|
||||
private fun newFile(): Path = Files.createTempDirectory("werkator-results-test").resolve("build-results.json")
|
||||
|
||||
private fun result(
|
||||
branch: String = "main",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.git.GitCommandRunner
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.git.GitCommandRunner
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -20,16 +20,16 @@ class GitWorktreeWorkspacesTest : FunSpec() {
|
||||
// hermetic git: fixed identity, no user/system config (hooks, gpg signing, ...)
|
||||
private val gitEnvironment =
|
||||
mapOf(
|
||||
"GIT_AUTHOR_NAME" to "GitTally Test",
|
||||
"GIT_AUTHOR_NAME" to "werkator Test",
|
||||
"GIT_AUTHOR_EMAIL" to "test@example.com",
|
||||
"GIT_COMMITTER_NAME" to "GitTally Test",
|
||||
"GIT_COMMITTER_NAME" to "werkator Test",
|
||||
"GIT_COMMITTER_EMAIL" to "test@example.com",
|
||||
"GIT_CONFIG_GLOBAL" to "/dev/null",
|
||||
"GIT_CONFIG_SYSTEM" to "/dev/null",
|
||||
)
|
||||
|
||||
private inner class Fixture {
|
||||
val repo: Path = Files.createTempDirectory("gittally-workspaces-test").resolve("repo")
|
||||
val repo: Path = Files.createTempDirectory("werkator-workspaces-test").resolve("repo")
|
||||
|
||||
init {
|
||||
Files.createDirectories(repo)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.build
|
||||
package de.hoennig.werkator.build
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -9,7 +9,7 @@ import java.nio.file.Path
|
||||
class ProcessBuildRunnerTest : FunSpec() {
|
||||
private val runner = ProcessBuildRunner()
|
||||
|
||||
private fun tempDir(): Path = Files.createTempDirectory("gittally-runner-test")
|
||||
private fun tempDir(): Path = Files.createTempDirectory("werkator-runner-test")
|
||||
|
||||
init {
|
||||
test("propagates the exit code") {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.config.ConfigLoader
|
||||
import de.hoennig.gittally.config.GitConfig
|
||||
import de.hoennig.gittally.config.GitTallyConfig
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.config.GitConfig
|
||||
import de.hoennig.werkator.config.WerkatorConfig
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import io.kotest.matchers.string.shouldNotContain
|
||||
@@ -26,7 +26,7 @@ class ConfigPrintCommandTest : FunSpec() {
|
||||
clearMocks(configLoader)
|
||||
every { configLoader.toYaml(any()) } answers { yamlWriter.toYaml(firstArg()) }
|
||||
every { configLoader.loadRaw() } returns rawConfig
|
||||
every { configLoader.load() } returns GitTallyConfig(git = GitConfig(account = "ci-user", token = "s3cr3t-token"))
|
||||
every { configLoader.load() } returns WerkatorConfig(git = GitConfig(account = "ci-user", token = "s3cr3t-token"))
|
||||
command.full = false
|
||||
command.showSecrets = false
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.ArtifactStore
|
||||
import de.hoennig.gittally.build.BuildExecutor
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.build.RunningBuild
|
||||
import de.hoennig.werkator.build.ArtifactStore
|
||||
import de.hoennig.werkator.build.BuildExecutor
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.build.RunningBuild
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
@@ -55,7 +55,7 @@ class ConsoleBuildRunnerTest : FunSpec() {
|
||||
init {
|
||||
beforeEach {
|
||||
clearMocks(buildExecutor, repository, artifactStore)
|
||||
tempDir = Files.createTempDirectory("gittally-console-build-test")
|
||||
tempDir = Files.createTempDirectory("werkator-console-build-test")
|
||||
}
|
||||
|
||||
afterEach {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.file.shouldExist
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -17,7 +17,7 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
init {
|
||||
test("creates config files with auto-detected values") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -25,21 +25,21 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val projectConfig = tempDir.resolve(".gittally.yml")
|
||||
val projectConfig = tempDir.resolve(".werkator.yml")
|
||||
projectConfig.toFile().shouldExist()
|
||||
val projectContent = projectConfig.toFile().readText()
|
||||
projectContent shouldContain "baseUrl: https://git.example.org"
|
||||
projectContent shouldContain "owner: my-org"
|
||||
projectContent shouldContain "repo: my-repo"
|
||||
|
||||
val repoConfig = tempDir.resolve(".git/gittally/.gittally.yml")
|
||||
val repoConfig = tempDir.resolve(".git/werkator/.werkator.yml")
|
||||
repoConfig.toFile().shouldExist()
|
||||
val repoContent = repoConfig.toFile().readText()
|
||||
repoContent shouldContain "account: \"\"" // no user in https URL
|
||||
}
|
||||
|
||||
test("creates the secrets config and its directory readable only by the owner") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -47,13 +47,13 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val repoConfig = tempDir.resolve(".git/gittally/.gittally.yml")
|
||||
val repoConfig = tempDir.resolve(".git/werkator/.werkator.yml")
|
||||
PosixFilePermissions.toString(Files.getPosixFilePermissions(repoConfig)) shouldBe "rw-------"
|
||||
PosixFilePermissions.toString(Files.getPosixFilePermissions(repoConfig.parent)) shouldBe "rwx------"
|
||||
}
|
||||
|
||||
test("detects account from https url") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -61,13 +61,13 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val repoConfig = tempDir.resolve(".git/gittally/.gittally.yml")
|
||||
val repoConfig = tempDir.resolve(".git/werkator/.werkator.yml")
|
||||
val repoContent = repoConfig.toFile().readText()
|
||||
repoContent shouldContain "account: \"ci-user\""
|
||||
}
|
||||
|
||||
test("parses ssh url") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -75,7 +75,7 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val projectConfig = tempDir.resolve(".gittally.yml")
|
||||
val projectConfig = tempDir.resolve(".werkator.yml")
|
||||
val projectContent = projectConfig.toFile().readText()
|
||||
projectContent shouldContain "baseUrl: https://git.example.org" // fallback to https
|
||||
projectContent shouldContain "owner: my-org"
|
||||
@@ -83,10 +83,10 @@ class InitCommandTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("does not overwrite existing files") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
val projectConfig = tempDir.resolve(".gittally.yml")
|
||||
val projectConfig = tempDir.resolve(".werkator.yml")
|
||||
projectConfig.toFile().writeText("existing: content")
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -98,10 +98,10 @@ class InitCommandTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("--systemd generates unit and environment file with install instructions") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
initCommand.systemd = true
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/gittally.jar") }
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/werkator.jar") }
|
||||
initCommand.javaExecutableResolver = { Paths.get("/usr/bin/java") }
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -110,20 +110,20 @@ class InitCommandTest : FunSpec() {
|
||||
initCommand.run()
|
||||
|
||||
val unitName = SystemdServiceFiles.unitName(tempDir)
|
||||
val unitFile = tempDir.resolve(".git/gittally/$unitName")
|
||||
val unitFile = tempDir.resolve(".git/werkator/$unitName")
|
||||
unitFile.toFile().shouldExist()
|
||||
val unitContent = unitFile.toFile().readText()
|
||||
unitContent shouldContain "WorkingDirectory=$tempDir"
|
||||
unitContent shouldContain """ExecStart="/usr/bin/java" ${'$'}JAVA_OPTS -jar "/home/ci/bin/gittally.jar" server"""
|
||||
unitContent shouldContain """ExecStart="/usr/bin/java" ${'$'}JAVA_OPTS -jar "/home/ci/bin/werkator.jar" server"""
|
||||
|
||||
tempDir.resolve(".git/gittally/gittally.env").toFile().shouldExist()
|
||||
tempDir.resolve(".git/werkator/werkator.env").toFile().shouldExist()
|
||||
}
|
||||
|
||||
test("--systemd also generates the nightly Docker cleanup timer") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
initCommand.systemd = true
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/gittally.jar") }
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/werkator.jar") }
|
||||
initCommand.javaExecutableResolver = { Paths.get("/usr/bin/java") }
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
@@ -131,22 +131,22 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val pruneService = tempDir.resolve(".git/gittally/gittally-docker-prune.service")
|
||||
val pruneService = tempDir.resolve(".git/werkator/werkator-docker-prune.service")
|
||||
pruneService.toFile().shouldExist()
|
||||
pruneService.toFile().readText() shouldContain "docker system prune -af"
|
||||
val pruneTimer = tempDir.resolve(".git/gittally/gittally-docker-prune.timer")
|
||||
val pruneTimer = tempDir.resolve(".git/werkator/werkator-docker-prune.timer")
|
||||
pruneTimer.toFile().shouldExist()
|
||||
pruneTimer.toFile().readText() shouldContain "OnCalendar=*-*-* 02:00:00"
|
||||
}
|
||||
|
||||
test("--systemd keeps an existing environment file") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
initCommand.systemd = true
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/gittally.jar") }
|
||||
initCommand.jarPathResolver = { Paths.get("/home/ci/bin/werkator.jar") }
|
||||
initCommand.javaExecutableResolver = { Paths.get("/usr/bin/java") }
|
||||
|
||||
val envFile = tempDir.resolve(".git/gittally/gittally.env")
|
||||
val envFile = tempDir.resolve(".git/werkator/werkator.env")
|
||||
Files.createDirectories(envFile.parent)
|
||||
envFile.toFile().writeText("JAVA_OPTS=-Xmx1g\n")
|
||||
|
||||
@@ -159,7 +159,7 @@ class InitCommandTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("--systemd without a resolvable jar path generates no unit file") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
initCommand.systemd = true
|
||||
initCommand.jarPathResolver = { null }
|
||||
@@ -169,12 +169,12 @@ class InitCommandTest : FunSpec() {
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val unitFile = tempDir.resolve(".git/gittally/${SystemdServiceFiles.unitName(tempDir)}")
|
||||
val unitFile = tempDir.resolve(".git/werkator/${SystemdServiceFiles.unitName(tempDir)}")
|
||||
unitFile.toFile().exists() shouldBe false
|
||||
}
|
||||
|
||||
test("reproduces path root mismatch issue") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test").toAbsolutePath().normalize()
|
||||
val tempDir = Files.createTempDirectory("werkator-init-test").toAbsolutePath().normalize()
|
||||
initCommand.workingDir = Paths.get(".") // Set to relative path as in real app
|
||||
|
||||
// We need to mock getTopLevel to return the absolute path
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.gittally.git.GitService
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import de.hoennig.gittally.build.BuildResult
|
||||
import de.hoennig.gittally.build.BuildResultRepository
|
||||
import de.hoennig.gittally.build.BuildStatus
|
||||
import de.hoennig.werkator.build.BuildResult
|
||||
import de.hoennig.werkator.build.BuildResultRepository
|
||||
import de.hoennig.werkator.build.BuildStatus
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.commands
|
||||
package de.hoennig.werkator.commands
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -9,8 +9,8 @@ import java.nio.file.Paths
|
||||
class SystemdServiceFilesTest : FunSpec() {
|
||||
init {
|
||||
test("unit name is derived from the sanitized repository directory name") {
|
||||
SystemdServiceFiles.unitName(Paths.get("/srv/repos/my-repo")) shouldBe "gittally-my-repo.service"
|
||||
SystemdServiceFiles.unitName(Paths.get("/srv/repos/my repo!")) shouldBe "gittally-my-repo-.service"
|
||||
SystemdServiceFiles.unitName(Paths.get("/srv/repos/my-repo")) shouldBe "werkator-my-repo.service"
|
||||
SystemdServiceFiles.unitName(Paths.get("/srv/repos/my repo!")) shouldBe "werkator-my-repo-.service"
|
||||
}
|
||||
|
||||
test("unit file runs the server jar in the repository with restart and environment file") {
|
||||
@@ -18,16 +18,16 @@ class SystemdServiceFilesTest : FunSpec() {
|
||||
SystemdServiceFiles.unitFileContent(
|
||||
repoRoot = Paths.get("/srv/repos/my-repo"),
|
||||
javaExecutable = Paths.get("/usr/lib/jvm/java-21/bin/java"),
|
||||
jarPath = Paths.get("/home/ci/bin/gittally.jar"),
|
||||
envFile = Paths.get("/srv/repos/my-repo/.git/gittally/gittally.env"),
|
||||
jarPath = Paths.get("/home/ci/bin/werkator.jar"),
|
||||
envFile = Paths.get("/srv/repos/my-repo/.git/werkator/werkator.env"),
|
||||
)
|
||||
|
||||
content shouldContain "Description=GitTally CI for my-repo"
|
||||
content shouldContain "Description=werkator CI for my-repo"
|
||||
content shouldContain "After=network-online.target docker.service"
|
||||
content shouldContain "WorkingDirectory=/srv/repos/my-repo"
|
||||
content shouldContain "EnvironmentFile=-/srv/repos/my-repo/.git/gittally/gittally.env"
|
||||
content shouldContain "EnvironmentFile=-/srv/repos/my-repo/.git/werkator/werkator.env"
|
||||
content shouldContain
|
||||
"""ExecStart="/usr/lib/jvm/java-21/bin/java" ${'$'}JAVA_OPTS -jar "/home/ci/bin/gittally.jar" server"""
|
||||
"""ExecStart="/usr/lib/jvm/java-21/bin/java" ${'$'}JAVA_OPTS -jar "/home/ci/bin/werkator.jar" server"""
|
||||
content shouldContain "Restart=always"
|
||||
content shouldContain "RestartSec=30"
|
||||
content shouldContain "WantedBy=default.target"
|
||||
@@ -38,13 +38,13 @@ class SystemdServiceFilesTest : FunSpec() {
|
||||
SystemdServiceFiles.unitFileContent(
|
||||
repoRoot = Paths.get("/srv/100%-repo"),
|
||||
javaExecutable = Paths.get("/usr/bin/java"),
|
||||
jarPath = Paths.get("/srv/100%-repo/gittally.jar"),
|
||||
envFile = Paths.get("/srv/100%-repo/gittally.env"),
|
||||
jarPath = Paths.get("/srv/100%-repo/werkator.jar"),
|
||||
envFile = Paths.get("/srv/100%-repo/werkator.env"),
|
||||
)
|
||||
|
||||
content shouldContain "WorkingDirectory=/srv/100%%-repo"
|
||||
content shouldContain "EnvironmentFile=-/srv/100%%-repo/gittally.env"
|
||||
content shouldContain """-jar "/srv/100%%-repo/gittally.jar" server"""
|
||||
content shouldContain "EnvironmentFile=-/srv/100%%-repo/werkator.env"
|
||||
content shouldContain """-jar "/srv/100%%-repo/werkator.jar" server"""
|
||||
}
|
||||
|
||||
test("prune service cleans containers and images but never volumes") {
|
||||
@@ -69,7 +69,7 @@ class SystemdServiceFilesTest : FunSpec() {
|
||||
val content = SystemdServiceFiles.envFileContent()
|
||||
|
||||
content shouldContain "#JAVA_OPTS="
|
||||
content shouldContain ".gittally.yml"
|
||||
content shouldContain ".werkator.yml"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
@@ -18,7 +18,7 @@ import java.util.Properties
|
||||
class ConfigLoaderTest : FunSpec() {
|
||||
private val loader = ConfigLoader()
|
||||
|
||||
/** A loader that knows which GitTally it is, for the `gitTally.version` checks. */
|
||||
/** A loader that knows which werkator it is, for the `werkator.version` checks. */
|
||||
private fun loaderRunning(version: String): ConfigLoader {
|
||||
val provider = mockk<ObjectProvider<BuildProperties>>()
|
||||
every { provider.getIfAvailable() } returns BuildProperties(Properties().apply { setProperty("version", version) })
|
||||
@@ -27,18 +27,18 @@ class ConfigLoaderTest : FunSpec() {
|
||||
|
||||
init {
|
||||
test("returns defaults when no config files exist") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
loader.load(dir) shouldBe GitTallyConfig()
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
loader.load(dir) shouldBe WerkatorConfig()
|
||||
}
|
||||
|
||||
test("loadRaw returns empty map when no config files exist") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
loader.loadRaw(dir).shouldBeEmpty()
|
||||
}
|
||||
|
||||
test("reads gitea config from .gittally.yml") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
test("reads gitea config from .werkator.yml") {
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitea:
|
||||
owner: my-org
|
||||
@@ -51,10 +51,10 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("reads executor.maxConcurrent and defaults it to 1") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
loader.load(dir).executor.maxConcurrent shouldBe 1
|
||||
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
executor:
|
||||
maxConcurrent: 3
|
||||
@@ -64,8 +64,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("the builds section holds named build definitions") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
executor:
|
||||
maxConcurrent: 2
|
||||
@@ -100,8 +100,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("an explicit builds.default entry overrides the implicit default build") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
@@ -113,11 +113,11 @@ class ConfigLoaderTest : FunSpec() {
|
||||
loader.load(dir).effectiveBuildDefinitions()["default"] shouldBe BuildDefinition(trigger = TriggerConfig(onPush = false))
|
||||
}
|
||||
|
||||
test("a config that needs a newer GitTally is refused, naming the file and both versions") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
test("a config that needs a newer werkator is refused, naming the file and both versions") {
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitTally:
|
||||
werkator:
|
||||
version:
|
||||
since: "0.9.16"
|
||||
""".trimIndent(),
|
||||
@@ -126,7 +126,7 @@ class ConfigLoaderTest : FunSpec() {
|
||||
val error = shouldThrow<ConfigVersionException> { loaderRunning("0.9.15").load(dir) }
|
||||
|
||||
error.message.shouldNotBeNull().let {
|
||||
it shouldContain ".gittally.yml"
|
||||
it shouldContain ".werkator.yml"
|
||||
it shouldContain "0.9.16"
|
||||
it shouldContain "0.9.15"
|
||||
it shouldContain "roll back"
|
||||
@@ -134,10 +134,10 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("a config within its declared range loads, and exceeding only the ceiling still loads") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitTally:
|
||||
werkator:
|
||||
version:
|
||||
since: "0.9.16"
|
||||
below: "1.0"
|
||||
@@ -149,20 +149,20 @@ class ConfigLoaderTest : FunSpec() {
|
||||
loaderRunning("0.9.16").load(dir).gitea.owner shouldBe "my-org"
|
||||
// beyond `below`: a warning, never a refusal — an unmaintained marker must not stop a CI
|
||||
loaderRunning("1.4.0").load(dir).gitea.owner shouldBe "my-org"
|
||||
loaderRunning("0.9.16").load(dir).gitTally.version shouldBe
|
||||
loaderRunning("0.9.16").load(dir).werkator.version shouldBe
|
||||
VersionRequirement(since = "0.9.16", below = "1.0")
|
||||
}
|
||||
|
||||
test("an incompatible branch config is refused as the branch's problem, not the server's") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText("gitea:\n owner: my-org")
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText("gitea:\n owner: my-org")
|
||||
|
||||
val error =
|
||||
shouldThrow<ConfigVersionException> {
|
||||
loaderRunning("0.9.15").loadWithBranchLayer(
|
||||
dir,
|
||||
"""
|
||||
gitTally:
|
||||
werkator:
|
||||
version:
|
||||
since: "2.0.0"
|
||||
""".trimIndent(),
|
||||
@@ -178,11 +178,11 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("the machine config is checked as its own file") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".git/gittally").toFile().mkdirs()
|
||||
dir.resolve(".git/gittally/.gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".git/werkator").toFile().mkdirs()
|
||||
dir.resolve(".git/werkator/.werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitTally:
|
||||
werkator:
|
||||
version:
|
||||
since: "1.0.0"
|
||||
""".trimIndent(),
|
||||
@@ -190,12 +190,12 @@ class ConfigLoaderTest : FunSpec() {
|
||||
|
||||
shouldThrow<ConfigVersionException> {
|
||||
loaderRunning("0.9.16").load(dir)
|
||||
}.message.shouldNotBeNull() shouldContain ".git/gittally/.gittally.yml"
|
||||
}.message.shouldNotBeNull() shouldContain ".git/werkator/.werkator.yml"
|
||||
}
|
||||
|
||||
test("a leftover builds.maxConcurrent is ignored instead of failing the config") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
maxConcurrent: 1
|
||||
@@ -211,8 +211,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("a branch may redefine the builds section for its own builds") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
pitest:
|
||||
@@ -221,8 +221,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
buildCommand: ./gradlew piTestPartial
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-test-worktree")
|
||||
worktree.resolve(".gittally.yml").toFile().writeText(
|
||||
val worktree = Files.createTempDirectory("werkator-test-worktree")
|
||||
worktree.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
pitest:
|
||||
@@ -246,21 +246,21 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("a branch cannot raise the concurrency limit or reach the sandbox policy through a build definition") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
requirePullRequest: true
|
||||
statusContext: GitTally
|
||||
statusContext: werkator
|
||||
docker:
|
||||
enabled: true
|
||||
network: none
|
||||
image: host-image
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-test-worktree")
|
||||
worktree.resolve(".gittally.yml").toFile().writeText(
|
||||
val worktree = Files.createTempDirectory("werkator-test-worktree")
|
||||
worktree.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
executor:
|
||||
maxConcurrent: 99
|
||||
@@ -269,7 +269,7 @@ class ConfigLoaderTest : FunSpec() {
|
||||
builds:
|
||||
default:
|
||||
requirePullRequest: false
|
||||
statusContext: GitTally/impersonated
|
||||
statusContext: werkator/impersonated
|
||||
docker:
|
||||
enabled: false
|
||||
network: host
|
||||
@@ -285,14 +285,14 @@ class ConfigLoaderTest : FunSpec() {
|
||||
settings.requirePullRequest shouldBe true
|
||||
settings.docker.enabled shouldBe true
|
||||
settings.docker.network shouldBe "none"
|
||||
settings.statusContext shouldBe "GitTally"
|
||||
settings.statusContext shouldBe "werkator"
|
||||
// everything that describes the build itself stays the branch's own business
|
||||
settings.docker.image shouldBe "attacker-image"
|
||||
}
|
||||
|
||||
test("a build the branch invents inherits the host's sandbox policy") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
@@ -302,8 +302,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
network: none
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-test-worktree")
|
||||
worktree.resolve(".gittally.yml").toFile().writeText(
|
||||
val worktree = Files.createTempDirectory("werkator-test-worktree")
|
||||
worktree.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
invented:
|
||||
@@ -327,8 +327,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("an exclusion pattern takes a branch out of a build that would otherwise select it") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
@@ -374,8 +374,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("a trigger key written outside the trigger block is refused, naming the definition") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
nightly:
|
||||
@@ -388,14 +388,14 @@ class ConfigLoaderTest : FunSpec() {
|
||||
// stops running is worse than a configuration that refuses to load
|
||||
val thrown = shouldThrow<ConfigFormatException> { loader.load(dir) }
|
||||
|
||||
thrown.message.shouldContain(".gittally.yml")
|
||||
thrown.message.shouldContain(".werkator.yml")
|
||||
thrown.message.shouldContain("builds.nightly: atTimes")
|
||||
thrown.message.shouldContain("trigger:")
|
||||
}
|
||||
|
||||
test("a branch writing its trigger flat fails only its own builds") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
@@ -424,8 +424,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("builds.default is the base of every other build, but never its trigger") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
builds:
|
||||
default:
|
||||
@@ -455,7 +455,7 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("branches is honored while no build is defined and ignored as soon as one is") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
val legacy =
|
||||
"""
|
||||
branches:
|
||||
@@ -464,14 +464,14 @@ class ConfigLoaderTest : FunSpec() {
|
||||
docker:
|
||||
enabled: true
|
||||
""".trimIndent()
|
||||
dir.resolve(".gittally.yml").toFile().writeText(legacy)
|
||||
dir.resolve(".werkator.yml").toFile().writeText(legacy)
|
||||
|
||||
// the leftover execution key is not a definition, so the legacy section still wins
|
||||
loader.load(dir).buildSettings("main", "default").buildCommand shouldBe "from-branches"
|
||||
dir.resolve(".gittally.yml").toFile().writeText("builds:\n maxConcurrent: 1\n" + legacy)
|
||||
dir.resolve(".werkator.yml").toFile().writeText("builds:\n maxConcurrent: 1\n" + legacy)
|
||||
loader.load(dir).buildSettings("main", "default").buildCommand shouldBe "from-branches"
|
||||
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
legacy +
|
||||
"\n" +
|
||||
"""
|
||||
@@ -487,8 +487,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("repo install config overrides project config for same keys") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitea:
|
||||
owner: original-org
|
||||
@@ -496,8 +496,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
token: from-project
|
||||
""".trimIndent(),
|
||||
)
|
||||
dir.resolve(".git/gittally").toFile().mkdirs()
|
||||
dir.resolve(".git/gittally/.gittally.yml").toFile().writeText(
|
||||
dir.resolve(".git/werkator").toFile().mkdirs()
|
||||
dir.resolve(".git/werkator/.werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitea:
|
||||
owner: override-org
|
||||
@@ -511,8 +511,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("loadRaw only returns explicitly set values") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
@@ -528,8 +528,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("branch-specific config inherits from branches.default") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
@@ -545,8 +545,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("branch-specific buildCommand overrides branches.default") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
@@ -560,8 +560,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("empty publicBaseUrl defaults to https://<nginx.serverName>/ when set") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
server:
|
||||
nginx:
|
||||
@@ -572,8 +572,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("explicit publicBaseUrl wins over the nginx.serverName default") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
server:
|
||||
publicBaseUrl: https://other.example.org/
|
||||
@@ -585,29 +585,29 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("publicBaseUrl stays empty without an nginx.serverName") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
loader.load(dir).server.publicBaseUrl shouldBe ""
|
||||
}
|
||||
|
||||
test("loadForWorktree lets the worktree override build config (worktree > .git > project)") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
buildCommand: from-project
|
||||
""".trimIndent(),
|
||||
)
|
||||
dir.resolve(".git/gittally").toFile().mkdirs()
|
||||
dir.resolve(".git/gittally/.gittally.yml").toFile().writeText(
|
||||
dir.resolve(".git/werkator").toFile().mkdirs()
|
||||
dir.resolve(".git/werkator/.werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
buildCommand: from-git
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-worktree")
|
||||
worktree.resolve(".gittally.yml").toFile().writeText(
|
||||
val worktree = Files.createTempDirectory("werkator-worktree")
|
||||
worktree.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
@@ -618,30 +618,30 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("loadForWorktree falls back to .git over project when the worktree sets nothing") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
buildCommand: from-project
|
||||
""".trimIndent(),
|
||||
)
|
||||
dir.resolve(".git/gittally").toFile().mkdirs()
|
||||
dir.resolve(".git/gittally/.gittally.yml").toFile().writeText(
|
||||
dir.resolve(".git/werkator").toFile().mkdirs()
|
||||
dir.resolve(".git/werkator/.werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
buildCommand: from-git
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-worktree")
|
||||
val worktree = Files.createTempDirectory("werkator-worktree")
|
||||
loader.loadForWorktree(dir, worktree).branches["default"]!!.buildCommand shouldBe "from-git"
|
||||
}
|
||||
|
||||
test("loadForWorktree pins secrets and the docker sandbox policy to .git, but allows docker.image") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".git/gittally").toFile().mkdirs()
|
||||
dir.resolve(".git/gittally/.gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".git/werkator").toFile().mkdirs()
|
||||
dir.resolve(".git/werkator/.werkator.yml").toFile().writeText(
|
||||
"""
|
||||
git:
|
||||
token: real-secret
|
||||
@@ -655,8 +655,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
image: trusted-image
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-worktree")
|
||||
worktree.resolve(".gittally.yml").toFile().writeText(
|
||||
val worktree = Files.createTempDirectory("werkator-worktree")
|
||||
worktree.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
git:
|
||||
token: stolen
|
||||
@@ -681,9 +681,9 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("loadWithBranchLayer applies a branch config read from git, pinning the same keys") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".git/gittally").toFile().mkdirs()
|
||||
dir.resolve(".git/gittally/.gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".git/werkator").toFile().mkdirs()
|
||||
dir.resolve(".git/werkator/.werkator.yml").toFile().writeText(
|
||||
"""
|
||||
git:
|
||||
token: real-secret
|
||||
@@ -717,8 +717,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("loadWithBranchLayer without a branch config equals load") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
branches:
|
||||
default:
|
||||
@@ -731,8 +731,8 @@ class ConfigLoaderTest : FunSpec() {
|
||||
}
|
||||
|
||||
test("loadForWorktree without a worktree config equals load") {
|
||||
val dir = Files.createTempDirectory("gittally-test")
|
||||
dir.resolve(".gittally.yml").toFile().writeText(
|
||||
val dir = Files.createTempDirectory("werkator-test")
|
||||
dir.resolve(".werkator.yml").toFile().writeText(
|
||||
"""
|
||||
gitea:
|
||||
owner: my-org
|
||||
@@ -741,12 +741,12 @@ class ConfigLoaderTest : FunSpec() {
|
||||
buildCommand: ./mvnw test
|
||||
""".trimIndent(),
|
||||
)
|
||||
val worktree = Files.createTempDirectory("gittally-worktree")
|
||||
val worktree = Files.createTempDirectory("werkator-worktree")
|
||||
loader.loadForWorktree(dir, worktree) shouldBe loader.load(dir)
|
||||
}
|
||||
|
||||
test("toYaml serializes GitTallyConfig with all sections") {
|
||||
val yaml = loader.toYaml(GitTallyConfig())
|
||||
test("toYaml serializes werkatorConfig with all sections") {
|
||||
val yaml = loader.toYaml(WerkatorConfig())
|
||||
yaml shouldContain "server:"
|
||||
yaml shouldContain "git:"
|
||||
yaml shouldContain "gitea:"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
@@ -14,7 +14,7 @@ class ConfigVersionsTest : FunSpec() {
|
||||
) = ConfigVersions.verdict(VersionRequirement(since = since, below = below), running)
|
||||
|
||||
init {
|
||||
test("a file needing a newer GitTally is refused, naming both versions") {
|
||||
test("a file needing a newer werkator is refused, naming both versions") {
|
||||
val result = verdict(since = "0.9.16", running = "0.9.15")
|
||||
|
||||
result
|
||||
@@ -45,7 +45,7 @@ class ConfigVersionsTest : FunSpec() {
|
||||
val description = "`builds:` is now `buildSpec:`"
|
||||
val written14 = VersionRequirement(since = "1.4.0")
|
||||
|
||||
// no ceiling declared, and none needed: GitTally knows its own breaking change
|
||||
// no ceiling declared, and none needed: werkator knows its own breaking change
|
||||
ConfigVersions
|
||||
.verdict(written14, "2.0.1", brokeIn, description)
|
||||
.shouldBeInstanceOf<VersionVerdict.Incompatible>()
|
||||
@@ -54,7 +54,7 @@ class ConfigVersionsTest : FunSpec() {
|
||||
it shouldContain "2.0.0"
|
||||
it shouldContain "buildSpec"
|
||||
}
|
||||
// a GitTally from before the change still reads that file
|
||||
// a werkator from before the change still reads that file
|
||||
ConfigVersions.verdict(written14, "1.9.0", brokeIn, description) shouldBe VersionVerdict.Compatible
|
||||
// and a file written after the change is fine on both sides of it
|
||||
ConfigVersions.verdict(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.config
|
||||
package de.hoennig.werkator.config
|
||||
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.framework
|
||||
package de.hoennig.werkator.framework
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.framework
|
||||
package de.hoennig.werkator.framework
|
||||
|
||||
import com.ninjasquad.springmockk.MockkBean
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.framework
|
||||
package de.hoennig.werkator.framework
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.hoennig.gittally.framework
|
||||
package de.hoennig.werkator.framework
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.aResponse
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user