@@ -3,24 +3,192 @@ name: Build and Push Tutorial Agent
33on :
44 workflow_dispatch :
55 inputs :
6- agent_path :
7- description : " Path to the agent directory (e.g., examples/tutorials/10_agentic/00_base/000_hello_acp)"
8- required : true
9- type : string
10- version_tag :
11- description : " Version tag for the agent build (e.g., v1.0.0, latest)"
12- required : true
13- type : string
14- default : " latest"
15-
16- workflow_call :
17- inputs :
18- agent_path :
19- description : " Path to the agent directory"
20- required : true
21- type : string
22- version_tag :
23- description : " Version tag for the agent build"
24- required : true
25- type : string
26- default : " latest"
6+ rebuild_all :
7+ description : " Rebuild all tutorial agents regardless of changes, this is reserved for maintainers only."
8+ required : false
9+ type : boolean
10+ default : false
11+
12+ pull_request :
13+ paths :
14+ - " examples/tutorials/**"
15+
16+ push :
17+ branches :
18+ - main
19+ paths :
20+ - " examples/tutorials/**"
21+
22+ permissions :
23+ contents : read
24+ packages : write
25+
26+ jobs :
27+ check-permissions :
28+ if : ${{ github.event_name == 'workflow_dispatch' }}
29+ runs-on : ubuntu-latest
30+ steps :
31+ - name : Check if user is maintainer
32+ uses : actions/github-script@v7
33+ with :
34+ script : |
35+ const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
36+ owner: context.repo.owner,
37+ repo: context.repo.repo,
38+ username: context.actor
39+ });
40+
41+ const allowedRoles = ['admin', 'maintain'];
42+ if (!allowedRoles.includes(permission.permission)) {
43+ throw new Error(`❌ User ${context.actor} does not have sufficient permissions. Required: ${allowedRoles.join(', ')}. Current: ${permission.permission}`);
44+ }
45+
46+ find-agents :
47+ runs-on : ubuntu-latest
48+ needs : [check-permissions]
49+ if : ${{ !cancelled() && !failure() }}
50+ outputs :
51+ agents : ${{ steps.get-agents.outputs.agents }}
52+ has_agents : ${{ steps.get-agents.outputs.has_agents }}
53+ steps :
54+ - name : Checkout repository
55+ uses : actions/checkout@v4
56+ with :
57+ fetch-depth : 0 # Fetch full history for git diff
58+
59+ - name : Find tutorial agents to build
60+ id : get-agents
61+ env :
62+ REBUILD_ALL : ${{ inputs.rebuild_all }}
63+ run : |
64+ # Find all tutorial directories with manifest.yaml
65+ all_agents=$(find examples/tutorials -name "manifest.yaml" -exec dirname {} \; | sort)
66+ agents_to_build=()
67+
68+ if [ "$REBUILD_ALL" = "true" ]; then
69+ echo "Rebuild all agents requested"
70+ agents_to_build=($(echo "$all_agents"))
71+
72+ echo "### 🔄 Rebuilding All Tutorial Agents" >> $GITHUB_STEP_SUMMARY
73+ else
74+ # Determine the base branch for comparison
75+ if [ "${{ github.event_name }}" = "pull_request" ]; then
76+ BASE_BRANCH="origin/${{ github.base_ref }}"
77+ echo "Comparing against PR base branch: $BASE_BRANCH"
78+ else
79+ BASE_BRANCH="HEAD~1"
80+ echo "Comparing against previous commit: $BASE_BRANCH"
81+ fi
82+
83+ # Check each agent directory for changes
84+ for agent_dir in $all_agents; do
85+ echo "Checking $agent_dir for changes..."
86+
87+ # Check if any files in this agent directory have changed
88+ if git diff --name-only $BASE_BRANCH HEAD | grep -q "^$agent_dir/"; then
89+ echo " ✅ Changes detected in $agent_dir"
90+ agents_to_build+=("$agent_dir")
91+ else
92+ echo " ⏭️ No changes in $agent_dir - skipping build"
93+ fi
94+ done
95+
96+ echo "### 🔄 Changed Tutorial Agents" >> $GITHUB_STEP_SUMMARY
97+ fi
98+
99+ # Convert array to JSON format and output summary
100+ if [ ${#agents_to_build[@]} -eq 0 ]; then
101+ echo "No agents to build"
102+ echo "agents=[]" >> $GITHUB_OUTPUT
103+ echo "has_agents=false" >> $GITHUB_OUTPUT
104+ else
105+ echo "Agents to build: ${#agents_to_build[@]}"
106+ agents_json=$(printf '%s\n' "${agents_to_build[@]}" | jq -R -s -c 'split("\n") | map(select(length > 0))')
107+ echo "agents=$agents_json" >> $GITHUB_OUTPUT
108+ echo "has_agents=true" >> $GITHUB_OUTPUT
109+
110+ echo "" >> $GITHUB_STEP_SUMMARY
111+ for agent in "${agents_to_build[@]}"; do
112+ echo "- \`$agent\`" >> $GITHUB_STEP_SUMMARY
113+ done
114+ echo "" >> $GITHUB_STEP_SUMMARY
115+ fi
116+
117+ build-agents :
118+ needs : find-agents
119+ if : ${{ needs.find-agents.outputs.has_agents == 'true' }}
120+ runs-on : ubuntu-latest
121+ timeout-minutes : 15
122+ strategy :
123+ matrix :
124+ agent_path : ${{ fromJson(needs.find-agents.outputs.agents) }}
125+ fail-fast : false
126+
127+ name : build-${{ matrix.agent_path }}
128+ steps :
129+ - name : Checkout repository
130+ uses : actions/checkout@v4
131+
132+ - name : Set up Docker Buildx
133+ uses : docker/setup-buildx-action@v3
134+
135+ - name : Set up Python
136+ uses : actions/setup-python@v4
137+ with :
138+ python-version : " 3.12"
139+
140+ - name : Get latest agentex-sdk version from PyPI
141+ id : get-version
142+ run : |
143+ LATEST_VERSION=$(curl -s https://pypi.org/pypi/agentex-sdk/json | jq -r '.info.version')
144+ echo "Latest agentex-sdk version: $LATEST_VERSION"
145+ echo "AGENTEX_SDK_VERSION=$LATEST_VERSION" >> $GITHUB_ENV
146+ pip install agentex-sdk==$LATEST_VERSION
147+ echo "Installed agentex-sdk version $LATEST_VERSION"
148+
149+ - name : Generate Image name
150+ id : image-name
151+ run : |
152+ # Remove examples/tutorials/ prefix and replace / with -
153+ AGENT_NAME=$(echo "${{ matrix.agent_path }}" | sed 's|^examples/tutorials/||' | sed 's|/|-|g')
154+ echo "AGENT_NAME=$AGENT_NAME" >> $GITHUB_ENV
155+ echo "agent_name=$AGENT_NAME" >> $GITHUB_OUTPUT
156+ echo "Agent name set to $AGENT_NAME"
157+
158+ - name : Login to GitHub Container Registry
159+ # Only login if we're going to push (main branch or rebuild_all)
160+ if : ${{ github.event_name == 'push' || inputs.rebuild_all }}
161+ uses : docker/login-action@v3
162+ with :
163+ registry : ghcr.io
164+ username : ${{ github.actor }}
165+ password : ${{ secrets.GITHUB_TOKEN }}
166+
167+ - name : Build and Conditionally Push Agent Image
168+ env :
169+ REGISTRY : ghcr.io
170+ run : |
171+ AGENT_NAME="${{ steps.image-name.outputs.agent_name }}"
172+ REPOSITORY_NAME="${{ github.repository }}/tutorial-agents/${AGENT_NAME}"
173+
174+ # Determine if we should push based on event type
175+ if [ "${{ github.event_name }}" = "push" ] || [ "${{ inputs.rebuild_all }}" = "true" ]; then
176+ SHOULD_PUSH=true
177+ VERSION_TAG="latest"
178+ echo "🚀 Building and pushing agent: ${{ matrix.agent_path }}"
179+ else
180+ SHOULD_PUSH=false
181+ VERSION_TAG="${{ github.commit.sha }}"
182+ echo "🔍 Validating build for agent: ${{ matrix.agent_path }}"
183+ fi
184+
185+ # Build command - add --push only if we should push
186+ BUILD_ARGS="--manifest ${{ matrix.agent_path }}/manifest.yaml --registry ${REGISTRY} --tag ${VERSION_TAG} --platforms linux/amd64 --repository-name ${REPOSITORY_NAME}"
187+
188+ if [ "$SHOULD_PUSH" = "true" ]; then
189+ agentex agents build $BUILD_ARGS --push
190+ echo "✅ Successfully built and pushed: ${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}"
191+ else
192+ agentex agents build $BUILD_ARGS
193+ echo "✅ Build validation successful for: ${{ matrix.agent_path }}"
194+ fi
0 commit comments