From 0b89138daf8afacd27e4c3b97b0db0b7dba8c45c Mon Sep 17 00:00:00 2001 From: ggman12 Date: Thu, 12 Feb 2026 15:40:01 -0500 Subject: [PATCH] modify existing json schema instead of creating a new file every time --- .github/workflows/update-community-prs.yaml | 56 +++++++------------ src/contributions/approve_submission.py | 23 ++++---- src/contributions/regenerate_pr_schema.py | 30 +++++----- src/contributions/update_schema.py | 62 ++++++++++----------- 4 files changed, 72 insertions(+), 99 deletions(-) diff --git a/.github/workflows/update-community-prs.yaml b/.github/workflows/update-community-prs.yaml index e7be6ea..711df76 100644 --- a/.github/workflows/update-community-prs.yaml +++ b/.github/workflows/update-community-prs.yaml @@ -5,7 +5,7 @@ on: branches: [main] paths: - 'community/**' - - 'schemas/community_submission.*.schema.json' + - 'schemas/community_submission.v1.schema.json' permissions: contents: write @@ -29,18 +29,9 @@ jobs: - name: Install dependencies run: pip install jsonschema - - name: Get current schema version - id: schema - run: | - # Find the latest schema version on main - latest=$(ls schemas/community_submission.v*.schema.json 2>/dev/null | sed 's/.*\.v\([0-9]*\)\.schema\.json/\1/' | sort -n | tail -1) - echo "latest_version=${latest:-1}" >> "$GITHUB_OUTPUT" - echo "Latest schema version: ${latest:-1}" - - name: Find and update open community PRs env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - LATEST_SCHEMA_VERSION: ${{ steps.schema.outputs.latest_version }} run: | # Get list of open community PRs prs=$(gh pr list --label community --state open --json number,headRefName --jq '.[] | "\(.number) \(.headRefName)"') @@ -57,35 +48,28 @@ jobs: git fetch origin "$branch_name" git checkout "$branch_name" - # Check if this PR has a schema file that needs updating - pr_schema=$(ls schemas/community_submission.v*.schema.json 2>/dev/null | sed 's/.*\.v\([0-9]*\)\.schema\.json/\1/' | sort -n | tail -1) + # Merge main into PR branch + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" - if [ "$pr_schema" -le "$LATEST_SCHEMA_VERSION" ] 2>/dev/null; then - echo " PR schema version ($pr_schema) <= main version ($LATEST_SCHEMA_VERSION)" + if git merge origin/main -m "Merge main to update schema"; then + # Regenerate schema for this PR's submission (adds any new tags) + python -m src.contributions.regenerate_pr_schema || true - # Merge main into PR branch - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - if git merge origin/main -m "Merge main to update schema baseline"; then - # Regenerate schema for this PR's submission - python -m src.contributions.regenerate_pr_schema || true - - # If there are changes, commit and push - if [ -n "$(git status --porcelain schemas/)" ]; then - new_version=$((LATEST_SCHEMA_VERSION + 1)) - git add schemas/ - git commit -m "Update schema to v${new_version} (rebased on main)" - git push origin "$branch_name" - echo " Updated PR #$pr_number with new schema" - else - git push origin "$branch_name" - echo " Merged main into PR #$pr_number" - fi + # If there are changes, commit and push + if [ -n "$(git status --porcelain schemas/)" ]; then + git add schemas/ + git commit -m "Update schema with new tags" + git push origin "$branch_name" + echo " Updated PR #$pr_number with schema changes" else - echo " Merge conflict in PR #$pr_number, adding comment" - gh pr comment "$pr_number" --body $'⚠️ **Merge Conflict**\n\nAnother community submission was merged and this PR has conflicts.\n\nA maintainer may need to:\n1. Close this PR\n2. Remove the `approved` label from the original issue\n3. Re-add the `approved` label to regenerate the PR' - git merge --abort + git push origin "$branch_name" + echo " Merged main into PR #$pr_number" + fi + else + echo " Merge conflict in PR #$pr_number, adding comment" + gh pr comment "$pr_number" --body $'⚠️ **Merge Conflict**\n\nAnother community submission was merged and this PR has conflicts.\n\nA maintainer may need to:\n1. Close this PR\n2. Remove the `approved` label from the original issue\n3. Re-add the `approved` label to regenerate the PR' + git merge --abort fi fi diff --git a/src/contributions/approve_submission.py b/src/contributions/approve_submission.py index 9436afe..6f0251d 100644 --- a/src/contributions/approve_submission.py +++ b/src/contributions/approve_submission.py @@ -21,13 +21,13 @@ import urllib.request import urllib.error from datetime import datetime, timezone -from .schema import extract_json_from_issue_body, extract_contributor_name_from_issue_body, parse_and_validate, get_latest_schema_version, load_schema +from .schema import extract_json_from_issue_body, extract_contributor_name_from_issue_body, parse_and_validate, load_schema, SCHEMAS_DIR from .contributor import ( generate_contributor_uuid, generate_submission_filename, compute_content_hash, ) -from .update_schema import generate_new_schema, check_for_new_tags, get_existing_tag_definitions +from .update_schema import generate_updated_schema, check_for_new_tags, get_existing_tag_definitions from .read_community_data import build_tag_type_registry @@ -190,17 +190,15 @@ def process_submission( commit_message = f"Add community submission from @{author_username} (closes #{issue_number})" create_or_update_file(file_path, content_json, commit_message, branch_name) - # Update schema with any new tags (creates new version if needed) + # Update schema with any new tags (modifies v1 in place) schema_updated = False - new_version = None new_tags = [] try: # Build tag registry from new submissions tag_registry = build_tag_type_registry(submissions) # Get current schema and merge existing tags - current_version = get_latest_schema_version() - current_schema = load_schema(current_version) + current_schema = load_schema() existing_tags = get_existing_tag_definitions(current_schema) # Merge existing tags into registry @@ -213,15 +211,14 @@ def process_submission( new_tags = check_for_new_tags(tag_registry, current_schema) if new_tags: - # Generate new schema version - new_version = current_version + 1 - new_schema = generate_new_schema(current_schema, tag_registry, new_version) - schema_json = json.dumps(new_schema, indent=2) + "\n" + # Generate updated schema + updated_schema = generate_updated_schema(current_schema, tag_registry) + schema_json = json.dumps(updated_schema, indent=2) + "\n" create_or_update_file( - f"schemas/community_submission.v{new_version}.schema.json", + "schemas/community_submission.v1.schema.json", schema_json, - f"Create schema v{new_version} with new tags: {', '.join(new_tags)}", + f"Update schema with new tags: {', '.join(new_tags)}", branch_name ) schema_updated = True @@ -231,7 +228,7 @@ def process_submission( # Create PR schema_note = "" if schema_updated: - schema_note = f"\n**Schema Updated:** Created v{new_version} with new tags: `{', '.join(new_tags)}`\n" + schema_note = f"\n**Schema Updated:** Added new tags: `{', '.join(new_tags)}`\n" pr_body = f"""## Community Submission diff --git a/src/contributions/regenerate_pr_schema.py b/src/contributions/regenerate_pr_schema.py index 9d3936d..5209e13 100644 --- a/src/contributions/regenerate_pr_schema.py +++ b/src/contributions/regenerate_pr_schema.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 """ Regenerate schema for a PR branch after main has been merged in. -This script looks at the submission files in this branch and generates -an updated schema version if new tags were introduced. +This script looks at the submission files in this branch and updates +the schema if new tags were introduced. Usage: python -m src.contributions.regenerate_pr_schema """ @@ -18,15 +18,14 @@ from src.contributions.read_community_data import read_all_submissions, build_ta from src.contributions.update_schema import ( get_existing_tag_definitions, check_for_new_tags, - generate_new_schema, + generate_updated_schema, ) -from src.contributions.schema import get_latest_schema_version, load_schema, SCHEMAS_DIR +from src.contributions.schema import load_schema, SCHEMAS_DIR def main(): """Main entry point.""" - # Get current schema version and load it - current_version = get_latest_schema_version() + # Load current schema current_schema = load_schema() # Get existing tag definitions from schema @@ -46,20 +45,19 @@ def main(): new_tags = check_for_new_tags(tag_registry, current_schema) if new_tags: - # Generate new schema version - new_version = current_version + 1 print(f"Found new tags: {new_tags}") - print(f"Generating schema v{new_version}") + print("Updating schema...") - # Generate new schema with updated tag definitions - new_schema = generate_new_schema(current_schema, tag_registry, new_version) + # Generate updated schema + updated_schema = generate_updated_schema(current_schema, tag_registry) - # Write new schema version - new_schema_path = SCHEMAS_DIR / f"community_submission.v{new_version}.schema.json" - with open(new_schema_path, 'w') as f: - json.dump(new_schema, f, indent=2) + # Write updated schema (in place) + schema_path = SCHEMAS_DIR / "community_submission.v1.schema.json" + with open(schema_path, 'w') as f: + json.dump(updated_schema, f, indent=2) + f.write("\n") - print(f"Created {new_schema_path}") + print(f"Updated {schema_path}") else: print("No new tags found, schema is up to date") diff --git a/src/contributions/update_schema.py b/src/contributions/update_schema.py index c1610f6..6a76cad 100644 --- a/src/contributions/update_schema.py +++ b/src/contributions/update_schema.py @@ -40,23 +40,19 @@ def type_name_to_json_schema(type_name: str) -> dict: return type_map.get(type_name, {"$ref": "#/$defs/tagValue"}) -def generate_new_schema(base_schema: dict, tag_registry: dict[str, str], new_version: int) -> dict: +def generate_updated_schema(base_schema: dict, tag_registry: dict[str, str]) -> dict: """ - Generate a new schema version with explicit tag definitions. + Generate an updated schema with explicit tag definitions. Args: - base_schema: The current schema to base the new one on + base_schema: The current schema to update tag_registry: Dict mapping tag name to type name - new_version: The new version number Returns: - Complete new schema dict + Updated schema dict """ schema = json.loads(json.dumps(base_schema)) # Deep copy - # Update title with new version - schema["title"] = f"PlaneQuery Aircraft Community Submission (v{new_version})" - # Build tag properties with explicit types tag_properties = {} for tag_name, type_name in sorted(tag_registry.items()): @@ -89,57 +85,55 @@ def check_for_new_tags(tag_registry: dict[str, str], current_schema: dict) -> li return [tag for tag in tag_registry if tag not in existing_tags] -def create_new_schema_version( +def update_schema_file( tag_registry: dict[str, str], check_only: bool = False -) -> tuple[int | None, list[str]]: +) -> tuple[bool, list[str]]: """ - Create a new schema version if there are new tags. + Update the v1 schema file with new tag definitions. Args: tag_registry: Dict mapping tag name to type name check_only: If True, only check if update is needed without writing Returns: - Tuple of (new_version or None if no update, list_of_new_tags) + Tuple of (was_updated, list_of_new_tags) """ - current_version = get_latest_schema_version() - current_schema = load_schema(current_version) + current_schema = load_schema() # Find new tags new_tags = check_for_new_tags(tag_registry, current_schema) if not new_tags: - return None, [] + return False, [] if check_only: - return current_version + 1, new_tags + return True, new_tags - # Generate and write new schema - new_version = current_version + 1 - new_schema = generate_new_schema(current_schema, tag_registry, new_version) - new_schema_path = get_schema_path(new_version) + # Generate and write updated schema (in place) + updated_schema = generate_updated_schema(current_schema, tag_registry) + schema_path = get_schema_path() - with open(new_schema_path, "w") as f: - json.dump(new_schema, f, indent=2) + with open(schema_path, "w") as f: + json.dump(updated_schema, f, indent=2) f.write("\n") - return new_version, new_tags + return True, new_tags -def update_schema_from_submissions(check_only: bool = False) -> tuple[int | None, list[str]]: +def update_schema_from_submissions(check_only: bool = False) -> tuple[bool, list[str]]: """ - Read all submissions and create a new schema version if needed. + Read all submissions and update the schema if needed. Args: check_only: If True, only check if update is needed without writing Returns: - Tuple of (new_version or None if no update, list_of_new_tags) + Tuple of (was_updated, list_of_new_tags) """ submissions = read_all_submissions() tag_registry = build_tag_type_registry(submissions) - return create_new_schema_version(tag_registry, check_only) + return update_schema_file(tag_registry, check_only) def main(): @@ -148,21 +142,21 @@ def main(): args = parser.parse_args() - new_version, new_tags = update_schema_from_submissions(check_only=args.check) + was_updated, new_tags = update_schema_from_submissions(check_only=args.check) if args.check: - if new_version: - print(f"Schema update needed -> v{new_version}. New tags: {', '.join(new_tags)}") + if was_updated: + print(f"Schema update needed. New tags: {', '.join(new_tags)}") sys.exit(1) else: - print(f"Schema is up to date (v{get_latest_schema_version()})") + print("Schema is up to date") sys.exit(0) else: - if new_version: - print(f"Created {get_schema_path(new_version)}") + if was_updated: + print(f"Updated {get_schema_path()}") print(f"Added tags: {', '.join(new_tags)}") else: - print(f"No update needed (v{get_latest_schema_version()})") + print("No update needed") if __name__ == "__main__":