<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://schrottner.at/feed.xml" rel="self" type="application/atom+xml" /><link href="https://schrottner.at/" rel="alternate" type="text/html" /><updated>2026-06-21T08:39:46+00:00</updated><id>https://schrottner.at/feed.xml</id><title type="html">Simon Schrottner</title><subtitle>OpenFeature maintainer &amp; CNCF Ambassador. Consulting and workshops on feature flagging, developer experience, and open-standards adoption — Austria, DACH region and remote.</subtitle><author><name>Simon Schrottner</name><email>simon@schrottner.at</email></author><entry><title type="html">A Fool with a Tool is Still a Fool</title><link href="https://schrottner.at/2026/06/20/A-Fool-with-a-Tool-is-Still-a-Fool.html" rel="alternate" type="text/html" title="A Fool with a Tool is Still a Fool" /><published>2026-06-20T07:00:00+00:00</published><updated>2026-06-20T07:00:00+00:00</updated><id>https://schrottner.at/2026/06/20/A-Fool-with-a-Tool-is-Still-a-Fool</id><content type="html" xml:base="https://schrottner.at/2026/06/20/A-Fool-with-a-Tool-is-Still-a-Fool.html"><![CDATA[<blockquote>
  <p>“A fool with a tool is still a fool.” — often attributed to Grady Booch</p>
</blockquote>

<p>I keep coming back to this quote when I watch teams adopt AI.</p>

<!--more-->

<p>In my <a href="https://schrottner.at/2026/06/18/The-Wrong-End-of-the-Problem.html">last post</a> I wrote about shifting the engineering process left — spec sessions, autonomous agents, humans reviewing output rather than writing it.
A few people asked the obvious follow-up: if an agent implements and an AI reviews, why do I need a team at all?</p>

<p>It’s a fair question.
And I think the answer is in that quote.</p>

<p>The agent validates against your prompt.
That’s it.
If your thinking is muddled, the output will be muddled — just faster and at greater cost.
An agent doesn’t tell you that you’re solving the wrong problem.
It solves whatever problem you gave it, thoroughly and without complaint.</p>

<p>Most AI usage right now treats AI as a tool.
Which means the quality of the output is bounded by the quality of the thinking that went into the prompt.
A fool with a tool is still a fool.
The tool just makes the foolishness more expensive.</p>

<p>The team is the check on intent.
Not after the agent has burned three sprints on the wrong thing — before it starts.</p>

<p>That’s what mob planning actually is, when you think about it.
Not a meeting.
Not process overhead.
It’s the place where bad ideas get caught before they get expensive.
Where someone asks “wait, why are we building this” before an agent runs with it for a week.</p>

<p>But there’s something else happening in that room that I think gets underestimated.</p>

<p>It’s where the learning happens.</p>

<p>Not just prompting.
System thinking.
Architectural patterns.
How to decompose a problem.
Why a certain approach fits this codebase and another doesn’t.
How a senior frames a problem before an agent ever touches it — the mental model that makes the output actually good.</p>

<p>Right now that knowledge isn’t transferring.
Everyone is heads-down with their own tools, developing their own habits in isolation.
Engineer A gets dramatically better output than engineer B.
Nobody knows why.
Prompting approaches are one small part of it — but the bigger part is the system thinking underneath.
And that only surfaces if there’s a room where people talk through problems together before they hand them to an agent.</p>

<p>That conversation only exists if there’s a room to have it in.</p>

<p>AI is quietly doing something to teams.
Everyone optimises their own workflow.
Everyone gets faster individually.
And the shared craft — the thing that used to live in code reviews, in pairing sessions, in hallway conversations about why the last approach didn’t work — starts to disappear.</p>

<p>The mob planning session gives it back.
It becomes the place where system design gets discussed, where architectural decisions get challenged before the agent runs with them, where a junior watches how a senior thinks through a problem and learns something they couldn’t have learned from reading generated code.
Prompting is part of that.
But it’s the smaller part.</p>

<p>The artifact changed.
The need for the room didn’t.</p>

<p>I don’t think teams are going away.
I think the ones that skip the room will produce faster, worse work — and won’t understand why.</p>

<p>The ones that keep the room, and take it seriously as the place where thinking happens, will end up somewhere different.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Agentic Systems" /><category term="Platform Engineering" /><category term="Software Engineering" /><summary type="html"><![CDATA[“A fool with a tool is still a fool.” — often attributed to Grady Booch I keep coming back to this quote when I watch teams adopt AI.]]></summary></entry><entry><title type="html">The Wrong End of the Problem</title><link href="https://schrottner.at/2026/06/18/The-Wrong-End-of-the-Problem.html" rel="alternate" type="text/html" title="The Wrong End of the Problem" /><published>2026-06-18T07:00:00+00:00</published><updated>2026-06-18T07:00:00+00:00</updated><id>https://schrottner.at/2026/06/18/The-Wrong-End-of-the-Problem</id><content type="html" xml:base="https://schrottner.at/2026/06/18/The-Wrong-End-of-the-Problem.html"><![CDATA[<p>Every company wants AI in their development process right now.
That part is clear.
What’s less clear is where they’re putting it.</p>

<!--more-->

<p>Most teams I see have done the same thing.
Handed developers access to an AI assistant and told them to move faster.
Copilot in the IDE.
Claude in the terminal.
Pick your tool.
The tickets stay the same.
The process stays the same.
The planning meetings stay the same.
The only thing that changed is how the code gets typed.</p>

<p>The tool got added.
The process didn’t move.</p>

