diff --git a/.yamato/_run-all.yml b/.yamato/_run-all.yml index e8181d962e..6c1257cf0e 100644 --- a/.yamato/_run-all.yml +++ b/.yamato/_run-all.yml @@ -17,6 +17,8 @@ run_quick_checks: dependencies: - .yamato/package-pack.yml#package_pack_-_ngo_ubuntu - .yamato/project-standards.yml#standards_ubuntu_testproject_trunk + # Run API validation to early-detect all new APIs that would force us to release new minor version of the package. Note that for this to work the package version in package.json must correspond to "actual package state" which means that it should be higher than last released version + - .yamato/vetting-test.yml#vetting_test # Runs all package tests run_all_package_tests: diff --git a/.yamato/_triggers.yml b/.yamato/_triggers.yml index bb27d1219b..6a274f869c 100644 --- a/.yamato/_triggers.yml +++ b/.yamato/_triggers.yml @@ -108,6 +108,8 @@ develop_nightly: # Build player for webgl platform on trunk and 2021 editors - .yamato/project-updated-dependencies-test.yml#updated-dependencies_testproject_NGO_ubuntu_trunk - .yamato/project-updated-dependencies-test.yml#updated-dependencies_testproject_NGO_win_2021.3 + # Run API validation to early-detect all new APIs that would force us to release new minor version of the package. Note that for this to work the package version in package.json must correspond to "actual package state" which means that it should be higher than last released version + - .yamato/vetting-test.yml#vetting_test # Run all tests on weekly bases diff --git a/.yamato/package-pack.yml b/.yamato/package-pack.yml index 61e794f110..bd0c3290e9 100644 --- a/.yamato/package-pack.yml +++ b/.yamato/package-pack.yml @@ -37,6 +37,7 @@ package_pack_-_ngo_{{ platform.name }}: variables: XRAY_PROFILE: "supported ./pvpExceptions.json" commands: + - python Tools/scripts/release.py # Needed to ensure that CHANGELOG is properly formatted for this test due to the fact that we have bumped package version (to properly perform vetting tests) - upm-pvp pack "com.unity.netcode.gameobjects" --output upm-ci~/packages - upm-pvp xray --packages "upm-ci~/packages/com.unity.netcode.gameobjects*.tgz" --results pvp-results - upm-pvp require {% if platform.name == "win" %}"%XRAY_PROFILE%"{% else %}"$XRAY_PROFILE"{% endif %} --results pvp-results --allow-missing diff --git a/.yamato/project.metafile b/.yamato/project.metafile index 4961ee08c3..ceef5a1241 100644 --- a/.yamato/project.metafile +++ b/.yamato/project.metafile @@ -161,8 +161,9 @@ validation_editors: - 6000.1 - 6000.2 - trunk - - + minimal: + - 2021.3 + # Scripting backends used by Standalone RunTimeTests--------------------------------------------------- scripting_backends: diff --git a/.yamato/vetting-test.yml b/.yamato/vetting-test.yml new file mode 100644 index 0000000000..3fbba0edd3 --- /dev/null +++ b/.yamato/vetting-test.yml @@ -0,0 +1,25 @@ +{% metadata_file .yamato/project.metafile %} # All configuration that is used to create different configurations (used in for loops) is taken from this file. +--- +# DESCRIPTION-------------------------------------------------------------------------- +# This configuration defines vetting tests for the Tools package which allows to validate if the package is in releasable state. This is important in particular because of API validation that allows to detect if we are introducing any new APIs that will force us to bump package version to new minor +# If this test fails with new API error we should either make those API internal OR bump package version to new minor (note that the package version reflects the current package state) + +# Note that we are packing the package only (no project context) so if package have any soft dependencies then project should be used to test it (to enable those APIs) +{% for editor in validation_editors.minimal -%} +vetting_test: + name: MP Tools - Vetting Test (Win, {{editor}} LTS) + agent: { type: Unity::VM, flavor: b1.large, image: package-ci/win11:v4 } + commands: + - python Tools/scripts/release.py # Needed to ensure that CHANGELOG is properly formatted for this test + - npm install -g "upm-ci-utils@stable" --registry https://artifactory.prd.it.unity3d.com/artifactory/api/npm/upm-npm + - unity-downloader-cli --fast --wait --unity-version {{ editor }} --components editor --arch x64 + - upm-ci package pack --package-path com.unity.netcode.gameobjects + - upm-ci package test -u .Editor --package-path com.unity.netcode.gameobjects --type vetting-tests + artifacts: + logs: + paths: + - pvp-results/* + - test-results/** + - upm-ci~/test-results/** + - upm-ci~/upm-ci.log +{% endfor -%} \ No newline at end of file diff --git a/Tools/scripts/release.py b/Tools/scripts/release.py new file mode 100644 index 0000000000..7c6d1c2b8e --- /dev/null +++ b/Tools/scripts/release.py @@ -0,0 +1,101 @@ +""" +This python script makes the NGO package release ready. What it does is: +1) Update changelogs +2) Update validation exception file based on manifest version + +Note that this script NEEDS TO BE RUN FROM THE ROOT of the project. +""" +#!/usr/bin/env python3 +import datetime +import json +import os +import re +import subprocess +import platform + +package_name = 'com.unity.netcode.gameobjects' + +def update_changelog(new_version): + """ + Cleans the [Unreleased] section of the changelog by removing empty subsections, + then replaces the '[Unreleased]' tag with the new version and release date. + """ + + changelog_entry = f'## [{new_version}] - {datetime.date.today().isoformat()}' + changelog_path = f'{package_name}/CHANGELOG.md' + print("Latest CHANGELOG entry will be modified to: " + changelog_entry) + + with open(changelog_path, 'r', encoding='UTF-8') as f: + changelog_text = f.read() + + # This pattern finds a line starting with '###', followed by its newline, + # and then two more lines that contain only whitespace. + # The re.MULTILINE flag allows '^' to match the start of each line. + pattern = re.compile(r"^###.*\n\n\n", re.MULTILINE) + + # Replace every match with an empty string. The goal is to remove empty CHANGELOG subsections. + cleaned_content = pattern.sub('', changelog_text) + + # Replace the [Unreleased] section with the new version + cleaned subsections + changelog_text = re.sub(r'## \[Unreleased\]', changelog_entry, cleaned_content) + + # Write the changes + with open(changelog_path, 'w', encoding='UTF-8', newline='\n') as file: + file.write(changelog_text) + + +def update_validation_exceptions(new_version): + """ + Updates the ValidationExceptions.json file with the new package version. + """ + + validation_file = f'{package_name}/ValidationExceptions.json' + + # If files do not exist, exit + if not os.path.exists(validation_file): + return + + # Update the PackageVersion in the exceptions + with open(validation_file, 'rb') as f: + json_text = f.read() + data = json.loads(json_text) + updated = False + for exceptionElements in ["WarningExceptions", "ErrorExceptions"]: + exceptions = data.get(exceptionElements) + + if exceptions is not None: + for exception in exceptions: + if 'PackageVersion' in exception: + exception['PackageVersion'] = new_version + updated = True + + # If no exceptions were updated, we do not need to write the file + if not updated: + return + + with open(validation_file, 'w', encoding='UTF-8', newline='\n') as json_file: + json.dump(data, json_file, ensure_ascii=False, indent=2) + json_file.write("\n") # Add newline cause Py JSON does not + print(f" updated `{validation_file}`") + + +def get_manifest_json_version(filename): + """ + Reads the package.json file and returns the version specified in it. + """ + with open(filename, 'rb') as f: + json_text = f.read() + data = json.loads(json_text) + + return data['version'] + + +if __name__ == '__main__': + manifest_path = f'{package_name}/package.json' + package_version = get_manifest_json_version(manifest_path) + + # Update the ValidationExceptions.json file + # with the new package version OR remove it if not a release branch + update_validation_exceptions(package_version) + # Clean the CHANGELOG and add latest entry + update_changelog(package_version)