From 65dce89e131310d74e9763b744061198f2a15743 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Thu, 7 Dec 2023 15:22:37 -0500 Subject: [PATCH 01/25] add backwards compatability policy --- BackwardsCompatibilityPolicy.md | 144 ++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 BackwardsCompatibilityPolicy.md diff --git a/BackwardsCompatibilityPolicy.md b/BackwardsCompatibilityPolicy.md new file mode 100644 index 000000000..ceeedc122 --- /dev/null +++ b/BackwardsCompatibilityPolicy.md @@ -0,0 +1,144 @@ +# Conda-Store backwards compatibility policy +## Introduction +In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy will provide guidance on how to the Conda-Store project will handle changes to software and services, ensuring that they do not disrupt or invalidate the experiences of current users, while still enabling innovation and forward progress. +## Breaking versus Non-Breaking Changes + +Breaking changes in code refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve removing existing functionality, altering existing functionality, or adding new requirements. These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. + +In contrast non-Breaking changes can add functionality or reduce requirements. Previously working code will continue to work with non-breaking changes. These changes allow software to evolve and grow without impacting existing users negatively. + +Note: the term breaking changes within this policy only refers to REST API endpoints, Database changes and public Python APIs. As long as no breaking changes are introduced to REST API endpoints, Database, or public Python APIs, changes will not be considered breaking. + +To summarize: Users of Conda-Store should be able to upgrade to newer versions without worrying that this will break existing integrations. Newer features will be available for users to adopt when they need to, but all existing code should continue to work. + +## Specific Implementation Guidance + +### Database changes +Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application and breaking changes to the Database can be destructive to data and prevent rolling back to earlier versions of Conda-Store. To avoid breaking older features, discipline needs to be exercised around database migrations. +In practice this means: +1. not removing or altering columns, or tables. Instead new columns or tables should be added. This will sometimes mean that data needs to be written to multiple columns, but this in necessary. +6. not renaming columns or tables. Aliases should be used to rename existing columns or tables if they are poorly named. + + +### REST API Endpoints + +REST API endpoints need to be versioned this versioning should be done on a per endpoint basis. This will allow individual endpoints to be versioned independently of each other. + +Non-breaking changes do not require a new version of an endpoint. Adding a parameter to the return value of an endpoint or making a previously mandatory input optional can be done without a new endpoint version. However, removing a parameter from the return value, altering the meaning of a value, or making a formerly optional parameter mandatory are breaking changes and would require a new endpoint version. + +It is not necessary to backport nonbreaking changes to previous versions of endpoints. + +#### Experimental changes +Conda-Store will expose experimental features within the `experimental` namespace. + +For example, if a new version of the `example.com/api/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/user/experimental` route. + +This allows Conda-Store contributers to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. + +Note: using the `experimental` namespace is not mandatory. New endpoints and features can be deployed to existing endpoint versions for non-breaking changes and to new versions for breaking changes. However, deploying a versioned endpoint does mean a commitment to support that code going forward, so it is highly encouraged that developers use the `experimental` namespace to test new endpoints and features before deploying them as stable. + +Experimental routes have no guarantees attached to them, they can removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. + +Once we determine the routes are stable and want to support them, they will be moved into the existing latest version of the API endpoint for nonbreaking changes or a new version for breaking changes. If the route is an entirely new endpoint, it will start at `v1` + + +#### Example HTTP routes + +##### Example: versioned stable route + +``` +https://example.com/v1/api/user +https://example.com/api/v2/user +``` + +Explanation: This route has breaking changes between `v1` and `v2`. `v1` will be stable, but clients must upgrade to `v2` to benefit from new features. + + +##### Example: Route that has never had breaking changes + +``` +https://example.com/api/v1/user +``` + +Explanation: This route has never had breaking changes introduced. + +##### Example: new `experimental` route + +``` +https://example.com/api/experimental/user/ +``` + +Explanation: this is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. + +#### Removing versions of API endpoints +It is not recommended to remove versions of API endpoints generally. Removing API endpoints, or versions of endpoints breaks backwards compatibility and should only be done under exceptional circumstances such as in case of a security vulnerability. + +In the case of a removed endpoint, or endpoint version, Conda-Store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). +``` +{ + "removalDate": "2021-06-24" + "removalReason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)" + "currentEndpointVersion" : "v3" +} +``` +### Python API + +Public Python classes, functions, methods, and so on are considered public APIs and subject to the same considerations as REST API endpoints. The only exception is names starting with a single underscore. This convention is used in the Python community to designate a class, function or method as private. + +Private examples: +- `_private_func_or_method` +- `_PrivateClass` +- `_PRIVATE_VAR`. + +Public examples: +- `public_func_or_method` +- `PublicClass` +- `PUBLIC_VAR`. + +The highest-level entity determines the visibility level. + +For example: + +```py +class _Private: + # everything is private here even without underscores + def this_is_also_private(self): pass +``` + +or + +```py +def _foo(): + def inner(): + # inner is also private - no way to call it without calling _foo, which is private. +``` + +This makes it clear which APIs are public and which are private. + +Additionally, any classes, methods, or functions within the `_internal` namespace are considered private by default. It is encouraged that developers use this for any internal logic. + +The only exception to this is code in `tests`. Tests are subject to change or deletion at any time and are never considered to be public code. + +Any Class, function or method not prepended with a single underscore will be considered public. Developers are encouraged to make all classes, methods, and functions private by default and only expose them as public if there is a legitimate use case. Keeping Classes, functions and methods private by default limits the public APIs that the Conda-Store project developers are commiting to supporting, and + +For all public classes, functions, and methods, breaking changes would be anything that changes the class, function, or method's signature or the meaning of a return value. + +For a function or a method, this means that the arguements (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. + +The function signature also includes whether the function is a async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is syncronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. + +Optional arguements may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. + +For a public class, this means that attributes and methods cannot be removed or changed. Rather than changing methods or attributes, new methods or attributes should be added. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing code can use the new attribute as well as long as that doesn't introduce breaking changes into their signatures. + +Clients should be able to upgrade without any additional changes. + +#### Deprecating Python APIs + +Depreciated Classes, methods, and functions should have a comment in the code stating why they are depreciated and what to use instead. This will encourage developers not to use them without breaking existing code. + +``` +"This function is deprecated [reason/details], use [replacement] instead" +``` + +This also shall be communicated on the website and as part of release notes. From c6f478dba9051ce7887838a06c7221ddaea29bb8 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Thu, 7 Dec 2023 17:53:05 -0500 Subject: [PATCH 02/25] fmt --- BackwardsCompatibilityPolicy.md | 46 +++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/BackwardsCompatibilityPolicy.md b/BackwardsCompatibilityPolicy.md index ceeedc122..f0ee7873a 100644 --- a/BackwardsCompatibilityPolicy.md +++ b/BackwardsCompatibilityPolicy.md @@ -1,45 +1,45 @@ # Conda-Store backwards compatibility policy ## Introduction -In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy will provide guidance on how to the Conda-Store project will handle changes to software and services, ensuring that they do not disrupt or invalidate the experiences of current users, while still enabling innovation and forward progress. +In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy will provide guidance on how to the Conda-Store project will handle changes to software and services, ensuring that they do not disrupt or invalidate the experiences of current users, while still enabling innovation and forward progress. ## Breaking versus Non-Breaking Changes Breaking changes in code refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve removing existing functionality, altering existing functionality, or adding new requirements. These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. -In contrast non-Breaking changes can add functionality or reduce requirements. Previously working code will continue to work with non-breaking changes. These changes allow software to evolve and grow without impacting existing users negatively. +In contrast, non-Breaking changes can add functionality or reduce requirements. Previously working code will continue to work with non-breaking changes. These changes allow software to evolve and grow without impacting existing users negatively. Note: the term breaking changes within this policy only refers to REST API endpoints, Database changes and public Python APIs. As long as no breaking changes are introduced to REST API endpoints, Database, or public Python APIs, changes will not be considered breaking. To summarize: Users of Conda-Store should be able to upgrade to newer versions without worrying that this will break existing integrations. Newer features will be available for users to adopt when they need to, but all existing code should continue to work. -## Specific Implementation Guidance +## Specific Implementation Guidance ### Database changes Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application and breaking changes to the Database can be destructive to data and prevent rolling back to earlier versions of Conda-Store. To avoid breaking older features, discipline needs to be exercised around database migrations. In practice this means: -1. not removing or altering columns, or tables. Instead new columns or tables should be added. This will sometimes mean that data needs to be written to multiple columns, but this in necessary. -6. not renaming columns or tables. Aliases should be used to rename existing columns or tables if they are poorly named. +1. not removing or altering columns, or tables. Instead new columns or tables should be added. This will sometimes mean that data needs to be written to multiple columns, but this is necessary to maintain backwards compatibility. +6. not renaming columns or tables. Aliases should be used to rename existing columns or tables if they are poorly named. ### REST API Endpoints -REST API endpoints need to be versioned this versioning should be done on a per endpoint basis. This will allow individual endpoints to be versioned independently of each other. +REST API endpoints need to be versioned. This versioning should be done on a per endpoint basis. This will allow individual endpoints to be versioned independently of each other. -Non-breaking changes do not require a new version of an endpoint. Adding a parameter to the return value of an endpoint or making a previously mandatory input optional can be done without a new endpoint version. However, removing a parameter from the return value, altering the meaning of a value, or making a formerly optional parameter mandatory are breaking changes and would require a new endpoint version. +Non-breaking changes do not require a new version of an endpoint. Adding a parameter to the return value of an endpoint or making a previously mandatory input optional can be done without a new endpoint version. However, removing a parameter from the return value, altering the meaning of a value, or making a formerly optional parameter mandatory are breaking changes and would require a new endpoint version. It is not necessary to backport nonbreaking changes to previous versions of endpoints. #### Experimental changes Conda-Store will expose experimental features within the `experimental` namespace. -For example, if a new version of the `example.com/api/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/user/experimental` route. +For example, if a new version of the `example.com/api/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/user/experimental` route. -This allows Conda-Store contributers to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. +This allows Conda-Store contributors to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. Note: using the `experimental` namespace is not mandatory. New endpoints and features can be deployed to existing endpoint versions for non-breaking changes and to new versions for breaking changes. However, deploying a versioned endpoint does mean a commitment to support that code going forward, so it is highly encouraged that developers use the `experimental` namespace to test new endpoints and features before deploying them as stable. -Experimental routes have no guarantees attached to them, they can removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. +Experimental routes have no guarantees attached to them, they can be removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. -Once we determine the routes are stable and want to support them, they will be moved into the existing latest version of the API endpoint for nonbreaking changes or a new version for breaking changes. If the route is an entirely new endpoint, it will start at `v1` +Once we determine the routes are stable and want to support them, they will be moved into the existing latest version of the API endpoint for non breaking changes or a new version for breaking changes. If the route is an entirely new endpoint, it will start at `v1` #### Example HTTP routes @@ -71,14 +71,14 @@ https://example.com/api/experimental/user/ Explanation: this is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. #### Removing versions of API endpoints -It is not recommended to remove versions of API endpoints generally. Removing API endpoints, or versions of endpoints breaks backwards compatibility and should only be done under exceptional circumstances such as in case of a security vulnerability. +It is not recommended to remove versions of API endpoints generally. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as in case of a security vulnerability. In the case of a removed endpoint, or endpoint version, Conda-Store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). ``` { - "removalDate": "2021-06-24" - "removalReason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)" - "currentEndpointVersion" : "v3" + "removalDate": "2021-06-24" + "removalReason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)" + "currentEndpointVersion" : "v3" } ``` ### Python API @@ -110,7 +110,7 @@ or ```py def _foo(): def inner(): - # inner is also private - no way to call it without calling _foo, which is private. + # inner is also private - no way to call it without calling _foo, which is private. ``` This makes it clear which APIs are public and which are private. @@ -119,15 +119,15 @@ Additionally, any classes, methods, or functions within the `_internal` namespac The only exception to this is code in `tests`. Tests are subject to change or deletion at any time and are never considered to be public code. -Any Class, function or method not prepended with a single underscore will be considered public. Developers are encouraged to make all classes, methods, and functions private by default and only expose them as public if there is a legitimate use case. Keeping Classes, functions and methods private by default limits the public APIs that the Conda-Store project developers are commiting to supporting, and +Any Class, function or method not prepended with a single underscore will be considered public. Developers are encouraged to make all classes, methods, and functions private by default and only expose them as public if there is a legitimate use case. Keeping Classes, functions and methods private by default limits the public APIs that the Conda-Store project developers are commiting to supporting, and For all public classes, functions, and methods, breaking changes would be anything that changes the class, function, or method's signature or the meaning of a return value. -For a function or a method, this means that the arguements (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. +For a function or a method, this means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. -The function signature also includes whether the function is a async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is syncronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. +The function signature also includes whether the function is an async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. -Optional arguements may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. +Optional parameters may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. For a public class, this means that attributes and methods cannot be removed or changed. Rather than changing methods or attributes, new methods or attributes should be added. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing code can use the new attribute as well as long as that doesn't introduce breaking changes into their signatures. @@ -137,8 +137,10 @@ Clients should be able to upgrade without any additional changes. Depreciated Classes, methods, and functions should have a comment in the code stating why they are depreciated and what to use instead. This will encourage developers not to use them without breaking existing code. -``` -"This function is deprecated [reason/details], use [replacement] instead" +```python +""" +This function is deprecated [reason/details], use [replacement] instead +""" ``` This also shall be communicated on the website and as part of release notes. From 4db7cfa569ac82d26175f6de0afb85418736e437 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Thu, 7 Dec 2023 18:34:54 -0500 Subject: [PATCH 03/25] update backwards compatibility policy --- BackwardsCompatibilityPolicy.md | 78 +++++++++++++++++---------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/BackwardsCompatibilityPolicy.md b/BackwardsCompatibilityPolicy.md index f0ee7873a..ec3aecb96 100644 --- a/BackwardsCompatibilityPolicy.md +++ b/BackwardsCompatibilityPolicy.md @@ -1,66 +1,57 @@ -# Conda-Store backwards compatibility policy +# Conda-store Backwards Compatibility Policy ## Introduction -In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy will provide guidance on how to the Conda-Store project will handle changes to software and services, ensuring that they do not disrupt or invalidate the experiences of current users, while still enabling innovation and forward progress. +In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy provides guidance on how to the conda-store project will handle changes to software and services, ensuring that they do not disrupt the workflows of current users, while still enabling innovation and forward progress. ## Breaking versus Non-Breaking Changes Breaking changes in code refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve removing existing functionality, altering existing functionality, or adding new requirements. These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. -In contrast, non-Breaking changes can add functionality or reduce requirements. Previously working code will continue to work with non-breaking changes. These changes allow software to evolve and grow without impacting existing users negatively. +In contrast, non-breaking changes can add functionality or reduce requirements, allowing software to evolve and grow without negatively impacting existing users. It's important to note that, within this policy, the term "breaking changes" specifically refers to REST API endpoints, database changes, and public Python APIs. -Note: the term breaking changes within this policy only refers to REST API endpoints, Database changes and public Python APIs. As long as no breaking changes are introduced to REST API endpoints, Database, or public Python APIs, changes will not be considered breaking. - -To summarize: Users of Conda-Store should be able to upgrade to newer versions without worrying that this will break existing integrations. Newer features will be available for users to adopt when they need to, but all existing code should continue to work. +To summarize, users of Conda-Store should be able to upgrade to newer versions without worrying about breaking existing integrations. Newer features will be available for users to adopt when needed, while all existing code should continue to work. ## Specific Implementation Guidance ### Database changes -Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application and breaking changes to the Database can be destructive to data and prevent rolling back to earlier versions of Conda-Store. To avoid breaking older features, discipline needs to be exercised around database migrations. -In practice this means: -1. not removing or altering columns, or tables. Instead new columns or tables should be added. This will sometimes mean that data needs to be written to multiple columns, but this is necessary to maintain backwards compatibility. -6. not renaming columns or tables. Aliases should be used to rename existing columns or tables if they are poorly named. +Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application. Introducing breaking changes to the Database can be destructive to data and prevent rolling back to earlier versions of conda-store. To maintain backwards compatiblity: +1. New columns or tables should be added instead of removing or altering existing ones. +2. Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. ### REST API Endpoints -REST API endpoints need to be versioned. This versioning should be done on a per endpoint basis. This will allow individual endpoints to be versioned independently of each other. - -Non-breaking changes do not require a new version of an endpoint. Adding a parameter to the return value of an endpoint or making a previously mandatory input optional can be done without a new endpoint version. However, removing a parameter from the return value, altering the meaning of a value, or making a formerly optional parameter mandatory are breaking changes and would require a new endpoint version. +REST API endpoints need to be versioned on a per endpoint basis to allow endpoints to be versioned independently. New endpoints will start at `v1`. -It is not necessary to backport nonbreaking changes to previous versions of endpoints. +Non-breaking changes do not require a new version of an endpoint. Adding a parameter to the return value of an endpoint or making a previously mandatory input optional can be done without a new endpoint version. However, removing a parameter from the return value, altering the meaning of a value, or making a formerly optional parameter mandatory are breaking changes and would require a new endpoint version. It is not necessary to backport nonbreaking changes to previous versions of endpoints. #### Experimental changes -Conda-Store will expose experimental features within the `experimental` namespace. - -For example, if a new version of the `example.com/api/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/user/experimental` route. +Conda-store will expose experimental features within the `experimental` namespace. -This allows Conda-Store contributors to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. - -Note: using the `experimental` namespace is not mandatory. New endpoints and features can be deployed to existing endpoint versions for non-breaking changes and to new versions for breaking changes. However, deploying a versioned endpoint does mean a commitment to support that code going forward, so it is highly encouraged that developers use the `experimental` namespace to test new endpoints and features before deploying them as stable. +For example, if a new version of the `example.com/api/v1/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/experimental/user` route. This allows conda-store contributors to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. Using the `experimental` namespace is not mandatory. However, deploying a versioned endpoint does mean a commitment to support that code going forward, so it is highly recommended that developers use the `experimental` namespace to test new endpoints and features before deploying them as stable. Experimental routes have no guarantees attached to them, they can be removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. -Once we determine the routes are stable and want to support them, they will be moved into the existing latest version of the API endpoint for non breaking changes or a new version for breaking changes. If the route is an entirely new endpoint, it will start at `v1` +Once endpoints are determined to properly stable and functional, they will be moved into the existing latest version of the API endpoint for non breaking changes or a new version for breaking changes. #### Example HTTP routes -##### Example: versioned stable route +##### Example: Versioned Stable Route ``` -https://example.com/v1/api/user +https://example.com/api/v1/user https://example.com/api/v2/user ``` -Explanation: This route has breaking changes between `v1` and `v2`. `v1` will be stable, but clients must upgrade to `v2` to benefit from new features. +Explanation: This route has breaking changes between `v1` and `v2`. `v1` will be stable and code written for the `v1` endpoint will continue to function, but all new features will only be available in the `v2` version of the endpoint. This empowers users to upgrade when they wish to rather than forcing them to do so.ss -##### Example: Route that has never had breaking changes +##### Example: Route That Has Never Had Breaking Changes ``` https://example.com/api/v1/user ``` -Explanation: This route has never had breaking changes introduced. +Explanation: This route has never had breaking changes introduced. Any code written against this endpoint will function regardless of when it was written. ##### Example: new `experimental` route @@ -71,9 +62,9 @@ https://example.com/api/experimental/user/ Explanation: this is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. #### Removing versions of API endpoints -It is not recommended to remove versions of API endpoints generally. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as in case of a security vulnerability. +It is not recommended to remove versions of API endpoints. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as a security vulnerability. -In the case of a removed endpoint, or endpoint version, Conda-Store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). +In the case of a removed endpoint, or endpoint version, conda-store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). ``` { "removalDate": "2021-06-24" @@ -83,7 +74,7 @@ In the case of a removed endpoint, or endpoint version, Conda-Store should retur ``` ### Python API -Public Python classes, functions, methods, and so on are considered public APIs and subject to the same considerations as REST API endpoints. The only exception is names starting with a single underscore. This convention is used in the Python community to designate a class, function or method as private. +Public Python modules, classes, functions, methods and variables are considered public APIs and subject to the same considerations as REST API endpoints. Any object that is prepended with an underscore is not considered to be public. This convention is used in the Python community to designate an object as private. Private examples: - `_private_func_or_method` @@ -112,26 +103,34 @@ def _foo(): def inner(): # inner is also private - no way to call it without calling _foo, which is private. ``` +Tests are never considered to be part of the public API. Any code within the `tests/` directory are always considered to be private. -This makes it clear which APIs are public and which are private. +The only exception to this is code in `tests`. Tests are subject to change or deletion at any time and are never considered to be public code. -Additionally, any classes, methods, or functions within the `_internal` namespace are considered private by default. It is encouraged that developers use this for any internal logic. +Developers are encouraged to make code private by default and only expose objects as public if there is a explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are commiting to supporting. -The only exception to this is code in `tests`. Tests are subject to change or deletion at any time and are never considered to be public code. +#### Types of Objects +##### Modules + +A breaking change for a module means that any element of the module's public API has a breaking change. + +##### Classes -Any Class, function or method not prepended with a single underscore will be considered public. Developers are encouraged to make all classes, methods, and functions private by default and only expose them as public if there is a legitimate use case. Keeping Classes, functions and methods private by default limits the public APIs that the Conda-Store project developers are commiting to supporting, and +In a public class, a breaking change is one that changes or removes attributes or methods or alters their meanings. Rather than changing methods or attributes, new methods or attributes should be added if needed. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. -For all public classes, functions, and methods, breaking changes would be anything that changes the class, function, or method's signature or the meaning of a return value. +##### Functions and Methods +For a function or a method, breaking changes alter the signature of the method or function or the meaning of the return value. t -For a function or a method, this means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. +This means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. The function signature also includes whether the function is an async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. Optional parameters may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. -For a public class, this means that attributes and methods cannot be removed or changed. Rather than changing methods or attributes, new methods or attributes should be added. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing code can use the new attribute as well as long as that doesn't introduce breaking changes into their signatures. +##### Variables and Constants +Public variables should not have their type changed. -Clients should be able to upgrade without any additional changes. +Public constants should not have their type or their value changed. #### Deprecating Python APIs @@ -143,4 +142,7 @@ This function is deprecated [reason/details], use [replacement] instead """ ``` -This also shall be communicated on the website and as part of release notes. +Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to depriciate, remove, or introduce breaking changes to objects in the public API. This should be avoided if possible. + + +All depreciations shall be communicated in documentation and as part of release notes. From 8cb85cf7c96a10e437101b9de6b464e7de22f4a6 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:44:38 -0500 Subject: [PATCH 04/25] move policy doc --- .../community/policies/backwards-compatibility.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename BackwardsCompatibilityPolicy.md => docusaurus-docs/community/policies/backwards-compatibility.md (100%) diff --git a/BackwardsCompatibilityPolicy.md b/docusaurus-docs/community/policies/backwards-compatibility.md similarity index 100% rename from BackwardsCompatibilityPolicy.md rename to docusaurus-docs/community/policies/backwards-compatibility.md From 891da26dda60693c440b80477fdfc045eff5b896 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 12 Dec 2023 08:38:54 -0500 Subject: [PATCH 05/25] edits to backwards compatability policy --- .../policies/backwards-compatibility.md | 103 ++++++++++++------ 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index ec3aecb96..deaa360df 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -1,51 +1,80 @@ -# Conda-store Backwards Compatibility Policy +# conda-store Backwards Compatibility Policy + ## Introduction -In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy provides guidance on how to the conda-store project will handle changes to software and services, ensuring that they do not disrupt the workflows of current users, while still enabling innovation and forward progress. -## Breaking versus Non-Breaking Changes -Breaking changes in code refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve removing existing functionality, altering existing functionality, or adding new requirements. These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. +In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy provides guidance on how the conda-store project will handle changes to software and services, ensuring that they do not disrupt the workflows of current users, while still enabling innovation and forward progress. + +## Breaking versus non-breaking changes + +Breaking changes in code refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve: + +- removing existing functionality +- altering existing functionality +- adding new requirements. + +These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. Changes are only breaking if they impact users through the REST API, the Python API, or the Database. -In contrast, non-breaking changes can add functionality or reduce requirements, allowing software to evolve and grow without negatively impacting existing users. It's important to note that, within this policy, the term "breaking changes" specifically refers to REST API endpoints, database changes, and public Python APIs. +In contrast, non-breaking changes can: + +- add functionality +- reduce requirements + +These changes allow software to evolve and grow without negatively impacting existing users. To summarize, users of Conda-Store should be able to upgrade to newer versions without worrying about breaking existing integrations. Newer features will be available for users to adopt when needed, while all existing code should continue to work. -## Specific Implementation Guidance +## Specific implementation guidance ### Database changes -Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application. Introducing breaking changes to the Database can be destructive to data and prevent rolling back to earlier versions of conda-store. To maintain backwards compatiblity: -1. New columns or tables should be added instead of removing or altering existing ones. -2. Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. + +Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application. Introducing breaking changes to the database can be destructive to data and prevent rolling back to earlier versions of conda-store. To maintain backwards compatiblity: +- New columns or tables should be added instead of removing or altering existing ones. +- Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. -### REST API Endpoints +### REST API endpoints REST API endpoints need to be versioned on a per endpoint basis to allow endpoints to be versioned independently. New endpoints will start at `v1`. -Non-breaking changes do not require a new version of an endpoint. Adding a parameter to the return value of an endpoint or making a previously mandatory input optional can be done without a new endpoint version. However, removing a parameter from the return value, altering the meaning of a value, or making a formerly optional parameter mandatory are breaking changes and would require a new endpoint version. It is not necessary to backport nonbreaking changes to previous versions of endpoints. +Non-breaking changes do not require a new version of an endpoint. For REST API endpoints, examples on non-breaking changes are: + +- Adding a parameter to the return value of an endpoint +- making a previously mandatory input optional + +These changes can be done without a new endpoint version. + +However, changes such as: + +- removing a parameter from the return value +- altering the meaning of a value +- making a formerly optional parameter mandatory + +are breaking changes and would require a new endpoint version. #### Experimental changes -Conda-store will expose experimental features within the `experimental` namespace. + +conda-store will expose experimental features within the `experimental` namespace. For example, if a new version of the `example.com/api/v1/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/experimental/user` route. This allows conda-store contributors to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. Using the `experimental` namespace is not mandatory. However, deploying a versioned endpoint does mean a commitment to support that code going forward, so it is highly recommended that developers use the `experimental` namespace to test new endpoints and features before deploying them as stable. Experimental routes have no guarantees attached to them, they can be removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. -Once endpoints are determined to properly stable and functional, they will be moved into the existing latest version of the API endpoint for non breaking changes or a new version for breaking changes. +Once endpoints are determined to stable and functional, they will be moved into the existing latest version of the API endpoint for non breaking changes or a new version for breaking changes. #### Example HTTP routes -##### Example: Versioned Stable Route +##### Versioned stable route ``` https://example.com/api/v1/user https://example.com/api/v2/user ``` -Explanation: This route has breaking changes between `v1` and `v2`. `v1` will be stable and code written for the `v1` endpoint will continue to function, but all new features will only be available in the `v2` version of the endpoint. This empowers users to upgrade when they wish to rather than forcing them to do so.ss +Explanation: This route has breaking changes between `v1` and `v2`. Code written for the `v1` endpoint will continue to function, but all new features will only be available in the `v2` version of the endpoint. This empowers users to upgrade when they wish to rather than forcing them to do so. -##### Example: Route That Has Never Had Breaking Changes +##### Route that has never had breaking changes ``` https://example.com/api/v1/user @@ -53,7 +82,7 @@ https://example.com/api/v1/user Explanation: This route has never had breaking changes introduced. Any code written against this endpoint will function regardless of when it was written. -##### Example: new `experimental` route +##### New `experimental` route ``` https://example.com/api/experimental/user/ @@ -62,19 +91,21 @@ https://example.com/api/experimental/user/ Explanation: this is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. #### Removing versions of API endpoints + It is not recommended to remove versions of API endpoints. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as a security vulnerability. In the case of a removed endpoint, or endpoint version, conda-store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). ``` { - "removalDate": "2021-06-24" - "removalReason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)" - "currentEndpointVersion" : "v3" + "removal_date": "2021-06-24" + "removal_reason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)" + "new_endpoint" : "api/v3/this/should/be/used/instead" } ``` + ### Python API -Public Python modules, classes, functions, methods and variables are considered public APIs and subject to the same considerations as REST API endpoints. Any object that is prepended with an underscore is not considered to be public. This convention is used in the Python community to designate an object as private. +Public Python modules, classes, functions, methods, and variables are considered public APIs and subject to the same considerations as REST API endpoints. Any object with a leading underscore is not considered to be public. This convention is used in the Python community to designate an object as private. Private examples: - `_private_func_or_method` @@ -92,43 +123,44 @@ For example: ```py class _Private: - # everything is private here even without underscores - def this_is_also_private(self): pass + # everything is private here even without underscores + def this_is_also_private(self): pass ``` or ```py def _foo(): - def inner(): + def inner(): # inner is also private - no way to call it without calling _foo, which is private. ``` -Tests are never considered to be part of the public API. Any code within the `tests/` directory are always considered to be private. +Tests are never considered to be part of the public API. Any code within the `tests/` directory is always considered to be private. -The only exception to this is code in `tests`. Tests are subject to change or deletion at any time and are never considered to be public code. +Developers are encouraged to make code private by default and only expose objects as public if there is an explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are commiting to supporting. -Developers are encouraged to make code private by default and only expose objects as public if there is a explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are commiting to supporting. +#### Types of objects -#### Types of Objects ##### Modules A breaking change for a module means that any element of the module's public API has a breaking change. ##### Classes -In a public class, a breaking change is one that changes or removes attributes or methods or alters their meanings. Rather than changing methods or attributes, new methods or attributes should be added if needed. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. +In a public class, a breaking change is one that changes or removes attributes or methods or alters their meanings. Rather than changing methods or attributes, new methods or attributes should be added if needed. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. + +##### Functions and methods -##### Functions and Methods For a function or a method, breaking changes alter the signature of the method or function or the meaning of the return value. t -This means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. +This means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. -The function signature also includes whether the function is an async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. +The function signature also includes whether the function is an async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. Optional parameters may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. -##### Variables and Constants -Public variables should not have their type changed. +##### Variables and constants + +Public variables should not have their type changed. Public constants should not have their type or their value changed. @@ -142,7 +174,6 @@ This function is deprecated [reason/details], use [replacement] instead """ ``` -Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to depriciate, remove, or introduce breaking changes to objects in the public API. This should be avoided if possible. - +Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to depriciate, remove, or introduce breaking changes to objects in the public API. This should be avoided if possible. All depreciations shall be communicated in documentation and as part of release notes. From 313e4b72f68da03f5f04aa48e11bdc65b2f1c167 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:02:41 -0500 Subject: [PATCH 06/25] update backwards-compatability policy --- .../community/policies/backwards-compatibility.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index deaa360df..8faa12101 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -150,11 +150,13 @@ In a public class, a breaking change is one that changes or removes attributes o ##### Functions and methods -For a function or a method, breaking changes alter the signature of the method or function or the meaning of the return value. t +For a function or a method, breaking changes alter its signature or the meaning of the return value. This means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. -The function signature also includes whether the function is an async function. Changing this is a breaking change.For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. +The function signature also includes whether the function is an async function. Changing this is a breaking change. + +For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. Optional parameters may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. @@ -166,7 +168,7 @@ Public constants should not have their type or their value changed. #### Deprecating Python APIs -Depreciated Classes, methods, and functions should have a comment in the code stating why they are depreciated and what to use instead. This will encourage developers not to use them without breaking existing code. +Deprecated classes, methods, and functions should have a comment and a warning (if possible) in the code stating why they are deprecated and what to use instead. This will encourage developers not to use them without breaking existing code. ```python """ @@ -176,4 +178,4 @@ This function is deprecated [reason/details], use [replacement] instead Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to depriciate, remove, or introduce breaking changes to objects in the public API. This should be avoided if possible. -All depreciations shall be communicated in documentation and as part of release notes. +All deprecations shall be communicated in documentation and as part of release notes. From 7c6b6d4033f3fc9cdb20062db2a6509cf749317a Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:04:33 -0500 Subject: [PATCH 07/25] fix merge conflict --- .../community/policies/backwards-compatibility.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 1f554660b..8faa12101 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -179,8 +179,3 @@ This function is deprecated [reason/details], use [replacement] instead Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to depriciate, remove, or introduce breaking changes to objects in the public API. This should be avoided if possible. All deprecations shall be communicated in documentation and as part of release notes. -# Backwards compatibility policy - -:::note -This page is in active development, and will be available soon. -::: From 6275f359e7883b7377c3323b630d46fa894fc959 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:52:00 -0500 Subject: [PATCH 08/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 8faa12101..143340767 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -2,7 +2,7 @@ ## Introduction -In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy provides guidance on how the conda-store project will handle changes to software and services, ensuring that they do not disrupt the workflows of current users, while still enabling innovation and forward progress. +In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy guides how the conda-store project will handle changes to software and services, ensuring that they do not disrupt the workflows of current users, while still enabling innovation and forward progress. ## Breaking versus non-breaking changes From 2702cca9900f46d5955ace4ff61e45d5eafcfd57 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:54:23 -0500 Subject: [PATCH 09/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 143340767..f21715ffc 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -6,7 +6,7 @@ In software development, it is essential to strike a balance between progress an ## Breaking versus non-breaking changes -Breaking changes in code refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve: +Breaking code changes refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve: - removing existing functionality - altering existing functionality From a3d548588ae8a60ac4bc9bc8656c53965efa1531 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:54:52 -0500 Subject: [PATCH 10/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- .../community/policies/backwards-compatibility.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index f21715ffc..399496885 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -21,7 +21,11 @@ In contrast, non-breaking changes can: These changes allow software to evolve and grow without negatively impacting existing users. -To summarize, users of Conda-Store should be able to upgrade to newer versions without worrying about breaking existing integrations. Newer features will be available for users to adopt when needed, while all existing code should continue to work. +:::info[TLD;R] + +conda-store users should be able to upgrade to newer versions without worrying about breaking existing integrations. Newer features will be available for users to adopt when needed, while all existing code should continue to work. + +::: ## Specific implementation guidance From 2ca481eb6e6d591062064f172d03eb94b95cd7d5 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:55:28 -0500 Subject: [PATCH 11/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 399496885..aa0e61291 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -140,7 +140,7 @@ def _foo(): ``` Tests are never considered to be part of the public API. Any code within the `tests/` directory is always considered to be private. -Developers are encouraged to make code private by default and only expose objects as public if there is an explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are commiting to supporting. +Developers are encouraged to make code private by default and only expose objects as public if there is an explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are committing to supporting. #### Types of objects From 2378c101a50aff36629f0253709cd2a51477ed79 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:59:59 -0500 Subject: [PATCH 12/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index aa0e61291..60fb259c4 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -31,7 +31,9 @@ conda-store users should be able to upgrade to newer versions without worrying a ### Database changes -Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold state for the application. Introducing breaking changes to the database can be destructive to data and prevent rolling back to earlier versions of conda-store. To maintain backwards compatiblity: +Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold the state for the application. +Introducing breaking changes to the database can be destructive to data and prevent rolling back to earlier versions of conda-store. To maintain backward compatibility we follow these principles: + - New columns or tables should be added instead of removing or altering existing ones. - Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. From 58fd99e1b9a9a36f3a52c506a1812fb5075d8f9a Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:06:21 -0500 Subject: [PATCH 13/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 60fb259c4..8dc48cf6d 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -40,7 +40,7 @@ Introducing breaking changes to the database can be destructive to data and prev ### REST API endpoints -REST API endpoints need to be versioned on a per endpoint basis to allow endpoints to be versioned independently. New endpoints will start at `v1`. +REST API endpoints are versioned on a per-endpoint basis. New endpoints will start at `v1`. Non-breaking changes do not require a new version of an endpoint. For REST API endpoints, examples on non-breaking changes are: From c14f93f580bf87458c956223554f1a51d407426f Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:06:40 -0500 Subject: [PATCH 14/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 8dc48cf6d..7ed4e4164 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -55,7 +55,7 @@ However, changes such as: - altering the meaning of a value - making a formerly optional parameter mandatory -are breaking changes and would require a new endpoint version. +are breaking changes and **require** a new endpoint version. #### Experimental changes From b84ec232b932e185eeab83502eb0f6c44161a77c Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:07:53 -0500 Subject: [PATCH 15/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Tania Allard --- docusaurus-docs/community/policies/backwards-compatibility.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 7ed4e4164..5b7409027 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -61,7 +61,9 @@ are breaking changes and **require** a new endpoint version. conda-store will expose experimental features within the `experimental` namespace. -For example, if a new version of the `example.com/api/v1/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/experimental/user` route. This allows conda-store contributors to test new changes and get community feedback without commiting to supporting a new version of an API endpoint. Using the `experimental` namespace is not mandatory. However, deploying a versioned endpoint does mean a commitment to support that code going forward, so it is highly recommended that developers use the `experimental` namespace to test new endpoints and features before deploying them as stable. +For example, if a new version of the `example.com/api/v1/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/experimental/user` route. +This allows conda-store contributors to test new changes and get community feedback without committing to supporting a new version of an API endpoint. +Using the `experimental` namespace is not mandatory. However, deploying a versioned endpoint expresses a commitment to support that code going forward, so it is highly recommended that developers use the `experimental` namespace to test new endpoints and features before marking them as stable. Experimental routes have no guarantees attached to them, they can be removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. From 9a72c27be4a4c1ac8f1df85687b9a4b7292c576c Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:36:17 -0500 Subject: [PATCH 16/25] update backwards compatibility policy --- .../policies/backwards-compatibility.md | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 5b7409027..0b9e11c69 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -10,14 +10,11 @@ Breaking code changes refer to modifications or updates made to software that ha - removing existing functionality - altering existing functionality -- adding new requirements. +- adding new requirements such as making a previously optional parameter required. These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. Changes are only breaking if they impact users through the REST API, the Python API, or the Database. -In contrast, non-breaking changes can: - -- add functionality -- reduce requirements +In contrast, non-breaking changes can add functionality or reduce requirements such as making a previously required These changes allow software to evolve and grow without negatively impacting existing users. @@ -37,15 +34,14 @@ Introducing breaking changes to the database can be destructive to data and prev - New columns or tables should be added instead of removing or altering existing ones. - Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. - ### REST API endpoints REST API endpoints are versioned on a per-endpoint basis. New endpoints will start at `v1`. Non-breaking changes do not require a new version of an endpoint. For REST API endpoints, examples on non-breaking changes are: -- Adding a parameter to the return value of an endpoint -- making a previously mandatory input optional +- adding a parameter to the return value of an endpoint +- making a previously mandatory input optional. These changes can be done without a new endpoint version. @@ -57,6 +53,10 @@ However, changes such as: are breaking changes and **require** a new endpoint version. +When a new version of an endpoint is created, then all new features will be added to the new version. + +Older versions of API endpoints are still considered supported and will receive bug fixes and security updates to their features but new features will not be backported to them. + #### Experimental changes conda-store will expose experimental features within the `experimental` namespace. @@ -67,8 +67,7 @@ Using the `experimental` namespace is not mandatory. However, deploying a versio Experimental routes have no guarantees attached to them, they can be removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. -Once endpoints are determined to stable and functional, they will be moved into the existing latest version of the API endpoint for non breaking changes or a new version for breaking changes. - +Once endpoints are determined to be stable and functional, they will be moved into the existing latest version of the API endpoint for non-breaking changes or a new version for breaking changes. #### Example HTTP routes @@ -79,7 +78,9 @@ https://example.com/api/v1/user https://example.com/api/v2/user ``` -Explanation: This route has breaking changes between `v1` and `v2`. Code written for the `v1` endpoint will continue to function, but all new features will only be available in the `v2` version of the endpoint. This empowers users to upgrade when they wish to rather than forcing them to do so. +Explanation: This route has breaking changes between `v1` and `v2`. +Code written for the `v1` endpoint will continue to function, but all new features will only be available in the `v2` version of the endpoint. +This empowers users to upgrade when they wish to rather than forcing them to do so. ##### Route that has never had breaking changes @@ -96,18 +97,20 @@ Explanation: This route has never had breaking changes introduced. Any code writ https://example.com/api/experimental/user/ ``` -Explanation: this is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. +Explanation: This is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. #### Removing versions of API endpoints It is not recommended to remove versions of API endpoints. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as a security vulnerability. In the case of a removed endpoint, or endpoint version, conda-store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). -``` + +```python { - "removal_date": "2021-06-24" - "removal_reason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)" - "new_endpoint" : "api/v3/this/should/be/used/instead" + "reference_pull_request": "https://github.com/conda-incubator/conda-store/pull/0000", # the pull request that removed the endpoint + "removal_date": "2021-06-24", # the date the endpoint was removed + "removal_reason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)", # the reason for the removal, ideally with a link to a CVE if one is available + "new_endpoint": "api/v3/this/should/be/used/instead", # the endpoint that developers should use as a replacement } ``` @@ -154,7 +157,10 @@ A breaking change for a module means that any element of the module's public API ##### Classes -In a public class, a breaking change is one that changes or removes attributes or methods or alters their meanings. Rather than changing methods or attributes, new methods or attributes should be added if needed. For example, if you wanted to change a user id from an int, to a uuid, a new attribute of User.uuid should be added, and all new code should use User.uuid. Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. +In a public class, a breaking change is one that changes or removes attributes or methods or alters their meanings. +Rather than changing methods or attributes, new methods or attributes should be added if needed. +For example, if you wanted to change a user id from an `int`, to a `uuid`, a new attribute `User.uuid` should be added, and all new code should use `User.uuid`. +Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. ##### Functions and methods From c4214200fcf7da0e7dd68bdc489bc14177f1ed43 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:41:48 -0500 Subject: [PATCH 17/25] wrap lines at 80 characters --- .../policies/backwards-compatibility.md | 235 +++++++++++------- 1 file changed, 143 insertions(+), 92 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 0b9e11c69..87536c4b4 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -2,25 +2,38 @@ ## Introduction -In software development, it is essential to strike a balance between progress and maintaining a stable environment for existing users. This policy guides how the conda-store project will handle changes to software and services, ensuring that they do not disrupt the workflows of current users, while still enabling innovation and forward progress. +In software development, it is essential to strike a balance between progress +and maintaining a stable environment for existing users. This policy guides how +the conda-store project will handle changes to software and services, ensuring +that they do not disrupt the workflows of current users, while still enabling +innovation and forward progress. ## Breaking versus non-breaking changes -Breaking code changes refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve: +Breaking code changes refer to modifications or updates made to software that +have the potential to disrupt the functionality of existing applications, +integrations, or systems. Breaking changes involve: -- removing existing functionality -- altering existing functionality -- adding new requirements such as making a previously optional parameter required. +- removing existing functionality - altering existing functionality - adding new +requirements such as making a previously optional parameter required. -These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining the trust and reputation of the software or service provider. Changes are only breaking if they impact users through the REST API, the Python API, or the Database. +These changes can lead to compatibility issues, causing frustration for +end-users, higher maintenance costs, and even system downtime, thus undermining +the trust and reputation of the software or service provider. Changes are only +breaking if they impact users through the REST API, the Python API, or the +Database. -In contrast, non-breaking changes can add functionality or reduce requirements such as making a previously required +In contrast, non-breaking changes can add functionality or reduce requirements +such as making a previously required -These changes allow software to evolve and grow without negatively impacting existing users. +These changes allow software to evolve and grow without negatively impacting +existing users. :::info[TLD;R] -conda-store users should be able to upgrade to newer versions without worrying about breaking existing integrations. Newer features will be available for users to adopt when needed, while all existing code should continue to work. +conda-store users should be able to upgrade to newer versions without worrying +about breaking existing integrations. Newer features will be available for users +to adopt when needed, while all existing code should continue to work. ::: @@ -28,151 +41,185 @@ conda-store users should be able to upgrade to newer versions without worrying a ### Database changes -Databases are one of the most critical areas to ensure there are no breaking changes. Databases hold the state for the application. -Introducing breaking changes to the database can be destructive to data and prevent rolling back to earlier versions of conda-store. To maintain backward compatibility we follow these principles: +Databases are one of the most critical areas to ensure there are no breaking +changes. Databases hold the state for the application. Introducing breaking +changes to the database can be destructive to data and prevent rolling back to +earlier versions of conda-store. To maintain backward compatibility we follow +these principles: -- New columns or tables should be added instead of removing or altering existing ones. -- Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. +- New columns or tables should be added instead of removing or altering existing +ones. - Columns and tables should not be renamed. Aliases should be used for +poorly named existing columns or tables. ### REST API endpoints -REST API endpoints are versioned on a per-endpoint basis. New endpoints will start at `v1`. +REST API endpoints are versioned on a per-endpoint basis. New endpoints will +start at `v1`. -Non-breaking changes do not require a new version of an endpoint. For REST API endpoints, examples on non-breaking changes are: +Non-breaking changes do not require a new version of an endpoint. For REST API +endpoints, examples on non-breaking changes are: -- adding a parameter to the return value of an endpoint -- making a previously mandatory input optional. +- adding a parameter to the return value of an endpoint - making a previously +mandatory input optional. These changes can be done without a new endpoint version. However, changes such as: -- removing a parameter from the return value -- altering the meaning of a value -- making a formerly optional parameter mandatory +- removing a parameter from the return value - altering the meaning of a value - +making a formerly optional parameter mandatory are breaking changes and **require** a new endpoint version. -When a new version of an endpoint is created, then all new features will be added to the new version. +When a new version of an endpoint is created, then all new features will be +added to the new version. -Older versions of API endpoints are still considered supported and will receive bug fixes and security updates to their features but new features will not be backported to them. +Older versions of API endpoints are still considered supported and will receive +bug fixes and security updates to their features but new features will not be +backported to them. #### Experimental changes -conda-store will expose experimental features within the `experimental` namespace. +conda-store will expose experimental features within the `experimental` +namespace. -For example, if a new version of the `example.com/api/v1/user` endpoint is being tested, but not yet considered stable, it can be made available at the `example.com/api/experimental/user` route. -This allows conda-store contributors to test new changes and get community feedback without committing to supporting a new version of an API endpoint. -Using the `experimental` namespace is not mandatory. However, deploying a versioned endpoint expresses a commitment to support that code going forward, so it is highly recommended that developers use the `experimental` namespace to test new endpoints and features before marking them as stable. +For example, if a new version of the `example.com/api/v1/user` endpoint is being +tested, but not yet considered stable, it can be made available at the +`example.com/api/experimental/user` route. This allows conda-store contributors +to test new changes and get community feedback without committing to supporting +a new version of an API endpoint. Using the `experimental` namespace is not +mandatory. However, deploying a versioned endpoint expresses a commitment to +support that code going forward, so it is highly recommended that developers use +the `experimental` namespace to test new endpoints and features before marking +them as stable. -Experimental routes have no guarantees attached to them, they can be removed or changed at any time without warning. This allows testing features with users in real-world scenarios without needing to commit to support that feature as is. +Experimental routes have no guarantees attached to them, they can be removed or +changed at any time without warning. This allows testing features with users in +real-world scenarios without needing to commit to support that feature as is. -Once endpoints are determined to be stable and functional, they will be moved into the existing latest version of the API endpoint for non-breaking changes or a new version for breaking changes. +Once endpoints are determined to be stable and functional, they will be moved +into the existing latest version of the API endpoint for non-breaking changes or +a new version for breaking changes. #### Example HTTP routes ##### Versioned stable route -``` -https://example.com/api/v1/user -https://example.com/api/v2/user -``` +``` https://example.com/api/v1/user https://example.com/api/v2/user ``` -Explanation: This route has breaking changes between `v1` and `v2`. -Code written for the `v1` endpoint will continue to function, but all new features will only be available in the `v2` version of the endpoint. -This empowers users to upgrade when they wish to rather than forcing them to do so. +Explanation: This route has breaking changes between `v1` and `v2`. Code +written for the `v1` endpoint will continue to function, but all new features +will only be available in the `v2` version of the endpoint. This empowers users +to upgrade when they wish to rather than forcing them to do so. ##### Route that has never had breaking changes -``` -https://example.com/api/v1/user -``` +``` https://example.com/api/v1/user ``` -Explanation: This route has never had breaking changes introduced. Any code written against this endpoint will function regardless of when it was written. +Explanation: This route has never had breaking changes introduced. Any code +written against this endpoint will function regardless of when it was written. ##### New `experimental` route -``` -https://example.com/api/experimental/user/ -``` +``` https://example.com/api/experimental/user/ ``` -Explanation: This is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. +Explanation: This is an experimental route. It can be changed or removed at any +moment without prior notice. This route should be used to test new features and +get community feedback. #### Removing versions of API endpoints -It is not recommended to remove versions of API endpoints. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as a security vulnerability. +It is not recommended to remove versions of API endpoints. Removing API +endpoints, or versions of endpoints, breaks backwards compatibility and should +only be done under exceptional circumstances such as a security vulnerability. -In the case of a removed endpoint, or endpoint version, conda-store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). +In the case of a removed endpoint, or endpoint version, conda-store should +return a status code of `410 Gone` to indicate the endpoint has been removed +along with a json object stating when and why the endpoint was removed and what +version of the endpoint is available currently (if any). -```python -{ - "reference_pull_request": "https://github.com/conda-incubator/conda-store/pull/0000", # the pull request that removed the endpoint - "removal_date": "2021-06-24", # the date the endpoint was removed - "removal_reason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)", # the reason for the removal, ideally with a link to a CVE if one is available - "new_endpoint": "api/v3/this/should/be/used/instead", # the endpoint that developers should use as a replacement -} -``` +```python { "reference_pull_request": +"https://github.com/conda-incubator/conda-store/pull/0000", # the pull request +that removed the endpoint "removal_date": "2021-06-24", # the date the endpoint +was removed "removal_reason": "Removed to address CVE-2021-32677 +(https://nvd.nist.gov/vuln/detail/CVE-2021-32677)", # the reason for the +removal, ideally with a link to a CVE if one is available "new_endpoint": +"api/v3/this/should/be/used/instead", # the endpoint that developers should use +as a replacement } ``` ### Python API -Public Python modules, classes, functions, methods, and variables are considered public APIs and subject to the same considerations as REST API endpoints. Any object with a leading underscore is not considered to be public. This convention is used in the Python community to designate an object as private. +Public Python modules, classes, functions, methods, and variables are considered +public APIs and subject to the same considerations as REST API endpoints. Any +object with a leading underscore is not considered to be public. This convention +is used in the Python community to designate an object as private. -Private examples: -- `_private_func_or_method` -- `_PrivateClass` -- `_PRIVATE_VAR`. +Private examples: - `_private_func_or_method` - `_PrivateClass` - +`_PRIVATE_VAR`. -Public examples: -- `public_func_or_method` -- `PublicClass` -- `PUBLIC_VAR`. +Public examples: - `public_func_or_method` - `PublicClass` - `PUBLIC_VAR`. The highest-level entity determines the visibility level. For example: -```py -class _Private: - # everything is private here even without underscores - def this_is_also_private(self): pass -``` +```py class _Private: +# everything is private here even without underscores +def this_is_also_private(self): pass ``` or -```py -def _foo(): - def inner(): - # inner is also private - no way to call it without calling _foo, which is private. -``` -Tests are never considered to be part of the public API. Any code within the `tests/` directory is always considered to be private. +```py def _foo(): def inner(): +# inner is also private - no way to call it without calling _foo, which is +# private. +``` Tests are never considered to be part of the public API. Any code within the +`tests/` directory is always considered to be private. -Developers are encouraged to make code private by default and only expose objects as public if there is an explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are committing to supporting. +Developers are encouraged to make code private by default and only expose +objects as public if there is an explicit need to do so. Keeping code private by +default limits the public API that the conda-store project developers are +committing to supporting. #### Types of objects ##### Modules -A breaking change for a module means that any element of the module's public API has a breaking change. +A breaking change for a module means that any element of the module's public API +has a breaking change. ##### Classes -In a public class, a breaking change is one that changes or removes attributes or methods or alters their meanings. -Rather than changing methods or attributes, new methods or attributes should be added if needed. -For example, if you wanted to change a user id from an `int`, to a `uuid`, a new attribute `User.uuid` should be added, and all new code should use `User.uuid`. -Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. +In a public class, a breaking change is one that changes or removes attributes +or methods or alters their meanings. Rather than changing methods or +attributes, new methods or attributes should be added if needed. For example, +if you wanted to change a user id from an `int`, to a `uuid`, a new attribute +`User.uuid` should be added, and all new code should use `User.uuid`. Existing +methods can use the new attribute or methods as well as long as that doesn't +introduce breaking changes for the method. ##### Functions and methods -For a function or a method, breaking changes alter its signature or the meaning of the return value. +For a function or a method, breaking changes alter its signature or the meaning +of the return value. -This means that the parameters (inputs) and return values (outputs) must be the same. Internal logic may be changed as long as it does not change return values. Extra care should be taken when making these changes however. Changing the way a return value is calculated may result in subtle changes which are not obvious. For example, rounding a decimal versus truncating it may return different results even though the function signature remains the same. +This means that the parameters (inputs) and return values (outputs) must be the +same. Internal logic may be changed as long as it does not change return values. +Extra care should be taken when making these changes however. Changing the way a +return value is calculated may result in subtle changes which are not obvious. +For example, rounding a decimal versus truncating it may return different +results even though the function signature remains the same. -The function signature also includes whether the function is an async function. Changing this is a breaking change. +The function signature also includes whether the function is an async function. +Changing this is a breaking change. -For example, if there is a function `def list_envs`, which is synchronous, and it should be asynchronous, a new function called `async def list_envs_async` should be added and `list_envs` should be kept as a synchronous call. +For example, if there is a function `def list_envs`, which is synchronous, and +it should be asynchronous, a new function called `async def list_envs_async` +should be added and `list_envs` should be kept as a synchronous call. -Optional parameters may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an object like a dict. These are considered non-breaking. +Optional parameters may be added as long as they have a specified default value +and additional fields may be added to return types if you are returning an +object like a dict. These are considered non-breaking. ##### Variables and constants @@ -182,14 +229,18 @@ Public constants should not have their type or their value changed. #### Deprecating Python APIs -Deprecated classes, methods, and functions should have a comment and a warning (if possible) in the code stating why they are deprecated and what to use instead. This will encourage developers not to use them without breaking existing code. +Deprecated classes, methods, and functions should have a comment and a warning +(if possible) in the code stating why they are deprecated and what to use +instead. This will encourage developers not to use them without breaking +existing code. -```python -""" -This function is deprecated [reason/details], use [replacement] instead -""" -``` +```python """ This function is deprecated [reason/details], use [replacement] +instead """ ``` -Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to depriciate, remove, or introduce breaking changes to objects in the public API. This should be avoided if possible. +Under exceptional circumstances such as a serious security vulnerability which +can't be fixed without breaking changes, it may be necessary to deprecate, +remove, or introduce breaking changes to objects in the public API. This should +be avoided if possible. -All deprecations shall be communicated in documentation and as part of release notes. +All deprecations shall be communicated in documentation and as part of release +notes. From 38534d38a7545567933733396a9229892c465a5e Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 22 Dec 2023 16:26:10 -0500 Subject: [PATCH 18/25] update backwards compatibility policy --- .../policies/backwards-compatibility.md | 114 ++++++++++++------ 1 file changed, 74 insertions(+), 40 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 87536c4b4..c2491da41 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -14,8 +14,9 @@ Breaking code changes refer to modifications or updates made to software that have the potential to disrupt the functionality of existing applications, integrations, or systems. Breaking changes involve: -- removing existing functionality - altering existing functionality - adding new -requirements such as making a previously optional parameter required. +- removing existing functionality +- altering existing functionality +- adding new requirements such as making a previously optional parameter required. These changes can lead to compatibility issues, causing frustration for end-users, higher maintenance costs, and even system downtime, thus undermining @@ -24,8 +25,7 @@ breaking if they impact users through the REST API, the Python API, or the Database. In contrast, non-breaking changes can add functionality or reduce requirements -such as making a previously required - +such as making a previously required parameter optional. These changes allow software to evolve and grow without negatively impacting existing users. @@ -134,19 +134,38 @@ It is not recommended to remove versions of API endpoints. Removing API endpoints, or versions of endpoints, breaks backwards compatibility and should only be done under exceptional circumstances such as a security vulnerability. +If the desire is to prevent a developer from relying on an API endpoint, adding +a warning to the API documentation along with a recommended alternative should +be used rather than a deprecation or removal. + In the case of a removed endpoint, or endpoint version, conda-store should return a status code of `410 Gone` to indicate the endpoint has been removed along with a json object stating when and why the endpoint was removed and what version of the endpoint is available currently (if any). -```python { "reference_pull_request": -"https://github.com/conda-incubator/conda-store/pull/0000", # the pull request -that removed the endpoint "removal_date": "2021-06-24", # the date the endpoint -was removed "removal_reason": "Removed to address CVE-2021-32677 -(https://nvd.nist.gov/vuln/detail/CVE-2021-32677)", # the reason for the -removal, ideally with a link to a CVE if one is available "new_endpoint": -"api/v3/this/should/be/used/instead", # the endpoint that developers should use -as a replacement } ``` +```python +{ + # the pull request that removed the endpoint + "reference_pull_request": "https://github.com/conda-incubator/conda-store/pull/0000", + # the date the endpoint was removed + "removal_date": "2021-06-24", + # the reason for the removal, ideally with a link to a CVE if one is available + "removal_reason": "Removed to address CVE-2021-32677 (https://nvd.nist.gov/vuln/detail/CVE-2021-32677)", + # the endpoint that developers should use as a replacement + "new_endpoint": "api/v3/this/should/be/used/instead", +} +``` + +If an API endpoint must be deprecated, a deprecation warning should be added +for at least one release before the endpoint is removed. This requirement may +be waived in the case of a serious security vulnerability. + +It should always be clearly communicated in release notes and documentation +when an API endpoint is deprecated or removed. This should include: +- version number of the release where this was deprecated +- provide suggestions for alternatives (if possible). +- provide justification for the removal (such as a link to the issue + or CVE that necessitated the removal) ### Python API @@ -164,16 +183,22 @@ The highest-level entity determines the visibility level. For example: -```py class _Private: -# everything is private here even without underscores -def this_is_also_private(self): pass ``` +```py +class _Private: + # everything is private here even without underscores + def this_is_also_private(self): pass +``` or -```py def _foo(): def inner(): -# inner is also private - no way to call it without calling _foo, which is -# private. -``` Tests are never considered to be part of the public API. Any code within the +```py + def _foo(): + def inner(): + # inner is also private - no way to call it without calling _foo, which is + # private. +``` + +Tests are never considered to be part of the public API. Any code within the `tests/` directory is always considered to be private. Developers are encouraged to make code private by default and only expose @@ -181,6 +206,33 @@ objects as public if there is an explicit need to do so. Keeping code private by default limits the public API that the conda-store project developers are committing to supporting. +#### Deprecating Python APIs + +Under exceptional circumstances such as a serious security vulnerability which +can't be fixed without breaking changes, it may be necessary to deprecate, +remove, or introduce breaking changes to objects in the public Python API. +This should be avoided if possible. + +If the desire is to prevent a developer from relying on a part of the Python +API, adding a warning to the documentation along with a recommended alternative +and a comment in the code should be used rather than a deprecation or removal. + +```python + """ + This function is deprecated [reason/details], use [replacement] instead + """ +``` +If part of the Python API must be deprecated or removed, a deprecation warning +should be added for at least one release before the endpoint is removed. This +requirement may be waived in the case of a serious security vulnerability. + +The deprecation or removal should always be clearly communicated in release +notes and documentation This should include: +- version number of the release where this was deprecated +- provide suggestions for alternatives (if possible). +- provide a reason for the deprecation or removal (such + as a link to a CVE or issue that necessitated the removal + #### Types of objects ##### Modules @@ -213,9 +265,9 @@ results even though the function signature remains the same. The function signature also includes whether the function is an async function. Changing this is a breaking change. -For example, if there is a function `def list_envs`, which is synchronous, and -it should be asynchronous, a new function called `async def list_envs_async` -should be added and `list_envs` should be kept as a synchronous call. +For example, if there is a function `list_envs`, which is synchronous, and +it should be asynchronous, a new function called ` list_envs_async` should be +added and `list_envs` should be kept as a synchronous call. Optional parameters may be added as long as they have a specified default value and additional fields may be added to return types if you are returning an @@ -226,21 +278,3 @@ object like a dict. These are considered non-breaking. Public variables should not have their type changed. Public constants should not have their type or their value changed. - -#### Deprecating Python APIs - -Deprecated classes, methods, and functions should have a comment and a warning -(if possible) in the code stating why they are deprecated and what to use -instead. This will encourage developers not to use them without breaking -existing code. - -```python """ This function is deprecated [reason/details], use [replacement] -instead """ ``` - -Under exceptional circumstances such as a serious security vulnerability which -can't be fixed without breaking changes, it may be necessary to deprecate, -remove, or introduce breaking changes to objects in the public API. This should -be avoided if possible. - -All deprecations shall be communicated in documentation and as part of release -notes. From 2cd9a90d6f236b13a1777b4e1e909412df9c89e7 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:56:27 -0500 Subject: [PATCH 19/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Nikita Karetnikov --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index c2491da41..68e1c733a 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -29,7 +29,7 @@ such as making a previously required parameter optional. These changes allow software to evolve and grow without negatively impacting existing users. -:::info[TLD;R] +:::info[TL;DR] conda-store users should be able to upgrade to newer versions without worrying about breaking existing integrations. Newer features will be available for users From ba718192276f121c53d919198efb707e784cb2a1 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:56:44 -0500 Subject: [PATCH 20/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Nikita Karetnikov --- .../community/policies/backwards-compatibility.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 68e1c733a..d1e4db192 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -48,8 +48,9 @@ earlier versions of conda-store. To maintain backward compatibility we follow these principles: - New columns or tables should be added instead of removing or altering existing -ones. - Columns and tables should not be renamed. Aliases should be used for -poorly named existing columns or tables. + ones. +- Columns and tables should not be renamed. Aliases should be used for + poorly named existing columns or tables. ### REST API endpoints From d93c13ff250918e12e8f17a9fb37601e2fa3d9a5 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:56:59 -0500 Subject: [PATCH 21/25] Update docusaurus-docs/community/policies/backwards-compatibility.md Co-authored-by: Nikita Karetnikov --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index d1e4db192..150798bdd 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -267,7 +267,7 @@ The function signature also includes whether the function is an async function. Changing this is a breaking change. For example, if there is a function `list_envs`, which is synchronous, and -it should be asynchronous, a new function called ` list_envs_async` should be +it should be asynchronous, a new function called `list_envs_async` should be added and `list_envs` should be kept as a synchronous call. Optional parameters may be added as long as they have a specified default value From 92e226136907ca07e5599a07026037310e9dd729 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:58:58 -0500 Subject: [PATCH 22/25] Apply suggestions from code review Co-authored-by: Nikita Karetnikov --- .../policies/backwards-compatibility.md | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 150798bdd..27a1145e1 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -42,9 +42,9 @@ to adopt when needed, while all existing code should continue to work. ### Database changes Databases are one of the most critical areas to ensure there are no breaking -changes. Databases hold the state for the application. Introducing breaking +changes. Databases hold the state for the application. Introducing breaking changes to the database can be destructive to data and prevent rolling back to -earlier versions of conda-store. To maintain backward compatibility we follow +earlier versions of conda-store. To maintain backwards compatibility we follow these principles: - New columns or tables should be added instead of removing or altering existing @@ -60,15 +60,16 @@ start at `v1`. Non-breaking changes do not require a new version of an endpoint. For REST API endpoints, examples on non-breaking changes are: -- adding a parameter to the return value of an endpoint - making a previously -mandatory input optional. +- adding a parameter to the return value of an endpoint +- making a previously mandatory input optional. These changes can be done without a new endpoint version. However, changes such as: -- removing a parameter from the return value - altering the meaning of a value - -making a formerly optional parameter mandatory +- removing a parameter from the return value +- altering the meaning of a value +- making a formerly optional parameter mandatory are breaking changes and **require** a new endpoint version. @@ -86,9 +87,9 @@ namespace. For example, if a new version of the `example.com/api/v1/user` endpoint is being tested, but not yet considered stable, it can be made available at the -`example.com/api/experimental/user` route. This allows conda-store contributors +`example.com/api/experimental/user` route. This allows conda-store contributors to test new changes and get community feedback without committing to supporting -a new version of an API endpoint. Using the `experimental` namespace is not +a new version of an API endpoint. Using the `experimental` namespace is not mandatory. However, deploying a versioned endpoint expresses a commitment to support that code going forward, so it is highly recommended that developers use the `experimental` namespace to test new endpoints and features before marking @@ -106,24 +107,31 @@ a new version for breaking changes. ##### Versioned stable route -``` https://example.com/api/v1/user https://example.com/api/v2/user ``` +``` +https://example.com/api/v1/user +https://example.com/api/v2/user +``` -Explanation: This route has breaking changes between `v1` and `v2`. Code +Explanation: This route has breaking changes between `v1` and `v2`. Code written for the `v1` endpoint will continue to function, but all new features -will only be available in the `v2` version of the endpoint. This empowers users +will only be available in the `v2` version of the endpoint. This empowers users to upgrade when they wish to rather than forcing them to do so. ##### Route that has never had breaking changes -``` https://example.com/api/v1/user ``` +``` +https://example.com/api/v1/user +``` Explanation: This route has never had breaking changes introduced. Any code written against this endpoint will function regardless of when it was written. ##### New `experimental` route -``` https://example.com/api/experimental/user/ ``` +``` +https://example.com/api/experimental/user +``` Explanation: This is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and @@ -164,9 +172,9 @@ be waived in the case of a serious security vulnerability. It should always be clearly communicated in release notes and documentation when an API endpoint is deprecated or removed. This should include: - version number of the release where this was deprecated -- provide suggestions for alternatives (if possible). +- provide suggestions for alternatives (if possible) - provide justification for the removal (such as a link to the issue - or CVE that necessitated the removal) + or CVE that necessitated the removal). ### Python API @@ -175,10 +183,15 @@ public APIs and subject to the same considerations as REST API endpoints. Any object with a leading underscore is not considered to be public. This convention is used in the Python community to designate an object as private. -Private examples: - `_private_func_or_method` - `_PrivateClass` - -`_PRIVATE_VAR`. +Private examples: +- `_private_func_or_method` +- `_PrivateClass` +- `_PRIVATE_VAR`. -Public examples: - `public_func_or_method` - `PublicClass` - `PUBLIC_VAR`. +Public examples: +- `public_func_or_method` +- `PublicClass` +- `PUBLIC_VAR`. The highest-level entity determines the visibility level. @@ -228,11 +241,11 @@ should be added for at least one release before the endpoint is removed. This requirement may be waived in the case of a serious security vulnerability. The deprecation or removal should always be clearly communicated in release -notes and documentation This should include: +notes and documentation. This should include: - version number of the release where this was deprecated -- provide suggestions for alternatives (if possible). +- provide suggestions for alternatives (if possible) - provide a reason for the deprecation or removal (such - as a link to a CVE or issue that necessitated the removal + as a link to a CVE or issue that necessitated the removal). #### Types of objects @@ -244,10 +257,10 @@ has a breaking change. ##### Classes In a public class, a breaking change is one that changes or removes attributes -or methods or alters their meanings. Rather than changing methods or -attributes, new methods or attributes should be added if needed. For example, -if you wanted to change a user id from an `int`, to a `uuid`, a new attribute -`User.uuid` should be added, and all new code should use `User.uuid`. Existing +or methods or alters their meanings. Rather than changing methods or +attributes, new methods or attributes should be added if needed. For example, +if you wanted to change a user id from an `int` to a `uuid`, a new attribute +`User.uuid` should be added, and all new code should use `User.uuid`. Existing methods can use the new attribute or methods as well as long as that doesn't introduce breaking changes for the method. From 53663e497e4c368ad23f4be4008a89441227cc22 Mon Sep 17 00:00:00 2001 From: Chuck McAndrew <6248903+dcmcand@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:03:10 -0500 Subject: [PATCH 23/25] lint --- .../community/policies/backwards-compatibility.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 27a1145e1..47f1417a0 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -48,7 +48,7 @@ earlier versions of conda-store. To maintain backwards compatibility we follow these principles: - New columns or tables should be added instead of removing or altering existing - ones. + ones. - Columns and tables should not be renamed. Aliases should be used for poorly named existing columns or tables. @@ -74,7 +74,7 @@ However, changes such as: are breaking changes and **require** a new endpoint version. When a new version of an endpoint is created, then all new features will be -added to the new version. +added to the new version. Older versions of API endpoints are still considered supported and will receive bug fixes and security updates to their features but new features will not be @@ -165,7 +165,7 @@ version of the endpoint is available currently (if any). } ``` -If an API endpoint must be deprecated, a deprecation warning should be added +If an API endpoint must be deprecated, a deprecation warning should be added for at least one release before the endpoint is removed. This requirement may be waived in the case of a serious security vulnerability. @@ -224,14 +224,14 @@ committing to supporting. Under exceptional circumstances such as a serious security vulnerability which can't be fixed without breaking changes, it may be necessary to deprecate, -remove, or introduce breaking changes to objects in the public Python API. +remove, or introduce breaking changes to objects in the public Python API. This should be avoided if possible. If the desire is to prevent a developer from relying on a part of the Python API, adding a warning to the documentation along with a recommended alternative and a comment in the code should be used rather than a deprecation or removal. -```python +```python """ This function is deprecated [reason/details], use [replacement] instead """ From e660002769eb76e8ca61b4e06e61804479db4c62 Mon Sep 17 00:00:00 2001 From: Tania Allard Date: Tue, 23 Jan 2024 10:35:55 +0000 Subject: [PATCH 24/25] Update docusaurus-docs/community/policies/backwards-compatibility.md --- docusaurus-docs/community/policies/backwards-compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 47f1417a0..84d7cc1b0 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -124,7 +124,7 @@ to upgrade when they wish to rather than forcing them to do so. https://example.com/api/v1/user ``` -Explanation: This route has never had breaking changes introduced. Any code +**Explanation**: This route has never had breaking changes introduced. Any code written against this endpoint will function regardless of when it was written. ##### New `experimental` route From a12415ce8151f47c5667382472c80214cf68a310 Mon Sep 17 00:00:00 2001 From: Tania Allard Date: Tue, 23 Jan 2024 10:36:35 +0000 Subject: [PATCH 25/25] Apply suggestions from code review --- docusaurus-docs/community/policies/backwards-compatibility.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docusaurus-docs/community/policies/backwards-compatibility.md b/docusaurus-docs/community/policies/backwards-compatibility.md index 84d7cc1b0..068b12f3f 100644 --- a/docusaurus-docs/community/policies/backwards-compatibility.md +++ b/docusaurus-docs/community/policies/backwards-compatibility.md @@ -133,7 +133,7 @@ written against this endpoint will function regardless of when it was written. https://example.com/api/experimental/user ``` -Explanation: This is an experimental route. It can be changed or removed at any +**Explanation**: This is an experimental route. It can be changed or removed at any moment without prior notice. This route should be used to test new features and get community feedback. @@ -212,8 +212,10 @@ or # private. ``` +:::important Tests are never considered to be part of the public API. Any code within the `tests/` directory is always considered to be private. +::: Developers are encouraged to make code private by default and only expose objects as public if there is an explicit need to do so. Keeping code private by