Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- [ ] My commits follow the [Conventional Commits](https://www.conventionalcommits.org/) format
- [ ] I have added/updated unit tests for any new or changed templates
- [ ] I have updated documentation (README, CONTRIBUTING, values comments) if needed
- [ ] I have updated the generated CRDs and Manifest
- [ ] I have updated the generated files using `make codegen`

## Related Issues

Expand Down
7 changes: 2 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,12 @@ jobs:
go-version-file: go.mod

- name: Run code generation
run: |
make manifests
make generate
make crd-docs
run: make codegen

- name: Check for uncommitted changes
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "::error::Generated code is out of date. Please run 'make manifests generate crd-docs' and commit the changes."
echo "::error::Generated code is out of date. Please run 'make codegen' and commit the changes."
echo ""
echo "Changed files:"
git status --short
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,3 @@ jobs:
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max

1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ go.work
!vendor/**/zz_generated.*

# editor and IDE paraphernalia
.vscode
*.swp
*.swo
*~
Expand Down
5 changes: 2 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ Ensure you run them against a dedicated [Kind](https://kind.sigs.k8s.io/) cluste

**After editing `*_types.go` or markers:**
```
make manifests # Regenerate CRDs/RBAC from markers
make generate # Regenerate DeepCopy methods
make codegen # Regenerate CRDs/RBAC, DeepCopy, docs, and validation schemas
```

**After editing `*.go` files:**
Expand Down Expand Up @@ -154,7 +153,7 @@ Tests use **Ginkgo + Gomega** (BDD style). Check `suite_test.go` for setup.

```bash
# 1. Regenerate manifests
make manifests generate
make codegen

# 2. Build & deploy
export IMG=<registry>/<project>:tag
Expand Down
13 changes: 8 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,18 @@ Run `make help` for the full list. The most important targets are:
| `make lint-fix` | Lint with auto-fix |
| `make generate` | Regenerate deepcopy and apply-configuration code |
| `make manifests` | Regenerate CRDs and RBAC from kubebuilder markers |
| `make codegen` | Run all code generation steps after an API change (manifests, generate, crd-docs, schemas) |
| `make install` | Install CRDs into the current cluster |
| `make deploy IMG=<image>` | Deploy the operator to the current cluster |
| `make undeploy` | Remove the operator from the current cluster |
| `make uninstall` | Remove CRDs from the current cluster |

### After Editing `*_types.go` or Kubebuilder Markers

Always regenerate manifests and code:
Always regenerate all derived artifacts:

```bash
make manifests generate
make codegen
```

### After Any Go Code Change
Expand Down Expand Up @@ -152,6 +153,8 @@ kubebuilder create webhook --group github --version v1alpha1 --kind <Kind> --def
| `config/crd/bases/*.yaml` | `make manifests` |
| `config/rbac/role.yaml` | `make manifests` |
| `config/webhook/manifests.yaml` | `make manifests` |
| `docs/crds.md` | `make crd-docs` |
| `schemas/*.json` | `make schemas` |
| `PROJECT` | Kubebuilder CLI |

### Where to Look
Expand Down Expand Up @@ -265,7 +268,7 @@ Edit `.env` freely — it won't be committed. The template (`.env.tmpl`) contain
2. Make your changes, following the conventions above.
3. Run the full validation suite:
```bash
make manifests generate # if you changed types or markers
make codegen # if you changed types or markers
make lint-fix
make test
```
Expand All @@ -277,10 +280,10 @@ Edit `.env` freely — it won't be committed. The template (`.env.tmpl`) contain

### Codegen Check

The **Codegen Check** workflow verifies that generated code is up to date on every PR. It runs `make manifests`, `make generate`, and `make crd-docs`, then fails if there are uncommitted changes. Always run these before pushing:
The **Codegen Check** workflow verifies that generated code is up to date on every PR. It runs all generation steps, then fails if there are uncommitted changes. Always run this before pushing:

```bash
make manifests generate crd-docs
make codegen
```

### Helm Chart Update
Expand Down
33 changes: 33 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ GINKGO ?= $(LOCALBIN)/ginkgo
## Tool Versions
KUSTOMIZE_VERSION ?= v5.8.1
CONTROLLER_TOOLS_VERSION ?= v0.21.0
KUBECONFORM_VERSION ?= v0.8.0

#ENVTEST_VERSION is the controller-runtime version to use for setup-envtest, derived from go.mod
ENVTEST_VERSION ?= $(shell v='$(call gomodver,sigs.k8s.io/controller-runtime)'; \
Expand All @@ -244,6 +245,7 @@ ENVTEST_K8S_VERSION ?= $(shell v='$(call gomodver,k8s.io/api)'; \

GOLANGCI_LINT_VERSION ?= v2.12.2
GINKGO_VERSION ?= v2.27.2 # Match the version in go.mod
OPENAPI2JSONSCHEMA ?= $(LOCALBIN)/openapi2jsonschema

.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
Expand Down Expand Up @@ -303,6 +305,19 @@ $(CRD_REF_DOCS): $(LOCALBIN)
crd-docs: crd-ref-docs generate
$(CRD_REF_DOCS) --source-path ./api/v1alpha1 --config ./crd-ref-docs.config.yaml --output-path=./docs/crds.md --renderer=markdown

.PHONY: codegen
codegen: manifests generate crd-docs schemas ## Regenerate all derived artifacts after an API change (CRDs, deepcopy, docs, schemas).

.PHONY: openapi2jsonschema-tool
openapi2jsonschema-tool: $(OPENAPI2JSONSCHEMA) ## Download and build openapi2jsonschema from kubeconform if necessary.
$(OPENAPI2JSONSCHEMA): $(LOCALBIN)
$(call clone-and-build-tool,$(OPENAPI2JSONSCHEMA),yannh/kubeconform,$(KUBECONFORM_VERSION),openapi2jsonschema-go)

.PHONY: schemas
schemas: manifests openapi2jsonschema-tool ## Generate per-kind JSON Schema files for CR validation into schemas/.
@mkdir -p schemas
@cd schemas && for crd in ../config/crd/bases/*.yaml; do "$(OPENAPI2JSONSCHEMA)" "$$crd"; done

# Add the Grafana plugin

.PHONY: grafana
Expand All @@ -326,6 +341,24 @@ mv "$(LOCALBIN)/$$(basename "$(1)")" "$(1)-$(3)" ;\
ln -sf "$$(basename "$(1)-$(3)")" "$(1)"
endef

# clone-and-build-tool clones a GitHub repo at a given tag and builds a Go binary from a subdirectory.
# $1 - target binary path (without version suffix)
# $2 - GitHub repo slug (e.g. yannh/kubeconform)
# $3 - version tag to clone
# $4 - subdirectory that contains the go.mod and main package
define clone-and-build-tool
@[ -f "$(1)-$(3)" ] || { \
set -e; \
echo "Building $$(basename "$(1)") from github.com/$(2) $(3)..."; \
tmpdir=$$(mktemp -d); \
git clone --quiet --depth=1 --branch "$(3)" "https://github.com/$(2).git" "$$tmpdir"; \
( cd "$$tmpdir/$(4)" && go build -o "$(1)-$(3)" . ); \
rm -rf "$$tmpdir"; \
}; \
[ -L "$(1)" ] && [ -e "$(1)" ] || \
ln -sf "$$(basename "$(1)-$(3)")" "$(1)"
endef

define gomodver
$(shell go list -m -f '{{if .Replace}}{{.Replace.Version}}{{else}}{{.Version}}{{end}}' $(1) 2>/dev/null)
endef
126 changes: 126 additions & 0 deletions schemas/autolinkspreset_v1alpha1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"description": "AutolinksPreset is the Schema for the autolinkspresets API",
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"type": "object"
},
"spec": {
"description": "spec defines the desired state of AutolinksPreset",
"properties": {
"autolinks": {
"description": "AutolinkList is a list of autolink configurations to create in repositories.\nEach autolink defines a prefix that triggers link generation and a URL template.",
"items": {
"description": "Autolink defines an automatic link reference for external resources.\nWhen a reference matching KeyPrefix is found in issues, pull requests, or commit messages,\nGitHub automatically converts it to a clickable link using the URLTemplate.\nSee: https://docs.github.com/en/rest/repos/autolinks",
"properties": {
"isAlphanumeric": {
"default": false,
"description": "IsAlphanumeric determines whether the reference must be alphanumeric.\n- true: the <num> parameter of the url_template matches alphanumeric characters `A-Z` (case insensitive), `0-9`, and `-`\n- false: reference only matches numeric characters.",
"type": "boolean"
},
"keyPrefix": {
"description": "KeyPrefix is the text prefix that triggers autolink creation.\nWhen text starts with this prefix followed by a reference, it becomes a link.\nExamples: \"JIRA-\", \"TICKET-\", \"BUG-\"",
"maxLength": 20,
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9-]{0,19}$",
"type": "string"
},
"urlTemplate": {
"description": "URLTemplate is the URL pattern used to generate links.\nUse <num> as a placeholder for the reference number/ID.\nExample: \"https://jira.example.com/browse/<num>\" converts \"JIRA-123\" to \"https://jira.example.com/browse/123\"",
"maxLength": 200,
"type": "string"
}
},
"required": [
"isAlphanumeric",
"keyPrefix",
"urlTemplate"
],
"type": "object",
"additionalProperties": false
},
"type": "array"
}
},
"type": "object",
"additionalProperties": false
},
"status": {
"description": "status defines the observed state of AutolinksPreset",
"properties": {
"conditions": {
"description": "conditions represent the current state of the AutolinksPreset resource.\nEach condition has a unique type and reflects the status of a specific aspect of the resource.\n\nStandard condition types include:\n- \"Available\": the resource is fully functional\n- \"Progressing\": the resource is being created or updated\n- \"Degraded\": the resource failed to reach or maintain its desired state\n\nThe status of each condition is one of True, False, or Unknown.",
"items": {
"description": "Condition contains details for one aspect of the current state of this API Resource.",
"properties": {
"lastTransitionTime": {
"description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.",
"format": "date-time",
"type": "string"
},
"message": {
"description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
"maxLength": 32768,
"type": "string"
},
"observedGeneration": {
"description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
"format": "int64",
"minimum": 0,
"type": "integer"
},
"reason": {
"description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
"maxLength": 1024,
"minLength": 1,
"pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
"type": "string"
},
"status": {
"description": "status of the condition, one of True, False, Unknown.",
"enum": [
"True",
"False",
"Unknown"
],
"type": "string"
},
"type": {
"description": "type of condition in CamelCase or in foo.example.com/CamelCase.",
"maxLength": 316,
"pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
"type": "string"
}
},
"required": [
"lastTransitionTime",
"message",
"reason",
"status",
"type"
],
"type": "object",
"additionalProperties": false
},
"type": "array",
"x-kubernetes-list-map-keys": [
"type"
],
"x-kubernetes-list-type": "map"
}
},
"type": "object",
"additionalProperties": false
}
},
"required": [
"spec"
],
"type": "object"
}
Loading