diff --git a/eng/automation/generate.py b/eng/automation/generate.py index 8f0583aa9b8c..263f22324e7a 100755 --- a/eng/automation/generate.py +++ b/eng/automation/generate.py @@ -6,7 +6,6 @@ import glob import logging import argparse -import shutil from typing import List pwd = os.getcwd() @@ -33,7 +32,6 @@ update_spec, generate_typespec_project, is_mgmt_premium, - copy_folder_recursive_sync, ) os.chdir(pwd) @@ -337,9 +335,6 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict: # compile succeeded = compile_arm_package(sdk_root, module) if succeeded: - if is_mgmt_premium(module): - move_premium_samples(sdk_root, service, module) - update_azure_resourcemanager_pom(sdk_root, module, current_version) # For output breaking changes, useful in sdk validation pipeline logging.info("[Changelog] Start breaking change detection for SDK automation.") breaking, changelog, breaking_change_items = compare_with_maven_package( @@ -427,122 +422,6 @@ def update_changelog_version(sdk_root: str, output_folder: str, current_version: os.chdir(pwd) -def move_premium_samples(sdk_root: str, service: str, module: str): - package_path = "com/" + module.replace("-", "/") - source_sample_dir = os.path.join( - sdk_root, "sdk", service, module, "src", "samples", "java", package_path, "generated" - ) - target_sample_dir = os.path.join( - sdk_root, "sdk", "resourcemanager", "azure-resourcemanager", "src", "samples", "java", package_path - ) - logging.info(f"Moving samples from {source_sample_dir} to {target_sample_dir}.") - copy_folder_recursive_sync(source_sample_dir, target_sample_dir) - shutil.rmtree(source_sample_dir, ignore_errors=True) - - -def update_azure_resourcemanager_pom(sdk_root: str, module: str, current_version: str): - """ - Updates azure-resourcemanager pom for premium package split: - 1. Add unreleased entry in eng/versioning/version_client.txt - 2. Update dependency in azure-resourcemanager/pom.xml to use unreleased dependency - """ - # 1. Add unreleased entry to version_client.txt - version_file = os.path.join(sdk_root, "eng/versioning/version_client.txt") - group_id = "com.azure.resourcemanager" - project = "{0}:{1}".format(group_id, module) - - # Check if unreleased entry already exists - unreleased_project = "unreleased_{0}".format(project) - unreleased_exists = False - with open(version_file, "r", encoding="utf-8") as fin: - content = fin.read() - if unreleased_project in content: - unreleased_exists = True - logging.info("[UNRELEASED][Skip] Unreleased entry already exists for %s", module) - - if not unreleased_exists: - # Find the unreleased section and add the entry - with open(version_file, "r", encoding="utf-8") as fin: - lines = fin.read().splitlines() - - # Find the unreleased section start - unreleased_section_start = -1 - for i, line in enumerate(lines): - if "# Unreleased dependencies:" in line: - unreleased_section_start = i - break - - if unreleased_section_start == -1: - logging.error("[UNRELEASED][Skip] Cannot find unreleased section in version_client.txt") - return - - # Determine insertion point: append to the end of the unreleased section - # by locating the first blank line after the last 'unreleased_' entry. - last_unreleased_idx = -1 - end_of_section_idx = -1 - seen_unreleased = False - for i in range(unreleased_section_start + 1, len(lines)): - line = lines[i] - if line.startswith("unreleased_"): - seen_unreleased = True - last_unreleased_idx = i - continue - if seen_unreleased: - # First blank line after we started seeing unreleased entries marks end of section - if line.strip() == "": - end_of_section_idx = i # insert before this blank line - break - # Or a new header line also marks the end - if line.startswith("# "): - end_of_section_idx = i - break - - if last_unreleased_idx != -1: - insert_index = end_of_section_idx if end_of_section_idx != -1 else last_unreleased_idx + 1 - else: - # No existing unreleased entries, insert after header comments and optional blank line - insert_index = unreleased_section_start + 1 - while insert_index < len(lines) and lines[insert_index].startswith("#"): - insert_index += 1 - if insert_index < len(lines) and lines[insert_index].strip() == "": - insert_index += 1 - - # Insert the unreleased entry - unreleased_entry = "unreleased_{0};{1}".format(project, current_version) - lines.insert(insert_index, unreleased_entry) - - with open(version_file, "w", encoding="utf-8") as fout: - fout.write("\n".join(lines)) - fout.write("\n") - - logging.info("[UNRELEASED][Success] Added unreleased entry: %s", unreleased_entry) - - # 2. Update azure-resourcemanager pom.xml - pom_file = os.path.join(sdk_root, "sdk/resourcemanager/azure-resourcemanager/pom.xml") - if not os.path.exists(pom_file): - logging.error("[POM][Skip] Cannot find azure-resourcemanager pom.xml") - return - - with open(pom_file, "r", encoding="utf-8") as fin: - pom_content = fin.read() - - # Pattern to find the dependency and its version comment - dependency_pattern = r"({0}\s*{1}\s*)[^<]+(\s*)".format( - re.escape(group_id), re.escape(module), re.escape(project) - ) - - # Replace current with unreleased dependency - replacement = r"\g<1>" + current_version + r"\g<2>unreleased_" + project + r"\g<3>" - updated_pom_content = re.sub(dependency_pattern, replacement, pom_content, flags=re.DOTALL) - - if updated_pom_content != pom_content: - with open(pom_file, "w", encoding="utf-8") as fout: - fout.write(updated_pom_content) - logging.info("[POM][Success] Updated azure-resourcemanager pom.xml to use unreleased dependency of %s", module) - else: - logging.warning("[POM][Skip] Could not find dependency for %s in azure-resourcemanager pom.xml", module) - - def main(): (parser, args) = parse_args() args = vars(args) @@ -553,7 +432,6 @@ def main(): base_dir = os.path.abspath(os.path.dirname(sys.argv[0])) sdk_root = os.path.abspath(os.path.join(base_dir, SDK_ROOT)) api_specs_file = os.path.join(base_dir, API_SPECS_FILE) - premium = False if args.get("tsp_config"): tsp_config = args["tsp_config"] @@ -562,8 +440,6 @@ def main(): tsp_project=tsp_config, sdk_root=sdk_root, remove_before_regen=True, group_id=GROUP_ID, **args ) - premium = is_mgmt_premium(module) - stable_version, current_version = set_or_increase_version(sdk_root, GROUP_ID, module, **args) args["version"] = current_version @@ -612,9 +488,6 @@ def main(): if succeeded: succeeded = compile_arm_package(sdk_root, module) if succeeded: - if premium: - move_premium_samples(sdk_root, service, module) - update_azure_resourcemanager_pom(sdk_root, module, current_version) latest_release_version = get_latest_release_version(stable_version, current_version) compare_with_maven_package(sdk_root, GROUP_ID, service, latest_release_version, current_version, module) diff --git a/sdk/resourcemanager/gulpfile.js b/sdk/resourcemanager/gulpfile.js index 2673b70c8513..4247241399e4 100644 --- a/sdk/resourcemanager/gulpfile.js +++ b/sdk/resourcemanager/gulpfile.js @@ -14,167 +14,6 @@ var exec = require("child_process").exec; const mappings = require("./api-specs.json"); const defaultSpecRoot = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main"; -const repoRoot = path.resolve(__dirname, "../.."); - -// Get current version from eng/versioning/version_client.txt normal entry -function getCurrentVersionForArtifact(artifactId) { - try { - const versionClientPath = path.resolve(repoRoot, "eng/versioning/version_client.txt"); - if (!fs.existsSync(versionClientPath)) { - return undefined; - } - const content = fs.readFileSync(versionClientPath, "utf8"); - const lines = content.split(/\r?\n/); - const normalPrefix = `com.azure.resourcemanager:${artifactId};`; - const normalLine = lines.find((l) => l.startsWith(normalPrefix)); - if (!normalLine) return undefined; - const parts = normalLine.split(";"); - return parts.length >= 3 ? parts[2].trim() : undefined; - } catch (_) { - return undefined; - } -} - -// Determine whether project has been split to sdk/{service} -function isSplitProject(project) { - const dir = mappings[project] && mappings[project].dir; - if (!dir) return false; - // Split projects use ../{service}/azure-resourcemanager-xxx - // Exclude ../resourcemanagerhybrid - return /^\.\.\/(?!resourcemanagerhybrid\/).+/.test(dir); -} - -// ensure unreleased entry exists in eng/versioning/version_client.txt -function ensureUnreleasedVersionClientEntry(artifactId) { - try { - const versionClientPath = path.resolve(repoRoot, "eng/versioning/version_client.txt"); - if (!fs.existsSync(versionClientPath)) { - console.warn(`version_client.txt not found at ${versionClientPath}`); - return; - } - const content = fs.readFileSync(versionClientPath, "utf8"); - const lines = content.split(/\r?\n/); - - const unreleasedPrefix = `unreleased_com.azure.resourcemanager:${artifactId};`; - const normalPrefix = `com.azure.resourcemanager:${artifactId};`; - - // If unreleased entry already exists, nothing to do - if (lines.some((l) => l.startsWith(unreleasedPrefix))) { - return; - } - - // Find normal line to get current version (the 3rd semicolon-delimited token) - const normalLine = lines.find((l) => l.startsWith(normalPrefix)); - if (!normalLine) { - console.warn(`Normal version entry for ${artifactId} not found in version_client.txt`); - return; - } - const parts = normalLine.split(";"); - // Expected: group:artifact;released;current - let currentVersion = parts.length >= 3 ? parts[2].trim() : ""; - if (!currentVersion) { - console.warn(`Unable to parse current version for ${artifactId} from: ${normalLine}`); - return; - } - - const newLine = `${unreleasedPrefix}${currentVersion}`; - - // Insert within the Unreleased dependencies section using the blank line after the last unreleased_ entry - const unreleasedHeaderIndex = lines.findIndex((l) => l.startsWith("# Unreleased dependencies")); - if (unreleasedHeaderIndex !== -1) { - // Scan for the unreleased block and blank line after it - let lastUnreleasedIdx = -1; - let endOfSectionIdx = -1; - let seenUnreleased = false; - for (let i = unreleasedHeaderIndex + 1; i < lines.length; i++) { - const line = lines[i]; - if (line.startsWith("unreleased_")) { - seenUnreleased = true; - lastUnreleasedIdx = i; - continue; - } - if (seenUnreleased) { - // First blank line after we started seeing unreleased entries marks end of section - if (line.trim() === "") { - endOfSectionIdx = i; // insert before this blank line - break; - } - // If not blank, but a new header starts, still treat as end of section - if (line.startsWith("# ")) { - endOfSectionIdx = i; - break; - } - } - } - - let insertIndex; - if (lastUnreleasedIdx !== -1) { - // There are existing unreleased entries - insertIndex = endOfSectionIdx !== -1 ? endOfSectionIdx : lastUnreleasedIdx + 1; - } else { - // No existing entries, insert after header comments and the following blank line if present - insertIndex = unreleasedHeaderIndex + 1; - // Skip comment lines immediately following the header - while (insertIndex < lines.length && lines[insertIndex].startsWith("#")) insertIndex++; - // If next is a blank line, insert after it to keep formatting clean - if (insertIndex < lines.length && lines[insertIndex].trim() === "") insertIndex++; - } - - lines.splice(insertIndex, 0, newLine); - const updated = lines.join("\n"); - fs.writeFileSync(versionClientPath, updated.endsWith("\n") ? updated : updated + "\n", "utf8"); - } else { - // Fallback: append at end of file - const updated = content.endsWith("\n") ? content + newLine + "\n" : content + "\n" + newLine + "\n"; - fs.writeFileSync(versionClientPath, updated, "utf8"); - } - console.log(`Added unreleased entry to version_client.txt: ${newLine}`); - } catch (e) { - console.warn(`Failed to update version_client.txt for ${artifactId}: ${e && e.message ? e.message : e}`); - } -} - -// Update sdk/resourcemanager/azure-resourcemanager/pom.xml to refer to the package by unreleased version -function updateAggregatorPomUnreleased(artifactId) { - try { - const pomPath = path.resolve(__dirname, "azure-resourcemanager/pom.xml"); - if (!fs.existsSync(pomPath)) { - console.warn(`azure-resourcemanager/pom.xml not found at ${pomPath}`); - return; - } - let pom = fs.readFileSync(pomPath, "utf8"); - - // Only update if this artifact is referenced - const artifactRef = `${artifactId}`; - if (pom.indexOf(artifactRef) === -1) { - return; // dependency not present in aggregator pom - } - - // Update the x-version-update comment target to unreleased_ for this artifact - const currentVersion = getCurrentVersionForArtifact(artifactId); - if (currentVersion) { - const groupId = "com.azure.resourcemanager"; - const project = `${groupId}:${artifactId}`; - // Match either existing or already-unreleased marker in the version update comment - const dependencyPattern = new RegExp( - `(com.azure.resourcemanager\\s*${artifactId}\\s*)[^<]+(\\s*)`, - 'gs' - ); - - newPom = pom.replace( - dependencyPattern, - (_, g1, g2, g3) => `${g1}${currentVersion}${g2}unreleased_${project}${g3}` - ); - } - - if (newPom !== pom) { - fs.writeFileSync(pomPath, newPom, "utf8"); - console.log(`Updated azure-resourcemanager/pom.xml to use unreleased reference for ${artifactId} with version ${currentVersion || "(unchanged)"}`); - } - } catch (e) { - console.warn(`Failed to update azure-resourcemanager/pom.xml for ${artifactId}: ${e && e.message ? e.message : e}`); - } -} async function defaultInfo() { console.log( @@ -273,9 +112,6 @@ function codegen(project, cb) { const sourcesToDelete = path.join(mappings[project].dir, "/src/main/java/", packagePath); deleteFolderRecursive(sourcesToDelete); - - generatedSamplesTarget = path.join("azure-resourcemanager/src/samples/java/", packagePath, "generated"); - deleteFolderRecursive(generatedSamplesTarget); } // path.join won't work if specRoot is a URL @@ -324,20 +160,6 @@ function codegen(project, cb) { console.log("Command: " + cmd); autorest_result = execa.sync(cmd, [], { shell: true, stdio: "inherit" }); - // move generated samples to azure-resourcemanager - generatedSamplesSource = path.join(mappings[project].dir, "/src/samples/java/", packagePath, "generated"); - generatedSamplesTarget = path.join("azure-resourcemanager/src/samples/java/", packagePath); - - copyFolderRecursiveSync(generatedSamplesSource, generatedSamplesTarget); - deleteFolderRecursive(generatedSamplesSource); - - // If already split, ensure version_client and pom updates - if (isSplitProject(project)) { - const artifactId = path.basename(path.resolve(mappings[project].dir)); // e.g., azure-resourcemanager-search - ensureUnreleasedVersionClientEntry(artifactId); - updateAggregatorPomUnreleased(artifactId); - } - return autorest_result; } @@ -360,44 +182,6 @@ function deleteFolderRecursive(path) { } } -function copyFileSync(source, target) { - var targetFile = target; - - // If target is a directory, a new file with the same name will be created - if (fs.existsSync(target)) { - if (fs.lstatSync(target).isDirectory()) { - targetFile = path.join(target, path.basename(source)); - } - } - - fs.writeFileSync(targetFile, fs.readFileSync(source)); -} - -function copyFolderRecursiveSync(source, target) { - if (fs.existsSync(source)) { - var files = []; - - // Check if folder needs to be created or integrated - var targetFolder = path.join(target, path.basename(source)); - if (!fs.existsSync(targetFolder)) { - fs.mkdirSync(targetFolder, { recursive: true }); - } - - // Copy - if (fs.lstatSync(source).isDirectory()) { - files = fs.readdirSync(source); - files.forEach(function (file) { - var curSource = path.join(source, file); - if (fs.lstatSync(curSource).isDirectory()) { - copyFolderRecursiveSync(curSource, targetFolder); - } else { - copyFileSync(curSource, targetFolder); - } - }); - } - } -} - async function prepareBuild() { return shell.task("mvn package javadoc:aggregate -DskipTests -q"); }