<p>And it breaks down fast.
One power user with AI can produce more code than a team can review.
Two or three power users in the same team and the review process is basically gone.
Nobody can keep up, and the code ships anyway.</p>

<p>There’s a term worth knowing here: Spec-Driven Development.
The idea is that a detailed specification becomes the source of truth, not the code.
Agents implement from it.
Requirements change, you update the spec.
<a href="https://unifiedprocess.ai/">AI Unified Process</a> is one example of this in practice.
It’s a sound technical approach.</p>

<p>But I think it stops short of the actual problem.</p>

<p>The spec has to come from somewhere.
Someone has to write it, and someone has to agree on it.
That part is still the old process, just with a new artifact at the end.</p>

<p>What I’d suggest looks a bit different.
And it has a name most engineers already know: shift left.</p>

<p>Not in the testing sense.
In the team sense.
The collaboration moves earlier.
The engineering work is now about defining what the system should do — precisely enough that an agent can run with it.</p>

<p>That happens in what I’d call a Spec Session.
Mob planning instead of mob programming — the whole team, working on one spec.
Or async — a pull request on the spec instead of on code.
Review comments about intent and edge cases, not implementation.
Engineers already know this workflow.
The artifact is just different now.</p>

<p>Once the spec is agreed, the agent picks up the work.
Not on anyone’s laptop — it’s sitting in your infrastructure, watching for ready tickets, the same way a CI runner watches for commits.
It implements, an AI reviewer checks the output, flags what doesn’t fit, cycles back.
That loop runs until it’s done.
The human comes back in at the end to review the final output — not to write code in the middle.</p>

<p>Stacked diffs are probably the right format here.
Smaller, sequential changesets the agent ships incrementally — easier to reason about, easier to review.
<a href="https://newsletter.pragmaticengineer.com/p/stacked-diffs">Gergely Orosz wrote a good primer</a> on why this workflow matters if you’re not familiar.</p>

<p>Ambiguous acceptance criteria used to be something a developer resolved mid-sprint.
In this model they surface in the Spec Session, where the whole team can catch them.
That’s the point.</p>

<p>I don’t think most teams are avoiding this intentionally.
It’s just that changing the process is harder than adding a tool.
Adding a tool has a procurement step and a license.
Changing how a team thinks about its own work is a different kind of problem.</p>

<p>But fitting AI into an existing process gets you faster typing.
The thinking stays the same depth as before.</p>

<p>I think the teams that treat the Spec Session as the primary engineering output — and let the loop handle the rest — will end up somewhere different.</p>

<p>One thing I haven’t figured out yet is what to call it.
Mob Planning.
Mob Specing.
Spec Session.
Extreme Specing.
All of them borrow from XP deliberately — the idea is the same, just one level up from code.
If you have a better name, I’d genuinely like to know.</p>

<p>I don’t know if anyone is actually running this way yet.
But I want to try.
Especially the part where the agent just picks up the work and runs.</p>

<blockquote>
  <p>Adding AI to your process makes the typing faster. Moving the engineering work to the spec — and letting the loop carry it from there — is the part that actually changes the depth of the thinking.</p>
</blockquote>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Agentic Systems" /><category term="Platform Engineering" /><category term="Software Engineering" /><summary type="html"><![CDATA[Every company wants AI in their development process right now. That part is clear. What’s less clear is where they’re putting it.]]></summary></entry><entry><title type="html">Somewhere to Put the Ideas</title><link href="https://schrottner.at/2026/06/18/Working-on-the-Blog.html" rel="alternate" type="text/html" title="Somewhere to Put the Ideas" /><published>2026-06-18T05:00:00+00:00</published><updated>2026-06-18T05:00:00+00:00</updated><id>https://schrottner.at/2026/06/18/Working-on-the-Blog</id><content type="html" xml:base="https://schrottner.at/2026/06/18/Working-on-the-Blog.html"><![CDATA[<p>This blog started as a place to collect ideas.
Mine, specifically.
Thoughts that might resonate with others, or at least stop rattling around in my head.</p>

<!--more-->

<p>I talk to a lot of people right now.
Exploring options, having conversations.
Every person brings a different view, a different way of working.
Combining all of that is genuinely fun.
It also generates an unreasonable number of ideas.
Hard to keep track.
Hard to follow up on all of them.</p>

<p>So I write them down here.</p>

<p>No deep research.
No polished arguments.
Brain dumps, mostly.
I use AI to help structure them — otherwise half of it would be unreadable.
The ideas are mine.
The shape is sometimes borrowed.</p>

<p>People have called me the crazy professor.
Doing too many things at once.
Fair.
I’m working on it.
The goal here is simple: short enough for between meetings, deep enough to matter, worth a conversation with peers.</p>

<p>Maybe something triggers a thought.
Maybe it shifts a perspective.
Hopefully it goes both ways.</p>

<p>Two small updates while I’m at it: I added GoatCounter to track visitors.
Just curious.
And I added Giscus for comments — some of these topics are worth discussing, and I’d rather have that conversation in the open than in a DM.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Blog" /><category term="Personal" /><summary type="html"><![CDATA[This blog started as a place to collect ideas. Mine, specifically. Thoughts that might resonate with others, or at least stop rattling around in my head.]]></summary></entry><entry><title type="html">Dancing the Limbo</title><link href="https://schrottner.at/2026/06/14/Dancing-the-limbo.html" rel="alternate" type="text/html" title="Dancing the Limbo" /><published>2026-06-14T07:00:00+00:00</published><updated>2026-06-14T07:00:00+00:00</updated><id>https://schrottner.at/2026/06/14/Dancing-the-limbo</id><content type="html" xml:base="https://schrottner.at/2026/06/14/Dancing-the-limbo.html"><![CDATA[<p>The current situation is odd, and I am not sure how to tackle it.
Getting laid off by Dynatrace was a first in my career.
Although I am enjoying this extended time off, it has a strange feeling to it.
Garden leave ends in June, and I am planning to extend my off time by two more months, just to enjoy a summer with my kids.</p>

