Skip to content

Commit bc052f6

Browse files
committed
Merge branch 'main' into stas/oci-helm-support
2 parents e3778c1 + a277f10 commit bc052f6

File tree

97 files changed

+10566
-808
lines changed

Some content is hidden

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

97 files changed

+10566
-808
lines changed

.github/workflows/agentex-tutorials-test.yml

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: Test Tutorial Agents
22

33
on:
44
pull_request:
5-
branches: [ main ]
5+
branches: [main]
66
push:
7-
branches: [ main ]
7+
branches: [main]
88
workflow_dispatch:
99

1010
jobs:
@@ -20,20 +20,14 @@ jobs:
2020
id: get-tutorials
2121
run: |
2222
cd examples/tutorials
23-
# Find all tutorials and exclude specific temporal ones
23+
# Find all tutorials with a manifest.yaml
2424
all_tutorials=$(find . -name "manifest.yaml" -exec dirname {} \; | sort | sed 's|^\./||')
2525
26-
# Filter out the specified temporal tutorials that are being updated
27-
filtered_tutorials=$(echo "$all_tutorials" | grep -v -E "(temporal)")
28-
2926
# Convert to JSON array
30-
tutorials=$(echo "$filtered_tutorials" | jq -R -s -c 'split("\n") | map(select(length > 0))')
27+
tutorials=$(echo "$all_tutorials" | jq -R -s -c 'split("\n") | map(select(length > 0))')
3128
3229
echo "tutorials=$tutorials" >> $GITHUB_OUTPUT
3330
echo "All tutorials found: $(echo "$all_tutorials" | wc -l)"
34-
echo "Filtered tutorials: $(echo "$filtered_tutorials" | wc -l)"
35-
echo "Excluded tutorials:"
36-
echo "$all_tutorials" | grep -E "(10_temporal/050_|10_temporal/070_|10_temporal/080_)" || echo " (none matched exclusion pattern)"
3731
echo "Final tutorial list: $tutorials"
3832
3933
test-tutorial:
@@ -58,8 +52,20 @@ jobs:
5852
- name: Pull latest AgentEx image
5953
run: |
6054
echo "🐳 Pulling latest Scale AgentEx Docker image..."
61-
docker pull ghcr.io/scaleapi/scale-agentex/agentex:latest
62-
echo "✅ Successfully pulled AgentEx Docker image"
55+
max_attempts=3
56+
attempt=1
57+
while [ $attempt -le $max_attempts ]; do
58+
echo "Attempt $attempt of $max_attempts..."
59+
if docker pull ghcr.io/scaleapi/scale-agentex/agentex:latest; then
60+
echo "✅ Successfully pulled AgentEx Docker image"
61+
exit 0
62+
fi
63+
echo "❌ Pull failed, waiting before retry..."
64+
sleep $((attempt * 10))
65+
attempt=$((attempt + 1))
66+
done
67+
echo "❌ Failed to pull image after $max_attempts attempts"
68+
exit 1
6369
6470
- name: Checkout scale-agentex repo
6571
uses: actions/checkout@v4
@@ -313,3 +319,9 @@ jobs:
313319
echo "ℹ️ **Tests were cancelled or skipped.**" >> $GITHUB_STEP_SUMMARY
314320
fi
315321
fi
322+
323+
- name: Fail if tests failed
324+
if: ${{ needs.test-tutorial.result != 'success' }}
325+
run: |
326+
echo "❌ Test jobs did not succeed. Result: ${{ needs.test-tutorial.result }}"
327+
exit 1

.github/workflows/build-and-push-tutorial-agent.yml

