Skip to content

Commit 9e384d8

Browse files
committed
add blog post about removal of common in favor of Makefile-common
1 parent aebdf26 commit 9e384d8

File tree

1 file changed

+303
-0
lines changed

1 file changed

+303
-0
lines changed
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
---
2+
date: 2025-08-29
3+
title: From slim common to no common
4+
summary: We're replacing the redundant common git subtree in our repositories with a single, centralized Makefile-common.
5+
author: Drew Minnear
6+
blog_tags:
7+
- patterns
8+
- announce
9+
---
10+
:toc:
11+
:imagesdir: /images
12+
13+
== Retiring the `common` Directory with a Smarter Makefile
14+
15+
We're simplifying our Validated Patterns workflow in a big way: the `common` directory is going away.
16+
17+
Why does this matter? Fewer moving parts, leaner repositories, and updates that flow automatically to every pattern. Instead of juggling wrapper scripts and redundant logic across repos, everything now runs through a *centralized, smarter Makefile*.
18+
19+
This post explains why we made the change, how it benefits you, and what you need to do to start using this streamlined approach.
20+
21+
=== The Old Way: A `common` Directory in Every Pattern
22+
23+
Originally, every pattern repository included a `common` directory. As the name suggests, it housed shared resources that didn't vary between patterns, primarily *Helm charts* and *Ansible playbooks*. While this worked, it meant that any update to a common script or chart had to be manually propagated across every single pattern repository.
24+
25+
=== The Evolution: Creating Central Hubs of Logic
26+
27+
To improve this, we began breaking the `common` directory apart in a few key stages:
28+
29+
. *Centralizing Helm charts:* We leveraged Argo CD's link:https://argo-cd.readthedocs.io/en/stable/user-guide/multiple_sources/[multi-source config] feature to publish and consume our Helm charts from a central repository, now available at link:https://charts.validatedpatterns.io/[].
30+
. *Creating an Ansible Collection:* We moved the common Ansible playbooks into their own dedicated Git repository and published them as a collection: link:https://github.com/validatedpatterns/rhvp.cluster_utils[`rhvp.cluster_utils`].
31+
. *Introducing the `utility-container`:* We created the link:https://quay.io/repository/validatedpatterns/utility-container[`utility-container`]. This container image bundles all our essential tools—the `rhvp.cluster_utils` Ansible collection, other collections like `kubernetes.core`, and common binaries (`oc`, `helm`, etc.).
32+
33+
This evolution gave us the ubiquitous `pattern.sh` script. By running `./pattern.sh make install`, you use the `utility-container` to deploy a pattern to an OpenShift cluster. This powerful script ensures you have the correct versions of all tools without needing to install them on your local machine.
34+
35+
At this point, the `common` directory was much slimmer, containing only the Makefile and some shell scripts that were mostly just thin wrappers for Ansible playbook calls.
36+
37+
=== Today's Change: Removing the `common` Directory Entirely
38+
39+
After slimming things down, we realized we could take one final step. We moved the logic from the few remaining wrapper scripts directly into our Ansible playbooks. This made the `common/scripts` directory redundant, and at that point, there was no reason to have the `common` directory at all.
40+
41+
Now, instead of a git subtree, patterns can use a single, powerful Makefile.
42+
43+
This new approach has several key advantages:
44+
45+
* *Lighter Repos:* Pattern repositories no longer need the `common` directory, making them much smaller.
46+
* *Centralized Updates:* When we fix a bug or add a feature to the common logic, we update it in one place. The changes are automatically available to all patterns using the new Makefile—no more updating dozens of repos!
47+
* *Simpler Makefiles:* Most patterns now only need a single line in their Makefile: `include Makefile-common`.
48+
49+
=== The Adjustment: Discoverability
50+
51+
One change to be aware of is *discoverability*. Without a local `common` directory full of scripts, it may not be immediately obvious which `make` targets exist or which environment variables you can tweak.
52+
53+
We've solved this in two ways:
54+
55+
. *Built-in docs:* Every `Makefile-common` includes a link back to this post, so the reference is always at your fingertips.
56+
. *`make help` target:* Run `./pattern.sh make help` to see the list of available targets directly in your terminal.
57+
58+
== Getting Started with the New Structure
59+
60+
Adopting the new approach is straightforward whether you're bootstrapping a brand-new pattern repository or upgrading an existing one.
61+
62+
=== New repositories
63+
64+
. From the root of your repo, run:
65+
+
66+
[source,bash]
67+
----
68+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer init
69+
----
70+
+
71+
Add secrets scaffolding at any time with:
72+
+
73+
[source,bash]
74+
----
75+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer init --with-secrets
76+
----
77+
. Review the changes (`values-*.yaml`, `pattern.sh`, `Makefile`, `Makefile-common`), then commit.
78+
. Try it out:
79+
+
80+
[source,bash]
81+
----
82+
./pattern.sh make show
83+
----
84+
+
85+
[source,bash]
86+
----
87+
./pattern.sh make install
88+
----
89+
90+
=== Existing repositories
91+
92+
Move from the legacy `common` structure to the new Makefile-driven setup with a single command:
93+
94+
[source,bash]
95+
----
96+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer upgrade
97+
----
98+
99+
What this does:
100+
* Removes `common` (if present)
101+
* Removes `./pattern.sh` (symlink or file), then copies the latest script
102+
* Copies `Makefile-common` to the repo root
103+
* Updates your `Makefile`:
104+
** If it already contains `include Makefile-common`, it is left unchanged
105+
** If it exists but lacks the include, the include is prepended to the first line
106+
** If it doesn't exist, a default `Makefile` is created
107+
108+
If you prefer to fully replace your `Makefile` with the default version, run:
109+
110+
[source,bash]
111+
----
112+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer upgrade --replace-makefile
113+
----
114+
115+
After upgrading, commit the changes and use the targets described below (for example, `./pattern.sh make show` or `./pattern.sh make install`).
116+
117+
== Using `Makefile-common`
118+
119+
Patterns shipped without the `common` dir now have a `Makefile-common` that provides consistent developer and user targets.
120+
121+
=== How commands are executed
122+
123+
All targets are thin wrappers around ansible playbooks defined in link:https://github.com/validatedpatterns/rhvp.cluster_utils[rhvp.cluster_utils]. By default, `ANSIBLE_STDOUT_CALLBACK` is set to `null` which means all of the noise from ansible is suppressed. If you need it, set that variable in your environment `export ANSIBLE_STDOUT_CALLBACK=default` or just directly use it as part of calling the make targets (`ANSIBLE_STDOUT_CALLBACK=default ./pattern.sh make <target>`).
124+
125+
When you are getting started with secrets it can be difficult to debug what may be wrong in your secret values files. To aid debugging, you could try running:
126+
127+
[source,bash]
128+
----
129+
ANSIBLE_STDOUT_CALLBACK=default EXTRA_PLAYBOOK_OPTS='-e hide_sensitive_output="false" -vvv' ./pattern.sh make load-secrets
130+
----
131+
132+
IMPORTANT: *DO NOT* do this in CI environments as it will expose your secrets...Also, for auto-generated secrets they will be different each time you run that command.
133+
134+
=== Overriding variables
135+
136+
All pattern settings can be overridden in *two ways*:
137+
138+
. *Ansible variable*
139+
+
140+
Via the env var `EXTRA_PLAYBOOK_OPTS`, e.g.:
141+
+
142+
[source,bash]
143+
----
144+
EXTRA_PLAYBOOK_OPTS="-e target_branch=myfeature -e target_origin=upstream" ./pattern.sh make show
145+
----
146+
. *Environment variable*
147+
+
148+
[source,bash]
149+
----
150+
TARGET_BRANCH=myfeature TARGET_ORIGIN=upstream ./pattern.sh make show
151+
----
152+
153+
*Precedence:*
154+
`-e var=value` (CLI/inventory) → environment variables → defaults.
155+
156+
== Targets
157+
158+
[[make-show]]
159+
=== `make show`
160+
161+
Renders the Helm template of the link:https://github.com/validatedpatterns/pattern-install-chart[pattern-install chart] to show the manifests that would be applied by <<make-install,`make install`>>.
162+
163+
WARNING: It does *not* render the namespaces, subscriptions, and projects managed by the Patterns Operator via the clustergroup-chart. It only shows:
164+
165+
* the Patterns Operator subscription and associated configmap
166+
* the `Pattern` CR which enables installation of the pattern
167+
168+
==== Overrides
169+
170+
[cols="2,2,4,2"]
171+
|===
172+
| Ansible var | Environment var | Purpose | Default
173+
174+
| `pattern_dir`
175+
| `PATTERN_DIR`
176+
| Directory containing the pattern repo to be shown/installed
177+
| current working directory
178+
179+
| `pattern_name`
180+
| `PATTERN_NAME`
181+
| Name for the Helm release / Pattern CR
182+
| basename of `pattern_dir`
183+
184+
| `pattern_install_chart`
185+
| `PATTERN_INSTALL_CHART`
186+
| OCI URL for the install chart
187+
| `oci://quay.io/validatedpatterns/pattern-install`
188+
189+
| `target_branch`
190+
| `TARGET_BRANCH`
191+
| Git branch used for the repo
192+
| `git rev-parse --abbrev-ref HEAD`
193+
194+
| `target_origin`
195+
| `TARGET_ORIGIN`
196+
| Git remote for the branch
197+
| `git config branch.<branch>.remote`
198+
199+
| `target_clustergroup`
200+
| `TARGET_CLUSTERGROUP`
201+
| Which clustergroup to install (if different from `main.clusterGroupName` in values-global.yaml)
202+
| value of `main.clusterGroupName` in values-global.yaml
203+
204+
| `token_secret`
205+
| `TOKEN_SECRET`
206+
| Secret name for private repos (link:https://validatedpatterns.io/blog/2023-12-20-private-repos/[docs])
207+
| empty
208+
209+
| `token_namespace`
210+
| `TOKEN_NAMESPACE`
211+
| Namespace of the secret
212+
| empty
213+
214+
| `extra_helm_opts`
215+
| `EXTRA_HELM_OPTS`
216+
| Extra args to pass to `helm template`
217+
| empty
218+
219+
| `uuid_file`
220+
| `UUID_FILE`
221+
| Path to a file containing a UUID used for analytics. Ensures team-internal deploys can be filtered from external ones. Users generally do not need to override this.
222+
| `~/.config/validated-patterns/pattern-uuid` if exists, otherwise unset
223+
|===
224+
225+
[[make-operator-deploy]]
226+
=== `make operator-deploy`
227+
228+
Performs validations and applies the manifests rendered by <<make-show,`make show`>> to your cluster.
229+
230+
The <<make-install,`make install`>> target is usually preferred for new installs, since it also handles secret loading.
231+
The primary use case for `operator-deploy` is updating an existing pattern to point to a different git repo, revision, or origin—without refreshing secrets.
232+
233+
==== Overrides
234+
235+
Same as <<make-show,`make show`>> plus:
236+
237+
[cols="2,2,4,1"]
238+
|===
239+
| Ansible var | Environment var | Purpose | Default
240+
241+
| `disable_validate_origin`
242+
| `DISABLE_VALIDATE_ORIGIN`
243+
| Whether git origin reachability should be validated
244+
| false
245+
|===
246+
247+
[[make-install]]
248+
=== `make install`
249+
250+
Identical to <<make-operator-deploy,`make operator-deploy`>> up through applying the pattern manifests.
251+
Afterward, if `global.secretLoader.disabled` is *not set* or is `false` in `values-global.yaml`, this target also runs <<make-load-secrets,`make load-secrets`>>.
252+
253+
* If your pattern doesn't use secrets, this is functionally identical to `operator-deploy`.
254+
* If your pattern does use secrets, `install` ensures they are loaded into Vault in the cluster.
255+
256+
==== Overrides
257+
258+
Same as <<make-operator-deploy,`make operator-deploy`>>.
259+
260+
=== `make validate-prereq`
261+
262+
Validates prerequisites needed for installation:
263+
264+
* Confirms the `pattern_name` matches the value in `values-global.yaml`
265+
* On host: checks for `python-kubernetes` and the `kubernetes.core` Ansible collection
266+
* In container: ensures `.main.multiSourceConfig.enabled` is set to `true` in `values-global.yaml`
267+
268+
Typically run as part of `make install`/`make operator-deploy` but can be invoked manually.
269+
270+
=== `make validate-origin`
271+
272+
Ensures the pattern's git origin and branch are reachable.
273+
Invoked automatically during install unless explicitly disabled, but can also be run standalone.
274+
275+
=== `make validate-cluster`
276+
277+
Ensures you are logged into an OpenShift cluster and that a storage class is available.
278+
This prevents failed installs due to missing cluster prerequisites.
279+
Invoked automatically during install but may be run manually for a quick sanity check.
280+
281+
[[make-load-secrets]]
282+
=== `make load-secrets`
283+
284+
Loads secrets into Vault in the cluster if `global.secretLoader.disabled` is not set or is `false`.
285+
Run automatically as part of <<make-install,`make install`>>, but can also be run independently if you need to reload secrets.
286+
287+
== Wrapping Up
288+
289+
By retiring the `common` directory, we've eliminated duplication and made every pattern repo smaller, simpler, and easier to maintain.
290+
291+
With a single, centralized Makefile:
292+
* Updates flow automatically across all patterns
293+
* Repositories stay lean and uncluttered
294+
* Developers get a consistent, predictable experience
295+
296+
Ready to try it? Run:
297+
298+
[source,bash]
299+
----
300+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer upgrade
301+
----
302+
303+
and commit the changes. Your repo will instantly be on the new path.

0 commit comments

Comments
 (0)