<!--more-->

<p>I am looking forward to this, but there is still this feeling of being lost.
Before, I had goals focusing around my project, bringing it forward, moving on, increasing visibility.
I am still trying to expose OpenFeature to the outside, still generating new talk ideas, pushing what OpenFeature in combination with OpenTelemetry can do.
But still there is a hole, and this hole is hard to fill.</p>

<p>I miss my daily check-ins with fellow engineers, discussing ideas, problems, improvements.
Figuring out a way to grow and to help others grow.
Actively engaging with a community on a regular basis, driving topics which benefit the overall community, but with a purpose, a goal, not just for the fact of doing it.
This goal is something I am currently missing.</p>

<p>I feel like I have achieved what I dreamed about back in the days.
Ten years ago I looked up to the people speaking at conferences, doing open source, sharing their insights, driving the community.
I feel like I reached that point.
The question is now: what is the topic, and how will it be sustainable for me in the long run.</p>

<p>The community has shown me that my way of engaging, collaborating, driving, and mentoring is something valuable.
The outreach and possibilities following my layoff announcement have been incredible.
A lot of great opportunities, but still the bigger question remains: is this my goal, or what is my goal.</p>

<p>I feel like the layoff is also something really positive.
I was in the comfort zone, and I was there for a long time.
A comfort zone where I chose when to exit, and to what discomfort.
Maybe too comfortable.
As Kent Beck would call it: the <a href="https://newsletter.kentbeck.com/p/forest-and-desert">Forest</a>, where you pick what you want to work on.
I see this layoff as a new way to grow.
The current void is nagging me.
Too scared to fully commit to being independent, unsure if I want full employment again.
What will my life be after September, after this year.</p>

<p>For now I am trying to summarize my thoughts here.
Writing feels like a nice way of reflection.
And I feel like we try not to talk about the uncomfortable things that much, although everyone is sometimes in this kind of limbo.
Maybe reading how others cope with it could help.</p>

<p>Anyways, this is my current state.
If you want to grab a coffee, virtual or in-person, let me know.</p>

<p>Let’s see what the next months will bring.
There is a lot moving.
Till then, I am dancing the limbo.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Personal" /><category term="Career" /><category term="OpenFeature" /><summary type="html"><![CDATA[The current situation is odd, and I am not sure how to tackle it. Getting laid off by Dynatrace was a first in my career. Although I am enjoying this extended time off, it has a strange feeling to it. Garden leave ends in June, and I am planning to extend my off time by two more months, just to enjoy a summer with my kids.]]></summary></entry><entry><title type="html">Adaptive Observability. The System Decides What to Watch.</title><link href="https://schrottner.at/2026/06/12/Adaptive-Observability-The-System-Decides-What-to-Watch.html" rel="alternate" type="text/html" title="Adaptive Observability. The System Decides What to Watch." /><published>2026-06-12T07:00:00+00:00</published><updated>2026-06-12T07:00:00+00:00</updated><id>https://schrottner.at/2026/06/12/Adaptive-Observability-The-System-Decides-What-to-Watch</id><content type="html" xml:base="https://schrottner.at/2026/06/12/Adaptive-Observability-The-System-Decides-What-to-Watch.html"><![CDATA[<p>We instrument everything and hope something useful comes out.</p>

<p>That’s not a strategy.
That’s noise management.</p>

<!--more-->

<p>The reaction path and the reasoning path are different problems.
The reasoning path needs breadth, history, correlation, anomaly detection, fleet-wide baselines.
That’s where observability platforms earn their place.
But the reaction path is different.
Signal in, decision out.
Local, low-latency, near-source.
Asking one system to serve both is where the architecture gets muddy.</p>

<p>So what does a proper reaction path look like.</p>

<p>If you control the SDK, you control what gets emitted in the first place.
OpenFeature can gate what your SDK emits.
Evaluate a flag, and based on the result decide whether to emit a trace, increase log verbosity, enable a specific metric.
The evaluation context is built from OTel semantic conventions — service name, environment, deployment version.
The system already knows about itself.
You’re just wiring that knowledge into the decision of what to observe next.</p>

<p>The system decides what to watch based on its own state.
Not a human configuring a sampling rule once and forgetting about it.
Not a dashboard someone checks during an incident.
The loop closes at the SDK level.</p>

<p>And it’s cheaper.
You reduce noise at the source instead of paying to ingest and filter downstream.</p>

<p>The primitives are all there.
OTel for the signal.
OpenFeature for the control.
The Collector as the routing layer.
The wiring between them doesn’t exist yet in any standardized form.</p>

<p>Maybe that’s on us.
The maintainers, the spec writers, the standard builders.
Making that easier to do, and harder to get wrong, is probably the next thing to work on.</p>

