-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added github action to update feature catalog MD file #1714
base: main
Are you sure you want to change the base?
Changes from all commits
0854c60
2d2a84d
967cb9e
9f2226f
b76f2a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
name: Update feature catalog page | ||
on: | ||
schedule: | ||
- cron: 0 10 * * MON | ||
workflow_dispatch: | ||
jobs: | ||
generate-feature-catalog-file: | ||
name: Generate feature catalog page | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout docs repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Latest run-id from community repository | ||
run: | | ||
latest_workflow_id=$(curl -s https://api.github.com/repos/localstack/localstack/actions/workflows \ | ||
| jq '.workflows[] | select(.name=="Artifact with features files").id') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment: similar to above: https://github.com/localstack/localstack-ext/pull/4302#discussion_r2028188292 |
||
latest_run_id=$(curl -s \ | ||
https://api.github.com/repos/localstack/localstack/actions/workflows/$latest_workflow_id/runs | jq '.workflow_runs[0].id') | ||
echo "Latest run-id: ${latest_run_id}" | ||
echo "FEATURES_ARTIFACTS_COMMUNITY_RUN_ID=${latest_run_id}" >> $GITHUB_ENV | ||
|
||
- name: Download features files from Collect feature files (GitHub) | ||
uses: actions/download-artifact@v4 | ||
with: | ||
path: features-files-community | ||
name: features-files | ||
github-token: ${{ secrets.GH_PAT_FEATURE_CATALOG_PAGE }} # PAT with access to artifacts from GH Actions | ||
repository: localstack/localstack | ||
run-id: ${{ env.FEATURES_ARTIFACTS_COMMUNITY_RUN_ID }} | ||
|
||
- name: Latest run-id from ext repository | ||
run: | | ||
latest_workflow_id=$(curl -s https://api.github.com/repos/localstack/localstack-ext/actions/workflows \ | ||
| jq '.workflows[] | select(.name=="Artifact with features files").id') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment: similar to above: https://github.com/localstack/localstack-ext/pull/4302#discussion_r2028188292 |
||
latest_run_id=$(curl -s \ | ||
https://api.github.com/repos/localstack/localstack-ext/actions/workflows/$latest_workflow_id/runs | jq '.workflow_runs[0].id') | ||
echo "Latest run-id: ${latest_run_id}" | ||
echo "FEATURES_ARTIFACTS_EXT_RUN_ID=${latest_run_id}" >> $GITHUB_ENV | ||
|
||
- name: Download features files from Collect feature files from PRO (GitHub) | ||
uses: actions/download-artifact@v4 | ||
with: | ||
path: features-files-ext | ||
name: features-files-ext | ||
repository: localstack/localstack | ||
github-token: ${{ secrets.GH_PAT_FEATURE_CATALOG_PAGE_PRO }} # PAT with access to artifacts from GH Actions | ||
run-id: ${{ env.FEATURES_ARTIFACTS_EXT_RUN_ID }} | ||
|
||
- name: Generate feature catalog page | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ques: do we have a sample MD file generated from this? If yes, could you please link it in the comments/description of the PR? |
||
run: python3 scripts/generate_feature_catalog_page.py | ||
env: | ||
PATH_FEATURE_FILES_COMMUNITY: 'features-files-community' | ||
PATH_FEATURE_FILES_EXT: 'features-files-ext' | ||
PATH_FEATURE_CATALOG_MD: 'content/en/user-guide/aws/feature-coverage.md' | ||
|
||
- name: Create PR | ||
uses: peter-evans/create-pull-request@v7 | ||
with: | ||
title: "Update Feature catalog page" | ||
body: "This PR updates Feature catalog page based on feature catalog YAML files" | ||
branch: "update-feature-catalog" | ||
add-paths: "content/en/user-guide/aws/feature-coverage.md" | ||
author: "LocalStack Bot <[email protected]>" | ||
committer: "LocalStack Bot <[email protected]>" | ||
commit-message: "Upgrade feature catalog" | ||
labels: "documentation" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import os | ||
import sys | ||
from pathlib import Path | ||
|
||
import yaml | ||
|
||
DEFAULT_STATUS = 'not supported' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment: We should consider having consistency in the status being displayed, as in features_schema.json.
That means using either |
||
DEFAULT_EMULATION_LEVEL = 'CRUD' | ||
FEATURES_FILE_NAME='features.yml' | ||
|
||
MD_FILE_HEADER = """--- | ||
title: "AWS Service Feature Coverage" | ||
linkTitle: "⭐ Feature Coverage" | ||
weight: 1 | ||
description: > | ||
Overview of the implemented AWS APIs and their level of parity with the AWS cloud | ||
aliases: | ||
- /localstack/coverage/ | ||
- /aws/feature-coverage/ | ||
hide_readingtime: true | ||
--- | ||
|
||
|
||
## Emulation Levels | ||
|
||
* CRUD: The service accepts requests and returns proper (potentially static) responses. | ||
No additional business logic besides storing entities. | ||
* Emulated: The service imitates the functionality, including synchronous and asynchronous business logic operating on service entities. | ||
|
||
| Service / Feature | Implementation status | Emulation Level | Limitations | | ||
|-------------------|----------------|-----------------|--------------------------|""" | ||
|
||
class FeatureCatalogMarkdownGenerator: | ||
md_content = [MD_FILE_HEADER] | ||
|
||
def __init__(self, file_path: str): | ||
self.file_path = file_path | ||
pass | ||
|
||
def add_service_section(self, feature_file_content: str): | ||
service_name = feature_file_content.get('name') | ||
emulation_level = feature_file_content.get('emulation_level', DEFAULT_EMULATION_LEVEL) | ||
self.md_content.append(f"| **{service_name}** | [Details 🔍] | {emulation_level} | |") | ||
|
||
def add_features_rows(self, feature_file_content: str): | ||
for feature in feature_file_content.get('features', []): | ||
feature_name = feature.get('name', '') | ||
documentation_page = feature.get('documentation_page') | ||
if documentation_page: | ||
feature_name = f'[{feature_name}]({documentation_page})' | ||
status = feature.get('status', DEFAULT_STATUS) | ||
|
||
limitations = feature.get('limitations', []) | ||
limitations_md = '\n '.join(limitations) if limitations else '' | ||
|
||
self.md_content.append(f"| {feature_name} | {status} | | {limitations_md} |") | ||
|
||
def generate_file(self): | ||
try: | ||
with open(self.file_path, "w") as feature_coverage_md_file: | ||
feature_coverage_md_file.writelines(s + '\n' for s in self.md_content) | ||
except Exception as e: | ||
print(f"Error writing to file: {e}") | ||
sys.exit(1) | ||
|
||
def load_yaml_file(file_path: str): | ||
try: | ||
with open(file_path, 'r') as file: | ||
return yaml.safe_load(file) | ||
except yaml.YAMLError as e: | ||
print(f"Error parsing YAML file: {e}") | ||
sys.exit(1) | ||
except FileNotFoundError: | ||
print(f"YAML file not found: {file_path}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Consider printing the errors with an annotation. |
||
sys.exit(1) | ||
|
||
def get_service_path_to_abs_community_ext_paths(community_files_path: str, ext_files_path: str) -> dict[str, (str, str)]: | ||
relative_to_abs_paths = {} | ||
for community_abs_path in Path(community_files_path).rglob(FEATURES_FILE_NAME): | ||
rel_path = str(community_abs_path.relative_to(community_files_path)) | ||
relative_to_abs_paths[rel_path] = (community_abs_path, None) | ||
|
||
for abs_path_ext in Path(ext_files_path).rglob(FEATURES_FILE_NAME): | ||
rel_path = str(abs_path_ext.relative_to(ext_files_path)) | ||
if rel_path in relative_to_abs_paths: | ||
community_abs_path, _ = relative_to_abs_paths[rel_path] | ||
relative_to_abs_paths[rel_path] = (community_abs_path, abs_path_ext) | ||
else: | ||
relative_to_abs_paths[rel_path] = (None, abs_path_ext) | ||
return relative_to_abs_paths | ||
|
||
def main(): | ||
community_feature_files_path = os.getenv('PATH_FEATURE_FILES_COMMUNITY') | ||
ext_feature_files_path = os.getenv('PATH_FEATURE_FILES_EXT') | ||
feature_catalog_md_file_path = os.getenv('PATH_FEATURE_CATALOG_MD') | ||
|
||
service_path_to_abs_paths = get_service_path_to_abs_community_ext_paths(community_feature_files_path, ext_feature_files_path) | ||
md_generator = FeatureCatalogMarkdownGenerator(feature_catalog_md_file_path) | ||
|
||
for service_name in sorted(service_path_to_abs_paths): | ||
abs_path_community, abs_path_ext = service_path_to_abs_paths.get(service_name) | ||
service_definition_created = False | ||
if abs_path_community: | ||
feature_file_community = load_yaml_file(abs_path_community) | ||
md_generator.add_service_section(feature_file_community) | ||
service_definition_created = True | ||
md_generator.add_features_rows(feature_file_community) | ||
if abs_path_ext: | ||
feature_file_ext = load_yaml_file(abs_path_ext) | ||
if not service_definition_created: | ||
md_generator.add_service_section(feature_file_community) | ||
md_generator.add_features_rows(feature_file_ext) | ||
md_generator.generate_file() | ||
|
||
if __name__ == "__main__": | ||
main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment: this would change as per relevant changes in https://github.com/localstack/localstack-ext/pull/4302#discussion_r2028189748.