Skip to content

Commit b85e9a3

Browse files
authored
Merge branch 'googleapis:main' into main
2 parents 00ae4ab + da0513b commit b85e9a3

File tree

6 files changed

+219
-5
lines changed

6 files changed

+219
-5
lines changed

.github/renovate.json5

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
extends: [
33
'config:recommended',
4-
':semanticCommits',
4+
':semanticCommitTypeAll(chore)',
55
':ignoreUnstable',
66
'group:allNonMajor',
77
':separateMajorReleases',
@@ -22,6 +22,22 @@
2222
],
2323
pinDigests: true,
2424
},
25+
{
26+
description: 'Auto-update genai-toolbox server version',
27+
matchPackageNames: [
28+
'googleapis/genai-toolbox',
29+
],
30+
matchManagers: [
31+
'regex',
32+
],
33+
"branchName": "auto-update/toolbox-server-v{{newValue}}",
34+
"commitMessageTopic": "update MCP Toolbox server version in integration tests to v{{newValue}}",
35+
"prTitle": "chore(deps): update mcp toolbox server for integration tests to v{{newValue}}",
36+
matchUpdateTypes: [
37+
'minor',
38+
'patch',
39+
],
40+
},
2541
{
2642
matchPackageNames: [
2743
'pytest',
@@ -55,4 +71,20 @@
5571
"enabled": false
5672
}
5773
],
74+
regexManagers: [
75+
{
76+
fileMatch: [
77+
'packages/toolbox-core/integration.cloudbuild.yaml',
78+
'packages/toolbox-langchain/integration.cloudbuild.yaml',
79+
'packages/toolbox-llamaindex/integration.cloudbuild.yaml',
80+
],
81+
matchStrings: [
82+
'_TOOLBOX_VERSION: [\'|"]?(?<currentValue>v?\\d+\\.\\d+\\.\\d+)[\'|"]?',
83+
],
84+
datasourceTemplate: 'github-releases',
85+
depNameTemplate: 'googleapis/genai-toolbox',
86+
versioningTemplate: 'semver',
87+
packageNameTemplate: 'googleapis/genai-toolbox',
88+
},
89+
],
5890
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
name: Export Cloud Build Failure Logs
15+
16+
permissions:
17+
contents: read
18+
checks: read
19+
issues: write
20+
pull-requests: write
21+
22+
on:
23+
check_suite:
24+
types: [completed]
25+
26+
concurrency:
27+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
28+
cancel-in-progress: true
29+
30+
jobs:
31+
detect-build-failure:
32+
name: Detect Cloud Build Failures
33+
runs-on: ubuntu-latest
34+
outputs:
35+
failure_detected: ${{ steps.detect_failures.outputs.failure_detected }}
36+
failed_checks: ${{ steps.detect_failures.outputs.failed_checks }}
37+
pr_number: ${{ steps.detect_failures.outputs.pr_number }}
38+
steps:
39+
- name: Detect all failed Cloud Build checks
40+
id: detect_failures
41+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
42+
with:
43+
github-token: ${{ secrets.GITHUB_TOKEN }}
44+
script: |
45+
const prefixes = [
46+
'core-python-sdk-pr-',
47+
'langchain-python-sdk-pr-',
48+
'llamaindex-python-sdk-pr-',
49+
];
50+
const prList = context.payload.check_suite.pull_requests;
51+
if (!prList || prList.length === 0) {
52+
core.info('No PR found for this check suite. Skipping.');
53+
core.setOutput('failure_detected', 'false');
54+
return;
55+
}
56+
const pr_number = prList[0].number;
57+
core.setOutput('pr_number', pr_number.toString());
58+
const { owner, repo } = context.repo;
59+
const sha = context.payload.check_suite.head_sha;
60+
const { data: checks } = await github.rest.checks.listForRef({ owner, repo, ref: sha, per_page: 100 });
61+
const failed = checks.check_runs.filter(
62+
c =>
63+
prefixes.some(prefix => c.name.startsWith(prefix)) &&
64+
c.status === 'completed' &&
65+
c.conclusion === 'failure'
66+
);
67+
if (failed.length === 0) {
68+
core.info('No failed Cloud Build checks detected.');
69+
core.setOutput('failure_detected', 'false');
70+
return;
71+
}
72+
core.info(`Detected ${failed.length} failed build(s).`);
73+
core.setOutput('failure_detected', 'true');
74+
core.setOutput('failed_checks', JSON.stringify(failed.map(f => ({ name: f.name, id: f.id, html_url: f.html_url, details_url: f.details_url, external_id: f.external_id || '' }))));
75+
76+
77+
process-failed-builds:
78+
needs: detect-build-failure
79+
if: needs.detect-build-failure.outputs.failure_detected == 'true'
80+
runs-on: ubuntu-latest
81+
env:
82+
GCLOUD_SERVICE_KEY: ${{ secrets.GCLOUD_SERVICE_KEY }}
83+
strategy:
84+
matrix:
85+
include: ${{ fromJson(needs.detect-build-failure.outputs.failed_checks) }}
86+
steps:
87+
- name: Parse build ID and set project ID
88+
id: parse_build_info
89+
run: |
90+
details_url="${{ matrix.details_url }}"
91+
build_id=$(echo "$details_url" | sed -n 's#.*/builds/\([^?]*\).*#\1#p')
92+
project_id=$(echo '${{ env.GCLOUD_SERVICE_KEY }}' | jq -r '.project_id')
93+
echo "Build ID: $build_id"
94+
echo "build_id=$build_id" >> $GITHUB_OUTPUT
95+
echo "project_id=$project_id" >> $GITHUB_OUTPUT
96+
- name: Authenticate to Google Cloud
97+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
98+
with:
99+
credentials_json: ${{ env.GCLOUD_SERVICE_KEY }}
100+
- name: Fetch Cloud Build logs
101+
id: fetch_cloud_build_logs
102+
run: |
103+
LOG_FILE="cloudbuild_error_logs.txt"
104+
GCLOUD_OUTPUT=$(gcloud builds log "${{ steps.parse_build_info.outputs.build_id }}" --project="${{ steps.parse_build_info.outputs.project_id }}" 2>&1)
105+
106+
if echo "$GCLOUD_OUTPUT" | grep -q "ERROR"; then
107+
echo "Failed to fetch logs from gcloud builds log." > "${LOG_FILE}"
108+
echo "--- gcloud command output ---" >> "${LOG_FILE}"
109+
echo "$GCLOUD_OUTPUT" >> "${LOG_FILE}"
110+
echo "-----------------------------" >> "${LOG_FILE}"
111+
echo "Log URL: ${{ matrix.details_url }}" >> "${LOG_FILE}"
112+
elif [ -z "$GCLOUD_OUTPUT" ]; then
113+
echo "Warning: No logs found or gcloud command returned empty output." > "${LOG_FILE}"
114+
echo "Log URL: ${{ matrix.details_url }}" >> "${LOG_FILE}"
115+
else
116+
echo "$GCLOUD_OUTPUT" > "${LOG_FILE}"
117+
fi
118+
echo "log_file_name=${LOG_FILE}" >> $GITHUB_OUTPUT
119+
- name: Upload Logs as Artifact
120+
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
121+
with:
122+
name: logs-${{ matrix.name }}-${{ steps.parse_build_info.outputs.build_id }}
123+
path: ${{ steps.fetch_cloud_build_logs.outputs.log_file_name }}
124+
retention-days: 15
125+
126+
post-pr-comment:
127+
needs: [detect-build-failure, process-failed-builds]
128+
runs-on: ubuntu-latest
129+
if: always()
130+
steps:
131+
- name: Compose and post PR comment with artifact links
132+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
133+
env:
134+
PR_NUMBER: ${{ needs.detect-build-failure.outputs.pr_number }}
135+
with:
136+
github-token: ${{ secrets.GITHUB_TOKEN }}
137+
script: |
138+
const prNumber = process.env.PR_NUMBER;
139+
if (!prNumber) {
140+
core.info('No PR number was passed from the detection job. Skipping.');
141+
return;
142+
}
143+
const { owner, repo } = context.repo;
144+
const run_id = context.runId;
145+
const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({ owner, repo, run_id });
146+
const logArtifacts = artifacts.artifacts.filter(a => a.name.startsWith('logs-'));
147+
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number: prNumber });
148+
149+
// The botLogin is 'github-actions' when using GITHUB_TOKEN
150+
// You should filter comments by user.login for robustness
151+
const botLogin = 'github-actions[bot]';
152+
const existing = comments.find(c => c.user.login === 'github-actions[bot]' && c.body && c.body.includes('**Download Error logs:**'));
153+
154+
if (logArtifacts.length > 0) {
155+
let body = '🔗 **Download Error logs:**\n\n';
156+
for (const artifact of logArtifacts) {
157+
const url = `https://github.com/${owner}/${repo}/actions/runs/${run_id}/artifacts/${artifact.id}`;
158+
const openParenIndex = artifact.name.indexOf('(');
159+
let displayName;
160+
if (openParenIndex !== -1) {
161+
displayName = artifact.name.substring(0, openParenIndex);
162+
} else {
163+
displayName = artifact.name.replace(/^logs-/, '');
164+
}
165+
displayName = displayName.trim();
166+
167+
body += `- [${displayName}](${url})\n`;
168+
}
169+
if (existing) {
170+
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
171+
core.info(`Updated existing comment in PR #${prNumber}.`);
172+
} else {
173+
await github.rest.issues.createComment({ owner, repo, issue_number: prNumber, body });
174+
core.info(`Posted new comment in PR #${prNumber}.`);
175+
}
176+
} else if (existing) {
177+
await github.rest.issues.deleteComment({ owner, repo, comment_id: existing.id });
178+
core.info(`Deleted previous failure comment in PR #${prNumber} as all tests now pass.`);
179+
} else {
180+
core.info('No failures found and no existing comment to delete.');
181+
}
182+