<p>Funny enough, this is the same problem I wrote about earlier this week.
<a href="/2026/06/08/We-Dont-Build-Software-Anymore.html">We don’t build software anymore</a> — we grow it.
Turns out we are still figuring out how to grow the nervous system itself.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Observability" /><category term="OpenTelemetry" /><category term="OpenFeature" /><category term="Agentic Systems" /><summary type="html"><![CDATA[We instrument everything and hope something useful comes out. That’s not a strategy. That’s noise management.]]></summary></entry><entry><title type="html">The Reaction Path Doesn’t Need a Dashboard</title><link href="https://schrottner.at/2026/06/10/The-Reaction-Path-Doesnt-Need-a-Dashboard.html" rel="alternate" type="text/html" title="The Reaction Path Doesn’t Need a Dashboard" /><published>2026-06-10T07:00:00+00:00</published><updated>2026-06-10T07:00:00+00:00</updated><id>https://schrottner.at/2026/06/10/The-Reaction-Path-Doesnt-Need-a-Dashboard</id><content type="html" xml:base="https://schrottner.at/2026/06/10/The-Reaction-Path-Doesnt-Need-a-Dashboard.html"><![CDATA[<p>Observability tooling was built for humans.
Dashboards, notebooks, query interfaces — they exist so an engineer can look at data and make a decision.
That’s a valid use case.
Business reporting, capacity planning, post-mortems.
Fine.</p>

<!--more-->

<p>But that’s not what agents need.</p>

<p>An agent doesn’t need a pretty graph.
It needs data.
Clean, structured, semantic data it can reason over.
The entire visualization layer is overhead.
And if that data has to travel through a SaaS ingest pipeline, get stored, get indexed, and then get queried, you’ve added latency, cost, and distance between your system and the thing reacting to it.</p>

<p>The OTel Collector already does the hard work.
It filters.
It batches.
It samples.
It enriches.
It can route data directly to wherever it needs to go.
Including an agent.
No SaaS layer required for the reaction path.</p>

<p>SaaS observability isn’t wrong.
For human-facing use cases it makes sense.
But for a reflex arc, you want the signal close to the muscle.</p>

<p>The counterargument is obvious.
Observability platforms already have the data, the context, the semantic layer.
Why not make them the agent’s data layer too.
Some vendors are betting exactly on that.
And it’s not a bad bet for certain use cases — investigation, root cause analysis, post-incident review.
Where you need breadth, history, and correlation across signals.</p>

<p>But that’s still a human-paced workflow dressed up in agent clothing.
The reaction path is different.
It needs low latency, minimal hops, and no dependency on external ingest availability.
When your system is degrading is exactly when you don’t want your response gated on a SaaS API call.</p>

<p>That is probably the bigger challenge for observability companies over the next year or two.
Not whether agents can reason over telemetry data.
But whether the reaction path still runs through them at all.
Human-facing use cases stay.
The reflex arc doesn’t need the dashboard layer.
Pricing models built on ingest volume will feel that.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Observability" /><category term="OpenTelemetry" /><category term="Agentic Systems" /><category term="SaaS" /><summary type="html"><![CDATA[Observability tooling was built for humans. Dashboards, notebooks, query interfaces — they exist so an engineer can look at data and make a decision. That’s a valid use case. Business reporting, capacity planning, post-mortems. Fine.]]></summary></entry><entry><title type="html">We Don’t Build Software Anymore</title><link href="https://schrottner.at/2026/06/08/We-Dont-Build-Software-Anymore.html" rel="alternate" type="text/html" title="We Don’t Build Software Anymore" /><published>2026-06-08T00:00:00+00:00</published><updated>2026-06-08T00:00:00+00:00</updated><id>https://schrottner.at/2026/06/08/We-Dont-Build-Software-Anymore</id><content type="html" xml:base="https://schrottner.at/2026/06/08/We-Dont-Build-Software-Anymore.html"><![CDATA[<p>There is a lot of conversation happening right now about agentic systems.
How to build them.
How to trust them.
How to keep humans involved.
The “human in the loop” crowd wants approval gates.
The “human on the loop” crowd wants oversight without bottlenecks.</p>

<!--more-->

<p>I’ve been sitting with a different question.
What if the role isn’t in the loop or on the loop, but on the system itself.
Designing the thing that decides.
Not intervening in decisions, but shaping the layer that makes them.</p>

<p>That framing leads somewhere interesting.</p>

<p>We grow software.
Poorly.
Slowly.
Mostly by accident.
Every pull request is a mutation.
Every deployment is a generation.
Every incident is selection pressure.
We’ve been running evolution for years without noticing.</p>

<p>Living organisms solved this differently.
They built nervous systems, layers that sense, layers that act, layers that maintain stability without conscious intervention.
Proprioception.
The organism’s awareness of its own state.
Where its limbs are.
What’s alive and what isn’t.</p>

<p>Most modern systems don’t have that.
They have dashboards.
They have flag states nobody queries.
They have business outcomes disconnected from the behaviors that caused them.</p>

<p>Mauricio Salatino <a href="https://www.salaboy.com/2026/06/08/reacting-to-ai/">published something today</a> that I keep thinking about.
He calls for a “learning layer” on top of Kubernetes, one that records, synthesizes, and lets agents make grounded decisions.
He ends where I always end up: unification, specs, standards.
But he doesn’t name what that layer is made of.</p>

<p>I think we already have the ingredients.</p>

<p>OpenTelemetry senses.
OpenFeature acts.
Something in between evaluates.
That’s not a dashboard.
That’s a reflex arc.
The organism responding to its own state without waiting for a human to read a chart.</p>

<p>The human isn’t in the loop.
The human isn’t on the loop.
The human designed the nervous system.
That’s a different job.
And it requires different primitives.</p>

<p>We’ve been building them piece by piece without knowing it.
Observability.
Feature flags.
Platform engineering.
Each built for a specific problem.
Each quietly doing more than we designed it for.</p>

<p>They don’t add up to something yet.
But I’d bet against that staying true.</p>

<p>And now vendors are naming it for us.
Proprietary agent control layers.
Closed nervous systems.
The metaphor is everywhere.
Most of them aren’t building on open standards.</p>

