Skip to content

Commit a7c5eb5

Browse files
authored
Merge branch 'microsoft-foundry:main' into main
2 parents 0c1feb0 + 669ed03 commit a7c5eb5

430 files changed

Lines changed: 213042 additions & 2384 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/.sync-sha

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
154cef9a84b8bdd6966acebaced70f9a5a0b3d46

.github/CODEOWNERS

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@
2424
/samples/REST/quickstart/quickstart-chat-with-agent.sh @microsoft-foundry/AI-Platform-Docs
2525
/samples/REST/quickstart/quickstart-create-agent.sh @microsoft-foundry/AI-Platform-Docs
2626
/samples/REST/quickstart/quickstart-responses.sh @microsoft-foundry/AI-Platform-Docs
27-
/samples/csharp/quickstart/quickstart-chat-with-agent.cs @microsoft-foundry/AI-Platform-Docs
28-
/samples/csharp/quickstart/quickstart-create-agent.cs @microsoft-foundry/AI-Platform-Docs
29-
/samples/csharp/quickstart/quickstart-responses.cs @microsoft-foundry/AI-Platform-Docs
30-
/samples/java/quickstart/src/main/java/com/microsoft/foundry/samples/ChatWithAgent.java @microsoft-foundry/AI-Platform-Docs
31-
/samples/java/quickstart/src/main/java/com/microsoft/foundry/samples/CreateAgent.java @microsoft-foundry/AI-Platform-Docs
32-
/samples/java/quickstart/src/main/java/com/microsoft/foundry/samples/CreateResponses.java @microsoft-foundry/AI-Platform-Docs
27+
/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/Evaluate/Program.cs @microsoft-foundry/AI-Platform-Docs
28+
/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/Program.cs @microsoft-foundry/AI-Platform-Docs
29+
/samples/csharp/quickstart/chat-with-agent/quickstart-chat-with-agent.cs @microsoft-foundry/AI-Platform-Docs
30+
/samples/csharp/quickstart/create-agent/quickstart-create-agent.cs @microsoft-foundry/AI-Platform-Docs
31+
/samples/csharp/quickstart/responses/quickstart-responses.cs @microsoft-foundry/AI-Platform-Docs
32+
/samples/java/quickstart/chat-with-agent/src/main/java/com/azure/ai/agents/ChatWithAgent.java @microsoft-foundry/AI-Platform-Docs
33+
/samples/java/quickstart/create-agent/src/main/java/com/azure/ai/agents/CreateAgent.java @microsoft-foundry/AI-Platform-Docs
3334
/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/evaluate.py @microsoft-foundry/AI-Platform-Docs
3435
/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/main.py @microsoft-foundry/AI-Platform-Docs
35-
/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/questions.jsonl @microsoft-foundry/AI-Platform-Docs
36-
/samples/python/quickstart/quickstart-chat-with-agent.py @microsoft-foundry/AI-Platform-Docs
37-
/samples/python/quickstart/quickstart-create-agent.py @microsoft-foundry/AI-Platform-Docs
38-
/samples/python/quickstart/quickstart-responses.py @microsoft-foundry/AI-Platform-Docs
39-
/samples/typescript/quickstart/src/quickstart-chat-with-agent.ts @microsoft-foundry/AI-Platform-Docs
40-
/samples/typescript/quickstart/src/quickstart-create-agent.ts @microsoft-foundry/AI-Platform-Docs
41-
/samples/typescript/quickstart/src/quickstart-responses.ts @microsoft-foundry/AI-Platform-Docs
42-
/samples/cli/finetuning/ @saanikaguptamicrosoft @achauhan-scc @kingernupur @ZubaeyrMSFT @rabollin @william-liang-MSFT
36+
/samples/python/quickstart/chat-with-agent/quickstart-chat-with-agent.py @microsoft-foundry/AI-Platform-Docs
37+
/samples/python/quickstart/create-agent/quickstart-create-agent.py @microsoft-foundry/AI-Platform-Docs
38+
/samples/python/quickstart/responses/quickstart-responses.py @microsoft-foundry/AI-Platform-Docs
39+
/samples/typescript/quickstart/chat-with-agent/src/quickstart-chat-with-agent.ts @microsoft-foundry/AI-Platform-Docs
40+
/samples/typescript/quickstart/create-agent/src/quickstart-create-agent.ts @microsoft-foundry/AI-Platform-Docs
41+
/samples/typescript/quickstart/responses/src/quickstart-responses.ts @microsoft-foundry/AI-Platform-Docs
42+
samples/python/hosted-agents/agent-framework/azure-ai-agents-in-workflow @microsoft-foundry/foundry-vscode-extension
43+
samples/csharp/hosted-agents/AgentFramework/AzureAIAgentsInWorkflow @microsoft-foundry/foundry-vscode-extension
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
name: Redirect Pull Requests
2+
3+
on:
4+
pull_request_target:
5+
types: [opened]
6+
7+
permissions:
8+
pull-requests: write
9+
10+
jobs:
11+
redirect:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Check org membership and redirect
15+
uses: actions/github-script@v7
16+
with:
17+
script: |
18+
const pr = context.payload.pull_request;
19+
const author = pr.user.login;
20+
21+
// Allow PRs from trusted automation bots (e.g., repo sync)
22+
const allowedBots = ['foundry-samples-repo-sync[bot]'];
23+
if (allowedBots.includes(author)) {
24+
console.log(`Skipping redirect for allowed bot: ${author}`);
25+
return;
26+
}
27+
28+
// Check if author is a Microsoft contributor using multiple signals.
29+
// The GITHUB_TOKEN can only see *public* members of the 'microsoft' org
30+
// (since this repo is in the 'microsoft-foundry' org), so we cascade
31+
// through several checks to catch contributors with private membership.
32+
let isInternal = false;
33+
let matchedSignal = null;
34+
35+
// Signal 1: Check microsoft-foundry org membership (full visibility via GITHUB_TOKEN)
36+
try {
37+
const res = await github.rest.orgs.checkMembershipForUser({
38+
org: 'microsoft-foundry',
39+
username: author,
40+
});
41+
if (res.status === 204) {
42+
isInternal = true;
43+
matchedSignal = 'microsoft-foundry org member';
44+
}
45+
} catch {
46+
// 404 or 302 means not a member
47+
}
48+
49+
// Signal 2: Check if author is a collaborator on this repo
50+
if (!isInternal) {
51+
try {
52+
const res = await github.rest.repos.checkCollaborator({
53+
owner: context.repo.owner,
54+
repo: context.repo.repo,
55+
username: author,
56+
});
57+
if (res.status === 204) {
58+
isInternal = true;
59+
matchedSignal = 'repo collaborator';
60+
}
61+
} catch {
62+
// 404 means not a collaborator
63+
}
64+
}
65+
66+
// Signal 3: Check microsoft org membership (catches public members only)
67+
if (!isInternal) {
68+
try {
69+
const res = await github.rest.orgs.checkMembershipForUser({
70+
org: 'microsoft',
71+
username: author,
72+
});
73+
if (res.status === 204) {
74+
isInternal = true;
75+
matchedSignal = 'microsoft org member (public)';
76+
}
77+
} catch {
78+
// 404 or 302 means not a member (or private membership not visible)
79+
}
80+
}
81+
82+
console.log(`Author: ${author}, isInternal: ${isInternal}, signal: ${matchedSignal || 'none'}`);
83+
84+
let body;
85+
if (isInternal) {
86+
body = [
87+
`👋 Thanks for your contribution, @${author}!`,
88+
'',
89+
'This repository is read-only. As a Microsoft contributor, please submit your PR to the private staging repository instead:',
90+
'',
91+
'👉 **[foundry-samples-pr](https://github.com/microsoft-foundry/foundry-samples-pr)**',
92+
'',
93+
'See [CONTRIBUTING.md](https://github.com/microsoft-foundry/foundry-samples/blob/main/CONTRIBUTING.md) for full instructions.',
94+
].join('\n');
95+
} else {
96+
body = [
97+
`👋 Thanks for your interest in contributing, @${author}!`,
98+
'',
99+
'This repository does not accept pull requests directly. If you\'d like to report a bug, suggest an improvement, or propose a new sample, please **[open an issue](https://github.com/microsoft-foundry/foundry-samples/issues/new)** instead.',
100+
'',
101+
'See [CONTRIBUTING.md](https://github.com/microsoft-foundry/foundry-samples/blob/main/CONTRIBUTING.md) for more details.',
102+
].join('\n');
103+
}
104+
105+
// Skip if the bot already commented (idempotent on re-runs)
106+
const comments = await github.rest.issues.listComments({
107+
owner: context.repo.owner,
108+
repo: context.repo.repo,
109+
issue_number: pr.number,
110+
});
111+
const alreadyCommented = comments.data.some(c =>
112+
c.user.login === 'github-actions[bot]' &&
113+
c.body.includes('This repository')
114+
);
115+
if (alreadyCommented) {
116+
console.log('Bot already commented on this PR, skipping.');
117+
return;
118+
}
119+
120+
await github.rest.issues.createComment({
121+
owner: context.repo.owner,
122+
repo: context.repo.repo,
123+
issue_number: pr.number,
124+
body,
125+
});
126+
127+
await github.rest.pulls.update({
128+
owner: context.repo.owner,
129+
repo: context.repo.repo,
130+
pull_number: pr.number,
131+
state: 'closed',
132+
});

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
##
44
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
55

