promote_unstable_docs_docusaurus.py
1 """ 2 This script promotes an unstable documentation version to a stable version at the time of a new Haystack release. 3 4 To understand how unstable doc versions are created, see create_unstable_docs_docusaurus.py. 5 """ 6 7 import argparse 8 import json 9 import os 10 import re 11 import shutil 12 import sys 13 14 VERSION_VALIDATOR = re.compile(r"^[0-9]+\.[0-9]+$") 15 MAX_STABLE_VERSIONS = 5 16 17 if __name__ == "__main__": 18 parser = argparse.ArgumentParser() 19 parser.add_argument("-v", "--version", help="The version to promote to stable (e.g. 2.20).", required=True) 20 args = parser.parse_args() 21 22 if VERSION_VALIDATOR.match(args.version) is None: 23 sys.exit("Version must be formatted like so <major>.<minor>") 24 25 target_version = f"{args.version}" # e.g., "2.20" - the target release version 26 major, minor = args.version.split(".") 27 28 target_unstable = f"{target_version}-unstable" # e.g., "2.20-unstable" 29 previous_stable = f"{major}.{int(minor) - 1}" # e.g., "2.19" - previous stable release 30 31 versions = [ 32 folder.replace("version-", "") 33 for folder in os.listdir("docs-website/versioned_docs") 34 if os.path.isdir(os.path.join("docs-website/versioned_docs", folder)) 35 ] 36 37 if target_version in versions: 38 sys.exit(f"{target_version} already exists (already released). Aborting.") 39 if target_unstable not in versions: 40 sys.exit(f"Can't find version {target_unstable} to promote to {target_version}") 41 42 print(f"Promoting unstable version {target_unstable} to stable version {target_version}") 43 44 ### Docusaurus updates 45 46 # move versioned_docs/version-target_unstable to versioned_docs/version-target_version 47 shutil.move( 48 f"docs-website/versioned_docs/version-{target_unstable}", 49 f"docs-website/versioned_docs/version-{target_version}", 50 ) 51 52 # move reference_versioned_docs/version-target_unstable to reference_versioned_docs/version-target_version 53 shutil.move( 54 f"docs-website/reference_versioned_docs/version-{target_unstable}", 55 f"docs-website/reference_versioned_docs/version-{target_version}", 56 ) 57 58 # move versioned_sidebars/version-target_unstable-sidebars.json 59 # to versioned_sidebars/version-target_version-sidebars.json 60 shutil.move( 61 f"docs-website/versioned_sidebars/version-{target_unstable}-sidebars.json", 62 f"docs-website/versioned_sidebars/version-{target_version}-sidebars.json", 63 ) 64 65 # move reference_versioned_sidebars/version-target_unstable-sidebars.json 66 # to reference_versioned_sidebars/version-target_version-sidebars.json 67 shutil.move( 68 f"docs-website/reference_versioned_sidebars/version-{target_unstable}-sidebars.json", 69 f"docs-website/reference_versioned_sidebars/version-{target_version}-sidebars.json", 70 ) 71 72 # replace unstable version with stable version in versions.json 73 with open("docs-website/versions.json") as f: 74 versions_list = json.load(f) 75 versions_list[versions_list.index(target_unstable)] = target_version 76 with open("docs-website/versions.json", "w") as f: 77 json.dump(versions_list, f) 78 79 # replace unstable version with stable version in reference_versions.json 80 with open("docs-website/reference_versions.json") as f: 81 reference_versions_list = json.load(f) 82 reference_versions_list[reference_versions_list.index(target_unstable)] = target_version 83 with open("docs-website/reference_versions.json", "w") as f: 84 json.dump(reference_versions_list, f) 85 86 # in docusaurus.config.js, replace previous stable version with the target version 87 with open("docs-website/docusaurus.config.js") as f: 88 config = f.read() 89 config = config.replace(f"lastVersion: '{previous_stable}'", f"lastVersion: '{target_version}'") # "2.19" -> "2.20" 90 with open("docs-website/docusaurus.config.js", "w") as f: 91 f.write(config) 92 93 # regenerate vercel.json redirects for inactive versions (those beyond the top MAX_STABLE_VERSIONS) 94 with open("docs-website/versions.json") as f: 95 updated_versions = json.load(f) 96 stable_versions = [v for v in updated_versions if not v.endswith("-unstable")] 97 inactive_versions = stable_versions[MAX_STABLE_VERSIONS:] 98 redirects = [] 99 for v in inactive_versions: 100 redirects.append({"source": f"/docs/{v}/:slug*", "destination": "/docs/:slug*", "permanent": True}) 101 redirects.append({"source": f"/reference/{v}/:slug*", "destination": "/reference/:slug*", "permanent": True}) 102 103 with open("docs-website/vercel.json") as f: 104 vercel_config = json.load(f) 105 106 existing_redirects = vercel_config.get("redirects", []) 107 existing_sources = {r.get("source") for r in existing_redirects} 108 109 for r in redirects: 110 if r["source"] not in existing_sources: 111 existing_redirects.append(r) 112 113 vercel_config["redirects"] = existing_redirects 114 with open("docs-website/vercel.json", "w") as f: 115 json.dump(vercel_config, f, indent=2) 116 f.write("\n") 117 print(f"Updated vercel.json with {len(redirects)} redirect(s) for inactive versions: {inactive_versions}")