<p>That gap is widening.</p>

<p>I have a talk about this.
Submitted.
Not yet scheduled.
But the idea needed to exist somewhere first.</p>

<p>This is the rough version.</p>

<blockquote>
  <p>Typing code is no longer the defining skill, but software engineering isn’t becoming unnecessary — the value moves up, from writing implementations to designing the systems that frame, decide, and regulate themselves.</p>
</blockquote>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="Agentic Systems" /><category term="OpenTelemetry" /><category term="OpenFeature" /><category term="Platform Engineering" /><category term="Observability" /><summary type="html"><![CDATA[There is a lot of conversation happening right now about agentic systems. How to build them. How to trust them. How to keep humans involved. The “human in the loop” crowd wants approval gates. The “human on the loop” crowd wants oversight without bottlenecks.]]></summary></entry><entry><title type="html">GitLab CI - Configurations via environment variables</title><link href="https://schrottner.at/gitlab-ci/2021/03/19/GitLab-CI-Environment-Variable.html" rel="alternate" type="text/html" title="GitLab CI - Configurations via environment variables" /><published>2021-03-19T00:00:00+00:00</published><updated>2021-03-19T00:00:00+00:00</updated><id>https://schrottner.at/gitlab-ci/2021/03/19/GitLab-CI-Environment-Variable</id><content type="html" xml:base="https://schrottner.at/gitlab-ci/2021/03/19/GitLab-CI-Environment-Variable.html"><![CDATA[<p>In our first post we learned how we can extract our build into an own centralized file.
Within this post we are focusing on configuration via environment variables.</p>

<!--more-->

<p>This is a post of a series on our approaches.
<!-- markdownlint-disable no-inline-html --></p>
<ol>


  <li><a href="/gitlab-ci/2021/03/19/GitLab-CI-Environment-Variable.html">GitLab CI - Configurations via environment variables</a></li>

  <li><a href="/gitlab-ci/2021/03/18/GitLab-CI-Centralize-Configuration.html">GitLab CI - Centralization Configuration</a></li>

</ol>
<!-- markdownlint-enable no-inline-html -->

<h2 id="environment-variables">Environment Variables</h2>

<p>The environment variables offer a good solution to define external changes.
There are two was to define them, both use the same <code class="language-plaintext highlighter-rouge">variables</code> directive, but one allows us to define a description which will be shown in the UI when manually triggering the pipeline.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">variables</span><span class="pi">:</span>
    <span class="c1"># without description</span>
    <span class="na">VARIABLE_A</span><span class="pi">:</span> <span class="s2">"</span><span class="s">value"</span>
    <span class="c1"># with a description</span>
    <span class="na">VARIABLE_B</span><span class="pi">:</span>
        <span class="na">value</span><span class="pi">:</span> <span class="s2">"</span><span class="s">value"</span>
        <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">description"</span>
</code></pre></div></div>

<p><img src="/assets/2021-03-19/run-pipeline.png" alt="Run Pipeline" /></p>

<h2 id="using-environment-variables">Using Environment Variables</h2>

<p>Environment variables can be called by their name in a bash like manner - <code class="language-plaintext highlighter-rouge">$VARIABLE_NAME</code>.</p>

<p>We will be using our <code class="language-plaintext highlighter-rouge">tools.gitlab-ci.yml</code> and our <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code> from our first blog post for this examples.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tools.gitlab-ci.yml</span>
<span class="na">job</span><span class="pi">:</span>
    <span class="na">stage</span><span class="pi">:</span> <span class="s">build</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">alpine:latest</span>
    <span class="na">before_script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "some tool specific setup"</span>
    <span class="na">script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "default action"</span>
</code></pre></div></div>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>
</code></pre></div></div>

<p>For the beginning we want to just replace our echo with a variable, let’s call it <code class="language-plaintext highlighter-rouge">ECHO</code>.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tools.gitlab-ci.yml</span>
<span class="na">job</span><span class="pi">:</span>
    <span class="na">stage</span><span class="pi">:</span> <span class="s">build</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">alpine:latest</span>
    <span class="na">before_script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "some tool specific setup"</span>
    <span class="na">script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "$ECHO"</span>
</code></pre></div></div>

<h2 id="defining-environment-variables">Defining Environment variables</h2>

<p>There are multiple ways how we can define the environment variables, each of them has their pros and cons.
I will try to shed some light and also reveal some of the thought processes behind it.</p>

<h3 id="within-gitlab-ciyml">within .gitlab-ci.yml</h3>

<p>I would not recommend to go this way, as the user needs to have deeper knowledge of the <code class="language-plaintext highlighter-rouge">jobs.gitlab-ci.yml</code>.
At least not fully, in later examples i will show you, how you can leverage this functionality together with the <code class="language-plaintext highlighter-rouge">jobs.gitlab-ci.yml</code></p>

<p>Defining it within <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code> can be achieved in two ways.
Either we define it globally like</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
    <span class="na">ECHO</span><span class="pi">:</span> <span class="s2">"</span><span class="s">our</span><span class="nv"> </span><span class="s">echo"</span>

<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>
</code></pre></div></div>

<p>… or we define it on the job like</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>

<span class="na">job</span><span class="pi">:</span>
    <span class="na">variables</span><span class="pi">:</span>
        <span class="na">ECHO</span><span class="pi">:</span> <span class="s2">"</span><span class="s">our</span><span class="nv"> </span><span class="s">echo"</span>
</code></pre></div></div>

<h3 id="within-toolsgitlab-ciyml">within tools.gitlab-ci.yml</h3>