6+
# macOS
7+
.DS_Store
8+
69
# User-specific files
710
*.rsuser
811
*.suo

.infra/pytest_plugins/changed_samples/build/lib/pytest_changed_samples/plugin.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
WORKING_TREE_CHANGES_OPTION = "--changed-samples-only"
1313
PR_CHANGES_OPTION = "--changed-samples-only-from"
1414

15+
1516
def is_plugin_active(config: pytest.Config) -> bool:
17+
"""Return whether any of the plugin provided options were provided on commandline."""
1618
return get_diff_paths_function(config) is not None
1719

20+
1821
def pytest_addoption(parser: pytest.Parser) -> None:
1922
parser.addoption(
2023
WORKING_TREE_CHANGES_OPTION,
@@ -39,11 +42,14 @@ def pytest_configure(config: pytest.Config) -> None:
3942
# Validate that mutually exclusive options haven't been provided
4043
mutually_exclusive_options = (WORKING_TREE_CHANGES_OPTION, PR_CHANGES_OPTION)
4144
if sum(bool(config.getoption(opt_var(o))) for o in mutually_exclusive_options) > 1:
42-
raise pytest.UsageError(f"{' and '.join(mutually_exclusive_options)} are mutually exclusive")
45+
raise pytest.UsageError(
46+
f"{' and '.join(mutually_exclusive_options)} are mutually exclusive"
47+
)
4348

4449

4550
@pytest.hookimpl(hookwrapper=True)
4651
def pytest_collection(session: pytest.Session) -> None:
52+
"""Set up path filtering based on git diff."""
4753
config = session.config
4854
diff_path_trie = Trie()
4955

@@ -64,7 +70,10 @@ def pytest_collection(session: pytest.Session) -> None:
6470
del config.stash[DIFF_PATH_TRIE_KEY]
6571

6672

67-
def pytest_ignore_collect(collection_path: Path, config: pytest.Config) -> Optional[bool]:
73+
def pytest_ignore_collect(
74+
collection_path: Path, config: pytest.Config
75+
) -> Optional[bool]:
76+
"""Ignore paths that were not touched by the current git diff."""
6877
if DIFF_PATH_TRIE_KEY not in config.stash:
6978
# Occurs when calling `pytest --fixtures`
7079
return None
@@ -80,6 +89,7 @@ def pytest_ignore_collect(collection_path: Path, config: pytest.Config) -> Optio
8089
# Either definitely ignore this path, or defer decision to other plugins
8190
return (not diff_path_trie.is_prefix(ignore_dir.resolve().parts)) or None
8291

92+
8393
@pytest.hookimpl(trylast=True)
8494
def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
8595
if not is_plugin_active(session.config):
@@ -88,7 +98,10 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
8898
if exitstatus == pytest.ExitCode.NO_TESTS_COLLECTED:
8999
session.exitstatus = pytest.ExitCode.OK
90100

91-
def get_diff_paths_function(config: pytest.Config) -> Optional[Callable[[], Iterable[Path]]]:
101+
102+
def get_diff_paths_function(
103+
config: pytest.Config,
104+
) -> Optional[Callable[[], Iterable[Path]]]:
92105
"""Get the function that returns paths present in a diff specfied by cmdline arguments
93106
94107
:param pytest.Config config: The pytest config

.pre-commit-config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ repos:
55
rev: v3.2.0
66
hooks:
77
- id: check-added-large-files
8+
- repo: https://github.com/rhysd/actionlint
9+
rev: v1.7.7
10+
hooks:
11+
- id: actionlint
812
- repo: local
913
hooks:
1014
- id: nb-clean

0 commit comments

Comments
 (0)