Skip to content

Commit 8337dcd

Browse files
committed
merge from main and resolve conflicts
2 parents 73b65c4 + 822df77 commit 8337dcd

8,124 files changed

Lines changed: 399847 additions & 219330 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/hooks/hooks.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"hooks": {
3+
"PostToolUse": [
4+
{
5+
"type": "command",
6+
"command": "pwsh eng/common/scripts/azsdk_tool_telemetry.ps1",
7+
"timeoutSec": 5
8+
}
9+
]
10+
}
11+
}

.github/workflows/event-processor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
run: >
6969
dotnet tool install
7070
Azure.Sdk.Tools.GitHubEventProcessor
71-
--version 1.0.0-dev.20260129.1
71+
--version 1.0.0-dev.20260403.1
7272
--add-source https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json
7373
--global
7474
shell: bash

.github/workflows/post-apiview.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ permissions:
1111
jobs:
1212
post-apiview:
1313
name: After APIView
14-
runs-on: ["self-hosted", "1ES.Pool=azsdk-pool-github-runners"]
14+
runs-on: ["self-hosted", "1ES.Pool=azsdk-pool-github-runners", "JobId=azsdk-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}"]
1515
if: |
1616
toJson(github.event.check_run.pull_requests) != '[]' &&
1717
github.event.check_run.check_suite.app.name == 'Azure Pipelines' && (

.github/workflows/scheduled-event-processor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
run: >
4040
dotnet tool install
4141
Azure.Sdk.Tools.GitHubEventProcessor
42-
--version 1.0.0-dev.20260129.1
42+
--version 1.0.0-dev.20260403.1
4343
--add-source https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json
4444
--global
4545
shell: bash

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,6 @@ stress-test-addons*
126126

127127
# Temp typespec files
128128
TempTypeSpecFiles/
129+
130+
# Azure Artifacts Credential Provider runtime
131+
.azure-artifacts/

CONTRIBUTING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ For detailed instructions, refer to the [Maven Credential Provider documentation
125125

126126
> **Note:** For Maven Azure DevOps pipeline authentication, use the [MavenAuthenticate@0](https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/maven-authenticate-v0) pipeline task.
127127
128+
##### Matching CI behavior locally
129+
130+
All Maven dependency and artifact resolution already uses the Azure Artifacts feed by default via `<repositories>` declarations in the project POMs. However, Maven plugins and extensions do not honor POM-level repositories. To route plugin traffic through the Azure Artifacts feed as well (matching CI behavior), copy the mirror settings:
131+
132+
```bash
133+
cp eng/settings.xml ~/.m2/settings.xml
134+
```
135+
128136
##### Troubleshooting 401 Unauthorized errors
129137

130138
If you encounter a `401 Unauthorized` error when running Maven commands:

NuGet.Config

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<clear />
5+
<!-- Do not add any additional feeds. If new packages are needed they need to
6+
come from the azure-sdk-for-net DevOps feed which has an upstream set to nuget.org -->
7+
<add key="azure-sdk-for-net" value="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" />
8+
</packageSources>
9+
<disabledPackageSources>
10+
<clear />
11+
</disabledPackageSources>
12+
</configuration>

eng/automation/generate.py

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -277,17 +277,68 @@ def sdk_automation_typespec(config: dict) -> List[dict]:
277277
return packages
278278

279279

280-
def verify_self_serve_parameters(api_version, sdk_release_type):
281-
if sdk_release_type and sdk_release_type not in ["stable", "beta"]:
282-
raise ValueError(f"Invalid SDK release type [{sdk_release_type}], only support 'stable' or 'beta'.")
283-
if api_version and sdk_release_type:
284-
if api_version.endswith("-preview") and sdk_release_type == "stable":
285-
raise ValueError(f"SDK release type is [stable], but API version [{api_version}] is preview.")
286-
logging.info(f"[SelfServe] Generate with apiVersion: {api_version} and sdkReleaseType: {sdk_release_type}")
287-
elif api_version or sdk_release_type:
288-
raise ValueError(
289-
"Both [API version] and [SDK release type] parameters are required for self-serve SDK generation."
290-
)
280+
def infer_sdk_release_type(sdk_root: str, sdk_folder: str, module: str) -> str:
281+
"""Infer SDK release type from the generated metadata JSON.
282+
283+
Reads {sdk_root}/{sdk_folder}/src/main/resources/META-INF/{module}_metadata.json
284+
and inspects the apiVersions values:
285+
- All GA (no 'preview' substring) -> 'stable'
286+
- Any preview or mixed -> 'beta'
287+
- Fallback on error -> 'beta' (safe default)
288+
"""
289+
metadata_path = os.path.join(sdk_root, sdk_folder, "src", "main", "resources", "META-INF", f"{module}_metadata.json")
290+
try:
291+
with open(metadata_path, "r") as f:
292+
metadata = json.load(f)
293+
api_versions = metadata.get("apiVersions", {})
294+
if not api_versions:
295+
logging.warning(f"[SelfServe] No apiVersions found in {metadata_path}, defaulting to beta.")
296+
return "beta"
297+
298+
has_preview = any("preview" in v.lower() for v in api_versions.values())
299+
inferred = "beta" if has_preview else "stable"
300+
logging.info(f"[SelfServe] Inferred sdkReleaseType={inferred} from apiVersions: {api_versions}")
301+
return inferred
302+
except FileNotFoundError:
303+
logging.warning(f"[SelfServe] Metadata file not found: {metadata_path}, defaulting to beta.")
304+
return "beta"
305+
except Exception as e:
306+
logging.warning(f"[SelfServe] Failed to read metadata file {metadata_path}: {e}, defaulting to beta.")
307+
return "beta"
308+
309+
310+
def update_revapi_skip(pom_path: str, beta: bool):
311+
"""Update revapi.skip property in pom.xml based on release type.
312+
313+
beta=True: ensure <revapi.skip>true</revapi.skip> (add if missing, flip if false)
314+
beta=False: flip <revapi.skip>true</revapi.skip> to false if present (skip if absent, as false is default)
315+
"""
316+
try:
317+
with open(pom_path, "r") as f:
318+
content = f.read()
319+
if beta:
320+
if "<revapi.skip>true</revapi.skip>" in content:
321+
return
322+
if "<revapi.skip>false</revapi.skip>" in content:
323+
new_content = content.replace("<revapi.skip>false</revapi.skip>", "<revapi.skip>true</revapi.skip>")
324+
logging.info(f"[SelfServe] Changed revapi.skip to true in {pom_path}")
325+
else:
326+
new_content = re.sub(
327+
r'([ \t]*)</properties>',
328+
r'\1 <revapi.skip>true</revapi.skip>\n\1</properties>',
329+
content,
330+
count=1,
331+
)
332+
logging.info(f"[SelfServe] Added revapi.skip=true to {pom_path}")
333+
else:
334+
if "<revapi.skip>true</revapi.skip>" not in content:
335+
return
336+
new_content = content.replace("<revapi.skip>true</revapi.skip>", "<revapi.skip>false</revapi.skip>")
337+
logging.info(f"[SelfServe] Changed revapi.skip to false in {pom_path}")
338+
with open(pom_path, "w") as f:
339+
f.write(new_content)
340+
except Exception as e:
341+
logging.warning(f"[SelfServe] Failed to update revapi.skip in {pom_path}: {e}")
291342

292343

293344
def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
@@ -299,14 +350,11 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
299350
repo_url: str = config["repoHttpsUrl"]
300351
sdk_release_type: str = config["sdkReleaseType"] if "sdkReleaseType" in config else None
301352
api_version = config["apiVersion"] if "apiVersion" in config else None
353+
# Generate with beta by default; will be corrected after inference if needed
302354
release_beta_sdk: bool = not sdk_release_type or sdk_release_type == "beta"
303355
breaking: bool = False
304356
changelog = ""
305357
breaking_change_items = []
306-
run_mode: str = config["runMode"] if "runMode" in config else None
307-
308-
if run_mode == "release" or run_mode == "local":
309-
verify_self_serve_parameters(api_version, sdk_release_type)
310358

311359
succeeded, require_sdk_integration, sdk_folder, service, module = generate_typespec_project(
312360
tsp_project,
@@ -317,10 +365,14 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
317365
remove_before_regen=True,
318366
group_id=GROUP_ID,
319367
api_version=api_version,
320-
generate_beta_sdk=release_beta_sdk,
321368
)
322369

323370
if succeeded:
371+
# Infer sdk release type from generated metadata when not explicitly provided
372+
if not sdk_release_type and sdk_folder and module:
373+
inferred_type = infer_sdk_release_type(sdk_root, sdk_folder, module)
374+
release_beta_sdk = inferred_type == "beta"
375+
324376
# TODO (weidxu): move to typespec-java
325377
if require_sdk_integration:
326378
update_service_files_for_new_lib(sdk_root, service, GROUP_ID, module)
@@ -332,6 +384,9 @@ def sdk_automation_typespec_project(tsp_project: str, config: dict) -> dict:
332384
output_folder = sdk_folder
333385
update_version(sdk_root, output_folder)
334386

387+
# Update revapi.skip based on release type
388+
update_revapi_skip(os.path.join(sdk_root, output_folder, "pom.xml"), beta=release_beta_sdk)
389+
335390
# compile
336391
succeeded = compile_arm_package(sdk_root, module)
337392
if succeeded:

eng/automation/generate_utils.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,6 @@ def generate_typespec_project(
532532
remove_before_regen: bool = False,
533533
group_id: str = None,
534534
api_version: str = None,
535-
generate_beta_sdk: bool = True,
536535
version: str = None, # SDK version
537536
disable_customization: bool = False,
538537
**kwargs,
@@ -610,10 +609,6 @@ def generate_typespec_project(
610609

611610
if remove_before_regen and group_id:
612611
remove_generated_source_code(os.path.join(sdk_root, sdk_folder), f"{group_id}.{service}")
613-
_, current_version = set_or_increase_version(
614-
sdk_root, group_id, module, version=version, preview=generate_beta_sdk
615-
)
616-
emitter_options.append(f"package-version={current_version}")
617612
if api_version:
618613
emitter_options.append(f"api-version={api_version}")
619614

eng/automation/test_generate.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import os
2+
import tempfile
3+
import unittest
4+
5+
from generate import update_revapi_skip
6+
7+
POM_WITH_REVAPI_TRUE = """\
8+
<project>
9+
<properties>
10+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
11+
<jacoco.min.linecoverage>0</jacoco.min.linecoverage>
12+
<revapi.skip>true</revapi.skip>
13+
</properties>
14+
</project>
15+
"""
16+
17+
POM_WITH_REVAPI_FALSE = """\
18+
<project>
19+
<properties>
20+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
21+
<jacoco.min.linecoverage>0</jacoco.min.linecoverage>
22+
<revapi.skip>false</revapi.skip>
23+
</properties>
24+
</project>
25+
"""
26+
27+
POM_WITHOUT_REVAPI = """\
28+
<project>
29+
<properties>
30+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
31+
<jacoco.min.linecoverage>0</jacoco.min.linecoverage>
32+
</properties>
33+
</project>
34+
"""
35+
36+
37+
class TestUpdateRevapiSkip(unittest.TestCase):
38+
39+
def _write_and_update(self, content: str, beta: bool) -> str:
40+
fd, path = tempfile.mkstemp(suffix=".xml")
41+
try:
42+
with os.fdopen(fd, "w") as f:
43+
f.write(content)
44+
update_revapi_skip(path, beta)
45+
with open(path, "r") as f:
46+
return f.read()
47+
finally:
48+
os.unlink(path)
49+
50+
# --- beta=True cases ---
51+
52+
def test_beta_already_true_no_change(self):
53+
result = self._write_and_update(POM_WITH_REVAPI_TRUE, beta=True)
54+
self.assertEqual(result, POM_WITH_REVAPI_TRUE)
55+
56+
def test_beta_false_flipped_to_true(self):
57+
result = self._write_and_update(POM_WITH_REVAPI_FALSE, beta=True)
58+
self.assertIn("<revapi.skip>true</revapi.skip>", result)
59+
self.assertNotIn("<revapi.skip>false</revapi.skip>", result)
60+
61+
def test_beta_missing_added_true(self):
62+
result = self._write_and_update(POM_WITHOUT_REVAPI, beta=True)
63+
self.assertIn("<revapi.skip>true</revapi.skip>", result)
64+
self.assertIn("</properties>", result)
65+
66+
# --- beta=False (stable) cases ---
67+
68+
def test_stable_true_flipped_to_false(self):
69+
result = self._write_and_update(POM_WITH_REVAPI_TRUE, beta=False)
70+
self.assertIn("<revapi.skip>false</revapi.skip>", result)
71+
self.assertNotIn("<revapi.skip>true</revapi.skip>", result)
72+
73+
def test_stable_already_false_no_change(self):
74+
result = self._write_and_update(POM_WITH_REVAPI_FALSE, beta=False)
75+
self.assertEqual(result, POM_WITH_REVAPI_FALSE)
76+
77+
def test_stable_missing_not_added(self):
78+
result = self._write_and_update(POM_WITHOUT_REVAPI, beta=False)
79+
self.assertNotIn("revapi.skip", result)
80+
self.assertEqual(result, POM_WITHOUT_REVAPI)
81+
82+
83+
if __name__ == "__main__":
84+
unittest.main()

0 commit comments

Comments
 (0)