Repository: crossplane/crossplane

Issue:
`EnvironmentConfig` drop alpha version entirely
As a follow up to:

* https://github.com/crossplane/crossplane/pull/6157#pullrequestreview-2482652310

We should take these next steps in the v1.21 milestone to finish maturing the `EnvironmentConfig` API:

* drop `alpha` version entirely

This should be done the release after:

* https://github.com/crossplane/crossplane/issues/6162

Discussion:
@github-actions: Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as `stale` because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment **starting with** `/fresh` will mark this issue as not stale.@jbw976: /fresh

Solution patch:
diff --git a/apis/apiextensions/v1alpha1/register.go b/apis/apiextensions/v1alpha1/register.go
index 1492c6837..b742fdae4 100644
--- a/apis/apiextensions/v1alpha1/register.go
+++ b/apis/apiextensions/v1alpha1/register.go
@@ -40,14 +40,6 @@ var (
 	AddToScheme = SchemeBuilder.AddToScheme
 )
 
-// EnvironmentConfig type metadata.
-var (
-	EnvironmentConfigKind             = reflect.TypeOf(EnvironmentConfig{}).Name()
-	EnvironmentConfigGroupKind        = schema.GroupKind{Group: Group, Kind: EnvironmentConfigKind}.String()
-	EnvironmentConfigKindAPIVersion   = EnvironmentConfigKind + "." + SchemeGroupVersion.String()
-	EnvironmentConfigGroupVersionKind = SchemeGroupVersion.WithKind(EnvironmentConfigKind)
-)
-
 // Usage type metadata.
 var (
 	UsageKind             = reflect.TypeOf(Usage{}).Name()
@@ -58,5 +50,4 @@ var (
 
 func init() {
 	SchemeBuilder.Register(&Usage{}, &UsageList{})
-	SchemeBuilder.Register(&EnvironmentConfig{}, &EnvironmentConfigList{})
 }
diff --git a/apis/apiextensions/v1alpha1/zz_generated.deepcopy.go b/apis/apiextensions/v1alpha1/zz_generated.deepcopy.go
index 45148977d..aa59124ea 100644
--- a/apis/apiextensions/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/apiextensions/v1alpha1/zz_generated.deepcopy.go
@@ -21,74 +21,9 @@ limitations under the License.
 package v1alpha1
 
 import (
-	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *EnvironmentConfig) DeepCopyInto(out *EnvironmentConfig) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	if in.Data != nil {
-		in, out := &in.Data, &out.Data
-		*out = make(map[string]v1.JSON, len(*in))
-		for key, val := range *in {
-			(*out)[key] = *val.DeepCopy()
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentConfig.
-func (in *EnvironmentConfig) DeepCopy() *EnvironmentConfig {
-	if in == nil {
-		return nil
-	}
-	out := new(EnvironmentConfig)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *EnvironmentConfig) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *EnvironmentConfigList) DeepCopyInto(out *EnvironmentConfigList) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ListMeta.DeepCopyInto(&out.ListMeta)
-	if in.Items != nil {
-		in, out := &in.Items, &out.Items
-		*out = make([]EnvironmentConfig, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentConfigList.
-func (in *EnvironmentConfigList) DeepCopy() *EnvironmentConfigList {
-	if in == nil {
-		return nil
-	}
-	out := new(EnvironmentConfigList)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *EnvironmentConfigList) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Resource) DeepCopyInto(out *Resource) {
 	*out = *in
diff --git a/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go b/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go
deleted file mode 100644
index 6ea863a9c..000000000
--- a/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-Copyright 2022 The Crossplane Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Generated from apis/apiextensions/v1beta1/environment_config_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-// +kubebuilder:object:root=true
-// +genclient
-// +genclient:nonNamespaced
-
-// An EnvironmentConfig contains user-defined unstructured values for
-// use in a Composition.
-//
-// Read the Crossplane documentation for
-// [more information about EnvironmentConfigs](https://docs.crossplane.io/latest/concepts/environment-configs).
-// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
-// +kubebuilder:resource:scope=Cluster,categories=crossplane,shortName=envcfg
-type EnvironmentConfig struct {
-	metav1.TypeMeta   `json:",inline"`
-	metav1.ObjectMeta `json:"metadata,omitempty"`
-
-	// The data of this EnvironmentConfig.
-	// This may contain any kind of structure that can be serialized into JSON.
-	// +optional
-	Data map[string]extv1.JSON `json:"data,omitempty"`
-}
-
-// +kubebuilder:object:root=true
-
-// EnvironmentConfigList contains a list of EnvironmentConfigs.
-type EnvironmentConfigList struct {
-	metav1.TypeMeta `json:",inline"`
-	metav1.ListMeta `json:"metadata,omitempty"`
-	Items           []EnvironmentConfig `json:"items"`
-}
diff --git a/cluster/crds/apiextensions.crossplane.io_environmentconfigs.yaml b/cluster/crds/apiextensions.crossplane.io_environmentconfigs.yaml
index 065e14ece..4c083730e 100644
--- a/cluster/crds/apiextensions.crossplane.io_environmentconfigs.yaml
+++ b/cluster/crds/apiextensions.crossplane.io_environmentconfigs.yaml
@@ -18,48 +18,6 @@ spec:
     singular: environmentconfig
   scope: Cluster
   versions:
-  - additionalPrinterColumns:
-    - jsonPath: .metadata.creationTimestamp
-      name: AGE
-      type: date
-    name: v1alpha1
-    schema:
-      openAPIV3Schema:
-        description: |-
-          An EnvironmentConfig contains user-defined unstructured values for
-          use in a Composition.
-
-          Read the Crossplane documentation for
-          [more information about EnvironmentConfigs](https://docs.crossplane.io/latest/concepts/environment-configs).
-        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
-          data:
-            additionalProperties:
-              x-kubernetes-preserve-unknown-fields: true
-            description: |-
-              The data of this EnvironmentConfig.
-              This may contain any kind of structure that can be serialized into JSON.
-            type: object
-          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
-        type: object
-    served: true
-    storage: false
-    subresources: {}
   - additionalPrinterColumns:
     - jsonPath: .metadata.creationTimestamp
       name: AGE
diff --git a/generate.go b/generate.go
index 9256e3ab4..4ab55c5d9 100644
--- a/generate.go
+++ b/generate.go
@@ -26,7 +26,6 @@ limitations under the License.
 
 // Replicate identical API versions
 
-//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1beta1/environment_config_types.go apis/apiextensions/v1alpha1 false
 //go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1beta1/usage_types.go apis/apiextensions/v1alpha1 true
 
 //go:generate ./hack/duplicate_api_type.sh apis/pkg/v1/package_types.go apis/pkg/v1beta1
diff --git a/go.mod b/go.mod
index 76580b5d9..30f923335 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.23.8
 toolchain go1.23.10
 
 require (
-	dario.cat/mergo v1.0.1
+	dario.cat/mergo v1.0.2
 	github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
 	github.com/Masterminds/semver v1.5.0
 	github.com/alecthomas/kong v1.4.0
diff --git a/go.sum b/go.sum
index a8dd2e7cb..ebad1a959 100644
--- a/go.sum
+++ b/go.sum
@@ -17,8 +17,8 @@ cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e h1:GwCVItFUPxw
 cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e/go.mod h1:ApHceQLLwcOkCEXM1+DyCXTHEJhNGDpJ2kmV6axsx24=
 cuelang.org/go v0.8.2 h1:vWfHI1kQlBvwkna7ktAqXjV5LUEAgU6vyMlJjvZZaDw=
 cuelang.org/go v0.8.2/go.mod h1:CoDbYolfMms4BhWUlhD+t5ORnihR7wvjcfgyO9lL5FI=
-dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
-dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=



Test patch:
diff --git a/test/e2e/manifests/apiextensions/environment/default/setup/environmentConfigs.yaml b/test/e2e/manifests/apiextensions/environment/default/setup/environmentConfigs.yaml
index 8648289c6..f69af9120 100644
--- a/test/e2e/manifests/apiextensions/environment/default/setup/environmentConfigs.yaml
+++ b/test/e2e/manifests/apiextensions/environment/default/setup/environmentConfigs.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-1
@@ -10,7 +10,7 @@ data:
       d: e
       f: "1"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-2
diff --git a/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatch1/setup/environmentConfigs.yaml b/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatch1/setup/environmentConfigs.yaml
index 365af33a3..32de098a5 100644
--- a/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatch1/setup/environmentConfigs.yaml
+++ b/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatch1/setup/environmentConfigs.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-1
@@ -10,7 +10,7 @@ data:
       d: e
       f: "1"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-2
@@ -22,7 +22,7 @@ data:
     c:
       f: "2"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-3
diff --git a/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatchNil/setup/environmentConfigs.yaml b/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatchNil/setup/environmentConfigs.yaml
index 365af33a3..32de098a5 100644
--- a/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatchNil/setup/environmentConfigs.yaml
+++ b/test/e2e/manifests/apiextensions/environment/multipleModeMaxMatchNil/setup/environmentConfigs.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-1
@@ -10,7 +10,7 @@ data:
       d: e
       f: "1"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-2
@@ -22,7 +22,7 @@ data:
     c:
       f: "2"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-3
diff --git a/test/e2e/manifests/apiextensions/environment/resolutionOptional/setup/environmentConfigs.yaml b/test/e2e/manifests/apiextensions/environment/resolutionOptional/setup/environmentConfigs.yaml
index 2e1b00b87..a891b483c 100644
--- a/test/e2e/manifests/apiextensions/environment/resolutionOptional/setup/environmentConfigs.yaml
+++ b/test/e2e/manifests/apiextensions/environment/resolutionOptional/setup/environmentConfigs.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-1
@@ -12,7 +12,7 @@ data:
 # We want to test that with Optional resolution, claims still become ready even
 # if one of the environment configs is missing, using the other one.
 #---
-#apiVersion: apiextensions.crossplane.io/v1alpha1
+#apiVersion: apiextensions.crossplane.io/v1beta1
 #kind: EnvironmentConfig
 #metadata:
 #  name: example-environment-2
diff --git a/test/e2e/manifests/apiextensions/environment/resolveAlways/01-addedEnvironmentConfig.yaml b/test/e2e/manifests/apiextensions/environment/resolveAlways/01-addedEnvironmentConfig.yaml
index 6f4c7c898..de12e5996 100644
--- a/test/e2e/manifests/apiextensions/environment/resolveAlways/01-addedEnvironmentConfig.yaml
+++ b/test/e2e/manifests/apiextensions/environment/resolveAlways/01-addedEnvironmentConfig.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-3
diff --git a/test/e2e/manifests/apiextensions/environment/resolveAlways/setup/environmentConfigs.yaml b/test/e2e/manifests/apiextensions/environment/resolveAlways/setup/environmentConfigs.yaml
index 8648289c6..f69af9120 100644
--- a/test/e2e/manifests/apiextensions/environment/resolveAlways/setup/environmentConfigs.yaml
+++ b/test/e2e/manifests/apiextensions/environment/resolveAlways/setup/environmentConfigs.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-1
@@ -10,7 +10,7 @@ data:
       d: e
       f: "1"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-2
diff --git a/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/01-addedEnvironmentConfig.yaml b/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/01-addedEnvironmentConfig.yaml
index 6f4c7c898..de12e5996 100644
--- a/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/01-addedEnvironmentConfig.yaml
+++ b/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/01-addedEnvironmentConfig.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-3
diff --git a/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/setup/environmentConfigs.yaml b/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/setup/environmentConfigs.yaml
index 8648289c6..f69af9120 100644
--- a/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/setup/environmentConfigs.yaml
+++ b/test/e2e/manifests/apiextensions/environment/resolveIfNotPresent/setup/environmentConfigs.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-1
@@ -10,7 +10,7 @@ data:
       d: e
       f: "1"
 ---
-apiVersion: apiextensions.crossplane.io/v1alpha1
+apiVersion: apiextensions.crossplane.io/v1beta1
 kind: EnvironmentConfig
 metadata:
   name: example-environment-2