Skip to content

Commit 1d65d7d

Browse files
authored
Merge branch 'main' into sdkauto/azure-mgmt-programenrollment-6420493
2 parents 203e906 + 89c1029 commit 1d65d7d

1,466 files changed

Lines changed: 251000 additions & 135932 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/CODEOWNERS

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@
235235
/sdk/durabletask/ @berndverst @cgillum @kaibocai @philliphoff @RyanLettieri @torosent
236236

237237
# PRLabel: %EngSys
238-
/sdk/template/ @benbp @scbedd @danieljurek @weshaggard
238+
/sdk/template/ @benbp @mikeharder @danieljurek
239239

240240
# PRLabel: %Evaluation
241241
/sdk/evaluation/ @Azure/azure-sdk-write-evaluation
@@ -810,33 +810,33 @@
810810
###########
811811
# Eng Sys and other
812812
###########
813-
/eng/ @scbedd @danieljurek @weshaggard @benbp
813+
/eng/ @danieljurek @mikeharder @benbp
814814
/eng/common/ @Azure/azure-sdk-eng
815-
/eng/tools/ @scbedd @danieljurek @mccoyp
815+
/eng/tools/ @danieljurek @mccoyp
816816
/.github/workflows/ @Azure/azure-sdk-eng
817817
/.github/workflows/typespec-python-regenerate.yml @Azure/azure-sdk-eng @tadelesh @msyyc @iscai-msft @ChenxiJiang333
818818
/.github/CODEOWNERS @lmazuel @kashifkhan @Azure/azure-sdk-eng
819819
/.github/copilot-instructions.md @l0lawrence @praveenkuttappan @maririos
820820
/.github/prompts/ @mccoyp @l0lawrence @benbp
821821
/.github/skills/ @mccoyp @l0lawrence @benbp
822-
/sdk/pullrequest.yml @scbedd @danieljurek @weshaggard @benbp
822+
/sdk/pullrequest.yml @danieljurek @mikeharder @benbp
823823

824-
/.config/1espt/ @benbp @weshaggard
825-
/.devcontainer/ @scbedd @danieljurek @mccoyp @benbp @weshaggard
826-
/.vscode/ @scbedd @danieljurek @mccoyp @benbp @weshaggard
824+
/.config/1espt/ @benbp @mikeharder
825+
/.devcontainer/ @danieljurek @mccoyp @benbp @mikeharder
826+
/.vscode/ @danieljurek @mccoyp @benbp @mikeharder
827827

828-
/scripts/ @scbedd @danieljurek @mccoyp
828+
/scripts/ @danieljurek @mccoyp
829829
/scripts/breaking_changes_checker/ @catalinaperalta
830-
/doc/ @scbedd @danieljurek @Azure/azure-python-sdk
831-
/conda/ @scbedd @danieljurek @lmazuel
830+
/doc/ @danieljurek @Azure/azure-python-sdk
831+
/conda/ @danieljurek @xiangyan99 @lmazuel
832832

833833
/shared_requirements.txt @azure/azure-sdk-eng @kashifkhan @xirzec
834834

835835
# Add owners for notifications for specific pipelines
836836
/eng/pipelines/templates/jobs/tests-nightly-python.yml @lmazuel @mccoyp
837837
/eng/pipelines/aggregate-reports.yml @lmazuel @mccoyp
838838
/eng/common/pipelines/codeowners-linter.yml @lmazuel @mccoyp
839-
/eng/pipelines/docindex.yml @danieljurek @scbedd @weshaggard @benbp
839+
/eng/pipelines/docindex.yml @danieljurek @benbp
840840

841841
# Add approvers for typespec-python emitter version updates
842842
/eng/emitter-package.json @mccoyp @catalinaperalta @iscai-msft @msyyc @ChenxiJiang333
@@ -845,8 +845,8 @@
845845
# TypeSpec Python generated tests and regeneration workflow
846846
/eng/tools/emitter/ @tadelesh @msyyc @iscai-msft @lmazuel @lirenhe @ChenxiJiang333
847847

848-
/pylintrc @l0lawrence @scbedd @danieljurek @mccoyp
849-
/sdk/**/ci.yml @msyyc @lmazuel @scbedd @danieljurek
848+
/pylintrc @l0lawrence @danieljurek @mccoyp
849+
/sdk/**/ci.yml @msyyc @lmazuel @danieljurek
850850

