From 39fe89c1e0ae28870105c3a576c4fc743107fa86 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:09:01 +0000 Subject: [PATCH 1/7] Initial plan From 0cd32eee9ad5923b324d72639fff52be3a529eed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:14:26 +0000 Subject: [PATCH 2/7] Add GitHub Action to monitor web-features npm package for new minor versions Co-authored-by: NiklasMerz <3585860+NiklasMerz@users.noreply.github.com> --- .../workflows/check_web_features_version.yml | 93 ++++++++++++++++++ .gitignore | 1 + tools/check_web_features_version.py | 97 +++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 .github/workflows/check_web_features_version.yml create mode 100755 tools/check_web_features_version.py diff --git a/.github/workflows/check_web_features_version.yml b/.github/workflows/check_web_features_version.yml new file mode 100644 index 0000000..1f141f6 --- /dev/null +++ b/.github/workflows/check_web_features_version.yml @@ -0,0 +1,93 @@ +name: Check web-features version + +on: + workflow_dispatch: + + schedule: + - cron: '0 0 * * 0' # Run at 00:00 UTC every Sunday + +permissions: + contents: read + issues: write + +jobs: + check_web_features: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Check for new minor version + id: version_check + run: | + if python tools/check_web_features_version.py; then + echo "new_version=false" >> $GITHUB_OUTPUT + else + EXIT_CODE=$? + if [ $EXIT_CODE -eq 1 ]; then + echo "new_version=true" >> $GITHUB_OUTPUT + # Extract the latest version for the issue + VERSION=$(python tools/check_web_features_version.py 2>&1 | \ + grep "Latest version:" | cut -d' ' -f3) + echo "latest_version=$VERSION" >> $GITHUB_OUTPUT + else + echo "Script error occurred" + exit 2 + fi + fi + + - name: Create issue for new minor version + if: steps.version_check.outputs.new_version == 'true' + uses: actions/github-script@v7 + with: + script: | + const latestVersion = \ + '${{ steps.version_check.outputs.latest_version }}'; + const title = \ + `New minor version of web-features available: ${latestVersion}`; + const body = \ + `A new minor version of the \`web-features\` npm package has been published. + + **Latest version:** ${latestVersion} + + Please review the [changelog](https://github.com/web-platform-dx/web-features/releases) and consider updating the package. + + To update: + 1. Review the changes in the new version + 2. Update the version in \`package.json\` + 3. Run \`npm install\` + 4. Test the changes + 5. Commit and push the updates + + --- + _This issue was automatically created by the [Check web-features version workflow](https://github.com/${{ github.repository }}/actions/workflows/check_web_features_version.yml)._`; + + // Check if an issue already exists for this version + const issues = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: ['dependencies', 'web-features'] + }); + + const existingIssue = issues.data.find(issue => + issue.title.includes(latestVersion) + ); + + if (existingIssue) { + console.log(`Issue already exists for version ${latestVersion}: #${existingIssue.number}`); + } else { + const issue = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + labels: ['dependencies', 'web-features'] + }); + console.log(`Created issue #${issue.data.number}`); + } diff --git a/.gitignore b/.gitignore index 9340436..955140e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ _site Gemfile.lock node_modules +__pycache__ diff --git a/tools/check_web_features_version.py b/tools/check_web_features_version.py new file mode 100755 index 0000000..f52fb15 --- /dev/null +++ b/tools/check_web_features_version.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 + +''' +This script checks if a new minor version of the web-features npm package +has been published. It compares the current version in package.json with +the latest version from npm registry. + +The script only detects new minor versions (e.g., 2.1.0 -> 2.2.0), not +major versions (e.g., 2.0.0 -> 3.0.0) or patch versions (e.g., 2.1.0 -> 2.1.1). + +Exit codes: + 0 - No new minor version detected + 1 - New minor version detected + 2 - Error occurred +''' + +import urllib.request +import json +import sys +import re + +NPM_REGISTRY_URL = "https://registry.npmjs.org/web-features" +PACKAGE_JSON_FILE = "package.json" + +def parse_version(version_string): + """Parse a semantic version string into major, minor, patch components.""" + # Remove any leading 'v' or '^' or '~' characters + version_string = version_string.lstrip('v^~') + + match = re.match(r'^(\d+)\.(\d+)\.(\d+)', version_string) + if not match: + return None + + return { + 'major': int(match.group(1)), + 'minor': int(match.group(2)), + 'patch': int(match.group(3)) + } + +def is_new_minor_version(current_version, latest_version): + """ + Check if latest_version is a new minor version compared to current_version. + Returns True only if: + - Major versions are the same + - Latest minor version is greater than current minor version + """ + current = parse_version(current_version) + latest = parse_version(latest_version) + + if not current or not latest: + print(f"Error: Invalid version format. Current: {current_version}, Latest: {latest_version}") + return False + + # Same major version and greater minor version + return (current['major'] == latest['major'] and + latest['minor'] > current['minor']) + +def get_latest_version(): + """Get the latest version of web-features from npm registry.""" + try: + with urllib.request.urlopen(NPM_REGISTRY_URL) as response: + data = json.load(response) + return data['dist-tags']['latest'] + except Exception as e: + print(f"Error fetching latest version from npm: {e}") + sys.exit(2) + +def get_current_version(): + """Get the current version of web-features from package.json.""" + try: + with open(PACKAGE_JSON_FILE, 'r') as file: + data = json.load(file) + if 'dependencies' in data and 'web-features' in data['dependencies']: + return data['dependencies']['web-features'] + else: + print("Error: web-features not found in package.json dependencies") + sys.exit(2) + except Exception as e: + print(f"Error reading package.json: {e}") + sys.exit(2) + +def main(): + current_version = get_current_version() + latest_version = get_latest_version() + + print(f"Current version: {current_version}") + print(f"Latest version: {latest_version}") + + if is_new_minor_version(current_version, latest_version): + print(f"New minor version detected: {latest_version}") + sys.exit(1) + else: + print("No new minor version detected") + sys.exit(0) + +if __name__ == "__main__": + main() From db42666f39d6128c6beb99003eb517e0175bcb87 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:17:39 +0000 Subject: [PATCH 3/7] Improve version parsing and extraction in web-features checker Co-authored-by: NiklasMerz <3585860+NiklasMerz@users.noreply.github.com> --- .github/workflows/check_web_features_version.yml | 6 +++--- tools/check_web_features_version.py | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check_web_features_version.yml b/.github/workflows/check_web_features_version.yml index 1f141f6..672c54d 100644 --- a/.github/workflows/check_web_features_version.yml +++ b/.github/workflows/check_web_features_version.yml @@ -31,9 +31,9 @@ jobs: EXIT_CODE=$? if [ $EXIT_CODE -eq 1 ]; then echo "new_version=true" >> $GITHUB_OUTPUT - # Extract the latest version for the issue + # Extract the latest version from the script output VERSION=$(python tools/check_web_features_version.py 2>&1 | \ - grep "Latest version:" | cut -d' ' -f3) + grep "^LATEST_VERSION=" | cut -d'=' -f2) echo "latest_version=$VERSION" >> $GITHUB_OUTPUT else echo "Script error occurred" @@ -76,7 +76,7 @@ jobs: }); const existingIssue = issues.data.find(issue => - issue.title.includes(latestVersion) + issue.title === title ); if (existingIssue) { diff --git a/tools/check_web_features_version.py b/tools/check_web_features_version.py index f52fb15..1d0306e 100755 --- a/tools/check_web_features_version.py +++ b/tools/check_web_features_version.py @@ -27,7 +27,10 @@ def parse_version(version_string): # Remove any leading 'v' or '^' or '~' characters version_string = version_string.lstrip('v^~') - match = re.match(r'^(\d+)\.(\d+)\.(\d+)', version_string) + # Handle pre-release versions by splitting on '-' or '+' + base_version = version_string.split('-')[0].split('+')[0] + + match = re.match(r'^(\d+)\.(\d+)\.(\d+)', base_version) if not match: return None @@ -85,6 +88,7 @@ def main(): print(f"Current version: {current_version}") print(f"Latest version: {latest_version}") + print(f"LATEST_VERSION={latest_version}") if is_new_minor_version(current_version, latest_version): print(f"New minor version detected: {latest_version}") From f89d7707a96bfe1eb1addcf1930cbfc61af55574 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 11:24:39 +0000 Subject: [PATCH 4/7] Update workflow to create issues for both major and minor versions Co-authored-by: NiklasMerz <3585860+NiklasMerz@users.noreply.github.com> --- .../workflows/check_web_features_version.yml | 8 ++--- tools/check_web_features_version.py | 34 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/.github/workflows/check_web_features_version.yml b/.github/workflows/check_web_features_version.yml index 672c54d..c7636f9 100644 --- a/.github/workflows/check_web_features_version.yml +++ b/.github/workflows/check_web_features_version.yml @@ -22,7 +22,7 @@ jobs: with: python-version: "3.10" - - name: Check for new minor version + - name: Check for new version id: version_check run: | if python tools/check_web_features_version.py; then @@ -41,7 +41,7 @@ jobs: fi fi - - name: Create issue for new minor version + - name: Create issue for new version if: steps.version_check.outputs.new_version == 'true' uses: actions/github-script@v7 with: @@ -49,9 +49,9 @@ jobs: const latestVersion = \ '${{ steps.version_check.outputs.latest_version }}'; const title = \ - `New minor version of web-features available: ${latestVersion}`; + `New version of web-features available: ${latestVersion}`; const body = \ - `A new minor version of the \`web-features\` npm package has been published. + `A new version of the \`web-features\` npm package has been published. **Latest version:** ${latestVersion} diff --git a/tools/check_web_features_version.py b/tools/check_web_features_version.py index 1d0306e..69776ca 100755 --- a/tools/check_web_features_version.py +++ b/tools/check_web_features_version.py @@ -1,16 +1,16 @@ #!/usr/bin/env python3 ''' -This script checks if a new minor version of the web-features npm package +This script checks if a new major or minor version of the web-features npm package has been published. It compares the current version in package.json with the latest version from npm registry. -The script only detects new minor versions (e.g., 2.1.0 -> 2.2.0), not -major versions (e.g., 2.0.0 -> 3.0.0) or patch versions (e.g., 2.1.0 -> 2.1.1). +The script detects new major or minor versions (e.g., 2.0.0 -> 3.0.0 or 2.0.0 -> 2.1.0), +but not patch versions (e.g., 2.1.0 -> 2.1.1). Exit codes: - 0 - No new minor version detected - 1 - New minor version detected + 0 - No new major or minor version detected + 1 - New major or minor version detected 2 - Error occurred ''' @@ -40,12 +40,13 @@ def parse_version(version_string): 'patch': int(match.group(3)) } -def is_new_minor_version(current_version, latest_version): +def is_new_version(current_version, latest_version): """ - Check if latest_version is a new minor version compared to current_version. - Returns True only if: - - Major versions are the same - - Latest minor version is greater than current minor version + Check if latest_version is a new major or minor version compared to current_version. + Returns True if: + - Major version is greater (e.g., 2.0.0 -> 3.0.0) + - OR same major version but minor version is greater (e.g., 2.0.0 -> 2.1.0) + Returns False for patch-only updates (e.g., 2.0.0 -> 2.0.1) """ current = parse_version(current_version) latest = parse_version(latest_version) @@ -54,9 +55,10 @@ def is_new_minor_version(current_version, latest_version): print(f"Error: Invalid version format. Current: {current_version}, Latest: {latest_version}") return False - # Same major version and greater minor version - return (current['major'] == latest['major'] and - latest['minor'] > current['minor']) + # Major version increase OR same major but minor version increase + return (latest['major'] > current['major'] or + (current['major'] == latest['major'] and + latest['minor'] > current['minor'])) def get_latest_version(): """Get the latest version of web-features from npm registry.""" @@ -90,11 +92,11 @@ def main(): print(f"Latest version: {latest_version}") print(f"LATEST_VERSION={latest_version}") - if is_new_minor_version(current_version, latest_version): - print(f"New minor version detected: {latest_version}") + if is_new_version(current_version, latest_version): + print(f"New major or minor version detected: {latest_version}") sys.exit(1) else: - print("No new minor version detected") + print("No new major or minor version detected") sys.exit(0) if __name__ == "__main__": From 1620201efac93574bd3b9f34cdafc6f269935c3c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 14:15:00 +0000 Subject: [PATCH 5/7] Add failure notification using jayqi/failed-build-issue-action Co-authored-by: NiklasMerz <3585860+NiklasMerz@users.noreply.github.com> --- .github/workflows/check_web_features_version.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/check_web_features_version.yml b/.github/workflows/check_web_features_version.yml index c7636f9..2d1470d 100644 --- a/.github/workflows/check_web_features_version.yml +++ b/.github/workflows/check_web_features_version.yml @@ -91,3 +91,14 @@ jobs: }); console.log(`Created issue #${issue.data.number}`); } + + - name: Notify failed build + uses: jayqi/failed-build-issue-action@v1 + if: failure() && github.event.pull_request == null + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + title-template: "web-features version check failed" + body-template: | + The web-features version check has failed. Please check the workflow for errors. + + Please check the [logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details. From b7dc6af3fca5bb28289811957458f87ad9b6eb6d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 15:08:49 +0000 Subject: [PATCH 6/7] Simplify workflow by using failed-build-issue-action for all issues Co-authored-by: NiklasMerz <3585860+NiklasMerz@users.noreply.github.com> --- .../workflows/check_web_features_version.yml | 78 +++---------------- 1 file changed, 12 insertions(+), 66 deletions(-) diff --git a/.github/workflows/check_web_features_version.yml b/.github/workflows/check_web_features_version.yml index 2d1470d..6b82416 100644 --- a/.github/workflows/check_web_features_version.yml +++ b/.github/workflows/check_web_features_version.yml @@ -23,82 +23,28 @@ jobs: python-version: "3.10" - name: Check for new version - id: version_check run: | - if python tools/check_web_features_version.py; then - echo "new_version=false" >> $GITHUB_OUTPUT - else - EXIT_CODE=$? - if [ $EXIT_CODE -eq 1 ]; then - echo "new_version=true" >> $GITHUB_OUTPUT - # Extract the latest version from the script output - VERSION=$(python tools/check_web_features_version.py 2>&1 | \ - grep "^LATEST_VERSION=" | cut -d'=' -f2) - echo "latest_version=$VERSION" >> $GITHUB_OUTPUT - else - echo "Script error occurred" - exit 2 - fi - fi + python tools/check_web_features_version.py - name: Create issue for new version - if: steps.version_check.outputs.new_version == 'true' - uses: actions/github-script@v7 + uses: jayqi/failed-build-issue-action@v1 + if: failure() && github.event.pull_request == null with: - script: | - const latestVersion = \ - '${{ steps.version_check.outputs.latest_version }}'; - const title = \ - `New version of web-features available: ${latestVersion}`; - const body = \ - `A new version of the \`web-features\` npm package has been published. - - **Latest version:** ${latestVersion} + github-token: ${{ secrets.GITHUB_TOKEN }} + title-template: "New version of web-features available" + body-template: | + A new version of the `web-features` npm package has been published. Please review the [changelog](https://github.com/web-platform-dx/web-features/releases) and consider updating the package. To update: 1. Review the changes in the new version - 2. Update the version in \`package.json\` - 3. Run \`npm install\` + 2. Update the version in `package.json` + 3. Run `npm install` 4. Test the changes 5. Commit and push the updates --- - _This issue was automatically created by the [Check web-features version workflow](https://github.com/${{ github.repository }}/actions/workflows/check_web_features_version.yml)._`; - - // Check if an issue already exists for this version - const issues = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - labels: ['dependencies', 'web-features'] - }); - - const existingIssue = issues.data.find(issue => - issue.title === title - ); - - if (existingIssue) { - console.log(`Issue already exists for version ${latestVersion}: #${existingIssue.number}`); - } else { - const issue = await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: title, - body: body, - labels: ['dependencies', 'web-features'] - }); - console.log(`Created issue #${issue.data.number}`); - } - - - name: Notify failed build - uses: jayqi/failed-build-issue-action@v1 - if: failure() && github.event.pull_request == null - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - title-template: "web-features version check failed" - body-template: | - The web-features version check has failed. Please check the workflow for errors. - - Please check the [logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details. + _This issue was automatically created by the [Check web-features version workflow](https://github.com/${{ github.repository }}/actions/workflows/check_web_features_version.yml)._ + + Please check the [logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for version details. From 237a0fad33e5ca011aa40a5253820ac418caf8d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Oct 2025 15:14:56 +0000 Subject: [PATCH 7/7] Refactor scripts to use shared version_utils module Co-authored-by: NiklasMerz <3585860+NiklasMerz@users.noreply.github.com> --- tools/check_web_features_version.py | 42 +------------ tools/update_bcd_version.py | 14 ++--- tools/version_utils.py | 95 +++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 49 deletions(-) create mode 100644 tools/version_utils.py diff --git a/tools/check_web_features_version.py b/tools/check_web_features_version.py index 69776ca..a21dab1 100755 --- a/tools/check_web_features_version.py +++ b/tools/check_web_features_version.py @@ -17,49 +17,11 @@ import urllib.request import json import sys -import re +from version_utils import is_minor_or_major_version_change NPM_REGISTRY_URL = "https://registry.npmjs.org/web-features" PACKAGE_JSON_FILE = "package.json" -def parse_version(version_string): - """Parse a semantic version string into major, minor, patch components.""" - # Remove any leading 'v' or '^' or '~' characters - version_string = version_string.lstrip('v^~') - - # Handle pre-release versions by splitting on '-' or '+' - base_version = version_string.split('-')[0].split('+')[0] - - match = re.match(r'^(\d+)\.(\d+)\.(\d+)', base_version) - if not match: - return None - - return { - 'major': int(match.group(1)), - 'minor': int(match.group(2)), - 'patch': int(match.group(3)) - } - -def is_new_version(current_version, latest_version): - """ - Check if latest_version is a new major or minor version compared to current_version. - Returns True if: - - Major version is greater (e.g., 2.0.0 -> 3.0.0) - - OR same major version but minor version is greater (e.g., 2.0.0 -> 2.1.0) - Returns False for patch-only updates (e.g., 2.0.0 -> 2.0.1) - """ - current = parse_version(current_version) - latest = parse_version(latest_version) - - if not current or not latest: - print(f"Error: Invalid version format. Current: {current_version}, Latest: {latest_version}") - return False - - # Major version increase OR same major but minor version increase - return (latest['major'] > current['major'] or - (current['major'] == latest['major'] and - latest['minor'] > current['minor'])) - def get_latest_version(): """Get the latest version of web-features from npm registry.""" try: @@ -92,7 +54,7 @@ def main(): print(f"Latest version: {latest_version}") print(f"LATEST_VERSION={latest_version}") - if is_new_version(current_version, latest_version): + if is_minor_or_major_version_change(current_version, latest_version): print(f"New major or minor version detected: {latest_version}") sys.exit(1) else: diff --git a/tools/update_bcd_version.py b/tools/update_bcd_version.py index 8c10ad0..dc34ffc 100755 --- a/tools/update_bcd_version.py +++ b/tools/update_bcd_version.py @@ -8,7 +8,9 @@ periodically update the version of this repository. ''' -import urllib.request, json +import urllib.request +import json +from version_utils import is_same_major_version CDN_URL = "https://unpkg.com/@mdn/browser-compat-data/data.json" VERSION_FILE = "bcd_version" @@ -17,20 +19,14 @@ # auto update the version if it is not a major version increase. # This will help us avoid accidentally breaking the site # without any human intervention. -def validateNotMajor(prevVersion, nextVersion): - prevVersion = prevVersion.split(".") - nextVersion = nextVersion.split(".") - - return (len(prevVersion) == 3 and - len(nextVersion) == 3 and - prevVersion[0] == nextVersion[0]) with urllib.request.urlopen(CDN_URL) as raw: data = json.load(raw) version = data["__meta"]["version"] with open(VERSION_FILE, "r+") as file: - if (validateNotMajor(file.read(), version)): + current_version = file.read() + if is_same_major_version(current_version, version): file.seek(0) file.write(version) file.truncate() diff --git a/tools/version_utils.py b/tools/version_utils.py new file mode 100644 index 0000000..825bbbe --- /dev/null +++ b/tools/version_utils.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +''' +Shared utility functions for version parsing and comparison. +Used by both check_web_features_version.py and update_bcd_version.py. +''' + +import re + +def parse_version(version_string): + """ + Parse a semantic version string into major, minor, patch components. + + Args: + version_string: Version string (e.g., "2.1.0", "^2.0.0", "v1.2.3", "2.1.0-alpha.1") + + Returns: + Dict with 'major', 'minor', 'patch' keys, or None if invalid + """ + # Remove any leading 'v' or '^' or '~' characters + version_string = version_string.lstrip('v^~') + + # Handle pre-release versions by splitting on '-' or '+' + base_version = version_string.split('-')[0].split('+')[0] + + match = re.match(r'^(\d+)\.(\d+)\.(\d+)', base_version) + if not match: + return None + + return { + 'major': int(match.group(1)), + 'minor': int(match.group(2)), + 'patch': int(match.group(3)) + } + +def is_major_version_change(current_version, latest_version): + """ + Check if there's a major version change between two versions. + + Args: + current_version: Current version string + latest_version: Latest version string + + Returns: + True if major version changed, False otherwise + """ + current = parse_version(current_version) + latest = parse_version(latest_version) + + if not current or not latest: + return False + + return current['major'] != latest['major'] + +def is_minor_or_major_version_change(current_version, latest_version): + """ + Check if there's a major or minor version change between two versions. + Ignores patch-only updates. + + Args: + current_version: Current version string + latest_version: Latest version string + + Returns: + True if major or minor version increased, False otherwise + """ + current = parse_version(current_version) + latest = parse_version(latest_version) + + if not current or not latest: + return False + + # Major version increase OR same major but minor version increase + return (latest['major'] > current['major'] or + (current['major'] == latest['major'] and + latest['minor'] > current['minor'])) + +def is_same_major_version(current_version, latest_version): + """ + Check if two versions have the same major version. + + Args: + current_version: Current version string + latest_version: Latest version string + + Returns: + True if same major version, False otherwise + """ + current = parse_version(current_version) + latest = parse_version(latest_version) + + if not current or not latest: + return False + + return current['major'] == latest['major']