<p>When you extracted functionality into an own <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code>-file, i recommend to provide either a good documentation about the options or make the extracted file as self explanatory as possible.
A simple way to achieve this, is using the value and description definition for environment variables.</p>

<p>This might spoil the overview of your pipeline, but there are ways to bypass this, which i will show you later.</p>

<p>Defining it is similar to the <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code> file:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tools.gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
    <span class="na">ECHO</span><span class="pi">:</span> 
        <span class="na">value</span><span class="pi">:</span> <span class="s2">"</span><span class="s">default</span><span class="nv"> </span><span class="s">echo"</span>
        <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">this</span><span class="nv"> </span><span class="s">will</span><span class="nv"> </span><span class="s">be</span><span class="nv"> </span><span class="s">printed</span><span class="nv"> </span><span class="s">by</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">job"</span>

<span class="na">job</span><span class="pi">:</span>
    <span class="na">stage</span><span class="pi">:</span> <span class="s">build</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">alpine:latest</span>
    <span class="na">before_script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "some tool specific setup"</span>
    <span class="na">script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "$ECHO"</span>
</code></pre></div></div>

<p><img src="/assets/2021-03-19/run-pipeline-default-echo.png" alt="Run Pipeline" /></p>

<h4 id="overwriting">Overwriting</h4>

<p>You also maybe want to overwrite those variables.
There are a few ways we can overwrite it:</p>

<ul>
  <li>Copy/Paste/Replace</li>
  <li>Overwrite and Hide</li>
</ul>

<h5 id="copypastereplace">Copy/Paste/Replace</h5>

<p>Therefore we can even combine the two ways of defining them within the <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code>, and provide a better readable and described variable for our run dialog.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
    <span class="na">ECHO</span><span class="pi">:</span> 
        <span class="na">value</span><span class="pi">:</span> <span class="s2">"</span><span class="s">our</span><span class="nv"> </span><span class="s">echo"</span>
        <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">this</span><span class="nv"> </span><span class="s">will</span><span class="nv"> </span><span class="s">be</span><span class="nv"> </span><span class="s">printed</span><span class="nv"> </span><span class="s">by</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">job</span><span class="nv"> </span><span class="s">now</span><span class="nv"> </span><span class="s">as</span><span class="nv"> </span><span class="s">we</span><span class="nv"> </span><span class="s">overwrite</span><span class="nv"> </span><span class="s">it"</span>

<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>
</code></pre></div></div>

<p><img src="/assets/2021-03-19/run-pipeline-overwriting-echo.png" alt="Run Pipeline" /></p>

<p>This will still show this information on the <code class="language-plaintext highlighter-rouge">run pipeline</code>-form.</p>

<h5 id="overwrite-and-hide">Overwrite and Hide</h5>

<p>The first approach showed us, how we can copy, paste and replace this information.
Maybe we want to not “spoil” our form, as we do not need to manipulate it anyways.</p>

<p>If not we are provided with simple tools and replace the definition with the first version.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
    <span class="na">ECHO</span><span class="pi">:</span> <span class="s2">"</span><span class="s">our</span><span class="nv"> </span><span class="s">echo"</span>

<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>
</code></pre></div></div>

<p><img src="/assets/2021-03-19/run-pipeline-hiding-and-overwriting-echo.png" alt="Run Pipeline" /></p>

<h2 id="hiding-extracted-environment-variables">Hiding extracted environment variables</h2>

<p>Sometimes we are fine with the default values and do not want to show any information about this variable within the <code class="language-plaintext highlighter-rouge">run pipeline</code>-form.</p>

<p>For smaller includes this can be easy, as the number of environment variables is small.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
    <span class="na">ECHO</span><span class="pi">:</span>
        <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">"</span>

<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>
</code></pre></div></div>

<p>But it again forces the user to have prior knowledge of his include, or if the include changes to also maintain his own build.</p>

<h3 id="with-an-own-file">with an own file</h3>

<p>As we were facing this regularly we came up with a small hack.
For each of our includes, we provide a second include, with the sole purpose of hiding the variables.
Besides the effect of hiding the variables, we are also able to provide additional information of the basic include to the user.</p>

<p>You might be wondering how we name this file and what the content is.
We named it <code class="language-plaintext highlighter-rouge">tools.hide.gitlab-ci.yml</code> and it just copies the environment variables of <code class="language-plaintext highlighter-rouge">tools.gitlab-ci.yml</code> but replaces the description.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tools.hide.gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
    <span class="na">ECHO</span><span class="pi">:</span>
        <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">"</span>
</code></pre></div></div>

<p>The include within the <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code> file is working the same way.
Now somebody can actively turn the description on and off if needed.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># .gitlab-ci.yml</span>
<span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> 
        <span class="pi">-</span> <span class="s">tools.gitlab-ci.yml</span>
        <span class="pi">-</span> <span class="s">tools.hide.gitlab-ci.yml</span>
</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>It is easy to provide some kind of configuration to the user.
It is also fairly easy to document them and make it visible within the pipeline.
Also with our hack it is easy to hide them, if they are not needed.</p>

<h2 id="word-of-advice">Word of Advice</h2>