851851
# Add Johnathan Walker as code owner for Event Hubs SDK
852852
/sdk/eventhub/azure-eventhub/* @j7nw4r @SwayGom @sagar0207

.github/actionlint.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
self-hosted-runner:
2+
labels:
3+
- 1ES.Pool=azsdk-pool-github-runners

.github/matchers/actionlint.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"problemMatcher": [
3+
{
4+
"owner": "actionlint",
5+
"pattern": [
6+
{
7+
"regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$",
8+
"file": 1,
9+
"line": 2,
10+
"column": 3,
11+
"message": 4,
12+
"code": 5
13+
}
14+
]
15+
}
16+
]
17+
}

.github/shared/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# `.github/shared`
2+
3+
Copied from https://github.com/Azure/azure-rest-api-specs/tree/main/.github/shared

.github/shared/src/cache.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Caches values in memory with a single key of any type.
3+
*
4+
* @template K, V
5+
*/
6+
export class KeyedCache {
7+
/** @type {Map<K, V>} */
8+
#map = new Map();
9+
10+
/**
11+
* Returns cached value, initializing if necessary
12+
*
13+
* @param {K} key
14+
* @param {() => V} factory
15+
* @returns {V} cached value
16+
*
17+
* @example
18+
* const result = cache.getOrCreate(42, async () => await doWork(42));
19+
*/
20+
getOrCreate(key, factory) {
21+
let value = this.#map.get(key);
22+
23+
if (value === undefined) {
24+
value = factory();
25+
this.#map.set(key, value);
26+
}
27+
28+
return value;
29+
}
30+
}
31+
32+
/**
33+
* Caches values in memory with an ordered pair of keys of any types.
34+
*
35+
* @template K1, K2, V
36+
*/
37+
export class KeyedPairCache {
38+
// Two-layer nested cache
39+
/** @type {KeyedCache<K1, KeyedCache<K2, V>>} */
40+
#cache1 = new KeyedCache();
41+
42+
/**
43+
* Returns cached value, initializing if necessary.
44+
* Keys are ordered, so (key1, key2) != (key2, key1).
45+
*
46+
* @param {K1} key1
47+
* @param {K2} key2
48+
* @param {() => V} factory
49+
* @returns {V} cached value
50+
*
51+
* @example
52+
* const result = cache.getOrCreate(42, 7, async () => await doWork(42, 7));
53+
*/
54+
getOrCreate(key1, key2, factory) {
55+
// key1 => cache for the next layer
56+
const cache2 = this.#cache1.getOrCreate(key1, () => new KeyedCache());
57+
58+
// key2 => final value
59+
return cache2.getOrCreate(key2, factory);
60+
}
61+
}

