Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
0577def
Created pattern specification validation CI checks.
chynasan Sep 15, 2025
cf64adc
Updated with a few notes
chynasan Sep 15, 2025
3a31ea5
Updated some pieces of this in a pairing session
chynasan Sep 15, 2025
1ccb606
Updated based on feedback and with simplified tasks and including sch…
chynasan Sep 16, 2025
eb05b66
Updated to ensure meaningful error messages, and to ensure github com…
chynasan Sep 16, 2025
206f2b2
Updated dev to 2.0.0 for testing.
chynasan Sep 16, 2025
c6c7d90
Testing the creation of pattern-schema-2.0.0, expected pass in CI
chynasan Sep 16, 2025
e8189b1
Test for mismatch 2.0.0/2.2.2 spec file - should fail CI.
chynasan Sep 16, 2025
d864ab7
Test for mismatch 2.0.0/2.2.2 schema file - should fail CI.
chynasan Sep 16, 2025
85ab63e
Test for mismatch 2.0.0/2.2.2 schema file - should fail CI, added ech…
chynasan Sep 16, 2025
28da52b
Test for mismatch 2.0.0/2.2.2 schema file - should fail CI, added ech…
chynasan Sep 16, 2025
e2131ed
Test for mismatch 1.0.0 schema file with 1.1.1 id value - should fail…
chynasan Sep 16, 2025
bf5b01d
Test for mismatch 1.0.0 schema file with 1.1.1 id value - should fail…
chynasan Sep 16, 2025
eda1ea6
Reconfigure the task to correctly exit the workflow step vs doing a s…
beeankha Sep 16, 2025
58d4b66
Add more debugging statements
beeankha Sep 16, 2025
726b96f
Remove debug statements
beeankha Sep 16, 2025
57bbe3f
Updated dev to 2.0.0 for testing, expected to pass validate-pattern-s…
chynasan Sep 16, 2025
e9991ca
Updated dev to 2.0.0 for testing, expected to pass validate-pattern-s…
chynasan Sep 16, 2025
fa0b4b7
Created pattern-schema-2.0.0 (but that was a lie), expected to pass v…
chynasan Sep 16, 2025
ec3059a
Created pattern-schema-2.0.0 (but that was a lie), updated latest, e…
chynasan Sep 16, 2025
9b58479
Created pattern-schema-2.0.0 (but that was a lie), did not change the…
chynasan Sep 16, 2025
e0fb8a9
Modified version number of pattern spec to 1.1.1, did not change the …
chynasan Sep 16, 2025
e795345
New 2.0.0 schema file with version match (should pass)
chynasan Sep 16, 2025
83e5c73
Updated latest to 2.0.0, should pass.
chynasan Sep 16, 2025
0c6750b
Update spec file validation task for subtask exit, add debug statements
beeankha Sep 16, 2025
f25d248
Make use of --diff-filter
beeankha Sep 17, 2025
e482b16
Add new spec file w/ version updated correctly (should pass)
beeankha Sep 17, 2025
892f93f
Add new spec file w/ version mismatch (should fail)
beeankha Sep 17, 2025
cedaae2
Spec file validation with changes to dev file (should pass)
beeankha Sep 17, 2025
4c9ef24
Spec file validation with changes to 1.0.0 file (should fail)
beeankha Sep 17, 2025
0abef90
Validate schema file with changes to dev (should pass)
beeankha Sep 17, 2025
4e02828
Add new schema file with version match in file + latest (should pass)
beeankha Sep 17, 2025
9260074
Update validation workflow
beeankha Sep 17, 2025
be4dfdd
Add more debug statements
beeankha Sep 17, 2025
5863abd
Try a 'skip' step to see if latest schema file validation works
beeankha Sep 17, 2025
f405445
Make more use of --diff-filter, remove debug statements
beeankha Sep 17, 2025
85f90a9
Validate new schema file with mismatch but matching latest (should f…
beeankha Sep 17, 2025
c5bed57
Validate new schema file with match but mismatching latest (should f…
beeankha Sep 17, 2025
d5e7e25
Validate change to 1.0.0 schema file (should fail)
beeankha Sep 17, 2025
f3a55af
Add a check for ANY modification to existing schema files
beeankha Sep 17, 2025
faede9b
Re-validate new schema file with change to latest (should pass)
beeankha Sep 17, 2025
2f95312
Make change to dev schema file (should pass)
beeankha Sep 17, 2025
3b19bd9
Re-validate new schema file (should pass)
beeankha Sep 17, 2025
2032676
Validate any change to existing spec file that isn't dev (should fail)
beeankha Sep 17, 2025
d228705
Validate new spec file with version match (should pass)
beeankha Sep 17, 2025
9a70f9d
Validate new spec file with version match (should pass)
beeankha Sep 17, 2025
33e9334
Validate changes to 1.00 spec file (should fail)
beeankha Sep 17, 2025
bb4c028
Everything back to normal (should pass)
beeankha Sep 17, 2025
0e97037
Validate new spec file with version mismatch (should fail)
beeankha Sep 17, 2025
fcc67bd
Validate new spec file with version match (should pass)
beeankha Sep 17, 2025
ab01027
Remove trailing white space
beeankha Sep 17, 2025
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
129 changes: 129 additions & 0 deletions .github/workflows/validate-pattern-specs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
name: Validate Pattern Specs

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
validate-pattern-specs:
runs-on: ubuntu-latest

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get changed files
id: changed-files
run: |
# New specification files
NEW_SPEC_FILES=$(git diff origin/main --name-only --diff-filter=A -- specifications/pattern-specification/*.md ":(exclude)*dev.md" || true)
echo "new_spec_files<<EOF" >> $GITHUB_OUTPUT
echo "$NEW_SPEC_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Modified specification files
MODIFIED_SPEC_FILES=$(git diff origin/main --name-only --diff-filter=M -- specifications/pattern-specification/*.md ":(exclude)*dev.md" || true)
echo "modified_spec_files<<EOF" >> $GITHUB_OUTPUT
echo "$MODIFIED_SPEC_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# All changed specification files
ALL_SPEC_FILES=$(git diff origin/main --name-only --diff-filter=AM -- specifications/pattern-specification/*.md ":(exclude)*dev.md" || true)
echo "spec_files<<EOF" >> $GITHUB_OUTPUT
echo "$ALL_SPEC_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# New schema files
NEW_SCHEMA_FILES=$(git diff origin/main --name-only --diff-filter=A -- specifications/pattern-schema/*.json ":(exclude)*dev.json" || true)
echo "new_schema_files<<EOF" >> $GITHUB_OUTPUT
echo "$NEW_SCHEMA_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Modified schema files
MODIFIED_SCHEMA_FILES=$(git diff origin/main --name-only --diff-filter=M -- specifications/pattern-schema/*.json ":(exclude)*dev.json" || true)
echo "modified_schema_files<<EOF" >> $GITHUB_OUTPUT
echo "$MODIFIED_SCHEMA_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# All changed schema files
ALL_SCHEMA_FILES=$(git diff origin/main --name-only --diff-filter=AM -- specifications/pattern-schema/*.json ":(exclude)*dev.json" || true)
echo "schema_files<<EOF" >> $GITHUB_OUTPUT
echo "$ALL_SCHEMA_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Validate pattern specification files
if: steps.changed-files.outputs.spec_files != ''
run: |
# First, check if any existing specification files were modified (not allowed)
if [ -n "${{ steps.changed-files.outputs.modified_spec_files }}" ]; then
echo "::error::Modifying existing versioned specification files is not allowed. Modified files: ${{ steps.changed-files.outputs.modified_spec_files }}"
exit 1
fi

# Then validate new specification files
NEW_SPEC_FILES="${{ steps.changed-files.outputs.new_spec_files }}"
while IFS= read -r file; do
if [ -n "$file" ]; then
# New specification file - validate version consistency
# Extract version once
FILENAME_VERSION=$(echo "$file" | sed -n 's/.*pattern-specification-\([^/]*\)\.md/\1/p')
FILE_VERSION=$(sed -n 's/^version:[[:space:]]*\([^[:space:]]*\).*/\1/p' "$file" | head -1)

# Validate filename vs content version
if [ "$FILENAME_VERSION" != "$FILE_VERSION" ]; then
echo "::error::Specification file name does not match the specification version. Expected: $FILENAME_VERSION, Got: $FILE_VERSION"
exit 1
fi
fi
done <<< "$NEW_SPEC_FILES"

- name: Validate pattern schema files
if: steps.changed-files.outputs.schema_files != ''
run: |
SCHEMA_FILES="${{ steps.changed-files.outputs.schema_files }}"
while IFS= read -r file; do
if [ -n "$file" ]; then
# Skip the latest file to ensure proper validation of $id field
if [[ "$file" == *"pattern-schema-latest.json" ]]; then
continue
fi

# Check if this is a modified existing versioned file (not allowed)
if git show origin/main:$file >/dev/null 2>&1; then
echo "::error::Modifying existing versioned schema files is not allowed. Modified file: $file"
exit 1
fi

# Extract version from filename
VERSION=$(echo "$file" | sed -n 's/.*pattern-schema-\([^/]*\)\.json/\1/p')
if [ -n "$VERSION" ]; then
# Construct expected ID for the new versioned file
EXPECTED_ID="https://raw.githubusercontent.com/ansible/pattern-service/main/specifications/pattern-schema/pattern-schema-${VERSION}.json"

# Validate versioned schema file's $id field
ACTUAL_ID=$(git show HEAD:$file | jq -r '.["$id"] // empty')
if [ "$ACTUAL_ID" != "$EXPECTED_ID" ]; then
echo "::error::Schema file $file has incorrect \$id field. Expected: $EXPECTED_ID, Got: $ACTUAL_ID"
exit 1
fi

# Validate latest schema file points to new version
LATEST_ID=$(git show HEAD:specifications/pattern-schema/pattern-schema-latest.json | jq -r '.["$id"] // empty')
if [ "$LATEST_ID" != "$EXPECTED_ID" ]; then
echo "::error::Latest schema file was not updated to point to new version $VERSION. Expected \$id: $EXPECTED_ID, Got: $LATEST_ID"
exit 1
fi
fi
fi
done <<< "$SCHEMA_FILES"
101 changes: 101 additions & 0 deletions specifications/pattern-specification/pattern-specification-2.0.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: Ansible Patterns Specification
author: Ansible Cloud Content team
version: 2.0.0
---

# Ansible Pattern Specification

## Introduction

This document describes the technical specification for an Ansible pattern, an extension of collections, which are the standard method for packaging and distributing Ansible content. Patterns are used by Ansible Automation Platform (AAP) to offer users the ability to start automating with minimal setup, enhancing productivity and efficiency.

A pattern defines an Ansible automation, such as a playbook, and the resources needed in AAP to run that automation, such as a project, execution environment, job template, and survey. The pattern definition can be consumed by the AAP API to create and configure those resources, allowing pattern catalogs to provide users with a seamless journey from identifying relevant patterns to using them in AAP.

Patterns are delivered as files within an Ansible collection. This approach ensures consistent integration with the Ansible ecosystem by leveraging the existing collection framework. These patterns are bundled during collection packaging, enabling them to be searchable, downloadable, and publishable alongside roles, modules, and plugins.

## Conventions

This document follows the IETF [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119) definitions of Key words for use in RFCs to Indicate Requirement Levels.

## Support

This pattern specification is supported and maintained by Ansible. To submit support or other requests for the specification, please contact Red Hat support.

Individual patterns that implement this specification are the responsibility of the collection maintainers for the collections in which they reside. For support or feature requests for individual patterns, contact their collection owners.

## Pattern Directory Structure

- A pattern **MUST** be contained within a single directory in the `/extensions/patterns/` directory of an Ansible collection.
- An Ansible pattern directory name **MUST** be limited to 64 characters and **MUST** only include lowercase ASCII letters, digits, and underscores.
- An Ansible collection **MAY** contain zero or more patterns.

## Required Files

### `meta/pattern.json`

The pattern definition meta file is the machine-readable entry point for creating an instance of the pattern in AAP. It defines the resources required to execute the pattern, such as a controller project, execution environment, job templates, and labels. The pattern definition also includes metadata about the pattern to enable its discovery and use, such as its title, audience, and tags. A [JSON schema](https://github.com/ansible/pattern-service/blob/main/specifications/pattern-schema/pattern-schema-1.0.0.json) has been published to aid with validation of the pattern definition file.

- A pattern **MUST** include exactly one meta file defining the pattern metadata and AAP resources it requires.
- The pattern definition meta file **MUST** be a valid instance of the [Ansible pattern schema](https://github.com/ansible/pattern-service/blob/main/specifications/pattern-schema/pattern-schema-1.0.0.json).

### `README.md`

The README file is the human-readable documentation for the pattern. It provides information on what the pattern does, its inputs, its dependencies, and how it can be used.

- A pattern **MUST** include a README file.
- The pattern README file **SHOULD** include all of the following:
- A description of what the pattern does
- A list of the AAP resources created by the pattern
- Documentation on how to use the pattern

### `playbooks/`

Pattern playbook files are included in the `/extensions/patterns/<pattern_name>/playbooks/` directory.

- A pattern **MUST** contain a `playbooks/` directory.
- The `playbooks/` directory **MUST** contain at least one playbook associated with a job template definition in the pattern's `meta/pattern.json` file.
- A pattern **MAY** contain multiple playbooks.
- If a pattern contains multiple playbooks, it **MUST** define a primary playbook in its `meta/pattern.json` file.

#### Playbook Requirements

- All required and optional input variables to a pattern playbook **MUST** be defined in a play argument spec following this example of the [play argument spec format](https://github.com/ansible/ansible-creator/blob/main/src/ansible_creator/resources/playbook_project/argspec_validation_plays.meta.yml).
- If a pattern playbook requires any user-provided information other than variables to launch as a job template, such as inventory or credentials, those **MUST** be specified as `ask_<field>_at_launch` in the relevant `controller_job_templates` section of the pattern definition meta file.

## Optional Files

### `templates/`

Templates for various types of catalog software in which patterns may be published. A template provides pattern data in the format required for a given catalog, such as Red Hat Developer Hub.

- A pattern **MAY** contain a `templates/` directory to hold templates specific to catalogs that may publish the pattern, such as Red Hat Developer Hub or ServiceNow.
- The `templates/` directory **MAY** contain one or more catalog template files.


## Validation

Pattern developers can use [ansible-lint](https://github.com/ansible/ansible-lint) to verify the structure of a pattern and its JSON against the pattern schema.

## Example Pattern Directory

```txt

/extensions/patterns/
├── network.backup/ # Backup pattern directory
│ ├── meta/pattern.json # Backup pattern definition
│ ├── README.md # Documentation for Backup pattern
│ ├── playbooks/ # Directory containing pattern playbooks
│ │ ├── backup.meta.yaml # Backup playbook arg spec
│ │ ├── backup.yaml # Backup playbook
│ ├── templates/ # Directory containing catalog templates
│ │ ├── rhdh.yaml # Display template for RHDH catalog

```

## Other Pattern Requirements

- A pattern **MUST** inherit the version number of the collection that contains it.
- A pattern **MUST** be valid according to the requirements specified in this document, including validation of each file contained in the pattern against its relevant schema.
- Changes to patterns **MUST** be noted in collection-level changelogs and release notes.
- All system, python, and Ansible collection dependencies needed to run a pattern's automations **MUST** be declared in the collection's dependency files, including but not limited to: `galaxy.yml`, `requirements.txt`, and `execution_environment.yml`.