Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b9e480d
Bump sigstore/cosign-installer from 4.0.0 to 4.1.0
dependabot[bot] Mar 18, 2026
2c79c72
Bump actions/upload-artifact from 4.6.2 to 7.0.0
dependabot[bot] Mar 18, 2026
c7d33b8
Bump actions/download-artifact from 4.3.0 to 8.0.1
dependabot[bot] Mar 25, 2026
e430523
Merge pull request #2 from validatedpatterns/dependabot/github_action…
mbaldessari Mar 25, 2026
d41d61f
Merge pull request #1 from validatedpatterns/dependabot/github_action…
mbaldessari Mar 25, 2026
2e4e792
Merge pull request #3 from validatedpatterns/dependabot/github_action…
mbaldessari Mar 25, 2026
d0bbe75
Initial schema validation
mbaldessari Mar 31, 2026
b577f9b
Add action to check for json schema
mbaldessari Mar 31, 2026
d8ff19f
Bump sigstore/cosign-installer from 4.1.0 to 4.1.1
dependabot[bot] Apr 8, 2026
fc2654f
feat: Add list make target, change org var to overridable
darkdoc Apr 13, 2026
b656d22
Merge pull request #5 from darkdoc/minor_improvements
mbaldessari Apr 13, 2026
6ca5f2b
Merge pull request #4 from validatedpatterns/dependabot/github_action…
mbaldessari Apr 13, 2026
562d59f
Add somre readme improvements for custom catalog
mbaldessari Apr 15, 2026
666bfc7
Add custom github org mention and values secret mention
mbaldessari Apr 15, 2026
cbb4492
Merge pull request #6 from mbaldessari/add-custom-catalog-docs
mbaldessari Apr 15, 2026
e483f13
Use ui-catalog-enabled as the topic to detect viable repos
mbaldessari Apr 15, 2026
4eb8b00
Merge pull request #7 from mbaldessari/new-topic
mbaldessari Apr 15, 2026
7857278
Update catalog
mbaldessari Apr 16, 2026
e37ac41
Fix schema and one metdata update
mbaldessari Apr 16, 2026
a11154b
Merge pull request #8 from mbaldessari/update-catalog
mbaldessari Apr 16, 2026
260ab8f
Add tech-preview mention
mbaldessari Apr 16, 2026
276b5d1
Merge pull request #9 from mbaldessari/add-tech-preview
darkdoc Apr 16, 2026
59bd4af
Update catalog
mbaldessari Apr 16, 2026
1e1f5f5
Merge pull request #10 from mbaldessari/update-catalog2
darkdoc Apr 16, 2026
79f8ae1
Merge remote-tracking branch 'upstream/main' into update-stable-v1
mbaldessari Apr 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
buildah push "${CONTAINER}-${TARGETARCH}" "docker-archive:/tmp/image-${TARGETARCH}.tar:${CONTAINER}-${TARGETARCH}"

- name: Upload image artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: image-${{ matrix.targetarch }}-${{ github.run_id }}
path: /tmp/image-${{ matrix.targetarch }}.tar
Expand All @@ -79,13 +79,13 @@ jobs:

steps:
- name: Download AMD64 image
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: image-amd64-${{ github.run_id }}
path: /tmp

- name: Download ARM64 image
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: image-arm64-${{ github.run_id }}
path: /tmp
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"

- name: Install cosign
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
with:
cosign-release: "v2.2.4"

Expand Down
51 changes: 51 additions & 0 deletions .github/workflows/jsonschema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: Verify json schema

on:
push:
paths:
- '.github/workflows/jsonschema.yaml'
- 'catalog/**'
- '*.schema.json'
pull_request:
paths:
- '.github/workflows/jsonschema.yaml'
- 'catalog/**'
- '*.schema.json'

permissions: read-all # zizmor: ignore[excessive-permissions]

jobs:
jsonschema_tests:
name: Json Schema tests
strategy:
matrix:
python-version: [3.11.3]
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install check-jsonschema

- name: Validate catalog.yaml
run: |
check-jsonschema --schemafile catalog.schema.json catalog/catalog.yaml

- name: Validate pattern metadata files
run: |
for f in catalog/*/pattern.yaml; do
echo "Validating ${f}..."
check-jsonschema --schemafile pattern.schema.json "${f}"
done
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ help: ## Display this help.

##@ Pattern Catalog

.PHONY: list-patterns
list-patterns: ## Lists all pattern repos
./list-all-patterns.sh

.PHONY: generate-catalog
generate-catalog: ## Generates actual catalog yaml tree
./generate-catalog.sh
Expand All @@ -23,6 +27,16 @@ generate-catalog: ## Generates actual catalog yaml tree
generate-dockerfile: ## Generate Dockerfile from template
VERSION=$(VERSION) SUPPORTED_OCP_VERSIONS=$(SUPPORTED_OCP_VERSIONS) envsubst < templates/pattern-ui-catalog.Dockerfile.template > $(PATTERN_CATALOG_DOCKERFILE)

.PHONY: schema-validate
schema-validate: ## Validate catalog YAML files against JSON schemas
@command -v check-jsonschema >/dev/null 2>&1 || { echo "Error: check-jsonschema not found. Install with: pip install check-jsonschema"; exit 1; }
check-jsonschema --schemafile catalog.schema.json catalog/catalog.yaml
@for f in catalog/*/pattern.yaml; do \
echo "Validating $$f..."; \
check-jsonschema --schemafile pattern.schema.json "$$f"; \
done
@echo "All catalog files validated successfully."

