Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/check_web_features_version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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 version
run: |
python tools/check_web_features_version.py

- name: Create issue for new version
uses: jayqi/failed-build-issue-action@v1
if: failure() && github.event.pull_request == null
with:
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`
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)._

Please check the [logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for version details.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
_site
Gemfile.lock
node_modules
__pycache__
65 changes: 65 additions & 0 deletions tools/check_web_features_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3

'''
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 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 major or minor version detected
1 - New major or minor version detected
2 - Error occurred
'''

import urllib.request
import json
import sys
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 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}")
print(f"LATEST_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:
print("No new major or minor version detected")
sys.exit(0)

if __name__ == "__main__":
main()
14 changes: 5 additions & 9 deletions tools/update_bcd_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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()
Expand Down
95 changes: 95 additions & 0 deletions tools/version_utils.py
Original file line number Diff line number Diff line change
@@ -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']