From 748d6912ec6a624679934cb0c0a5571865599848 Mon Sep 17 00:00:00 2001 From: devppratik Date: Thu, 4 Jun 2026 20:13:57 +0530 Subject: [PATCH] Update boilerplate for CI Fixes Co-Authored-By: Claude Sonnet 4.5 --- .pre-commit-config.yaml | 13 +- boilerplate/_data/last-boilerplate-commit | 2 +- .../golang-osd-operator/docs/pre-commit.md | 123 ++++++ .../golang-osd-operator/olm_pko_migration.py | 4 +- .../pre-commit-config.yaml | 13 +- .../openshift/golang-osd-operator/standard.mk | 22 +- build/Dockerfile | 2 +- build/Dockerfile.olm-registry | 2 +- ...tyintegrations.pagerduty.openshift.io.yaml | 379 +++++++++--------- 9 files changed, 355 insertions(+), 205 deletions(-) create mode 100644 boilerplate/openshift/golang-osd-operator/docs/pre-commit.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14ecdd9b..94e5b26c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,8 +4,14 @@ # ============================================================================= # # INSTALL -# pip install pre-commit -# pre-commit install +# For detailed setup instructions including uv (recommended) and pip, +# see: boilerplate/openshift/golang-osd-operator/docs/pre-commit.md +# +# Quick start (uv): +# uv sync && source .venv/bin/activate && pre-commit install +# +# Quick start (pip): +# pip install 'pre-commit==4.6.0' && pre-commit install # # USAGE # pre-commit run # staged files only (developer / agent workflow) @@ -35,6 +41,9 @@ # pre-existing violations on the first run. Stage and commit those fixes # separately before day-to-day use. # +# Fix commits can be excluded from git blame +# https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-filefile +# # ============================================================================= repos: diff --git a/boilerplate/_data/last-boilerplate-commit b/boilerplate/_data/last-boilerplate-commit index 2c85e9bf..e1285a81 100644 --- a/boilerplate/_data/last-boilerplate-commit +++ b/boilerplate/_data/last-boilerplate-commit @@ -1 +1 @@ -5c9b1484a283341e2d9aca8300bf97cfc665ca69 +1cb129aed5a91f2098f70c0e141561e00b1e16fc diff --git a/boilerplate/openshift/golang-osd-operator/docs/pre-commit.md b/boilerplate/openshift/golang-osd-operator/docs/pre-commit.md new file mode 100644 index 00000000..88ff5bca --- /dev/null +++ b/boilerplate/openshift/golang-osd-operator/docs/pre-commit.md @@ -0,0 +1,123 @@ +# Pre-Commit Hooks Setup Guide + +## Installation + +### Recommended: Using uv + +[uv](https://github.com/astral-sh/uv) is recommended for Python dependency management. It provides dependency locking with package hashes (supply-chain protection), virtual environment management, and is 10-100x faster than pip. + +**Install uv:** +```bash +# macOS/Linux +curl -LsSf https://astral.sh/uv/install.sh | sh + +# Windows +powershell -c "irm https://astral.sh/uv/install.ps1 | iex" + +# Via pip +pip install uv +``` + +**First-time setup:** +```bash +uv init --bare # creates pyproject.toml +uv add --dev pre-commit==4.6.0 # adds dependency, generates uv.lock +source .venv/bin/activate # macOS/Linux (.venv\Scripts\activate on Windows) +pre-commit install +``` + +**Subsequent setup** (when `pyproject.toml` and `uv.lock` exist): +```bash +uv sync +source .venv/bin/activate +pre-commit install +``` + +### Alternative: Using pip + +```bash +pip install 'pre-commit==4.6.0' # pinned version (Golden Rule 15) +pre-commit install +``` + +Add to `requirements-dev.txt`: `pre-commit==4.6.0` + +## First-Time Setup + +Run on all files to catch existing issues: +```bash +pre-commit run --all-files +``` + +Auto-fix hooks will modify files on first run. Stage and commit these separately: +```bash +git diff +git add . +git commit -m "Fix: Apply pre-commit auto-fixes" +``` + +**Exclude fix commits from git blame:** +```bash +# Create .git-blame-ignore-revs with commit hashes +git config blame.ignoreRevsFile .git-blame-ignore-revs +``` + +See [git-blame docs](https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-filefile). + +## Usage + +**Automatic** (runs on `git commit`): +```bash +git add +git commit -m "Message" +``` + +**Manual:** +```bash +pre-commit run # staged files only +pre-commit run --all-files # entire repo +pre-commit run --files path/to/file # specific files +``` + +**Bypass (use sparingly):** +```bash +SKIP=hook-id git commit -m "Message" # skip one hook +git commit --no-verify # NEVER use (Golden Rule 16) +``` + +Rules: Agents never bypass hooks. Security hooks (gitleaks) never bypassable. + +## Troubleshooting + +**macOS timeout issues:** +```bash +brew install coreutils # provides gtimeout +``` + +**Virtual environment not found:** +```bash +source .venv/bin/activate +uv sync +``` + +**Hooks not running:** +```bash +ls -la .git/hooks/pre-commit # verify installation +pre-commit install # reinstall +``` + +**Hook failures:** Read error messages and fix issues: +- `go-build`: Fix compilation errors +- `go-mod-tidy`: Run `go mod tidy` and stage go.mod/go.sum +- `check-yaml`: Fix YAML syntax + +## CI Integration + +Pre-commit mirrors `ci/prow/lint`. CI is authoritative; pre-commit is developer convenience. All hooks run in CI with same config. + +If pre-commit passes but CI fails: `pre-commit autoupdate` + +## Resources + +- [Pre-Commit Documentation](https://pre-commit.com/) +- [uv Documentation](https://github.com/astral-sh/uv) diff --git a/boilerplate/openshift/golang-osd-operator/olm_pko_migration.py b/boilerplate/openshift/golang-osd-operator/olm_pko_migration.py index abcd28d3..e9866b3e 100644 --- a/boilerplate/openshift/golang-osd-operator/olm_pko_migration.py +++ b/boilerplate/openshift/golang-osd-operator/olm_pko_migration.py @@ -11,7 +11,7 @@ import subprocess import sys from pathlib import Path -from typing import Any +from typing import Any, Optional import yaml @@ -629,7 +629,7 @@ def write_pko_dockerfile(): ) ) -def extract_deployment_selector() -> str | None: +def extract_deployment_selector() -> Optional[str]: """ Extract the clusterDeploymentSelector from hack/olm-registry/olm-artifacts-template.yaml. diff --git a/boilerplate/openshift/golang-osd-operator/pre-commit-config.yaml b/boilerplate/openshift/golang-osd-operator/pre-commit-config.yaml index 14ecdd9b..94e5b26c 100644 --- a/boilerplate/openshift/golang-osd-operator/pre-commit-config.yaml +++ b/boilerplate/openshift/golang-osd-operator/pre-commit-config.yaml @@ -4,8 +4,14 @@ # ============================================================================= # # INSTALL -# pip install pre-commit -# pre-commit install +# For detailed setup instructions including uv (recommended) and pip, +# see: boilerplate/openshift/golang-osd-operator/docs/pre-commit.md +# +# Quick start (uv): +# uv sync && source .venv/bin/activate && pre-commit install +# +# Quick start (pip): +# pip install 'pre-commit==4.6.0' && pre-commit install # # USAGE # pre-commit run # staged files only (developer / agent workflow) @@ -35,6 +41,9 @@ # pre-existing violations on the first run. Stage and commit those fixes # separately before day-to-day use. # +# Fix commits can be excluded from git blame +# https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-filefile +# # ============================================================================= repos: diff --git a/boilerplate/openshift/golang-osd-operator/standard.mk b/boilerplate/openshift/golang-osd-operator/standard.mk index c6356e27..4f617e93 100644 --- a/boilerplate/openshift/golang-osd-operator/standard.mk +++ b/boilerplate/openshift/golang-osd-operator/standard.mk @@ -243,8 +243,28 @@ else $(info Did not find 'config/default' - skipping kustomize manifest generation) endif +.PHONY: sync-pko-crds +sync-pko-crds: +ifneq (,$(wildcard deploy_pko)) + @if [ -d deploy/crds ]; then \ + yq_yaml_flag=""; \ + if $(YQ) --version 2>&1 | grep -qE "^yq [0-9]"; then \ + yq_yaml_flag="-y"; \ + fi; \ + for crd in deploy/crds/*.yaml; do \ + [ -f "$$crd" ] || continue; \ + name=$$($(YQ) -r '.metadata.name' "$$crd"); \ + $(YQ) $$yq_yaml_flag '.metadata.annotations["package-operator.run/phase"] = "crds" | .metadata.annotations["package-operator.run/collision-protection"] = "IfNoController"' \ + "$$crd" > "deploy_pko/CustomResourceDefinition-$$name.yaml"; \ + echo "Synced CRD $$name to deploy_pko/"; \ + done; \ + fi +else + $(info deploy_pko/ not found - skipping PKO CRD sync) +endif + .PHONY: generate -generate: op-generate go-generate openapi-generate manifests +generate: op-generate go-generate openapi-generate manifests sync-pko-crds ifeq (${FIPS_ENABLED}, true) go-build: ensure-fips diff --git a/build/Dockerfile b/build/Dockerfile index c1e35e1a..10a4c8b0 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -8,7 +8,7 @@ COPY . . RUN make go-build #### -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.8-1779809423 +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.8-1780378819 ENV USER_UID=1001 \ USER_NAME=pagerduty-operator diff --git a/build/Dockerfile.olm-registry b/build/Dockerfile.olm-registry index 7b5899ea..408bc99d 100644 --- a/build/Dockerfile.olm-registry +++ b/build/Dockerfile.olm-registry @@ -4,7 +4,7 @@ COPY ${SAAS_OPERATOR_DIR} manifests RUN initializer --permissive # ubi-micro does not work for clusters with fips enabled unless we make OpenSSL available -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.8-1779809423 +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.8-1780378819 COPY --from=builder /bin/registry-server /bin/registry-server COPY --from=builder /bin/grpc_health_probe /bin/grpc_health_probe diff --git a/deploy_pko/CustomResourceDefinition-pagerdutyintegrations.pagerduty.openshift.io.yaml b/deploy_pko/CustomResourceDefinition-pagerdutyintegrations.pagerduty.openshift.io.yaml index 85056a76..c0bb0bde 100644 --- a/deploy_pko/CustomResourceDefinition-pagerdutyintegrations.pagerduty.openshift.io.yaml +++ b/deploy_pko/CustomResourceDefinition-pagerdutyintegrations.pagerduty.openshift.io.yaml @@ -14,209 +14,198 @@ spec: listKind: PagerDutyIntegrationList plural: pagerdutyintegrations shortNames: - - pdi + - pdi singular: pagerdutyintegration scope: Namespaced versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: PagerDutyIntegration is the Schema for the pagerdutyintegrations - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More 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. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PagerDutyIntegrationSpec defines the desired state of PagerDutyIntegration - properties: - acknowledgeTimeout: - description: |- - Time in seconds that an incident changes to the Triggered State after - being Acknowledged. Value must not be negative. Omitting or setting - this field to 0 will disable the feature. - minimum: 0 - type: integer - alertGroupingParameters: - description: Configures alert grouping for PD services - properties: - config: - description: |- - AlertGroupingParametersConfigSpec defines the specifics for how an alert grouping type - should behave - properties: - timeout: - type: integer - type: object - type: - type: string - type: object - clusterDeploymentSelector: - description: |- - A label selector used to find which clusterdeployment CRs receive a - PD integration based on this configuration. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: PagerDutyIntegration is the Schema for the pagerdutyintegrations API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More 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. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: PagerDutyIntegrationSpec defines the desired state of PagerDutyIntegration + properties: + acknowledgeTimeout: + description: |- + Time in seconds that an incident changes to the Triggered State after + being Acknowledged. Value must not be negative. Omitting or setting + this field to 0 will disable the feature. + minimum: 0 + type: integer + alertGroupingParameters: + description: Configures alert grouping for PD services + properties: + config: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + AlertGroupingParametersConfigSpec defines the specifics for how an alert grouping type + should behave properties: - key: - description: key is the label key that the selector applies - to. + timeout: + type: integer + type: object + type: + type: string + type: object + clusterDeploymentSelector: + description: |- + A label selector used to find which clusterdeployment CRs receive a + PD integration based on this configuration. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + escalationPolicy: + description: ID of an existing Escalation Policy in PagerDuty. + type: string + pagerdutyApiKeySecretRef: + description: Reference to the secret containing PAGERDUTY_API_KEY. + properties: + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + resolveTimeout: + description: |- + Time in seconds that an incident is automatically resolved if left + open for that long. Value must not be negative. Omitting or setting + this field to 0 will disable the feature. + minimum: 0 + type: integer + serviceOrchestration: + description: ' The status of the serviceOrchestration and the referenced configmap resource' + properties: + enabled: + type: boolean + ruleConfigConfigMapRef: + description: ObjectReference contains enough information to let you inspect or modify the referred object. + properties: + apiVersion: + description: API version of the referent. type: string - operator: + fieldPath: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. type: string - values: + kind: description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string type: object - type: array - matchLabels: - additionalProperties: + x-kubernetes-map-type: atomic + required: + - enabled + type: object + servicePrefix: + description: Prefix to set on the PagerDuty Service name. + type: string + targetSecretRef: + description: Name and namespace in the target cluster where the secret is synced. + properties: + name: + description: name is unique within a namespace to reference a secret resource. type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - escalationPolicy: - description: ID of an existing Escalation Policy in PagerDuty. - type: string - pagerdutyApiKeySecretRef: - description: Reference to the secret containing PAGERDUTY_API_KEY. - properties: - name: - description: name is unique within a namespace to reference a - secret resource. - type: string - namespace: - description: namespace defines the space within which the secret - name must be unique. - type: string - type: object - x-kubernetes-map-type: atomic - resolveTimeout: - description: |- - Time in seconds that an incident is automatically resolved if left - open for that long. Value must not be negative. Omitting or setting - this field to 0 will disable the feature. - minimum: 0 - type: integer - serviceOrchestration: - description: ' The status of the serviceOrchestration and the referenced - configmap resource' - properties: - enabled: - type: boolean - ruleConfigConfigMapRef: - description: ObjectReference contains enough information to let - you inspect or modify the referred object. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - enabled - type: object - servicePrefix: - description: Prefix to set on the PagerDuty Service name. - type: string - targetSecretRef: - description: Name and namespace in the target cluster where the secret - is synced. - properties: - name: - description: name is unique within a namespace to reference a - secret resource. - type: string - namespace: - description: namespace defines the space within which the secret - name must be unique. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - clusterDeploymentSelector - - escalationPolicy - - pagerdutyApiKeySecretRef - - servicePrefix - - targetSecretRef - type: object - status: - description: PagerDutyIntegrationStatus defines the observed state of - PagerDutyIntegration - type: object - type: object - served: true - storage: true - subresources: - status: {} + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - clusterDeploymentSelector + - escalationPolicy + - pagerdutyApiKeySecretRef + - servicePrefix + - targetSecretRef + type: object + status: + description: PagerDutyIntegrationStatus defines the observed state of PagerDutyIntegration + type: object + type: object + served: true + storage: true + subresources: + status: {}