Ubitec GmbH
Templating + Git = ❤
Description
Dominik Aumayr von Ubitec spricht in seinem devjobs.at TechTalk darüber, wie das Unternehmen die individuellen Anforderungen ihrer verschiedenen Chatbots innerhalb eines einheitlichen Frameworks umsetzt.
By playing the video, you agree to data transfer to YouTube and acknowledge the privacy policy.
Video Summary
In Templating + Git = ❤, Dominik Aumayr of Ubitec GmbH explains how his team builds on‑premise chatbot projects from a shared UbiTech Bot Framework and pushes template changes safely across many Git repositories. The method combines Cookiecutter (Jinja2) with a project‑embedded replay file and Git tags: regenerate two template versions with the project’s values, compute the diff, then git apply it to the real repo; scripts automate most updates and CI‑driven merge requests are planned. Viewers can adopt this Cookiecutter‑replay plus Git diff/apply workflow to propagate framework updates consistently across Docker, Kubernetes, and OpenShift deployments.
Templating + Git = ❤: A practical pattern to propagate template changes across many on‑prem chatbots
Context: On‑prem chatbots, public sector constraints, many variants
In “Templating + Git = ❤” by Dominik Aumayr (Ubitec GmbH), we watched a candid engineering story about keeping dozens of customer projects in sync with a moving template. Ubitec builds dialog‑based products and services—chatbots—run on‑premise. Their client base spans public sector and member organizations, including the Ministry of Finance (“Fred”), ÖAMTC, and the City of Vienna.
On‑premise brings diversity by default: different deployment schemes (Docker/Docker Compose, Kubernetes, OpenShift), branding differences (avatars, colors), customer‑specific functionality and API integrations. The team has a homogeneous core, but every installation carries specific adjustments. That’s where update and maintenance challenges start piling up.
Architecture overview: One core, many bots
The setup consists of two layers:
- A core system, the “Ubitech Bot Framework,” shared across all chatbots.
- Individual bot projects built from that framework—each with its own repository, branding, integrations, and deployment configuration.
A central template defines what a bot project looks like. From that, new project trees are generated. The caveat: while the basic structure is common, customizations are allowed and expected—additional containers, special deployment requirements, project‑specific differences in Helm charts, and so forth.
The base tools: Cookiecutter and Git
Ubitec’s approach builds on two tools:
- Cookiecutter to generate project scaffolds from templates.
- Git to version both the framework and every bot project, track changes, and tag releases.
Cookiecutter as a generator
Cookiecutter is a command‑line utility that produces full project trees from a template using Jinja2. Variables can be used inside file content and file names alike. In Ubitec’s case, values like bot name, slug, and version get substituted, and the project tree falls out deterministically.
The team created a single, central template that codifies the file layout for bot projects and defines the set of variables to ask for. It’s a straightforward way to ensure new projects start from the same, up‑to‑date foundation.
Git to version everything
The Ubitech Bot Framework has its own repository, as does each bot project. Git tracks every change. Tags denote releases of the framework and the individual projects. That makes it easy to see when something changed in the base—say a tweak in a Helm chart, a new field for a deployment schema, or a content change in a configuration file.
Together, Cookiecutter and Git solve the initial scaffolding problem elegantly. But they raise the next question: what happens when the template evolves after projects have already been generated and personalized?
The hard part: Post‑generation template drift
Once a bot project is generated, it starts to live. Customers request custom behavior, deployments get tailored, extra containers are added, and so on. Meanwhile, the central template continues to evolve—new files are introduced, Helm charts change, new fields appear, and content shifts.
Manually porting those template updates into every existing project would be tedious and error‑prone. Ubitec needed a way to propagate template changes in a controlled, automatable, and reviewable fashion—without trampling customer‑specific changes.
The key trick: Replay file + Git diff + patch apply
Cookiecutter’s “replay” feature unlocks the solution. Besides interactive prompts, Cookiecutter can consume a JSON replay file with all variable answers, making generation fully non‑interactive.
Ubitec leverages this and goes further: they include the replay file inside the generated project itself. That means each bot project carries the exact set of answers used to create it—its own name, slug, version, and any other variables. As Dominik Aumayr puts it, the bot project can “regenerate itself.”
With that in place, the update procedure is four steps end‑to‑end:
1) Materialize old and new template versions
- Check out two template versions—e.g., tag “v1” and tag “v2.”
- For both versions, run Cookiecutter non‑interactively using the bot project’s replay file.
- Result: two full project trees, generated from the old and the new template, both populated with the same project‑specific values.
2) Compute the diff
- Create a Git diff between the two generated trees.
- The resulting change set reflects only what changed between template v1 and v2—already translated into the exact values of this specific bot project.
3) Apply the patch
- Apply that diff to the real bot repository using Git Apply.
- Template additions and changes are transferred into the project; customer‑specific customizations remain intact unless there’s a direct conflict.
4) Automate and scale
- Wrap the process in a shell script and move it into CI.
- The envisioned trigger: when a new template tag is pushed, run the update against every customer project and open a merge request with the changes.
- Developers review and merge—most standard projects sail through; heavily customized projects may trigger conflicts, which Git makes explicit.
“All of a sudden we’re in a situation where the bot—this bot project—can regenerate itself.”
The elegance here lies in diffing two materialized end states rather than abstract template files. Both “old” and “new” versions are rendered with the same concrete project values first; only then are they diffed. That makes the patch relevant and ready to apply to the real project.
A concrete example: Helm chart edits and new fields
Aumayr shows a realistic case: the team changed the Helm chart’s description and added further fields for the deployment schema. Those are exactly the kinds of changes that hit many projects. With the replay‑diff‑apply workflow, those edits are captured and transferred—conflicts only appear where a customer’s chart diverged significantly.
The benefits are straightforward:
- Routine template updates land in all projects automatically.
- Project‑specific customizations remain untouched when possible.
- Conflicts aren’t hidden; they surface cleanly in Git for explicit resolution.
Git at the core: Tag, diff, apply
The entire approach relies on using Git where it excels:
- Tag the framework (“v1,” “v2,” …) to mark versions unambiguously.
- Diff materialized outputs of those versions built with the same replay values.
- Apply the resulting patch to the target project using Git Apply.
No custom merge engine, no bespoke diff logic—just Git’s battle‑tested primitives in a structured workflow.
The CI vision: Tag hook, automatic merge requests
Once scripted, this procedure naturally moves into CI. The idea is simple:
- A server hook listens for new tags in the template repository.
- For each bot project, run the replay‑diff‑apply cycle.
- Create a merge request in GitLab with the changes.
Most standard projects can be merged quickly. Heavily customized ones require a human look at the diff, which is exactly where you want engineers to spend their time. One important note from the talk: this CI part is planned but not yet implemented—Ubitec is looking for engineers to help build it.
Why it works: Three design choices that matter
1) Projects remain regenerable at all times
Including the replay file inside each project upgrades reproducibility from “initial scaffold” to “permanent capability.” A project isn’t a one‑time printout; it’s always regenerable with its own parameters.
2) Differences are computed on concrete end states
Rather than comparing abstract template files and attempting to map placeholders across projects, Ubitec generates two fully materialized trees for the same project (old vs. new) and diffs those. The result is a patch that matches reality.
3) Git handles conflict and history
The method leans on Git’s strengths—tracking, diffing, applying patches, surfacing conflicts. It minimizes custom logic, keeps the workflow familiar, and preserves a transparent history.
Boundaries and how to handle divergence
The goal isn’t to force uniformity; it’s to automate the common path and highlight true divergence:
- When a customer project deviates heavily (say, a significantly different Helm chart), the patch will conflict.
- That’s by design—the conflict is the signal to review how to adapt the template update for this specific case.
- According to the talk, “most things will be applied automatically.” Only customized projects demand hands‑on decisions.
This keeps the routine work automated and the exceptional cases visible and deliberate.
Lessons engineers can apply elsewhere
Even if your domain isn’t chatbots, the principles are broadly useful. Our key takeaways from the session:
- Strong templating is about regenerability. Put the replay file into the project.
- Version your template rigorously with tags; they’re easy to consume in CI.
- Use Git’s primitives (diff/patch) instead of inventing bespoke merge logic.
- Diff concrete materializations built with the same replay values; avoid abstract diffs that ignore context.
- Accept that some divergence is valid. Automate the 80% path; review the rest explicitly.
A step‑by‑step playbook you can mirror
Here is a faithful translation of the method outlined in the talk, without adding extra tools beyond those mentioned:
1) Define your template
- In Cookiecutter, capture all variables that uniquely define a project (name, slug, version, deployment flags, etc.).
- Use variables both in file contents and file names/directories where appropriate.
2) Generate and ship the replay file
- Ensure the replay JSON is produced on first generation.
- Keep it in the project so it’s versioned and always at hand.
3) Organize your Git repositories
- Keep the template and each derived project in its own repository.
- Tag template releases; those tags will drive your updates.
4) Write the update procedure
- For a target project: check out template “old,” generate with the project’s replay; check out template “new,” generate with the same replay.
- Create a Git diff of the two generated trees.
- Apply that diff as a patch to the target project repository.
5) Plan the CI integration
- Trigger on new template tags.
- For each project, run the replay‑diff‑apply cycle and open a merge request.
- Establish review rules: fast‑merge for standard projects; inspect the rest.
This is exactly the workflow described in the session—no additional bells and whistles needed.
On‑prem reality check: Why this fits
On‑prem deployments in the public sector often require multiple deployment schemes for the same software. Ubitec explicitly mentioned Docker/Docker Compose, Kubernetes, and OpenShift across different customers. Add bespoke containers, security constraints, and API integrations, and you get a fleet of related yet different projects.
A “spray and pray” update approach won’t do. You need something that:
- respects project‑specific reality,
- automates standard updates,
- makes divergence visible,
- and stays within familiar developer workflows (Git, merge requests).
Replay + diff of materialized outputs + Git Apply delivers exactly that.
Quotes and memorable lines
- On self‑regeneration: “All of a sudden … the bot project can regenerate itself.”
- On automation culture: “Because we’re lazy programmers” — bundle it into a script and let CI do the heavy lifting.
- On CI status: Server hooks and automatic merge requests are the intended next step; not yet implemented—an open invitation for engineers to help build it.
Closing thoughts: A pragmatic recipe to scale template updates
“Templating + Git = ❤” isn’t just a catchy title—it’s a proven combination. Cookiecutter ensures deterministic generation, the replay file preserves perpetual regenerability, and Git provides diff/patch mechanics and history. The result is a workflow that propagates template evolution into many individualized projects in a controlled, reviewable way.
For teams maintaining a central framework with many on‑prem customer projects, this serves as a template in itself. Most updates apply cleanly; true divergences surface as conflicts that engineers resolve intentionally. That’s how a living template keeps evolving without erasing the reality of production projects.
And if building the CI side of this approach sounds exciting: Dominik Aumayr made it clear there’s room to contribute—Ubitec GmbH is working toward that next step. From our DevJobs.at vantage point, the lesson is refreshing: you don’t always need new tools. Sometimes, combining the right ones—templating and Git—is all it takes.