Skip to content

Commit 1b4ded8

Browse files
committed
feat: Add OpenAPI schema validation for CRD
* Defined OpenAPI v3 schema for the Repository Custom Resource Definition (CRD). This enhanced resource validation, improved client-side tooling like IDE autocompletion, and provided clearer API documentation. * Automated schema generation via a new `make update-schemas` target using `controller-gen`. This ensured schema accuracy and simplified maintenance. * Added a CI job to verify that generated OpenAPI schemas were current. This prevented stale schemas from being merged. * Documented the usage and benefits of the OpenAPI schema for users. This guided users on leveraging schema validation and tooling. * Enhanced `kubectl get repo` output with additional status columns for better observability. JIRA: https://issues.redhat.com/browse/SRVKP-7605 Signed-off-by: Chmouel Boudjnah <[email protected]>
1 parent d4af516 commit 1b4ded8

File tree

10 files changed

+828
-160
lines changed

10 files changed

+828
-160
lines changed

.tekton/linter.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,38 @@ spec:
9090
9191
exit $failed
9292
93+
- name: check-generated-schemas
94+
displayName: "Check generated OpenAPI schemas"
95+
image: golang:1.23
96+
workingDir: $(workspaces.source.path)
97+
env:
98+
- name: HUB_TOKEN
99+
valueFrom:
100+
secretKeyRef:
101+
name: "nightly-ci-github-hub-token"
102+
key: "hub-token"
103+
script: |
104+
set -eu
105+
git config --global --add safe.directory $(workspaces.source.path)
106+
107+
if uname -m | grep -q aarch64; then
108+
arch=arm64
109+
else
110+
arch=amd64
111+
fi
112+
113+
# version=$(curl -H "Authorization: Bearer ${HUB_TOKEN}" -L -s https://api.github.com/repos/mikefarah/yq/releases/latest|python3 -c 'import sys, json;dico=json.load(sys.stdin);print(dico["tag_name"])')
114+
version=v4.45.2
115+
curl -sH "Authorization: Bearer ${HUB_TOKEN}" -L https://github.com/mikefarah/yq/releases/download/${version}/yq_linux_${arch} -o /usr/bin/yq && \
116+
chmod +x /usr/bin/yq
117+
118+
curl -L -o/usr/bin/kubectl "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${arch}/kubectl" && \
119+
chmod +x /usr/bin/kubectl
120+
121+
make update-schemas
122+
# check now that the is no changes in config with git
123+
git diff --exit-code config/ || { echo "Error: you need to run 'make update-schemas' and commit it."; exit 1; }
124+
93125
- name: conventional-commits
94126
displayName: "conventional commit check"
95127
image: registry.access.redhat.com/ubi9/python-312

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ update-golden: ## run unit tests (updating golden files)
181181
@echo "Running unit tests to update golden files..."
182182
@./hack/update-golden.sh
183183

184+
.PHONY: update-schemas
185+
update-schemas: ## update openapi schemas
186+
@echo "Running update schemas..."
187+
@./hack/update-schemas.sh
188+
184189
.PHONY: generated
185190
generated: update-golden fumpt ## generate all files that needs to be generated
186191

config/300-repositories.yaml

Lines changed: 315 additions & 127 deletions
Large diffs are not rendered by default.