packages/toolbox-core/integration.cloudbuild.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,5 @@ options:
4747
logging: CLOUD_LOGGING_ONLY
4848
substitutions:
4949
_VERSION: '3.13'
50-
_TOOLBOX_VERSION: '0.17.0'
50+
_TOOLBOX_VERSION: '0.19.1'
5151
_TOOLBOX_MANIFEST_VERSION: '34'

packages/toolbox-langchain/integration.cloudbuild.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,5 @@ options:
4747
logging: CLOUD_LOGGING_ONLY
4848
substitutions:
4949
_VERSION: '3.13'
50-
_TOOLBOX_VERSION: '0.17.0'
50+
_TOOLBOX_VERSION: '0.19.1'
5151
_TOOLBOX_MANIFEST_VERSION: '34'

packages/toolbox-langchain/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ authors = [
1010
]
1111
dependencies = [
1212
"toolbox-core==0.5.2", # x-release-please-version
13-
"langchain-core>=0.2.23,<1.0.0",
13+
"langchain-core>=0.2.23,<2.0.0",
1414
"PyYAML>=6.0.1,<7.0.0",
1515
"pydantic>=2.7.0,<3.0.0",
1616
"aiohttp>=3.8.6,<4.0.0",

packages/toolbox-llamaindex/integration.cloudbuild.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,5 @@ options:
4747
logging: CLOUD_LOGGING_ONLY
4848
substitutions:
4949
_VERSION: '3.13'
50-
_TOOLBOX_VERSION: '0.17.0'
50+
_TOOLBOX_VERSION: '0.19.1'
5151
_TOOLBOX_MANIFEST_VERSION: '34'

0 commit comments

Comments
 (0)