.github/shared/src/exec.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import child_process from "child_process";
2+
import { dirname, join } from "path";
3+
import { promisify } from "util";
4+
const execFileImpl = promisify(child_process.execFile);
5+
6+
/**
7+
* @typedef {Object} ExecOptions
8+
* @property {string} [cwd] Current working directory. Default: process.cwd().
9+
* @property {import('./logger.js').ILogger} [logger]
10+
* @property {boolean} [logOutput] Log captured stdout/stderr at info level. Default: false.
11+
* @property {number} [maxBuffer] Max bytes allowed on stdout or stderr. Default: 16 * 1024 * 1024.
12+
*/
13+
14+
/**
15+
* @typedef {Object} NpmPrefixOptions
16+
* @property {string} [prefix] Prefix to pass to npm via "--prefix".
17+
*/
18+
19+
/**
20+
* @typedef {ExecOptions & NpmPrefixOptions} ExecNpmOptions
21+
*/
22+
23+
/**
24+
* @typedef {Object} ExecResult
25+
* @property {string} stdout
26+
* @property {string} stderr
27+
*/
28+
29+
/**
30+
* @typedef {Error & { stdout?: string, stderr?: string, code?: number }} ExecError
31+
*/
32+
33+
/**
34+
* Checks whether an unknown error object is an ExecError.
35+
* @param {unknown} error
36+
* @returns {error is ExecError}
37+
*/
38+
export function isExecError(error) {
39+
if (!(error instanceof Error)) return false;
40+
41+
const e = /** @type {ExecError} */ (error);
42+
return typeof e.stdout === "string" || typeof e.stderr === "string";
43+
}
44+
45+
/**
46+
* Wraps `child_process.execFile()`, adding logging and a larger default maxBuffer.
47+
*
48+
* @param {string} file
49+
* @param {string[]} [args]
50+
* @param {ExecOptions} [options]
51+
* @returns {Promise<ExecResult>}
52+
* @throws {ExecError}
53+
*/
54+
export async function execFile(file, args, options = {}) {
55+
const {
56+
cwd,
57+
logger,
58+
logOutput = false,
59+
// Node default is 1024 * 1024, which is too small for some git commands returning many entities or large file content.
60+
// To support "git show", should be larger than the largest swagger file in the repo (2.5 MB as of 2/28/2025).
61+
maxBuffer = 16 * 1024 * 1024,
62+
} = options;
63+
64+
logger?.info(`execFile("${file}", ${JSON.stringify(args)})`);
65+
66+
try {
67+
// execFile(file, args) is more secure than exec(cmd), since the latter is vulnerable to shell injection
68+
const result = await execFileImpl(file, args, {
69+
cwd,
70+
maxBuffer,
71+
});
72+
73+
logger?.debug(`stdout: '${result.stdout}'`);
74+
logger?.debug(`stderr: '${result.stderr}'`);
75+
if (logOutput) {
76+
if (result.stdout) {
77+
logger?.info(result.stdout.trimEnd());
78+
}
79+
if (result.stderr) {
80+
logger?.info(result.stderr.trimEnd());
81+
}
82+
}
83+
84+
return result;
85+
} catch (error) {
86+
/* v8 ignore next */
87+
logger?.debug(`error: '${JSON.stringify(error)}'`);
88+
if (logOutput && isExecError(error)) {
89+
if (error.stdout) {
90+
logger?.info(error.stdout.trimEnd());
91+
}
92+
if (error.stderr) {
93+
logger?.info(error.stderr.trimEnd());
94+
}
95+
}
96+
97+
throw error;
98+
}
99+
}
100+
101+
/**
102+
* Calls `execFile()` with appropriate arguments to run `npm` on all platforms
103+
*
104+
* @param {string[]} args
105+
* @param {ExecNpmOptions} [options]
106+
* @returns {Promise<ExecResult>}
107+
* @throws {ExecError}
108+
*/
109+
export async function execNpm(args, options = {}) {
110+
const { prefix } = options;
111+
112+
// Exclude platform-specific code from coverage
113+
/* v8 ignore start */
114+
const { file, defaultArgs } =
115+
process.platform === "win32"
116+
? {
117+
// Only way I could find to run "npm" on Windows, without using the shell (e.g. "cmd /c npm ...")
118+
//
119+
// "node.exe", ["--", "npm-cli.js", ...args]
120+
//
121+
// The "--" MUST come BEFORE "npm-cli.js", to ensure args are sent to the script unchanged.
122+
// If the "--" comes after "npm-cli.js", the args sent to the script will be ["--", ...args],
123+
// which is NOT equivalent, and can break if args itself contains another "--".
124+
125+
// example: "C:\Program Files\nodejs\node.exe"
126+
file: process.execPath,
127+
128+
// example: "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js"
129+
defaultArgs: [
130+
"--",
131+
join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"),
132+
],
133+
}
134+
: { file: "npm", defaultArgs: [] };
135+
/* v8 ignore stop */
136+
137+
const prefixArgs = prefix ? ["--prefix", prefix] : [];
138+
139+
return await execFile(file, [...defaultArgs, ...prefixArgs, ...args], options);
140+
}
141+
142+
/**
143+
* Calls `execNpm()` with arguments ["exec", "--no", "--"] prepended.
144+
*
145+
* @param {string[]} args
146+
* @param {ExecNpmOptions} [options]
147+
* @returns {Promise<ExecResult>}
148+
* @throws {ExecError}
149+
*/
150+
export async function execNpmExec(args, options = {}) {
151+
return await execNpm(["exec", "--no", "--", ...args], options);
152+
}

.github/shared/src/logger.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* @typedef {Object} ILogger
3+
* @property {(message:string) => void} debug
4+
* @property {(message:string) => void} error
5+
* @property {(message:string) => void} info
6+
* @property {(message:string) => void} warning
7+
* @property {() => boolean} isDebug
8+
*/
9+
10+
/**
11+
* @implements {ILogger}
12+
*/
13+
export class ConsoleLogger {
14+
/** @type {boolean} */
15+
#isDebug;
16+
17+
/**
18+
* @param {boolean} [isDebug] - If true, debug logs will be printed. Default: false.
19+
*/
20+
constructor(isDebug = false) {
21+
this.#isDebug = isDebug;
22+
}
23+
24+
/**
25+
* @param {string} message
26+
*/
27+
debug(message) {
28+
if (this.isDebug()) {
29+
console.debug(message);
30+
}
31+
}
32+
33+
/**
34+
* @param {string} message
35+
*/
36+
error(message) {
37+
console.error(message);
38+
}
39+
40+
/**
41+
* @param {string} message
42+
*/
43+
info(message) {
44+
console.log(message);
45+
}
46+
47+
/**
48+
* @returns {boolean}
49+
*/
50+
isDebug() {
51+
return this.#isDebug;
52+
}
53+
54+
/**
55+
* @param {string} message
56+
*/
57+
warning(message) {
58+
console.warn(message);
59+
}
60+
}
61+
62+
// Singleton loggers
63+
export const defaultLogger = new ConsoleLogger();
64+
export const debugLogger = new ConsoleLogger(/*isDebug*/ true);

0 commit comments

Comments
 (0)