Lines changed: 168 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ jobs:
5656
needs: [check-permissions]
5757
outputs:
5858
agents: ${{ steps.get-agents.outputs.agents }}
59+
all_agents: ${{ steps.get-agents.outputs.all_agents }}
5960
has_agents: ${{ steps.get-agents.outputs.has_agents }}
6061
steps:
6162
- name: Checkout repository
@@ -72,6 +73,10 @@ jobs:
7273
all_agents=$(find examples/tutorials -name "manifest.yaml" -exec dirname {} \; | sort)
7374
agents_to_build=()
7475
76+
# Output all agents for deprecation check
77+
all_agents_json=$(printf '%s\n' $all_agents | jq -R -s -c 'split("\n") | map(select(length > 0))')
78+
echo "all_agents=$all_agents_json" >> $GITHUB_OUTPUT
79+
7580
if [ "$REBUILD_ALL" = "true" ]; then
7681
echo "Rebuild all agents requested"
7782
agents_to_build=($(echo "$all_agents"))
@@ -163,15 +168,13 @@ jobs:
163168
echo "Agent name set to $AGENT_NAME"
164169
165170
- name: Login to GitHub Container Registry
166-
# Only login if we're going to push (main branch or rebuild_all)
167-
if: ${{ github.event_name == 'push' || inputs.rebuild_all }}
168171
uses: docker/login-action@v3
169172
with:
170173
registry: ghcr.io
171174
username: ${{ github.actor }}
172175
password: ${{ secrets.GITHUB_TOKEN }}
173176