<p>Those are highly opinionated solutions, which are covering our use cases.
They might not be the ideal fit for your solution.
But I hope they offer inspiration.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="gitlab-ci" /><category term="ci" /><category term="configuration" /><category term="environment" /><category term="gitlab" /><summary type="html"><![CDATA[In our first post we learned how we can extract our build into an own centralized file. Within this post we are focusing on configuration via environment variables.]]></summary></entry><entry><title type="html">GitLab CI - Centralization Configuration</title><link href="https://schrottner.at/gitlab-ci/2021/03/18/GitLab-CI-Centralize-Configuration.html" rel="alternate" type="text/html" title="GitLab CI - Centralization Configuration" /><published>2021-03-18T00:00:00+00:00</published><updated>2021-03-18T00:00:00+00:00</updated><id>https://schrottner.at/gitlab-ci/2021/03/18/GitLab-CI-Centralize-Configuration</id><content type="html" xml:base="https://schrottner.at/gitlab-ci/2021/03/18/GitLab-CI-Centralize-Configuration.html"><![CDATA[<p>My company is currently migrating to GitLab and also to GitLab CI.
We do have a lot of similar projects which rely on similar tooling and therefore the CI configuration is also pretty similar.
This created the need to centralize it but we still wanted to provide some configurational options with an explanation without spoiling the run pipeline UI.</p>

<!--more-->

<p>This is a post of a series on our approaches.
<!-- markdownlint-disable no-inline-html --></p>
<ol>


  <li><a href="/gitlab-ci/2021/03/19/GitLab-CI-Environment-Variable.html">GitLab CI - Configurations via environment variables</a></li>

  <li><a href="/gitlab-ci/2021/03/18/GitLab-CI-Centralize-Configuration.html">GitLab CI - Centralization Configuration</a></li>

</ol>
<!-- markdownlint-enable no-inline-html -->

<h2 id="centralized-configuration">Centralized Configuration</h2>

<p>The idea of generalizing configuration or of loading from a different repository was born due to a simple need - or own custom tools.
Sometimes our tools do have their own build images and need their own build step, which is a lot of prior knowledge if you just want to apply them to your project and use them.</p>

<p>Therefore we decided to move the CI definitions for those files into own projects or to the build image project.
The benefits are:</p>

<ul>
  <li>
    <p>lifecycle of job definition and tool are unified.</p>

    <p>If a project updates the job definitions, they will also use the appropriate image linked to it.</p>
  </li>
  <li>
    <p>User does not need to know internals of tool</p>

    <p>The user has a simple way to use the tool within his CI.
  There is no prior logic needed, but if there is the need, it allows manipulation from the outside.</p>
  </li>
  <li>
    <p>We can provide versioned updates for tool and job definition</p>
  </li>
</ul>

<h3 id="so-how-those-this-work">So how those this work?</h3>

<p>We will be working within one repository to show this functionality, but it is not much effort to change this to multiple projects.
Additionally we use the assumption that <code class="language-plaintext highlighter-rouge">alpine:latest</code> is our own docker image build tool :).</p>

<p>A normal <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code> looks like:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">job</span><span class="pi">:</span>
    <span class="na">stage</span><span class="pi">:</span> <span class="s">stage</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">alpine:latest</span>
    <span class="na">before_script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "some tool specific setup"</span>
    <span class="na">script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "default action"</span>
</code></pre></div></div>

<p>Our user is quiet unhappy, because he needs to write all those lines, just for doing the default action.
Also he has to know about all those things upfront.
Furthermore if the tool implementation changes are changing he also need to be aware of that.</p>

<p>For easier usage, we need to</p>

<ol>
  <li>extract the job definition</li>
  <li>apply the extracted job definition</li>
</ol>

<h4 id="extraction-into-own-ci-file">Extraction into own CI file</h4>

<p>Instead we can extract this whole job definition into our own <code class="language-plaintext highlighter-rouge">tools.gitlab-ci.yml</code> which will look like exactly within the <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code></p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">job</span><span class="pi">:</span>
    <span class="na">stage</span><span class="pi">:</span> <span class="s">build</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">alpine:latest</span>
    <span class="na">before_script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "some tool specific setup"</span>
    <span class="na">script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "default action"</span>
</code></pre></div></div>

<h4 id="usage-of-extracted-file">Usage of extracted file</h4>

<p>To use the newly created <code class="language-plaintext highlighter-rouge">tools.gitlab-ci.yml</code> we need to include it within our build.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>
</code></pre></div></div>

<p>Voila the first step is done.
We centralized the configuration into an own file!</p>

<h4 id="change-the-action">Change the action</h4>

<p>As mentioned earlier, we also want to offer the user the possibility to change this definition.
Luckily GitLab got us covered here.
They over a really great merging of those <code class="language-plaintext highlighter-rouge">yml</code>-files and in the end they are combined.</p>

<p>This allows us to reuse the same definition and just override parts of it within our <code class="language-plaintext highlighter-rouge">.gitlab-ci.yml</code></p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">local</span><span class="pi">:</span> <span class="s">tools.gitlab-ci.yml</span>

<span class="na">job</span><span class="pi">:</span>
    <span class="na">stage</span><span class="pi">:</span> <span class="s">test</span>
    <span class="na">script</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">echo "do this instead"</span>
</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>Extracting functionality into an own file is easy.
Using extracted functionality is also not that hard.
Modifying extracted functionality works also like a charm.</p>

<h2 id="word-of-advise">Word of advise</h2>

