Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
2cbed67
added getKeys script to get .env keys from keyvault
robgruen Nov 21, 2025
4dbd7b3
Continue if role name is invalid. Show progress while getting keys
robgruen Nov 21, 2025
48982d9
Fixed pyright issues
robgruen Nov 21, 2025
88f4a1e
obfuscated failed secret retreival
robgruen Nov 21, 2025
4a72ee7
lint
robgruen Nov 21, 2025
89a0b99
add simple online test
robgruen Nov 21, 2025
64b00c2
Added launch.json and extensions.json for sync & play capability in V…
robgruen Nov 21, 2025
653bb61
Potential fix for code scanning alert no. 22: Clear-text logging of s…
robgruen Nov 21, 2025
715039c
Merge branch 'dev/robgruen/online_tests' of https://github.com/micros…
robgruen Nov 21, 2025
34eba6e
updated to run getkeys and run tests
robgruen Nov 21, 2025
f76af89
updated secret names
robgruen Nov 21, 2025
a4ab6e7
updated environment
robgruen Nov 21, 2025
f2d6ef4
added environment to test block
robgruen Nov 21, 2025
a928659
updated test path
robgruen Nov 21, 2025
cc0f38b
updated path
robgruen Nov 21, 2025
d10abc8
updated command
robgruen Nov 21, 2025
4faa382
added UV dependency
robgruen Nov 21, 2025
235aae2
updated working dir
robgruen Nov 21, 2025
d90ac0a
fixed typo
robgruen Nov 21, 2025
9cdcd9b
output dir
robgruen Nov 21, 2025
01d687d
updated working dir to dist
robgruen Nov 21, 2025
01b906e
listing what's in dist
robgruen Nov 21, 2025
239875a
updated dir
robgruen Nov 21, 2025
1b14fce
removed test section to simply pipeline (no upload/download/unzip/etc).
robgruen Nov 21, 2025
219050f
removed dir output
robgruen Nov 21, 2025
ec3db66
obfuscated key name
robgruen Nov 21, 2025
f74be99
added back artifact upload
robgruen Nov 21, 2025
c8d7967
moved to extras
robgruen Nov 21, 2025
a356daf
moved to python file naming convention
robgruen Nov 21, 2025
91cfc82
sorted
robgruen Nov 21, 2025
32bc298
only publish as part of the merge queue
robgruen Nov 21, 2025
3116da7
using colorama now
robgruen Nov 21, 2025
78adee2
better exception handling
robgruen Nov 21, 2025
146e874
exception printing
robgruen Nov 21, 2025
450d939
removed dev branch trigger.
robgruen Nov 21, 2025
e17ce07
fixed whitespace
robgruen Nov 21, 2025
8ef0c02
do perms check first
robgruen Nov 21, 2025
2c849ff
revert release and moved test functionality to CI.
robgruen Nov 23, 2025
18a7114
only log into azure and get keys if we are running tests.
robgruen Nov 23, 2025
14ff672
remved merge queue
robgruen Nov 23, 2025
7976d8e
skippable test if keys aren't configured
robgruen Nov 23, 2025
b25404e
more debuggable test.
robgruen Nov 23, 2025
d58276f
lint
robgruen Nov 23, 2025
09e61de
added azure identity broker so CI test won't fail on windows.
robgruen Nov 23, 2025
a97cb2d
removed identity broker, ci still fails on windows.
robgruen Nov 23, 2025
bae6f12
trying to fix auth issue
robgruen Nov 24, 2025
cd1d860
lint
robgruen Nov 24, 2025
677a2ab
added comment
robgruen Nov 24, 2025
f6afd5e
Updated to handle None server_params
robgruen Nov 24, 2025
b7df68d
reverted changes
robgruen Nov 24, 2025
058e58f
Update CI workflow to trigger only on 'main' branch
robgruen Nov 24, 2025
c1bc03c
Enable TestPyPI repository URL in release workflow
robgruen Nov 24, 2025
08b8b80
Fix missing newline at end of extensions.json
robgruen Nov 24, 2025
a1ba4a6
Fix formatting in launch.json
robgruen Nov 24, 2025
29d6804
Only one newline at end of file
gvanrossum-ms Nov 24, 2025
0569484
Fix trailing newline
gvanrossum-ms Nov 24, 2025
c14824e
Fixed white space.
robgruen Nov 24, 2025
ceed779
Remove unnecessary blank line in test_mcp_server.py
robgruen Nov 24, 2025
5db9beb
Removed unused keys
robgruen Nov 24, 2025
11d09e7
Update get_keys.config.json
robgruen Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]