.PHONY: pattern-ui-catalog-build
pattern-ui-catalog-build: generate-dockerfile## Build the pattern catalog image
@echo "Building pattern catalog image..."
Expand Down
194 changes: 186 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ A catalog of [Validated Patterns](https://validatedpatterns.io) metadata, served
The `generate-catalog.sh` script queries the GitHub API for all repositories tagged with `pattern` in the `validatedpatterns` and `validatedpatterns-sandbox` organizations. For each repository it:

1. Fetches `pattern-metadata.yaml` and normalizes it into a consistent schema
2. Fetches `values-secret.yaml.template` if present
3. Writes per-pattern files under `catalog/<pattern-name>/`
4. Generates a `catalog/catalog.yaml` index listing all discovered patterns
1. Fetches `values-secret.yaml.template` if present
1. Writes per-pattern files under `catalog/<pattern-name>/`
1. Generates a `catalog/catalog.yaml` index listing all discovered patterns

The resulting `catalog/` directory is served by an nginx container image that the patterns-operator deploys on-cluster.

Expand Down Expand Up @@ -55,16 +55,194 @@ pushes to `main` or `stable-v1` when files in `catalog/`, `templates/`, or the
workflow itself change:

1. **validate-yaml** — validates all YAML files under `catalog/` with `yamllint`
2. **build-container** — builds the image for amd64 and arm64 in parallel on native runners
3. **push-multiarch-manifest** — assembles a multi-arch manifest, pushes to Quay, and signs with cosign (only in the upstream `validatedpatterns/pattern-ui-catalog` repo)
1. **build-container** — builds the image for amd64 and arm64 in parallel on native runners
1. **push-multiarch-manifest** — assembles a multi-arch manifest, pushes to Quay, and signs with cosign (only in the upstream `validatedpatterns/pattern-ui-catalog` repo)

| Branch | Image tag |
| Branch | Image tag |
|-------------|---------------|
| `main` | `:latest` |
| `stable-v1` | `:stable-v1` |
| `main` | `:latest` |
| `stable-v1` | `:stable-v1` |

The workflow requires `QUAY_USERNAME` and `QUAY_PASSWORD` secrets configured in a `quay` environment.

## Creating a custom catalog

You can build your own catalog image containing a curated set of patterns. This
is useful when you maintain internal or third-party patterns that are not part of
the upstream `validatedpatterns` organizations.

If the patterns you want to include are all hosted on GitHub you can just run the
following script:

```sh
TOPIC=pattern ORGS="org1 org2" make generate-catalog
```

The above script will generate the catalog bit by using
any repo with the `pattern` topic (topics are some sort of tags on GitHub)
in `org1` and `org2` on github. Then you can just skip to section
[Build and push the image](#2-build-and-push-the-image).

```sh
make UPLOADREGISTRY=quay.io/<my_own_org> pattern-ui-catalog-build pattern-ui-catalog-push
```

### 1. Prepare the catalog directory

Create a `catalog/` tree with the following structure:

```txt
catalog/
catalog.yaml
my-pattern/pattern.yaml
my-pattern/values-secret.yaml.template # optional
another-pattern/pattern.yaml
```

**`catalog/catalog.yaml`** — the index file listing every pattern in the catalog:

```yaml
generated_at: "2026-04-15T00:00:00Z"
generator_version: "1.0"
catalog_description: "My custom pattern catalog"
patterns:
- my-pattern
- another-pattern
```

**`catalog/<name>/pattern.yaml`** — metadata for each pattern. Required fields
are defined by `pattern.schema.json`; a minimal example:

```yaml
metadata_version: "1.0"
name: my-pattern
pattern_version: "1.0"
display_name: My Pattern
repo_url: https://github.com/my-org/my-pattern
docs_repo_url: https://github.com/my-org/my-pattern-docs
issues_url: https://github.com/my-org/my-pattern/issues
docs_url: https://my-org.github.io/my-pattern/
ci_url: https://my-org.github.io/my-pattern/ci
tier: sandbox # maintained | tested | sandbox
owners:
- my-github-user
requirements:
hub:
compute:
aws:
replicas: 3
type: m5.2xlarge
controlPlane:
aws:
replicas: 3
type: m5.xlarge
extra_features:
hypershift_support: false
spoke_support: false
external_requirements: null
org: my-org
spoke: null
```

**`catalog/<name>/values-secret.yaml.template`** - metadata for secret material
for the pattern. See [here](https://validatedpatterns.io/learn/secrets-management-in-the-validated-patterns-framework/) for more information.

You can optionally validate your files against the JSON schemas shipped in this
repository:

```sh
make schema-validate
```

### 2. Build and push the image

Override `UPLOADREGISTRY` (and optionally `VERSION`) to point at your own
registry:

```sh
make UPLOADREGISTRY=quay.io/my-org VERSION=1.0.0 pattern-ui-catalog-build
make UPLOADREGISTRY=quay.io/my-org VERSION=1.0.0 pattern-ui-catalog-push
```

This produces `quay.io/my-org/pattern-ui-catalog:1.0.0`.

### 3. Point the patterns-operator at your catalog image

The [patterns-operator](https://github.com/validatedpatterns/patterns-operator)
reads an optional `catalog.image` key from its ConfigMap. By default it deploys
`quay.io/validatedpatterns/pattern-ui-catalog:stable-v1`. To override it, patch
(or create) the `patterns-operator-config` ConfigMap in the operator namespace
(`patterns-operator` by default):

```sh
oc patch configmap patterns-operator-config \
-n patterns-operator \
--type merge \
-p '{"data":{"catalog.image":"quay.io/my-org/pattern-ui-catalog:1.0.0"}}'
```

If the ConfigMap does not exist yet:

```sh
oc create configmap patterns-operator-config \
-n patterns-operator \
--from-literal=catalog.image=quay.io/my-org/pattern-ui-catalog:1.0.0
```

The operator picks up the change on its next reconciliation loop and performs a
rolling update of the catalog deployment.

## Authenticated container registries

If your custom catalog image is hosted on a registry that requires
authentication (e.g. a private Quay repository), you need to configure a pull
secret so that the cluster can pull the image.

### 1. Create a pull secret

Create an authentication secret in the operator namespace:

```sh
oc create secret docker-registry my-catalog-pull-secret \
-n patterns-operator \
--docker-server=quay.io \
--docker-username='<username>' \
--docker-password='<password>'
```

### 2. Link the secret to the operator service account

The catalog deployment runs under the `patterns-operator-controller-manager`
service account. Link the pull secret to it:

```sh
oc secrets link patterns-operator-controller-manager my-catalog-pull-secret \
-n patterns-operator \
--for=pull
```

### 3. Alternative: global pull secret

If multiple workloads need access to the same registry, you can add the
credentials to the cluster-wide pull secret instead. Extract the current secret,
merge your credentials, and apply:

```sh
oc get secret/pull-secret -n openshift-config --template='{{index .data ".dockerconfigjson" | base64decode}}' > /tmp/pull-secret.json

# Authenticate to your registry (this merges the new entry into the file)
oc registry login --registry=quay.io \
--auth-basic='<username>:<password>' \
--to=/tmp/pull-secret.json

oc set data secret/pull-secret -n openshift-config \
--from-file=.dockerconfigjson=/tmp/pull-secret.json
```

> **Note:** Updating the global pull secret triggers a rolling reboot of all
> nodes in the cluster. Prefer the per-service-account approach when only the
> catalog needs access.

## Repository structure

```
Expand Down
34 changes: 34 additions & 0 deletions catalog.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://validatedpatterns.io/catalog.schema.json",
"title": "Pattern Catalog",
"description": "Schema for the pattern catalog index file (catalog.yaml)",
"type": "object",
"required": ["generated_at", "generator_version", "catalog_description", "patterns"],
"additionalProperties": false,
"properties": {
"generated_at": {
"type": "string",
"description": "ISO 8601 timestamp of catalog generation",
"format": "date-time"
},
"generator_version": {
"type": "string",
"description": "Version of the catalog generator",
"pattern": "^[0-9]+\\.[0-9]+$"
},
"catalog_description": {
"type": "string",
"description": "Description shown in the catalog UI"
},
"patterns": {
"type": "array",
"description": "List of pattern identifiers included in the catalog",
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9-]*$"
},
"minItems": 1
}
}
}
1 change: 1 addition & 0 deletions catalog/ansible-edge-gitops/pattern.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
metadata_version: "2.0"
name: ansible-edge-gitops
pattern_version: "2.0"
description: Ansible Edge GitOps demonstrates managing edge devices and VMs at scale using Ansible Automation Platform on OpenShift, bringing GitOps practices to environments that lack native GitOps support.
display_name: Ansible Edge GitOps
repo_url: https://github.com/validatedpatterns/ansible-edge-gitops
docs_repo_url: https://github.com/validatedpatterns/docs
Expand Down
11 changes: 6 additions & 5 deletions catalog/catalog.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
generated_at: "2026-03-13T15:39:18Z"
generated_at: "2026-04-16T09:03:31Z"
generator_version: "1.0"
catalog_description: 'Additional patterns can be found here: <a href="https://validatedpatterns.io">validatedpatterns.io</a>'
catalog_description: '(Tech-Preview) Additional patterns can be found here: <a href="https://validatedpatterns.io">validatedpatterns.io</a>'
patterns:
- ansible-edge-gitops
- industrial-edge
- medical-diagnosis
- layered-zero-trust
- mlops-fraud-detection
- multicloud-gitops
- rag-llm-gitops
- openshift-ai
- travelops
- hypershift
Loading