Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Normalize all text files to LF
* text=auto eol=lf

# Ensure patch files always use LF line endings
*.patch text eol=lf
2 changes: 1 addition & 1 deletion features/Cloud Shadows/Shaders/Features/CloudShadows.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-2-1
Version = 1-3-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 2-3-1
Version = 2-3-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-1
Version = 1-2-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 3-0-3
Version = 3-0-3
2 changes: 1 addition & 1 deletion features/Grass Lighting/Shaders/Features/GrassLighting.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 2-0-1
Version = 2-0-1
2 changes: 1 addition & 1 deletion features/Hair Specular/Shaders/Features/HairSpecular.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
2 changes: 1 addition & 1 deletion features/IBL/Shaders/Features/ImageBasedLighting.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-0-1
Version = 1-1-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 4-1-0
Version = 4-1-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 2-1-0
Version = 2-1-0
2 changes: 1 addition & 1 deletion features/Sky Sync/Shaders/Features/SkySync.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-0-1
Version = 1-1-0
2 changes: 1 addition & 1 deletion features/Skylighting/Shaders/Features/Skylighting.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-2-4
Version = 1-2-4
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-0-2
Version = 1-0-2
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
2 changes: 1 addition & 1 deletion features/Unified Water/Shaders/Features/UnifiedWater.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-0-1
Version = 1-0-1
2 changes: 1 addition & 1 deletion features/Upscaling/Shaders/Features/Upscaling.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-4-0
Version = 1-3-0
2 changes: 1 addition & 1 deletion features/VR/Shaders/Features/VR.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
2 changes: 1 addition & 1 deletion features/Weather Editor/Shaders/Features/WeatherEditor.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-1-0
Version = 1-1-0
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 3-2-0
Version = 3-1-0
69 changes: 56 additions & 13 deletions tools/feature_version_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,12 @@ def extract_feature_metadata(feature_headers_dir):
})
return feature_info

def get_latest_release_tag():
def get_latest_release_tag(ref="HEAD"):
try:
output = subprocess.check_output([
"git", "tag", "--list", "v*.*.*"
], stderr=subprocess.DEVNULL).decode("utf-8")
output = subprocess.check_output(
["git", "tag", "--merged", ref, "--list", "v*.*.*"],
stderr=subprocess.DEVNULL,
).decode("utf-8")
tags = [t.strip() for t in output.splitlines() if re.match(r"^v\d+\.\d+\.\d+$", t.strip())]
if not tags:
return None
Expand Down Expand Up @@ -307,12 +308,14 @@ def propose_new_version(prior_version, commits):
else:
return (major, minor, patch + 1)

def analyze_features(FEATURES_DIR, feature_meta_map, base_ref, only_changed=False):
def analyze_features(FEATURES_DIR, feature_meta_map, base_ref, only_changed=False, release_ref=None):
bump_suggestions = []
new_features = []
actionable = False
feature_actions = {}
feature_analysis = []
# version_ref: base for version comparison (last release tag in PR mode; otherwise same as base_ref)
version_ref = release_ref if release_ref else base_ref
# If only_changed, build a set of changed feature names
changed_features = set()
if only_changed:
Expand Down Expand Up @@ -376,16 +379,22 @@ def get_feature_key(feature_dir, feature_meta_map):

meta = feature_meta_map.get(feature_key)
ini_path = get_feature_ini(feature_dir)
prior_ver = get_prior_version(ini_path, base_ref) if ini_path else None
# Use last release tag (version_ref) as the baseline for version proposals so that
# multiple PRs between releases don't accumulate spurious bumps.
prior_ver = get_prior_version(ini_path, version_ref) if ini_path else None
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# PR-scoped prior version: used for new-feature detection and as the effective
# current version when the PR branch is behind base_ref (non-rebased PRs).
pr_prior_ver = get_prior_version(ini_path, base_ref) if (ini_path and version_ref != base_ref) else prior_ver
new_ver = get_version_from_ini(ini_path) if ini_path else None

# PR-scoped changes: used for change-type display and new-feature detection
changes = get_changed_files(feature_dir, base_ref)
# Also check src/Features
cpp_types = (".h", ".hpp", ".cpp", ".c")
if meta:
header_path = DEFAULT_FEATURE_HEADERS_DIR / (meta['name'] + ".h")
cpp_path = DEFAULT_FEATURE_HEADERS_DIR / (meta['name'] + ".cpp")
feature_src_dir = DEFAULT_FEATURE_HEADERS_DIR / meta['name']
cpp_types = (".h", ".hpp", ".cpp", ".c")
if header_path.exists():
changes.extend(get_changed_files(header_path, base_ref, file_types=cpp_types))
if cpp_path.exists():
Expand All @@ -394,12 +403,28 @@ def get_feature_key(feature_dir, feature_meta_map):
changes.extend(get_changed_files(feature_src_dir, base_ref, file_types=cpp_types))
changes = list(set(changes))