<p>This seems to be great functionality and offers a lot of DRY possibilities.
I still urge you to evaluate what you try to reduce and how the user perspective is.
It is nice if it is DRY, but it can still be really confusing for the user.</p>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="gitlab-ci" /><category term="ci" /><category term="configuration" /><category term="centralization" /><category term="gitlab" /><summary type="html"><![CDATA[My company is currently migrating to GitLab and also to GitLab CI. We do have a lot of similar projects which rely on similar tooling and therefore the CI configuration is also pretty similar. This created the need to centralize it but we still wanted to provide some configurational options with an explanation without spoiling the run pipeline UI.]]></summary></entry><entry><title type="html">Gradle Repositories Plugin - The Struggle is Real</title><link href="https://schrottner.at/2021/03/17/Grade-Repositories-Plugin-the-struggle-is-real.html" rel="alternate" type="text/html" title="Gradle Repositories Plugin - The Struggle is Real" /><published>2021-03-17T00:00:00+00:00</published><updated>2021-03-17T00:00:00+00:00</updated><id>https://schrottner.at/2021/03/17/Grade-Repositories-Plugin-the-struggle-is-real</id><content type="html" xml:base="https://schrottner.at/2021/03/17/Grade-Repositories-Plugin-the-struggle-is-real.html"><![CDATA[<p>I released version 0.3.0 due to some interesting bugs and some misconceptions.
All the functionality is covered, but i opened a box which was maybe not a good idea to open.</p>

<h2 id="fixed-topics">Fixed topics</h2>

<h3 id="misconception">Misconception</h3>

<p>I was not careful enough when reading the GitLab Documentation regarding Gradle and the GitLab Package Registry.
It turns out, that you are able to download from two different endpoints:</p>

<ul>
  <li>Group endpoint:
  <code class="language-plaintext highlighter-rouge">&lt;url&gt;/api/v4/groups/&lt;groupId&gt;/-/packages/maven</code></li>
  <li>Project endpoint:
  <code class="language-plaintext highlighter-rouge">&lt;url&gt;/api/v4/projects/&lt;projectId&gt;/packages/maven</code></li>
</ul>

<p>Also logical you can only upload to one, the project endpoint.
My previous implementation did not cover projects at all.
Therefore i now deprecated my first API endpoint <code class="language-plaintext highlighter-rouge">maven(args)</code>.
Instead i offer now a <code class="language-plaintext highlighter-rouge">groups(args)</code> and a <code class="language-plaintext highlighter-rouge">projects(args)</code> endpoint.</p>

<h3 id="upload">Upload</h3>

<p>Together with the misconception this was also the reason, why upload did not work.
As we still need to somehow provide where we want those repositories to be added, i am currently still stuck with <code class="language-plaintext highlighter-rouge">.upload(owner, 'projectId')</code>.
But finally it works, and we are at a usable state.</p>

<h2 id="plans-for-the-future">Plans for the Future</h2>

<p>Simply said, reduce complexity and make it more elegant.
Currently there is too much code in the plugin from trial and error.
I think it is cluttered, it is missing structure, and it is confusing as hell.</p>

<h3 id="dsl-like-api">DSL-like API</h3>

<p>My way of configuring the plugin is not ideal.
It works, but it could be better and in a nicer groovy way.
I will change it to a <a href="https://docs.gradle.org/current/userguide/implementing_gradle_plugins.html#modeling_dsl_like_apis">DSL-like API</a>.</p>

<p>The benefit is within the lazy evaluation, which might be beneficiary.
Although currently there is not much to gain, as the configuration is happening during the evaluation anyways, and not when the task is executed.</p>

<h3 id="hand-over-from-settings-to-projects">Hand over from Settings to Projects</h3>

<p>The current way is a little bit clumsy and suboptimal - fetching, recreation, applying, etc.</p>

<p>I would love to clean this up, make it more concise and easier to grasp.</p>

<p>Currently I also think that some of those limitations might be also caused by my need to support Gradle 4.10.3.
If my understandings are correct, i can remove this handover of artifacts to the projects in the future.
As soon as i can drop support of 4.10.3 - the question is, if i leave the functionality, but just ignore it in that case.</p>

<h3 id="how-we-add-repositories">How we add repositories</h3>

<p>Currently the plugin is applied in two different ways:</p>

<ul>
  <li>Downloading:
  Here I rely on the information at hand when the plugin is applied.
  I store the repositories of the <code class="language-plaintext highlighter-rouge">ExtensionAware</code>-Object which was used to instantiate the extension.
  This works fine for the dependency repositories, but also limits it to just them</li>
  <li>Uploading:
  Here we pass on the owner and use this information to add the repositories.
  I do not like this because it adds complexity to the API.</li>
</ul>

<p>I try now to investigate, how i can maybe unify the API and reduce complexity.</p>

<ol>
  <li>Ideally i manage to add a method to the <code class="language-plaintext highlighter-rouge">DefaultRepositoryHandler</code> but this seems to be a hard task.</li>
  <li>Alternatively i could change the way the repositories are applied and return the <code class="language-plaintext highlighter-rouge">Action</code> instead of adding it within the plugin.</li>
</ol>

<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">repositories</span> <span class="o">{</span>
    <span class="c1">// Current way</span>
    <span class="n">gitLab</span><span class="o">.</span><span class="na">groups</span><span class="o">(</span><span class="s1">'groupId'</span><span class="o">)</span>
    <span class="c1">// 1. if i manage to extend DefaultRepositoryHandler</span>
    <span class="n">gitLabGroups</span><span class="o">(</span><span class="s1">'groupId'</span><span class="o">)</span>
    <span class="c1">// 2. not having influence on where it is added</span>
    <span class="n">maven</span> <span class="n">gitLab</span><span class="o">.</span><span class="na">groups</span><span class="o">(</span><span class="s1">'groupId'</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>]]></content><author><name>[&quot;Simon Schrottner&quot;]</name></author><category term="gradle" /><category term="gitlab" /><summary type="html"><![CDATA[I released version 0.3.0 due to some interesting bugs and some misconceptions. All the functionality is covered, but i opened a box which was maybe not a good idea to open.]]></summary></entry></feed>