Skip to content

Commit caf2c3d

Browse files
authored
Merge pull request #594 from dminnear-rh/new-makefile-structure
add blog post about removal of common in favor of Makefile-common
2 parents 6182e5e + ee73cc1 commit caf2c3d

File tree

1 file changed

+305
-0
lines changed

1 file changed

+305
-0
lines changed
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
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+
TIP: You can always set the environment variable `PATTERN_UTILITY_CONTAINER` inside or outside of pattern.sh to a specific semver tag to manually control the updates. (For example, you can set it to `quay.io/validatedpatterns/utility-container:v1.0.0`.)
50+
51+
=== The Adjustment: Discoverability
52+
53+
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.
54+
55+
We've solved this in two ways:
56+
57+
. *Built-in docs:* Every `Makefile-common` includes a link back to this post, so the reference is always at your fingertips.
58+
. *`make help` target:* Run `./pattern.sh make help` to see the list of available targets directly in your terminal.
59+
60+
== Getting Started with the New Structure
61+
62+
Adopting the new approach is straightforward whether you're bootstrapping a brand-new pattern repository or upgrading an existing one.
63+
64+
=== New repositories
65+
66+
. From the root of your repo, run:
67+
+
68+
[source,bash]
69+
----
70+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer init
71+
----
72+
+
73+
Add secrets scaffolding at any time with:
74+
+
75+
[source,bash]
76+
----
77+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer init --with-secrets
78+
----
79+
. Review the changes (`values-*.yaml`, `pattern.sh`, `Makefile`, `Makefile-common`), then commit.
80+
. Try it out:
81+
+
82+
[source,bash]
83+
----
84+
./pattern.sh make show
85+
----
86+
+
87+
[source,bash]
88+
----
89+
./pattern.sh make install
90+
----
91+
92+
=== Existing repositories
93+
94+
Move from the legacy `common` structure to the new Makefile-driven setup with a single command:
95+
96+
[source,bash]
97+
----
98+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer upgrade
99+
----
100+
101+
What this does:
102+
* Removes `common` (if present)
103+
* Removes `./pattern.sh` (symlink or file), then copies the latest script
104+
* Copies `Makefile-common` to the repo root
105+
* Updates your `Makefile`:
106+
** If it already contains `include Makefile-common`, it is left unchanged
107+
** If it exists but lacks the include, the include is prepended to the first line
108+
** If it doesn't exist, a default `Makefile` is created
109+
110+
If you prefer to fully replace your `Makefile` with the default version, run:
111+
112+
[source,bash]
113+
----
114+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer upgrade --replace-makefile
115+
----
116+
117+
After upgrading, commit the changes and use the targets described below (for example, `./pattern.sh make show` or `./pattern.sh make install`).
118+
119+
== Using `Makefile-common`
120+
121+
Patterns shipped without the `common` dir now have a `Makefile-common` that provides consistent developer and user targets.
122+
123+
=== How commands are executed
124+
125+
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>`).
126+
127+
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:
128+
129+
[source,bash]
130+
----
131+
ANSIBLE_STDOUT_CALLBACK=default EXTRA_PLAYBOOK_OPTS='-e hide_sensitive_output="false" -vvv' ./pattern.sh make load-secrets
132+
----
133+
134+
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.
135+
136+
=== Overriding variables
137+
138+
All pattern settings can be overridden in *two ways*:
139+
140+
. *Ansible variable*
141+
+
142+
Via the env var `EXTRA_PLAYBOOK_OPTS`, e.g.:
143+
+
144+
[source,bash]
145+
----
146+
EXTRA_PLAYBOOK_OPTS="-e target_branch=myfeature -e target_origin=upstream" ./pattern.sh make show
147+
----
148+
. *Environment variable*
149+
+
150+
[source,bash]
151+
----
152+
TARGET_BRANCH=myfeature TARGET_ORIGIN=upstream ./pattern.sh make show
153+
----
154+
155+
*Precedence:*
156+
`-e var=value` (CLI/inventory) → environment variables → defaults.
157+
158+
== Targets
159+
160+
[[make-show]]
161+
=== `make show`
162+
163+
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`>>.
164+
165+
WARNING: It does *not* render the namespaces, subscriptions, and projects managed by the Patterns Operator via the clustergroup-chart. It only shows:
166+
167+
* the Patterns Operator subscription and associated configmap
168+
* the `Pattern` CR which enables installation of the pattern
169+
170+
==== Overrides
171+
172+
[cols="2,2,4,2"]
173+
|===
174+
| Ansible var | Environment var | Purpose | Default
175+
176+
| `pattern_dir`
177+
| `PATTERN_DIR`
178+
| Directory containing the pattern repo to be shown/installed
179+
| current working directory
180+
181+
| `pattern_name`
182+
| `PATTERN_NAME`
183+
| Name for the Helm release / Pattern CR
184+
| basename of `pattern_dir`
185+
186+
| `pattern_install_chart`
187+
| `PATTERN_INSTALL_CHART`
188+
| OCI URL for the install chart
189+
| `oci://quay.io/validatedpatterns/pattern-install`
190+
191+
| `target_branch`
192+
| `TARGET_BRANCH`
193+
| Git branch used for the repo
194+
| `git rev-parse --abbrev-ref HEAD`
195+
196+
| `target_origin`
197+
| `TARGET_ORIGIN`
198+
| Git remote for the branch
199+
| `git config branch.<branch>.remote`
200+
201+
| `target_clustergroup`
202+
| `TARGET_CLUSTERGROUP`
203+
| Which clustergroup to install (if different from `main.clusterGroupName` in values-global.yaml)
204+
| value of `main.clusterGroupName` in values-global.yaml
205+
206+
| `token_secret`
207+
| `TOKEN_SECRET`
208+
| Secret name for private repos (link:https://validatedpatterns.io/blog/2023-12-20-private-repos/[docs])
209+
| empty
210+
211+
| `token_namespace`
212+
| `TOKEN_NAMESPACE`
213+
| Namespace of the secret
214+
| empty
215+
216+
| `extra_helm_opts`
217+
| `EXTRA_HELM_OPTS`
218+
| Extra args to pass to `helm template`
219+
| empty
220+
221+
| `uuid_file`
222+
| `UUID_FILE`
223+
| 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.
224+
| `~/.config/validated-patterns/pattern-uuid` if exists, otherwise unset
225+
|===
226+
227+
[[make-operator-deploy]]
228+
=== `make operator-deploy`
229+
230+
Performs validations and applies the manifests rendered by <<make-show,`make show`>> to your cluster.
231+
232+
The <<make-install,`make install`>> target is usually preferred for new installs, since it also handles secret loading.
233+
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.
234+
235+
==== Overrides
236+
237+
Same as <<make-show,`make show`>> plus:
238+
239+
[cols="2,2,4,1"]
240+
|===
241+
| Ansible var | Environment var | Purpose | Default
242+
243+
| `disable_validate_origin`
244+
| `DISABLE_VALIDATE_ORIGIN`
245+
| Whether git origin reachability should be validated
246+
| false
247+
|===
248+
249+
[[make-install]]
250+
=== `make install`
251+
252+
Identical to <<make-operator-deploy,`make operator-deploy`>> up through applying the pattern manifests.
253+
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`>>.
254+
255+
* If your pattern doesn't use secrets, this is functionally identical to `operator-deploy`.
256+
* If your pattern does use secrets, `install` ensures they are loaded into Vault in the cluster.
257+
258+
==== Overrides
259+
260+
Same as <<make-operator-deploy,`make operator-deploy`>>.
261+
262+
=== `make validate-prereq`
263+
264+
Validates prerequisites needed for installation:
265+
266+
* Confirms the `pattern_name` matches the value in `values-global.yaml`
267+
* On host: checks for `python-kubernetes` and the `kubernetes.core` Ansible collection
268+
* In container: ensures `.main.multiSourceConfig.enabled` is set to `true` in `values-global.yaml`
269+
270+
Typically run as part of `make install`/`make operator-deploy` but can be invoked manually.
271+
272+
=== `make validate-origin`
273+
274+
Ensures the pattern's git origin and branch are reachable.
275+
Invoked automatically during install unless explicitly disabled, but can also be run standalone.
276+
277+
=== `make validate-cluster`
278+
279+
Ensures you are logged into an OpenShift cluster and that a storage class is available.
280+
This prevents failed installs due to missing cluster prerequisites.
281+
Invoked automatically during install but may be run manually for a quick sanity check.
282+
283+
[[make-load-secrets]]
284+
=== `make load-secrets`
285+
286+
Loads secrets into Vault in the cluster if `global.secretLoader.disabled` is not set or is `false`.
287+
Run automatically as part of <<make-install,`make install`>>, but can also be run independently if you need to reload secrets.
288+
289+
== Wrapping Up
290+
291+
By retiring the `common` directory, we've eliminated duplication and made every pattern repo smaller, simpler, and easier to maintain.
292+
293+
With a single, centralized Makefile:
294+
* Updates flow automatically across all patterns
295+
* Repositories stay lean and uncluttered
296+
* Developers get a consistent, predictable experience
297+
298+
Ready to try it? Run:
299+
300+
[source,bash]
301+
----
302+
podman run -v "$PWD:/repo:z" quay.io/validatedpatterns/patternizer upgrade
303+
----
304+
305+
and commit the changes. Your repo will instantly be on the new path.

0 commit comments

Comments
 (0)