174-
- name: Build and Conditionally Push Agent Image
177+
- name: Build Agent Image
175178
env:
176179
REGISTRY: ghcr.io
177180
run: |
@@ -182,20 +185,174 @@ jobs:
182185
if [ "${{ github.event_name }}" = "push" ] || [ "${{ inputs.rebuild_all }}" = "true" ]; then
183186
SHOULD_PUSH=true
184187
VERSION_TAG="latest"
185-
echo "🚀 Building and pushing agent: ${{ matrix.agent_path }}"
188+
echo "🚀 Building agent (will push after validation): ${{ matrix.agent_path }}"
186189
else
187190
SHOULD_PUSH=false
188191
VERSION_TAG="${{ github.sha }}"
189-
echo "🔍 Validating build for agent: ${{ matrix.agent_path }}"
192+
echo "🔍 Building agent for validation: ${{ matrix.agent_path }}"
193+
# Set full image name for validation step (local build)
194+
echo "FULL_IMAGE=${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}" >> $GITHUB_ENV
195+
# Skip image validation for PRs since Buildx doesn't load multi-platform images locally
196+
echo "SKIP_VALIDATION=true" >> $GITHUB_ENV
190197
fi
191198
192-
# Build command - add --push only if we should push
199+
# Always build locally first (without push)
193200
BUILD_ARGS="--manifest ${{ matrix.agent_path }}/manifest.yaml --registry ${REGISTRY} --tag ${VERSION_TAG} --platforms linux/amd64,linux/arm64 --repository-name ${REPOSITORY_NAME}"
194201
195-
if [ "$SHOULD_PUSH" = "true" ]; then
196-
agentex agents build $BUILD_ARGS --push
197-
echo "✅ Successfully built and pushed: ${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}"
202+
agentex agents build $BUILD_ARGS
203+
echo "✅ Successfully built: ${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}"
204+
205+
# Set environment variables for subsequent steps
206+
echo "FULL_IMAGE=${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}" >> $GITHUB_ENV
207+
echo "SHOULD_PUSH=${SHOULD_PUSH}" >> $GITHUB_ENV
208+
209+
- name: Validate agent image
210+
if: env.SKIP_VALIDATION != 'true'
211+
run: |
212+
set -e
213+
214+
FULL_IMAGE="${{ env.FULL_IMAGE }}"
215+
AGENT_PATH="${{ matrix.agent_path }}"
216+
AGENT_NAME="${{ env.AGENT_NAME }}"
217+
218+
echo "🔍 Validating agent image: $FULL_IMAGE"
219+
220+
# Determine ACP type from path
221+
if [[ "$AGENT_PATH" == *"10_async"* ]]; then
222+
ACP_TYPE="async"
198223
else
199-
agentex agents build $BUILD_ARGS
200-
echo "✅ Build validation successful for: ${{ matrix.agent_path }}"
224+
ACP_TYPE="sync"
201225
fi
226+
227+
# Common environment variables for validation
228+
ENV_VARS="-e ENVIRONMENT=development \
229+
-e AGENT_NAME=${AGENT_NAME} \
230+
-e ACP_URL=http://localhost:8000 \
231+
-e ACP_PORT=8000 \
232+
-e ACP_TYPE=${ACP_TYPE}"
233+
234+
# 1. Validate ACP entry point exists and is importable
235+
echo "📦 Checking ACP entry point..."
236+
docker run --rm $ENV_VARS "$FULL_IMAGE" python -c "from project.acp import acp; print('✅ ACP entry point validated')"
237+
238+
# 2. Check if tests/test_agent.py exists (required for integration tests)
239+
# Tests are located at /app/<agent_dir>/tests/test_agent.py
240+
echo "🧪 Checking for tests/test_agent.py..."
241+
TEST_FILE=$(docker run --rm "$FULL_IMAGE" find /app -name "test_agent.py" -path "*/tests/*" 2>/dev/null | head -1)
242+
243+
if [ -n "$TEST_FILE" ]; then
244+
echo "✅ Found test file at: $TEST_FILE"
245+
else
246+
echo "❌ No tests/test_agent.py found in image - this is required for all tutorial agents"
247+
echo " Please add a tests/test_agent.py file to your agent"
248+
exit 1
249+
fi
250+
251+
# 3. Validate container can start (may fail due to missing services, but should initialize)
252+
echo "🏥 Validating container starts..."
253+
CONTAINER_NAME="validate-agent-$$"
254+
255+
# Start container in background with required env vars
256+
docker run -d --name "$CONTAINER_NAME" \
257+
$ENV_VARS \
258+
-p 8000:8000 \
259+
"$FULL_IMAGE"
260+
261+
# Give it a few seconds to attempt startup
262+
sleep 5
263+
264+
# Check if container is still running (it may exit due to missing services, that's ok)
265+
# We just want to see that it attempted to start properly
266+
echo "📋 Container logs:"
267+
docker logs "$CONTAINER_NAME" 2>&1 || true
268+
269+
# Check for successful ACP initialization in logs
270+
if docker logs "$CONTAINER_NAME" 2>&1 | grep -q "instance created "; then
271+
echo "✅ Container initialized ACP successfully"
272+
else
273+
echo "⚠️ Could not verify ACP initialization from logs"
274+
fi
275+
276+
# Cleanup container
277+
docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
278+
docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
279+
280+
echo "✅ All validations passed for: $FULL_IMAGE"
281+
282+
- name: Push Agent Image
283+
if: env.SHOULD_PUSH == 'true'
284+
run: |
285+
FULL_IMAGE="${{ env.FULL_IMAGE }}"
286+
echo "🚀 Pushing validated image: $FULL_IMAGE"
287+
docker push "$FULL_IMAGE"
288+
echo "✅ Successfully pushed: $FULL_IMAGE"
289+
290+
deprecate-agents:
291+
name: "Deprecate Removed Agents"
292+
runs-on: ubuntu-latest
293+
needs: [find-agents]
294+
steps:
295+
- name: Find and delete deprecated agent packages
296+
env:
297+
GITHUB_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
298+
run: |
299+
set -e
300+
301+
echo "🔍 Agents in repo (from find-agents):"
302+
# Convert JSON array of paths to package names
303+
# e.g., "examples/tutorials/00_sync/000_hello_acp" -> "00_sync-000_hello_acp"
304+
REPO_AGENTS=$(echo '${{ needs.find-agents.outputs.all_agents }}' | jq -r '.[]' | \
305+
sed 's|examples/tutorials/||' | \
306+
sed 's|/|-|g')
307+
echo "$REPO_AGENTS"
308+
309+
echo ""
310+
echo "🔍 Fetching packages from GitHub Container Registry..."
311+
PACKAGES=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
312+
-H "Accept: application/vnd.github+json" \
313+
"https://api.github.com/orgs/scaleapi/packages?package_type=container&per_page=100")
314+
315+
# Check for API errors
316+
if echo "$PACKAGES" | jq -e '.message' > /dev/null 2>&1; then
317+
echo "❌ GitHub API error:"
318+
echo "$PACKAGES" | jq '.'
319+
exit 1
320+
fi
321+
322+
# Filter for tutorial-agents from this repo
323+
TUTORIAL_PACKAGES=$(echo "$PACKAGES" | \
324+
jq -r '.[] | select(.repository != null and .repository.name == "scale-agentex-python" and (.name | contains("tutorial-agents"))) | .name')
325+
326+
echo "Tutorial packages in registry:"
327+
echo "$TUTORIAL_PACKAGES"
328+
329+
echo ""
330+
echo "🔍 Checking for deprecated packages..."
331+
while IFS= read -r package_name; do
332+
[ -z "$package_name" ] && continue
333+
334+
# Extract agent name: scale-agentex-python/tutorial-agents/00_sync-000_hello_acp -> 00_sync-000_hello_acp
335+
agent_name=$(echo "$package_name" | sed 's|.*/tutorial-agents/||')
336+
337+
if ! echo "$REPO_AGENTS" | grep -q "^${agent_name}$"; then
338+
echo "🗑️ $agent_name - NOT in repo, deleting..."
339+
# URL encode the package name (replace / with %2F)
340+
encoded_package=$(echo "$package_name" | sed 's|/|%2F|g')
341+
response=$(curl -s -w "\n%{http_code}" -X DELETE \
342+
-H "Authorization: Bearer $GITHUB_TOKEN" \
343+
-H "Accept: application/vnd.github+json" \
344+
"https://api.github.com/orgs/scaleapi/packages/container/${encoded_package}")
345+
346+
http_code=$(echo "$response" | tail -n1)
347+
body=$(echo "$response" | sed '$d')
348+
349+
if [ "$http_code" = "204" ] || [ "$http_code" = "200" ]; then
350+
echo " ✅ Deleted: $package_name"
351+
else
352+
echo " ⚠️ Failed to delete $package_name (HTTP $http_code): $body"
353+
fi
354+
fi
355+
done <<< "$TUTORIAL_PACKAGES"
356+
357+
echo ""
358+
echo "✅ Deprecation check complete"

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
runs-on: ${{ github.repository == 'stainless-sdks/agentex-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
2020
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
2121
steps:
22-
- uses: actions/checkout@v4
22+
- uses: actions/checkout@v6
2323

2424
- name: Install Rye
2525
run: |
@@ -44,7 +44,7 @@ jobs:
4444
id-token: write
4545
runs-on: ${{ github.repository == 'stainless-sdks/agentex-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
4646
steps:
47-
- uses: actions/checkout@v4
47+
- uses: actions/checkout@v6
4848

4949
- name: Install Rye
5050
run: |
@@ -63,7 +63,7 @@ jobs:
6363
- name: Get GitHub OIDC Token
6464
if: github.repository == 'stainless-sdks/agentex-sdk-python'
6565
id: github-oidc
66-
uses: actions/github-script@v6
66+
uses: actions/github-script@v8
6767
with:
6868
script: core.setOutput('github_token', await core.getIDToken());
6969

@@ -81,7 +81,7 @@ jobs:
8181
runs-on: ${{ github.repository == 'stainless-sdks/agentex-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
8282
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
8383
steps:
84-
- uses: actions/checkout@v4
84+
- uses: actions/checkout@v6
8585

8686
- name: Install Rye
8787
run: |

.github/workflows/main.yml

Lines changed: 0 additions & 6 deletions
This file was deleted.

.github/workflows/publish-pypi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@v6
1818

1919
- name: Install Rye
2020
run: |

.github/workflows/release-doctor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
if: github.repository == 'scaleapi/scale-agentex-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')
1313

1414
steps:
15-
- uses: actions/checkout@v4
15+
- uses: actions/checkout@v6
1616

1717
- name: Check release environment
1818
run: |

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.7.3"
2+
".": "0.9.1"
33
}

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 35
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp%2Fagentex-sdk-6feb0601dafb255298a2f1da01d64541d40da90aeb527e2f444c49c993e8c162.yml
3-
openapi_spec_hash: 973cd2ed3c945818d15b7deee0b25d71
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp%2Fagentex-sdk-c9b5ca9e03141b62fa981944af1c880cd4562f0b697ed5f110c0e0e754f455ba.yml
3+
openapi_spec_hash: 9ed347fceac28248d2a0acb49c4eb356
44
config_hash: 32eb65911c08ac84d117cecdf2759869

0 commit comments

Comments
 (0)