From d082071be5d5029a52cd211575319aabf20457f4 Mon Sep 17 00:00:00 2001
From: Marc Wrobel
Date: Sat, 17 Dec 2022 13:23:05 +0100
Subject: [PATCH] Add API v1 (#2595, #2425, #2331, #2066, #2062, #1762, #759,
#394, #2530)
This is a major rework of the API with a lot of breaking changes. See CHANGELOG_API.md for more information.
Note that we thought of disabling API generation in development (using JEKYLL_ENV like the Jekyll Feed plugin - see https://github.com/jekyll/jekyll-feed/blob/master/lib/jekyll-feed/generator.rb#L145), but it was finally reverted. It does not work well with Netlify preview, and generate production URL (i.e. https://endoflife.date URLs) in development which makes it difficult to use.
---
CHANGELOG_API.md | 96 ++++++
HACKING.md | 8 +-
README.md | 7 +-
_config.yml | 2 +-
_headers | 4 +
_layouts/json.json | 1 +
_layouts/product.html | 4 +-
_layouts/swagger-ui.html | 31 ++
_plugins/generate-api-v1.rb | 342 +++++++++++++++----
_plugins/product-data-enricher.rb | 21 +-
_redirects | 16 +-
api_v1/openapi.yml | 535 ++++++++++++++++++++++++++++++
api_v1/swagger-ui.md | 6 +
assets/404.json | 3 -
humans.txt | 2 +-
index.md | 4 +-
16 files changed, 992 insertions(+), 90 deletions(-)
create mode 100644 CHANGELOG_API.md
create mode 100644 _layouts/json.json
create mode 100644 _layouts/swagger-ui.html
create mode 100644 api_v1/openapi.yml
create mode 100644 api_v1/swagger-ui.md
delete mode 100644 assets/404.json
diff --git a/CHANGELOG_API.md b/CHANGELOG_API.md
new file mode 100644
index 00000000000..3bc9e66b4bd
--- /dev/null
+++ b/CHANGELOG_API.md
@@ -0,0 +1,96 @@
+## API v1.0.0
+
+### Summary
+
+API v1 is a major rework of the API v0 with a lot of breaking changes. Compared to the API v0, API
+v1:
+
+- feels more _Restful_ (#2431),
+- expose almost all product's data (#394, #759, #2062, #2595),
+- expose new metadata such as `schema version` (#2331), `total` (for lists), `generated_at` or
+ `last modified` date,
+- is easier to consume thanks to:
+ - new computed fields such as `is_maintained`,
+ - the replacement of fields that were using union types with two separate single-type fields:
+ - `lts` -> `isLts` and `ltsFrom`,
+ - `support` -> `isActiveSupportOver` and `activeSupportUntil`,
+ - `eol` -> `isEol` and `eolFrom`,
+ - `discontinued` -> `isDiscontinued` and `discontinuedFrom`,
+ - `extendedSupport` -> `isExtendedSupportOver` and `extendedSupportUntil`.
+- provide new endpoints (#2078, #2160, #2530)
+- is versioned using the `api/v1` prefix (#2066), making it easier to implement
+ non-backward-compatible changes in the future,
+- is documented using [swagger-ui](https://swagger.io/tools/swagger-ui/) instead of [Stoplight
+ Elements WebComponent](https://github.com/stoplightio/elements/blob/main/docs/getting-started/elements/html.md)
+ (#905),
+- but reverts #2425 due to incompatibilities in redirect rules.
+
+The API v1 is now generated using a Jekyll Generator (see https://jekyllrb.com/docs/plugins/generators/)
+instead of a custom script.
+
+Note that the API v0 is still generated to give time to users to migrate to API v1. It will be
+decommissioned at least one year after the API v1 release date.
+
+API v1 documentation can be seen on .
+The old API v0 documentation can still be seen on .
+
+### Changes in the "All products" endpoint
+
+- Path has been changed from `api/all.json` to `api/v1/products/`
+- Response has been changed from a simple array of strings to a JSON document.
+ This made it possible to include additional metadata, such as the schema version and the number of
+ products.
+- Response items has been changed from a simple string (the product name) to a JSON document (#2062).
+ This made it possible to include additional information about the product, such as its category
+ and tags.
+- See for a detailed description of the
+ response.
+
+### Changes in the "Product" endpoint
+
+- Path has been changed from `api/.json` to `api/v1/products//`.
+- Response has been changed from a simple array of versions to a JSON document.
+ This made it possible to include :
+ - additional metadata, such as the schema version and the last modified date,
+ - product-level information, such as the product label or category (#2062).
+- Cycles data now always contain all the release cycles properties, even if they are null
+ (example: `discontinued`, `latest`, `latestReleaseDate`, `support`...).
+- See for a detailed
+ description of the response.
+
+### Changes in the "Cycle" endpoint
+
+- Path has been changed from `api//.json` to `api/v1/products//cycles//`.
+- Response has been changed to make it possible to include additional metadata, such as the schema
+ version and the last modified date,
+- Cycles data now always contain all the release cycles properties, even if they are null
+ (example: `discontinued`, `latest`, `latestReleaseDate`, `support`...).
+- A special `/api/v1/products//cycles/latest/` cycle, containing the same data as the
+ latest cycle, has been added (#2078).
+- See for a
+ detailed description of the response.
+
+### Changes in 404 error responses
+
+404 error JSON responses are not returned anymore. #2425 has been reverted because it conflicted
+with the rule that rewrites the paths to add `/index.json` to all requests, which is also a global
+rule and [takes precedence](https://docs.netlify.com/routing/redirects/#rule-processing-order).
+
+### New endpoints
+
+- `/api/v1/categories/`: Get a list of all categories.
+- `/api/v1/categories/`: Get a list of all products within the given category.
+- `/api/v1/tags/`: Get a list of all tags.
+- `/api/v1/tags/`: Get a list of all products having the given tag.
+- `/api/v1/products/full/`: Get a list of all products with all their details (including cycles).
+ This endpoint provides a dump of nearly all the endoflife.date data.
+
+
+
+## API v0
+
+On 2023-03-02 the v0 endpoints were:
+
+- "All products" (`/api/all.json`) : Get a list of all product names.
+- "Product" (`/api/{product}.json`) : Get all release cycles details for a given product.
+- "Cycle" (`/api/{product}/{cycle}.json`) : Get details for a single release cycle of a given product.
diff --git a/HACKING.md b/HACKING.md
index fe54fdc52c5..deae201869d 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -105,7 +105,13 @@ The API is just JSON files generated in the `api` directory by `_plugins/create-
### API Documentation
-The API Documentation is available at and is generated from an OpenAPI Specification file located at `_data/openapi.yml`. The documentation is rendered [Stoplight Elements](https://meta.stoplight.io/docs/elements/ZG9jOjMyNjU4OTY0-introduction-to-elements).
+The current API v1 documentation is available at and is
+generated from an OpenAPI Specification file located at `api_v1/openapi.yml`. The documentation is
+rendered by [Swagger UI](https://swagger.io/tools/swagger-ui/).
+
+The old API v0 documentation is available at and is
+generated from an OpenAPI Specification file located at `assets/openapi.yml`. The documentation is
+rendered by [Stoplight Elements](https://meta.stoplight.io/docs/elements/ZG9jOjMyNjU4OTY0-introduction-to-elements).
## Contributing Workflow
diff --git a/README.md b/README.md
index b0cc43798b9..e0036321b99 100644
--- a/README.md
+++ b/README.md
@@ -26,9 +26,8 @@ While participating in the project, you must abide by its [Code of Conduct](CODE
## API
-An API is available for integration with CI platforms.
-API documentation is available at https://endoflife.date/docs/api.
-The API is currently in Alpha, and breaking changes can happen.
+An API is available for integration with CI platforms. API documentation is available at https://endoflife.date/docs/api/v1/.
+The API is currently in Beta, and breaking changes can happen.
## License
@@ -46,6 +45,8 @@ endoflife.date is relying on various amazing software and components :
- [Just the Docs](https://github.com/just-the-docs/just-the-docs), a documentation theme for Jekyll.
- [Stoplight Elements](https://stoplight.io/open-source/elements), a collection of UI components for
displaying beautiful developer documentation from any OpenAPI document.
+- [Swagger UI](https://swagger.io/tools/swagger-ui/), a documentation generator for OpenAPI
+ Specification.
- [Simple Icons](https://simpleicons.org/), free SVG icons for popular brands.
- Our icon is derived from [Hourglass icon (orange)](https://commons.wikimedia.org/wiki/File:Hourglass_icon_%28orange%29.svg)
by David Abián and Serhio Magpie on the English Wikipedia. Remixed under the CC-BY-SA-4.0 license.
diff --git a/_config.yml b/_config.yml
index 3fee2a5da02..1e0b428ad7a 100644
--- a/_config.yml
+++ b/_config.yml
@@ -40,7 +40,7 @@ aux_links:
source:
- https://github.com/endoflife-date/endoflife.date
api:
- - /docs/api
+ - /docs/api/v1/
jekyll_timeago:
# Use 2 terms in relative timestamps:
# [YES] x years, y months
diff --git a/_headers b/_headers
index 24cb2b006d9..c1460af8cf6 100644
--- a/_headers
+++ b/_headers
@@ -56,6 +56,10 @@ layout: null
Content-Security-Policy: default-src 'none'; manifest-src 'self'; connect-src 'self'; script-src 'self'; style-src 'self'; img-src {{ defaultCspImgSrc }} {{ releaseImageSrc }}
Link: /api{{page.permalink}}.json; rel=alternate;type=application/json
Link: /calendar{{page.permalink}}.ics; rel=alternate;type=text/calendar
+ {% elsif page.permalink contains '/docs/api/v' %}
+ {%- comment %}Used contains to match all API version (startswith does not exist){% endcomment %}
+ # unsafe-inline and data: should not be an issue for a static site
+ Content-Security-Policy: default-src 'none'; manifest-src 'self'; connect-src 'self'; script-src 'self' 'unsafe-inline' https://unpkg.com/; style-src 'self' https://unpkg.com/; img-src 'self' data:
{% elsif page.permalink == '/docs/api' %}
Content-Security-Policy: default-src 'none'; manifest-src 'self'; connect-src 'self'; script-src 'self' https://unpkg.com/@stoplight/elements/web-components.min.js; style-src 'self' https://unpkg.com/@stoplight/elements/
{% else %}
diff --git a/_layouts/json.json b/_layouts/json.json
new file mode 100644
index 00000000000..8c98299c885
--- /dev/null
+++ b/_layouts/json.json
@@ -0,0 +1 @@
+{{ page.data | jsonify }}
diff --git a/_layouts/product.html b/_layouts/product.html
index e30ec9000cf..6aff5c0e341 100644
--- a/_layouts/product.html
+++ b/_layouts/product.html
@@ -182,7 +182,7 @@