# Release-scoped changes: all changes since last release, used to propose the correct
# version so that a bump already applied by a prior PR satisfies this check.
release_changes = get_changed_files(feature_dir, version_ref)
if meta:
header_path = DEFAULT_FEATURE_HEADERS_DIR / (meta['name'] + ".h")
cpp_path = DEFAULT_FEATURE_HEADERS_DIR / (meta['name'] + ".cpp")
feature_src_dir = DEFAULT_FEATURE_HEADERS_DIR / meta['name']
if header_path.exists():
release_changes.extend(get_changed_files(header_path, version_ref, file_types=cpp_types))
if cpp_path.exists():
release_changes.extend(get_changed_files(cpp_path, version_ref, file_types=cpp_types))
if feature_src_dir.exists() and feature_src_dir.is_dir():
release_changes.extend(get_changed_files(feature_src_dir, version_ref, file_types=cpp_types))
release_changes = list(set(release_changes))

change_types = set(os.path.splitext(f)[1].lower() for _, f in changes)
all_commits = []
bump_commit = None
bump_author = None
for status, f in release_changes:
all_commits.extend(get_commits_for_file(f, version_ref))
Comment thread
coderabbitai[bot] marked this conversation as resolved.
for status, f in changes:
all_commits.extend(get_commits_for_file(f, base_ref))
if not bump_commit:
bump_commit = get_bump_commit(f, base_ref)
if bump_commit:
Expand All @@ -411,7 +436,11 @@ def get_feature_key(feature_dir, feature_meta_map):
bump_author = get_commit_author(any_commit)

proposed_ver = propose_new_version(prior_ver, all_commits) if ini_path else None
needs_bump = (proposed_ver is not None and new_ver is not None and proposed_ver > new_ver)
# Use max(new_ver, pr_prior_ver) as the effective current version so that a version
# bump already on base_ref (e.g. from a parallel PR) satisfies the check even when
# the PR branch has not been rebased.
effective_new_ver = max(new_ver, pr_prior_ver) if (new_ver and pr_prior_ver) else (new_ver or pr_prior_ver)
needs_bump = (proposed_ver is not None and effective_new_ver is not None and proposed_ver > effective_new_ver)
proposed_ver_str = "-".join(map(str, proposed_ver)) if proposed_ver else "-"
prior_ver_str = "-".join(map(str, prior_ver)) if prior_ver else "-"
new_ver_str = "-".join(map(str, new_ver)) if new_ver else "-"
Expand All @@ -428,8 +457,9 @@ def get_feature_key(feature_dir, feature_meta_map):
note = "New feature (missing ini!)"
new_features.append((feature_dir.name, "-", bump_commit))
is_attention = True
# Detect new ini added
if ini_path and prior_ver is None and new_ver is not None:
# Detect new ini added — use pr_prior_ver (base_ref baseline) so features added
# earlier in the release cycle are not re-reported as new in subsequent PRs.
if ini_path and pr_prior_ver is None and new_ver is not None:
note = f"New ini added (v{new_ver_str})"
new_features.append((feature_dir.name, new_ver_str, bump_commit))
is_attention = True
Expand Down Expand Up @@ -658,13 +688,26 @@ def main():
if args.base:
base_ref = args.base
else:
detected_base = detect_pr_base() if args.pr_check else get_latest_release_tag()
detected_base = detect_pr_base() if args.pr_check else get_latest_release_tag(HEAD_REF)
if detected_base:
base_ref = detected_base
else:
print("No valid base ref found.", file=sys.stderr)
sys.exit(1)

# In PR check mode, determine the last release tag so version proposals are anchored
# to the release baseline rather than to the tip of the target branch. This prevents
# multiple PRs between releases from each requiring an additional version bump.
# Use --merged base_ref so only tags reachable from the target branch are considered;
# hotfix tags on unrelated branches cannot skew the baseline.
release_ref = None
if args.pr_check:
release_ref = get_latest_release_tag(base_ref)
if release_ref:
print(f"Using release tag for version baseline: {release_ref}", file=sys.stderr)
else:
print("No release tag found; falling back to base_ref for version baseline.", file=sys.stderr)

Comment thread
coderabbitai[bot] marked this conversation as resolved.
base_date_iso = None
base_date_human = None
try:
Expand All @@ -684,7 +727,7 @@ def normalize_name(name): return ''.join(name.lower().split())
feature_meta_map = {normalize_name(f['name']): f for f in feature_metadata}

feature_analysis, bump_suggestions, new_features, actionable, feature_actions = analyze_features(
FEATURES_DIR, feature_meta_map, base_ref, only_changed=args.pr_check)
FEATURES_DIR, feature_meta_map, base_ref, only_changed=args.pr_check, release_ref=release_ref)

now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
date_tag = datetime.datetime.now().strftime('%Y-%m-%d')
Expand Down
Loading