on:
push:
branches: [ "main" ]
pull_request_target:
branches: [ "main" ]
workflow_dispatch: # manual run

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
pull-requests: read
contents: read
id-token: write

jobs:
ci:
environment:
name: build-pipeline
strategy:
fail-fast: false
matrix:
Expand All @@ -19,6 +36,29 @@ jobs:
name: ${{ matrix.os }} ${{ matrix.task }} (py ${{ matrix.python-version }})

steps:

# The following two steps (permissions checks) ensure that only users with write access can run this workflow on a PR (except the merge queue bot)
# PRs from forks we check the permissions of the user that triggered the workflow (github.triggering_actor)
# This means that if a user without write access opens a PR from a fork, they cannot run this workflow
# Users with write access can still run this workflow on a PR from a fork
# For PRs from the same repo, we allow the workflow to run as normal
- name: Get User Permission
if: ${{ github.event_name == 'pull_request_target' || github.triggering_actor != 'github-merge-queue[bot]' }}
id: checkAccess
uses: actions-cool/check-user-permission@v2
with:
require: write
username: ${{ github.triggering_actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: ${{ (github.event_name == 'pull_request_target' || github.triggering_actor != 'github-merge-queue[bot]') && steps.checkAccess.outputs.require-result == 'false' }}
run: |
echo "${{ github.triggering_actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
echo "Job originally triggered by ${{ github.actor }}"
exit 1

- uses: actions/checkout@v4

- name: Set up Python
Expand Down Expand Up @@ -46,8 +86,25 @@ jobs:
run: |
uv run black -tpy312 -tpy313 -tpy314 typeagent test tools gmail demo --check

- name: Login to Azure
if: matrix.task == 'test'
uses: azure/login@v2.2.0
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}

- name: Get Keys
if: matrix.task == 'test'
run: |
uv run python tools/get_keys.py --vault build-pipeline-kv

- name: Run Test
shell: bash
if: matrix.task == 'test'
run: |
uv run pytest

- name: Clean up Keys
run: |
node -e "try{require('fs').unlinkSync('./.env');}catch(e){}"
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"ms-python.python",
"ms-python.debugpy",
"ms-python.vscode-pylance",
"ms-python.vscode-python-envs"
]
}
33 changes: 33 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {
"PATH": "${env:PATH}"
}
},
{
"name": "Python Debugger: Debug Tests",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": [
"${file}",
"-v"
],
"console": "integratedTerminal",
"justMyCode": false,
"env": {
"PATH": "${env:PATH}"
}
}
]
}
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ dependencies = [

[project.optional-dependencies]
dev = [
"azure-mgmt-authorization>=4.0.0",
"azure-mgmt-keyvault>=12.1.1",
"coverage[toml]>=7.9.1",
"google-api-python-client>=2.184.0",
"google-auth-httplib2>=0.2.0",
Expand Down
19 changes: 18 additions & 1 deletion test/test_mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ async def test_mcp_server_query_conversation_slow(
from mcp import ClientSession
from mcp.client.stdio import stdio_client

# Pass through environment variables needed for authentication
# otherwise this test will fail in the CI on Windows only
if not (server_params.env) is None:
server_params.env.update(
{
k: v
for k, v in os.environ.items()
if k.startswith(("AZURE_", "OPENAI_")) or k in ("CREDENTIALS_JSON",)
}
)

# Create client session and connect to server
async with stdio_client(server_params) as (read, write):
async with ClientSession(
Expand Down Expand Up @@ -123,7 +134,13 @@ async def test_mcp_server_query_conversation_slow(
# Parse response (it should be JSON with success, answer, time_used)
import json

response_data = json.loads(response_text)
try:
response_data = json.loads(response_text)
except json.JSONDecodeError as e:
pytest.fail(
f"Response is not valid JSON: {e}\nResponse text: {response_text}"
)

assert "success" in response_data
assert "answer" in response_data
assert "time_used" in response_data
Expand Down
44 changes: 44 additions & 0 deletions test/test_online.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import pytest

from fixtures import really_needs_auth # type: ignore

from typeagent.aitools.utils import create_async_openai_client


@pytest.mark.asyncio
async def test_why_is_sky_blue(really_needs_auth: None):
"""Test that chat agent responds correctly to 'why is the sky blue?'"""

# Create an async OpenAI client
try:
client = create_async_openai_client()
except RuntimeError as e:
if "Neither OPENAI_API_KEY nor AZURE_OPENAI_API_KEY was provided." in str(e):
pytest.skip("API keys not configured")
raise

# Send the user request
response = await client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": "why is the sky blue?",
}
],
temperature=0,
)

# Get the response message
msg = response.choices[0].message.content
assert msg is not None, "Chat agent didn't respond"

print(f"Chat agent response: {msg}")

# Check that the response contains the expected keyword
assert (
"scatter" in msg.lower()
), "Chat agent didn't respond with the expected message about scattering."
40 changes: 40 additions & 0 deletions tools/get_keys.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"defaultDotEnvPath": "../.env",
"env": {
"shared": [
"AZURE_OPENAI_ENDPOINT",
"AZURE_OPENAI_API_KEY_GPT_v",
"AZURE_OPENAI_ENDPOINT_GPT_4_O",
"AZURE_OPENAI_ENDPOINT_GPT_4_O_MINI",
"AZURE_OPENAI_RESPONSE_FORMAT",
"AZURE_OPENAI_MAX_CONCURRENCY",
"AZURE_OPENAI_MAX_TIMEOUT",
"AZURE_OPENAI_MAX_RETRYATTEMPTS",
"AZURE_OPENAI_API_KEY",
"AZURE_OPENAI_API_KEY_GPT_35_TURBO",
"AZURE_OPENAI_ENDPOINT_GPT_v",
"AZURE_OPENAI_API_KEY_GPT_4_O",
"AZURE_OPENAI_API_KEY_GPT_4_O_MINI",
"AZURE_OPENAI_API_KEY_EMBEDDING",
"AZURE_OPENAI_ENDPOINT_EMBEDDING",
"AZURE_OPENAI_API_KEY_GPT_5",
"AZURE_OPENAI_ENDPOINT_GPT_5",
"AZURE_OPENAI_API_KEY_GPT_5_MINI",
"AZURE_OPENAI_ENDPOINT_GPT_5_MINI",
"AZURE_OPENAI_API_KEY_GPT_5_NANO",
"AZURE_OPENAI_ENDPOINT_GPT_5_NANO",
"AZURE_OPENAI_API_KEY_GPT_5_CHAT",
"AZURE_OPENAI_ENDPOINT_GPT_5_CHAT",
"OPENAI_ENDPOINT_LOCAL",
"OPENAI_API_KEY_LOCAL",
"OPENAI_MODEL_LOCAL",
"OPENAI_ORGANIZATION_LOCAL",
"OPENAI_RESPONSE_FORMAT_LOCAL"
],
"private": [],
"delete": []
},
"vault": {
"shared": "aisystems"
}
}
Loading