Skip to content

Commit ef9e3ea

Browse files
XiaofeiCaoCopilot
andauthored
mgmt premium generation, update azure-resourcemanager/pom.xml to use unreleased of the split package (#46416)
* update generate.py python * update gulpfile.js * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 72b5d03 commit ef9e3ea

File tree

2 files changed

+274
-0
lines changed

2 files changed

+274
-0
lines changed

eng/automation/generate.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
338338
if succeeded:
339339
if is_mgmt_premium(module):
340340
move_premium_samples(sdk_root, service, module)
341+
update_azure_resourcemanager_pom(sdk_root, service, module)
341342
logging.info("[Changelog] Start breaking change detection for SDK automation.")
342343
breaking, changelog, breaking_change_items = compare_with_maven_package(
343344
sdk_root,
@@ -432,6 +433,109 @@ def move_premium_samples(sdk_root: str, service: str, module: str):
432433
shutil.rmtree(source_sample_dir, ignore_errors=True)
433434

434435

436+
def update_azure_resourcemanager_pom(sdk_root: str, module: str, current_version: str):
437+
"""
438+
Updates azure-resourcemanager pom for premium package split:
439+
1. Add unreleased entry in eng/versioning/version_client.txt
440+
2. Update dependency in azure-resourcemanager/pom.xml to use unreleased dependency
441+
"""
442+
# 1. Add unreleased entry to version_client.txt
443+
version_file = os.path.join(sdk_root, "eng/versioning/version_client.txt")
444+
group_id = "com.azure.resourcemanager"
445+
project = "{0}:{1}".format(group_id, module)
446+
447+
# Check if unreleased entry already exists
448+
unreleased_project = "unreleased_{0}".format(project)
449+
unreleased_exists = False
450+
with open(version_file, "r", encoding="utf-8") as fin:
451+
content = fin.read()
452+
if unreleased_project in content:
453+
unreleased_exists = True
454+
logging.info("[UNRELEASED][Skip] Unreleased entry already exists for %s", module)
455+
456+
if not unreleased_exists:
457+
# Find the unreleased section and add the entry
458+
with open(version_file, "r", encoding="utf-8") as fin:
459+
lines = fin.read().splitlines()
460+
461+
# Find the unreleased section start
462+
unreleased_section_start = -1
463+
for i, line in enumerate(lines):
464+
if "# Unreleased dependencies:" in line:
465+
unreleased_section_start = i
466+
break
467+
468+
if unreleased_section_start == -1:
469+
logging.error("[UNRELEASED][Skip] Cannot find unreleased section in version_client.txt")
470+
return
471+
472+
# Determine insertion point: append to the end of the unreleased section
473+
# by locating the first blank line after the last 'unreleased_' entry.
474+
last_unreleased_idx = -1
475+
end_of_section_idx = -1
476+
seen_unreleased = False
477+
for i in range(unreleased_section_start + 1, len(lines)):
478+
line = lines[i]
479+
if line.startswith("unreleased_"):
480+
seen_unreleased = True
481+
last_unreleased_idx = i
482+
continue
483+
if seen_unreleased:
484+
# First blank line after we started seeing unreleased entries marks end of section
485+
if line.strip() == "":
486+
end_of_section_idx = i # insert before this blank line
487+
break
488+
# Or a new header line also marks the end
489+
if line.startswith("# "):
490+
end_of_section_idx = i
491+
break
492+
493+
if last_unreleased_idx != -1:
494+
insert_index = end_of_section_idx if end_of_section_idx != -1 else last_unreleased_idx + 1
495+
else:
496+
# No existing unreleased entries, insert after header comments and optional blank line
497+
insert_index = unreleased_section_start + 1
498+
while insert_index < len(lines) and lines[insert_index].startswith("#"):
499+
insert_index += 1
500+
if insert_index < len(lines) and lines[insert_index].strip() == "":
501+
insert_index += 1
502+
503+
# Insert the unreleased entry
504+
unreleased_entry = "unreleased_{0};{1}".format(project, current_version)
505+
lines.insert(insert_index, unreleased_entry)
506+
507+
with open(version_file, "w", encoding="utf-8") as fout:
508+
fout.write("\n".join(lines))
509+
fout.write("\n")
510+
511+
logging.info("[UNRELEASED][Success] Added unreleased entry: %s", unreleased_entry)
512+
513+
# 2. Update azure-resourcemanager pom.xml
514+
pom_file = os.path.join(sdk_root, "sdk/resourcemanager/azure-resourcemanager/pom.xml")
515+
if not os.path.exists(pom_file):
516+
logging.error("[POM][Skip] Cannot find azure-resourcemanager pom.xml")
517+
return
518+
519+
with open(pom_file, "r", encoding="utf-8") as fin:
520+
pom_content = fin.read()
521+
522+
# Pattern to find the dependency and its version comment
523+
dependency_pattern = r"(<groupId>{0}</groupId>\s*<artifactId>{1}</artifactId>\s*<version>)[^<]+(</version>\s*<!-- {{x-version-update;){2}(;dependency}} -->)".format(
524+
re.escape(group_id), re.escape(module), re.escape(project)
525+
)
526+
527+
# Replace current with unreleased dependency
528+
replacement = r"\g<1>" + current_version + r"\g<2>unreleased_" + project + r"\g<3>"
529+
updated_pom_content = re.sub(dependency_pattern, replacement, pom_content, flags=re.DOTALL)
530+
531+
if updated_pom_content != pom_content:
532+
with open(pom_file, "w", encoding="utf-8") as fout:
533+
fout.write(updated_pom_content)
534+
logging.info("[POM][Success] Updated azure-resourcemanager pom.xml to use unreleased dependency of %s", module)
535+
else:
536+
logging.warning("[POM][Skip] Could not find dependency for %s in azure-resourcemanager pom.xml", module)
537+
538+
435539
def main():
436540
(parser, args) = parse_args()
437541
args = vars(args)
@@ -490,6 +594,7 @@ def main():
490594
service = get_and_update_service_from_api_specs(api_specs_file, spec, args["service"], suffix)
491595
args["service"] = service
492596
module = ARTIFACT_FORMAT.format(service)
597+
premium = is_mgmt_premium(module)
493598
stable_version, current_version = set_or_increase_version(sdk_root, GROUP_ID, module, **args)
494599
args["version"] = current_version
495600
output_folder = OUTPUT_FOLDER_FORMAT.format(service)
@@ -503,6 +608,7 @@ def main():
503608
if succeeded:
504609
if premium:
505610
move_premium_samples(sdk_root, service, module)
611+
update_azure_resourcemanager_pom(sdk_root, module, current_version)
506612
latest_release_version = get_latest_release_version(stable_version, current_version)
507613
compare_with_maven_package(sdk_root, GROUP_ID, service, latest_release_version, current_version, module)
508614

sdk/resourcemanager/gulpfile.js

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,167 @@ var exec = require("child_process").exec;
1414

1515
const mappings = require("./api-specs.json");
1616
const defaultSpecRoot = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main";
17+
const repoRoot = path.resolve(__dirname, "../..");
18+
19+
// Get current version from eng/versioning/version_client.txt normal entry
20+
function getCurrentVersionForArtifact(artifactId) {
21+
try {
22+
const versionClientPath = path.resolve(repoRoot, "eng/versioning/version_client.txt");
23+
if (!fs.existsSync(versionClientPath)) {
24+
return undefined;
25+
}
26+
const content = fs.readFileSync(versionClientPath, "utf8");
27+
const lines = content.split(/\r?\n/);
28+
const normalPrefix = `com.azure.resourcemanager:${artifactId};`;
29+
const normalLine = lines.find((l) => l.startsWith(normalPrefix));
30+
if (!normalLine) return undefined;
31+
const parts = normalLine.split(";");
32+
return parts.length >= 3 ? parts[2].trim() : undefined;
33+
} catch (_) {
34+
return undefined;
35+
}
36+
}
37+
38+
// Determine whether project has been split to sdk/{service}
39+
function isSplitProject(project) {
40+
const dir = mappings[project] && mappings[project].dir;
41+
if (!dir) return false;
42+
// Split projects use ../{service}/azure-resourcemanager-xxx
43+
// Exclude ../resourcemanagerhybrid
44+
return /^\.\.\/(?!resourcemanagerhybrid\/).+/.test(dir);
45+
}
46+
47+
// ensure unreleased entry exists in eng/versioning/version_client.txt
48+
function ensureUnreleasedVersionClientEntry(artifactId) {
49+
try {
50+
const versionClientPath = path.resolve(repoRoot, "eng/versioning/version_client.txt");
51+
if (!fs.existsSync(versionClientPath)) {
52+
console.warn(`version_client.txt not found at ${versionClientPath}`);
53+
return;
54+
}
55+
const content = fs.readFileSync(versionClientPath, "utf8");
56+
const lines = content.split(/\r?\n/);
57+
58+
const unreleasedPrefix = `unreleased_com.azure.resourcemanager:${artifactId};`;
59+
const normalPrefix = `com.azure.resourcemanager:${artifactId};`;
60+
61+
// If unreleased entry already exists, nothing to do
62+
if (lines.some((l) => l.startsWith(unreleasedPrefix))) {
63+
return;
64+
}
65+
66+
// Find normal line to get current version (the 3rd semicolon-delimited token)
67+
const normalLine = lines.find((l) => l.startsWith(normalPrefix));
68+
if (!normalLine) {
69+
console.warn(`Normal version entry for ${artifactId} not found in version_client.txt`);
70+
return;
71+
}
72+
const parts = normalLine.split(";");
73+
// Expected: group:artifact;released;current
74+
let currentVersion = parts.length >= 3 ? parts[2].trim() : "";
75+
if (!currentVersion) {
76+
console.warn(`Unable to parse current version for ${artifactId} from: ${normalLine}`);
77+
return;
78+
}
79+
80+
const newLine = `${unreleasedPrefix}${currentVersion}`;
81+
82+
// Insert within the Unreleased dependencies section using the blank line after the last unreleased_ entry
83+
const unreleasedHeaderIndex = lines.findIndex((l) => l.startsWith("# Unreleased dependencies"));
84+
if (unreleasedHeaderIndex !== -1) {
85+
// Scan for the unreleased block and blank line after it
86+
let lastUnreleasedIdx = -1;
87+
let endOfSectionIdx = -1;
88+
let seenUnreleased = false;
89+
for (let i = unreleasedHeaderIndex + 1; i < lines.length; i++) {
90+
const line = lines[i];
91+
if (line.startsWith("unreleased_")) {
92+
seenUnreleased = true;
93+
lastUnreleasedIdx = i;
94+
continue;
95+
}
96+
if (seenUnreleased) {
97+
// First blank line after we started seeing unreleased entries marks end of section
98+
if (line.trim() === "") {
99+
endOfSectionIdx = i; // insert before this blank line
100+
break;
101+
}
102+
// If not blank, but a new header starts, still treat as end of section
103+
if (line.startsWith("# ")) {
104+
endOfSectionIdx = i;
105+
break;
106+
}
107+
}
108+
}
109+
110+
let insertIndex;
111+
if (lastUnreleasedIdx !== -1) {
112+
// There are existing unreleased entries
113+
insertIndex = endOfSectionIdx !== -1 ? endOfSectionIdx : lastUnreleasedIdx + 1;
114+
} else {
115+
// No existing entries, insert after header comments and the following blank line if present
116+
insertIndex = unreleasedHeaderIndex + 1;
117+
// Skip comment lines immediately following the header
118+
while (insertIndex < lines.length && lines[insertIndex].startsWith("#")) insertIndex++;
119+
// If next is a blank line, insert after it to keep formatting clean
120+
if (insertIndex < lines.length && lines[insertIndex].trim() === "") insertIndex++;
121+
}
122+
123+
lines.splice(insertIndex, 0, newLine);
124+
const updated = lines.join("\n");
125+
fs.writeFileSync(versionClientPath, updated.endsWith("\n") ? updated : updated + "\n", "utf8");
126+
} else {
127+
// Fallback: append at end of file
128+
const updated = content.endsWith("\n") ? content + newLine + "\n" : content + "\n" + newLine + "\n";
129+
fs.writeFileSync(versionClientPath, updated, "utf8");
130+
}
131+
console.log(`Added unreleased entry to version_client.txt: ${newLine}`);
132+
} catch (e) {
133+
console.warn(`Failed to update version_client.txt for ${artifactId}: ${e && e.message ? e.message : e}`);
134+
}
135+
}
136+
137+
// Update sdk/resourcemanager/azure-resourcemanager/pom.xml to refer to the package by unreleased version
138+
function updateAggregatorPomUnreleased(artifactId) {
139+
try {
140+
const pomPath = path.resolve(__dirname, "azure-resourcemanager/pom.xml");
141+
if (!fs.existsSync(pomPath)) {
142+
console.warn(`azure-resourcemanager/pom.xml not found at ${pomPath}`);
143+
return;
144+
}
145+
let pom = fs.readFileSync(pomPath, "utf8");
146+
147+
// Only update if this artifact is referenced
148+
const artifactRef = `<artifactId>${artifactId}</artifactId>`;
149+
if (pom.indexOf(artifactRef) === -1) {
150+
return; // dependency not present in aggregator pom
151+
}
152+
153+
// Update the x-version-update comment target to unreleased_ for this artifact
154+
const currentVersion = getCurrentVersionForArtifact(artifactId);
155+
if (currentVersion) {
156+
const groupId = "com.azure.resourcemanager";
157+
const project = `${groupId}:${artifactId}`;
158+
// Match either existing or already-unreleased marker in the version update comment
159+
const dependencyPattern = new RegExp(
160+
`(<groupId>com.azure.resourcemanager</groupId>\\s*<artifactId>${artifactId}</artifactId>\\s*<version>)[^<]+(</version>\\s*<!-- \\{x-version-update;)(?:unreleased_)?${project}(;dependency\\} -->)`,
161+
'gs'
162+
);
163+
164+
newPom = pom.replace(
165+
dependencyPattern,
166+
(_, g1, g2, g3) => `${g1}${currentVersion}${g2}unreleased_${project}${g3}`
167+
);
168+
}
169+
170+
if (newPom !== pom) {
171+
fs.writeFileSync(pomPath, newPom, "utf8");
172+
console.log(`Updated azure-resourcemanager/pom.xml to use unreleased reference for ${artifactId} with version ${currentVersion || "(unchanged)"}`);
173+
}
174+
} catch (e) {
175+
console.warn(`Failed to update azure-resourcemanager/pom.xml for ${artifactId}: ${e && e.message ? e.message : e}`);
176+
}
177+
}
17178

18179
async function defaultInfo() {
19180
console.log(
@@ -170,6 +331,13 @@ function codegen(project, cb) {
170331
copyFolderRecursiveSync(generatedSamplesSource, generatedSamplesTarget);
171332
deleteFolderRecursive(generatedSamplesSource);
172333

334+
// If already split, ensure version_client and pom updates
335+
if (isSplitProject(project)) {
336+
const artifactId = path.basename(path.resolve(mappings[project].dir)); // e.g., azure-resourcemanager-search
337+
ensureUnreleasedVersionClientEntry(artifactId);
338+
updateAggregatorPomUnreleased(artifactId);
339+
}
340+
173341
return autorest_result;
174342
}
175343

0 commit comments

Comments
 (0)