docs/content/docs/dev/_index.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,25 @@ We use [golden](https://pkg.go.dev/gotest.tools/v3/golden) files in our tests, f
195195
make update-golden
196196
```
197197

198-
Head over to the [./test/README.md](./test/README.md) for more information on how to update the golden files on the E2E tests.
198+
Head over to the
199+
[./test/README.md](https://github.com/openshift-pipelines/pipelines-as-code/blob/main/test/README.md)
200+
for more information on how to update the golden files on the E2E tests.
201+
202+
## Update OpenAPI Schemas
203+
204+
The CRD schemas are automatically generated from the Go code (generally
205+
`pkg/apis/pipelinesascode/v1alpha1/types.go`). After modifying
206+
any type definitions, you'll need to regenerate these schemas to update the CRD
207+
in `config/300-repositories.yaml`.
208+
209+
When modifying types, ensure the validation logic is appropriate, then run:
210+
211+
```shell
212+
make update-schemas
213+
```
214+
215+
There is a PAC CI check that will ensure that the CRD is up to date with the go
216+
code.
199217

200218
## Configuring the Pre Push Git checks
201219

docs/content/docs/guide/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: CLI tkn-pac
3-
weight: 100
3+
weight: 70
44
---
55
# Pipelines-as-Code CLI
66

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
title: OpenAPI Schema Validation
3+
weight: 80
4+
---
5+
6+
# OpenAPI Schema Validation for Repository CRDs
7+
8+
Pipelines-as-Code provides [OpenAPI](https://www.openapis.org/) schema validation for its Custom Resource
9+
Definitions (CRDs), which helps in writing the Repository resources. This page
10+
explains what OpenAPI schemas are, their benefits, and how to leverage them in
11+
your development environment.
12+
13+
## What is OpenAPI Schema Validation?
14+
15+
OpenAPI schema validation is a mechanism that adds metadata to Kubernetes CRDs, providing:
16+
17+
- **Type information**: Specifies expected data types for fields
18+
- **Required fields**: Marks which fields must be present
19+
- **Pattern validation**: Enforces specific formats (e.g., URLs must start with http:// or https://)
20+
- **Enumeration validation**: Limits fields to a predefined set of values
21+
- **Field descriptions**: Documents the purpose of each field
22+
23+
When you create or modify a Repository resource, the OpenAPI schema helps
24+
validate your configuration before it's applied to the cluster, catching errors
25+
early in the development process.
26+
27+
## Benefits of OpenAPI Schema Validation
28+
29+
Using OpenAPI schemas with Pipelines-as-Code provides numerous advantages:
30+
31+
1. **Early Error Detection**: Identifies configuration errors before applying resources to your cluster
32+
2. **Improved Documentation**: Field descriptions provide built-in documentation
33+
3. **Better IDE Support**: Enables rich autocompletion and validation in code editors
34+
4. **Standardized Formatting**: Ensures your resources follow expected formats
35+
5. **Self-Documenting API**: Makes it easier to understand the Repository CRD structure
36+
37+
## Using OpenAPI Schemas in VS Code
38+
39+
Visual Studio Code and other modern editors can leverage OpenAPI schemas to
40+
provide real-time validation, autocompletion, and documentation while editing
41+
your Repository resources.
42+
43+
### Setting Up VS Code for CRD Validation
44+
45+
![VSCode and openapi Schema](/images/vscode-openapi-schema.png)
46+
47+
1. Install the [Kubernetes](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools) extension (by Microsoft)
48+
2. Install the [YAML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) extension (by Red Hat)
49+
50+
These extensions will automatically detect and use the OpenAPI schema from your Kubernetes cluster when editing Repository resources.
51+
52+
### Example: Editing a Repository Resource in VS Code
53+
54+
When editing a Repository resource in VS Code with the appropriate extensions, you'll experience:
55+
56+
- **Autocompletion** for fields like `url`, `git_provider`, `settings`, etc.
57+
- **Validation** for required fields and field formats
58+
- **Documentation tooltips** when hovering over fields
59+
- **Enum dropdown suggestions** for fields with predefined values
60+
61+
Here's an example of what you'll see:
62+
63+
```yaml
64+
apiVersion: pipelinesascode.tekton.dev/v1alpha1
65+
kind: Repository
66+
metadata:
67+
name: my-repository
68+
spec:
69+
# VS Code will show an error if this required field is missing
70+
url: https://github.com/myorg/myrepo
71+
72+
# Autocompletion will suggest all available fields
73+
git_provider:
74+
# Dropdown will show available provider types
75+
type: github
76+
77+
# Pattern validation ensures the URL format is correct
78+
url: https://api.github.com
79+
80+
# Documentation tooltips show field descriptions
81+
webhook_secret:
82+
name: webhook-secret
83+
key: token
84+
85+
# Validation for minimum values
86+
concurrency_limit: 5
87+
88+
settings:
89+
# Enum validation limits to specific options
90+
pipelinerun_provenance: default_branch
91+
```
92+
93+
## Other Tools Using OpenAPI Schemas
94+
95+
Beyond VS Code, OpenAPI schemas are useful with:
96+
97+
1. **kubectl**: Validates resources before applying them
98+
99+
```bash
100+
kubectl create -f my-repository.yaml --validate=true
101+
```
102+
103+
2. **kube-linter**: Validates resources as part of CI/CD pipelines
104+
105+
3. **Kubernetes Dashboard**: Shows field descriptions and validations
106+
107+
4. **OpenAPI documentation generators**: Create API documentation from schemas
108+
109+
## How to Get the OpenAPI Schema
110+
111+
The OpenAPI schema for Repository resources is embedded in the CRD itself. You can view it with:
112+
113+
```bash
114+
kubectl get crd repositories.pipelinesascode.tekton.dev -o jsonpath='{.spec.versions[0].schema.openAPIV3Schema}' | jq
115+
```
116+
117+
Or to see all available fields with their descriptions:
118+
119+
```bash
120+
kubectl explain repository.spec --recursive
121+
```
122+
123+
## Troubleshooting Schema Validation Errors
124+
125+
If you encounter validation errors when creating or updating a Repository:
126+
127+
1. **Check field types**: Ensure values match expected types
128+
2. **Verify required fields**: Make sure all required fields are present
129+
3. **Review pattern validations**: URLs must follow the correct format
130+
4. **Check enum values**: Some fields accept only specific values
131+
132+
Error messages typically provide specific details about which validation failed, making it easier to correct your resources.
133+
134+
{{< hint info >}}
135+
Even with client-side validation, the webhook validation in Pipelines-as-Code provides an additional layer of validation for complex logic that cannot be expressed in OpenAPI schemas.
136+
{{< /hint >}}

docs/content/docs/install/gitlab.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ $ tkn pac create repo
119119
url: "https://gitlab.com/group/project"
120120
git_provider:
121121
# url: "https://gitlab.example.com/ # Set this if you are using a private GitLab instance
122+
type: "gitlab"
122123
secret:
123124
name: "gitlab-webhook-config"
124125
# Set this if you have a different key in your secret
270 KB
Loading

hack/update-schemas.sh

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2025 The Tekton Authors
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
# Imported from tektoncd/pipeline/hack/update-schemas.sh and vibed/adapted for
17+
# PAAC.
18+
19+
set -o errexit
20+
set -o nounset
21+
set -o pipefail
22+
23+
OLDGOFLAGS="${GOFLAGS:-}"
24+
GOFLAGS=""
25+
26+
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
27+
CRD_PATH="${SCRIPT_DIR}/../config"
28+
API_PATH="${SCRIPT_DIR}/../pkg/apis"
29+
TEMP_DIR_LOGS=$(mktemp -d)
30+
31+
echo "=== Generating CRD schemas with OpenAPI validation ==="
32+
33+
# List of CRDs to process
34+
CRD_FILES=(
35+
"${CRD_PATH}/300-repositories.yaml"
36+
# Add more CRD files here as they are created
37+
)
38+
39+
for FILENAME in "${CRD_FILES[@]}"; do
40+
BASENAME=$(basename "$FILENAME")
41+
echo "Generating OpenAPI schema for $FILENAME"
42+
43+
# Extract group from the CRD file
44+
GROUP=$(grep -E '^ group:' $FILENAME)
45+
GROUP=${GROUP#" group: "}
46+
API_SUBDIR=${GROUP%".tekton.dev"}
47+
48+
TEMP_DIR=$(mktemp -d)
49+
cp -p $FILENAME $TEMP_DIR/.
50+
LOG_FILE=$TEMP_DIR_LOGS/log-schema-generation-$(basename $FILENAME)
51+
52+
echo " Processing API group: $GROUP, subdir: $API_SUBDIR"
53+
54+
counter=0 limit=5
55+
while [ "$counter" -lt "$limit" ]; do
56+
set +e
57+
# Use controller-gen to generate the schema
58+
go run sigs.k8s.io/controller-tools/cmd/[email protected] \
59+
crd:crdVersions=v1 \
60+
output:crd:artifacts:config=$TEMP_DIR \
61+
paths=$API_PATH/$API_SUBDIR/... >$LOG_FILE 2>&1
62+
rc=$?
63+
set -e
64+
65+
if [ $rc -eq 0 ]; then
66+
echo " ✅ Successfully generated schema"
67+
68+
# Find the auto-generated CRD file
69+
if command -v yq >/dev/null 2>&1 && yq --version | grep -q "mikefarah/yq"; then
70+
echo " 🔄 Syncing schema from temporary CRD to $BASENAME"
71+
72+
# Find the auto-generated CRD file in the temp directory
73+
AUTO_GENERATED_CRD=$(find $TEMP_DIR -name "${GROUP}_*.yaml")
74+
75+
if [ -f "$AUTO_GENERATED_CRD" ]; then
76+
# Extract schema from auto-generated CRD and apply it to the original CRD
77+
yq eval '.spec.versions[0].schema' "$AUTO_GENERATED_CRD" >/tmp/schema.yaml
78+
yq eval -i '.spec.versions[0].schema = load("/tmp/schema.yaml")' "$FILENAME"
79+
echo " ✅ Schema successfully synced to $BASENAME"
80+
81+
# Clean up temporary schema file
82+
rm -f /tmp/schema.yaml
83+
else
84+
echo " ⚠️ Warning: Auto-generated CRD not found in temporary directory"
85+
fi
86+
else
87+
echo " ⚠️ Warning: mikefarah/yq not available, cannot automatically sync schema"
88+
echo " Manual action required: Copy schema from auto-generated CRD to $BASENAME"
89+
fi
90+
91+
# Now generate directly to the config directory for the final step
92+
# but we'll delete the auto-generated file afterward
93+
go run sigs.k8s.io/controller-tools/cmd/[email protected] \
94+
crd:crdVersions=v1 \
95+
output:crd:artifacts:config=$CRD_PATH \
96+
paths=$API_PATH/$API_SUBDIR/... >/dev/null 2>&1
97+
98+
# Find and delete the auto-generated CRD file from the config directory
99+
AUTO_GENERATED_CRD=$(find $CRD_PATH -name "${GROUP}_*.yaml")
100+
if [ -f "$AUTO_GENERATED_CRD" ]; then
101+
echo " 🗑️ Removing auto-generated CRD file: $(basename "$AUTO_GENERATED_CRD")"
102+
rm -f "$AUTO_GENERATED_CRD"
103+
fi
104+
105+
break
106+
fi
107+
108+
# Check if we can proceed despite errors
109+
if grep -q 'exit status 1' $LOG_FILE; then
110+
echo " ⚠️ Warning: Encountered errors during schema generation"
111+
echo " 📝 Check $LOG_FILE for details"
112+
# Attempt to extract and display useful error information
113+
ERROR_MSG=$(grep -A 3 'Error:' $LOG_FILE 2>/dev/null || echo "Unknown error")
114+
echo " Error summary: $ERROR_MSG"
115+
break
116+
fi
117+
118+
counter=$((counter + 1))
119+
if [ $counter -eq $limit ]; then
120+
echo " ❌ Failed to generate CRD schema after $limit attempts"
121+
echo " 📝 Check $LOG_FILE for details"
122+
cat ${LOG_FILE}
123+
exit 1
124+
fi
125+
126+
echo " Retrying (attempt $counter of $limit)..."
127+
sleep 1
128+
done
129+
130+
# Validate the generated CRD
131+
echo " Validating generated CRD"
132+
if command -v kubectl >/dev/null 2>&1; then
133+
# Try using the newer "kubectl server-side validation" approach
134+
if kubectl explain crd &>/dev/null; then
135+
if kubectl apply --server-side --dry-run=server --validate=strict -f "$FILENAME" >/dev/null 2>&1; then
136+
echo " ✅ CRD validation successful using server-side validation"
137+
else
138+
echo " ⚠️ Warning: Server-side CRD validation failed, validation may not be complete"
139+
fi
140+
else
141+
echo " ⚠️ Warning: kubectl API resources not available, skipping validation"
142+
fi
143+
else
144+
echo " ⚠️ Warning: kubectl not found, skipping validation"
145+
fi
146+
147+
rm -rf $TEMP_DIR
148+
done
149+
150+
echo "=== Schema generation complete ==="
151+
echo "Generated schemas saved to: $CRD_PATH"
152+
echo "OpenAPI schema has been successfully added to the numbered CRD files"
153+
echo "Auto-generated reference CRD files have been removed as requested"
154+
echo "Log files available at: $TEMP_DIR_LOGS"
155+
156+
GOFLAGS="${OLDGOFLAGS}"

0 commit comments

Comments
 (0)