Skip to content

Commit cd41f6c

Browse files
committed
Added script to verify if release conditions are met
1 parent 69c9a62 commit cd41f6c

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"""
2+
Determines if NGO release automation job should run.
3+
4+
The script will check the following conditions:
5+
1. **Is today a release Saturday?**
6+
- The script checks if today is a Saturday that falls on the 4-week cycle for Netcode releases.
7+
2. **Is the [Unreleased] section of the CHANGELOG.md not empty?**
8+
- The script checks if the [Unreleased] section in the CHANGELOG.md contains meaningful entries.
9+
3. **Does the release branch already exist?**
10+
- If the release branch for the target release already exists, the script will not run.
11+
- For this you need to use separate function, see verifyNetcodeReleaseConditions definition
12+
"""
13+
#!/usr/bin/env python3
14+
import datetime
15+
import re
16+
import sys
17+
import os
18+
19+
UTILS_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '../Utils'))
20+
sys.path.insert(0, UTILS_DIR)
21+
from general_utils import get_package_version_from_manifest # nopep8
22+
from git_utils import GithubUtils # nopep8
23+
from config import getPackageManifestPath, getNetcodeGithubRepo, getPackageChangelogPath, getNetcodeReleaseBranchName # nopep8
24+
25+
def is_release_date(weekday, release_week_cycle, anchor_date):
26+
"""
27+
Checks if today is a weekday that falls on the release_week_cycle starting from anchor_date .
28+
Returns True if it is, False otherwise.
29+
"""
30+
today = datetime.date.today()
31+
# Condition 1: Must be a given weekday
32+
# Note as for example you could run a job that utilizes the fact that weekly trigger as per https://internaldocs.unity.com/yamato_continuous_integration/usage/jobs/recurring-jobs/#cron-syntax runs every Saturday, between 2 and 8 AM UTC depending on the load
33+
if today.weekday() != weekday:
34+
return False
35+
36+
# Condition 2: Must be on a release_week_cycle interval from the anchor_date.
37+
days_since_anchor = (today - anchor_date).days
38+
weeks_since_anchor = days_since_anchor / 7
39+
40+
# We run on the first week of every release_week_cycle (e.g., week 0, 4, 8, ...)
41+
if weeks_since_anchor % release_week_cycle == 0:
42+
return True
43+
44+
return False
45+
46+
def is_changelog_empty(changelog_path):
47+
"""
48+
Checks if the [Unreleased] section in the CHANGELOG.md contains meaningful entries.
49+
It is considered "empty" if the section only contains headers (like ### Added) but no actual content.
50+
"""
51+
if not os.path.exists(changelog_path):
52+
print(f"Error: Changelog file not found at {changelog_path}")
53+
sys.exit(1)
54+
55+
with open(changelog_path, 'r', encoding='UTF-8') as f:
56+
content = f.read()
57+
58+
# This pattern starts where Unreleased section is placed
59+
# Then it matches in the first group all empty sections (only lines that are empty or start with ##)
60+
# The second group matches the start of the next Changelog entry (## [).
61+
# if both groups are matched it means that the Unreleased section is empty.
62+
pattern = re.compile(r"^## \[Unreleased\]\n((?:^###.*\n|^\s*\n)*)(^## \[)", re.MULTILINE)
63+
match = pattern.search(content)
64+
65+
# If we find a match for the "empty unreleased changelog entry" pattern, it means the changelog IS empty.
66+
if match:
67+
print("Found an [Unreleased] section containing no release notes.")
68+
return True
69+
70+
# If the pattern does not match, it means there must be meaningful content.
71+
return False
72+
73+
def verifyNetcodeReleaseConditions():
74+
"""
75+
Checks conditions and exits with appropriate status code.
76+
"""
77+
78+
tools_manifest_path = getPackageManifestPath()
79+
tools_changelog_path = getPackageChangelogPath()
80+
tools_package_version = get_package_version_from_manifest(tools_manifest_path)
81+
tools_github_repo = getNetcodeGithubRepo()
82+
tools_release_branch_name = getNetcodeReleaseBranchName(tools_package_version)
83+
tools_github_token = os.environ.get("GITHUB_TOKEN")
84+
85+
# An anchor date that was a Saturday. This is used to establish the 4-week cycle.
86+
# You can set this to any past Saturday that you want to mark as the start of a cycle (week 0). We use 2025-07-19 as starting point (previous release date).
87+
anchor_saturday = datetime.date(2025, 7, 19)
88+
89+
print("--- Checking conditions for NGO release ---")
90+
91+
if not os.path.exists(tools_manifest_path):
92+
print(f" Path does not exist: {tools_manifest_path}")
93+
sys.exit(1)
94+
95+
if not os.path.exists(tools_changelog_path):
96+
print(f" Path does not exist: {tools_changelog_path}")
97+
sys.exit(1)
98+
99+
if tools_package_version is None:
100+
print(f"Package version not found at {tools_manifest_path}")
101+
sys.exit(1)
102+
103+
if not tools_github_token:
104+
print("Error: GITHUB_TOKEN environment variable not set.", file=sys.stderr)
105+
sys.exit(1)
106+
107+
if not is_release_date(weekday=5, release_week_cycle=4, anchor_date=anchor_saturday):
108+
print("Condition not met: Today is not the scheduled release Saturday.")
109+
print("Job will not run. Exiting.")
110+
sys.exit(1)
111+
112+
print("Condition met: Today is a scheduled release Saturday.")
113+
114+
if is_changelog_empty(tools_changelog_path):
115+
print("Condition not met: The [Unreleased] section of the changelog is empty.")
116+
print("Job will not run. Exiting.")
117+
sys.exit(1)
118+
119+
print("Condition met: The changelog contains entries to be released.")
120+
121+
# Initialize PyGithub and get the repository object
122+
github_manager = GithubUtils(tools_github_token, tools_github_repo)
123+
124+
if github_manager.is_branch_present(tools_release_branch_name):
125+
print("Condition not met: The release branch already exists.")
126+
print("Job will not run. Exiting.")
127+
sys.exit(1)
128+
129+
print("Condition met: The release branch does not yet exist.")
130+
131+
print("\nAll conditions met. The release preparation job can proceed.")
132+
sys.exit(0)
133+
134+
if __name__ == "__main__":
135+
verifyNetcodeReleaseConditions()

0 commit comments

Comments
 (0)