Files
werkator/docs/bootstrapping.md
mhoennigandClaude Fable 5 5f1a669771 Step 23 session A: init --apply, the applied instance layer, control-token
'werkator init --apply FILE' installs a config-schema YAML fragment as
its own layer: validated strictly (an unknown key is refused loudly,
never ignored — a typo must not install a silent no-op), then copied
verbatim to .git/werkator/.werkator.applied.yml, above the project
config and below the hand-edited machine config, which always wins.
Deviation from the plan sketch, recorded there: a separate layer
instead of an in-place merge, because merging would re-serialize the
machine config — destroying its comments and rewriting the file that
holds the secrets; re-apply is a plain file replacement.

init --systemd now also generates werkator.htaccess beside the units
whenever a publicBaseUrl is configured — generated host integration for
the managed-webspace Apache, copied into the docroot by the wrapper.

New subcommand 'werkator control-token' prints (and lazily creates) the
token via ControlTokenService, so no wrapper needs its own generator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 18:46:31 +02:00

6.3 KiB

Werkator Bootstrapping

Bootstrapping prepares a git repository for use with werkator. It creates the config files described in configuration.md. With init --systemd it also generates a systemd user unit for running the server permanently, see deployment.md.

Run init once per repository, from within a checked-out working tree.

Prerequisites

  • Git repository with at least one commit
  • A remote named origin (used for auto-detection)
  • Java runtime available (JRE 21)

Running init

First, in <werkator-root>, build the application to generate the executable JAR file:

./gradlew build

Then run init using the generated JAR (not the -plain.jar):

java -jar <werkator-root>/build/libs/werkator.jar init

init performs the following steps in order:

1. Detect the Repository Root

Werkator resolves the repository root by running git rev-parse --show-toplevel. If the current directory is not inside a git repository, init exits with an error.

2. Auto-detect Gitea Connection from origin

If gitea.baseUrl, gitea.owner, and gitea.repo are already set in .werkator.yml, these values are used.

Otherwise, Werkator inspects the origin remote URL and derives the Gitea connection defaults:

Origin URL form Detected values
https://git.example.org/my-org/my-repo baseUrl, owner, repo
git@git.example.org:my-org/my-repo.git baseUrl, owner, repo

The .git suffix is stripped from the repo name. The username embedded in HTTPS URLs (e.g. https://user@git.example.org/…) is used as the default git.account.

  • gitea.owner: The Gitea user or organization owning the repository. Used for Gitea API operations, such as reporting build status checks.
  • git.account: The technical username used for git HTTPS authentication.

3. Create the Repo-Install Config

Creates .git/werkator/.werkator.yml (and its parent directory if needed). This file is never committed to the repository and is used for all branches, as long as not overridden by a project config.

If the file already exists, init prints a notice and leaves it untouched.

The generated file contains the machine-local secrets with auto-detected values pre-filled:

git:
  account: <detected-or-placeholder>
  token:   # paste your Gitea API token here

4. Create the Branch/Project Config

Creates .werkator.yml in the repository root with project-level defaults.

If the file already exists, init prints a notice and leaves it untouched.

The generated file is a commented template based on the defaults documented in configuration.md and includes the auto-detected Gitea settings:

gitea:
  baseUrl: <detected-or-placeholder>
  owner:   <detected-or-placeholder>
  repo:    <detected-or-placeholder>

...

Then, you have to configure Werkator by amending this config file according to configuration.md.

5. Optionally Install an Instance Fragment (--apply)

init --apply FILE installs a YAML fragment in the configuration schema as the applied instance layer — see configuration.md. Deployment tooling hands its parameters over this way instead of patching config files; the fragment is validated strictly and replaced wholesale on re-apply. It runs before --systemd, so an applied server.port reaches the generated unit and the Apache .htaccess (written beside the units when a publicBaseUrl is configured).

Output

init prints one line per action taken:

created .git/werkator/.werkator.yml
created .werkator.yml

Or, when files already exist:

.git/werkator/.werkator.yml already exists — not overwritten
.werkator.yml already exists — not overwritten

Hosts Without a Java Runtime

Werkator is intended to run on Hostsharing Container Server environments, which provide Docker and git but no Java runtime. For these hosts, ./gradlew runtimeBundle builds a self-contained runtime bundle (jlink-trimmed JRE + JAR + launcher) — see deployment.md and ADR 0006. A containerized Werkator runtime was considered and rejected there.

Next Steps After init

  1. Open .git/werkator/.werkator.yml and set git.token and git.account.
  2. Review .werkator.yml and add/adjust any branch build settings.
  3. Verify the effective configuration:
    java -jar build/libs/werkator.jar config:print --full
    
  4. Start the server:
    java -jar build/libs/werkator.jar server
    
  5. For permanent operation, install the systemd user service described in deployment.md.

Example: Test Server with a Fake Build

examples/setup-werkator-testserver.sh starts a Werkator server against a scratch repository with a fake build — the setup used for the manual UI/API smoke tests during development. It creates a local bare origin plus a work clone, commits a slow fake build script (live log output, demo report artifact) with a pollInterval: 5s config, and starts the server on port 18980. The origin gets a second branch (feature/demo), so the Branches view shows more than one entry. No Gitea, no credentials, no Docker; INSTALL_DIR, SERVER_PORT, and BUILD_SECONDS can be overridden via environment variables. While the server runs, push empty commits from the work clone to trigger builds; a commit message containing [fail] makes the build fail, and pushing a new branch exercises the new-origin-branch path.

Example: Self-Hosting Werkator

examples/setup-werkator-selfhost.sh shows the full sequence as a runnable script: it sets up a Werkator instance that watches and builds Werkator itself. Run it from a working checkout; it builds the JAR, creates a dedicated clone, runs init, writes the machine-specific config, and starts the server. INSTALL_DIR, ORIGIN_URL, SERVER_PORT, GIT_ACCOUNT, and GIT_TOKEN can be overridden via environment variables. The script also demonstrates the kick-start trick: resetting the local ref one commit behind origin makes the very first poll build immediately, instead of waiting for the next push.