-
Notifications
You must be signed in to change notification settings - Fork 0
feat(ci): testing tuto capabilities in github actions #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
farah-t-trigui
wants to merge
2
commits into
main
Choose a base branch
from
feat/automating-tuto-examples-testing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,235 @@ | ||
| on: | ||
| push: | ||
| paths: | ||
| - 'src/main/**' | ||
| - 'pom.xml' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| test-tutorial: | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }} | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Pull Naftiko Docker image | ||
| run: docker pull ghcr.io/naftiko/framework:latest | ||
|
|
||
| - name: Run Naftiko with My First Capability | ||
| run: | | ||
| docker run -d \ | ||
| -p 8081:8081 \ | ||
| -v ${{ github.workspace }}/src/main/resources/schemas/tutorial/step-1-my-first-capability.yml:/app/step-1-my-first-capability.yml \ | ||
| --name my_first_capability \ | ||
| ghcr.io/naftiko/framework:latest \ | ||
| /app/step-1-my-first-capability.yml | ||
|
|
||
| - name: Consume /hello endpoint - My First Capability | ||
| run: | | ||
| # Wait for the Naftiko framework to fully start before hitting the endpoint | ||
| sleep 2 | ||
| RESPONSE=$(curl -s -f http://localhost:8081/hello || true) | ||
| if [[ -z "$RESPONSE" ]]; then | ||
| echo "My First Capability endpoint did not respond in time" | ||
| exit 1 | ||
| fi | ||
| echo "Response: $RESPONSE" | ||
|
|
||
| - name: Show logs - My First Capability | ||
| if: always() | ||
| run: docker logs my_first_capability | ||
|
|
||
| - name: Stop My First Capability container | ||
| if: always() | ||
| run: | | ||
| docker stop my_first_capability | ||
| docker rm my_first_capability | ||
|
|
||
| - name: Run Naftiko with Forwarding API Resource | ||
| run: | | ||
| docker run -d \ | ||
| -p 8081:8081 \ | ||
| -v ${{ github.workspace }}/src/main/resources/schemas/tutorial/step-2-forwarding-api-resource.yml:/app/step-2-forwarding-api-resource.yml \ | ||
| --name forwarding_api_resource \ | ||
| ghcr.io/naftiko/framework:latest \ | ||
| /app/step-2-forwarding-api-resource.yml | ||
|
|
||
| - name: Consume /notion/users/me endpoint - Forwarding API Resource | ||
| run: | | ||
| # Wait for the Naftiko framework to fully start before hitting the endpoint | ||
| sleep 2 | ||
| RESPONSE=$(curl -s -f \ | ||
| -H "Authorization: Bearer $NOTION_API_KEY" \ | ||
| -H "Notion-Version: 2025-09-03" \ | ||
| http://localhost:8081/notion/users/me || true) | ||
| if [[ -z "$RESPONSE" ]]; then | ||
| echo "Forwarding API Resource endpoint did not respond in time" | ||
| exit 1 | ||
| fi | ||
| echo "Response: $RESPONSE" | ||
|
|
||
| - name: Show logs - Forwarding API Resource | ||
| if: always() | ||
| run: docker logs forwarding_api_resource | ||
|
|
||
| - name: Stop Forwarding API Resource container | ||
| if: always() | ||
| run: | | ||
| docker stop forwarding_api_resource | ||
| docker rm forwarding_api_resource | ||
|
|
||
| - name: Run Naftiko with Encapsulating Headers | ||
| run: | | ||
| docker run -d \ | ||
| -p 8081:8081 \ | ||
| -v ${{ github.workspace }}/src/main/resources/schemas/tutorial/step-3-encapsulating-headers.yml:/app/step-3-encapsulating-headers.yml \ | ||
| --env notion_api_key=$NOTION_API_KEY \ | ||
| --name encapsulating_headers \ | ||
| ghcr.io/naftiko/framework:latest \ | ||
| /app/step-3-encapsulating-headers.yml | ||
|
|
||
| - name: Consume /notion/users/me endpoint - Encapsulating Headers | ||
| run: | | ||
| # Wait for the Naftiko framework to fully start before hitting the endpoint | ||
| sleep 2 | ||
| RESPONSE=$(curl -s -f http://localhost:8081/notion/users/me || true) | ||
| if [[ -z "$RESPONSE" ]]; then | ||
| echo "Encapsulating Headers endpoint did not respond in time" | ||
| exit 1 | ||
| fi | ||
| echo "Response: $RESPONSE" | ||
|
|
||
| - name: Show logs - Encapsulating Headers | ||
| if: always() | ||
| run: docker logs encapsulating_headers | ||
|
|
||
| - name: Stop Encapsulating Headers container | ||
| if: always() | ||
| run: | | ||
| docker stop encapsulating_headers | ||
| docker rm encapsulating_headers | ||
|
|
||
| - name: Run Naftiko with Filter Response | ||
| run: | | ||
| docker run -d \ | ||
| -p 8081:8081 \ | ||
| -v ${{ github.workspace }}/src/main/resources/schemas/tutorial/step-4-filter-reponse.yml:/app/step-4-filter-reponse.yml \ | ||
| --env notion_api_key=$NOTION_API_KEY \ | ||
| --name filter_response \ | ||
| ghcr.io/naftiko/framework:latest \ | ||
| /app/step-4-filter-reponse.yml | ||
|
|
||
| - name: Consume /notion/users/me endpoint - Filter Response | ||
| run: | | ||
| # Wait for the Naftiko framework to fully start before hitting the endpoint | ||
| sleep 2 | ||
| RESPONSE=$(curl -s -f http://localhost:8081/notion/users/me || true) | ||
| if [[ -z "$RESPONSE" ]]; then | ||
| echo "Filter Response endpoint did not respond in time" | ||
| exit 1 | ||
| fi | ||
| echo "Response: $RESPONSE" | ||
|
|
||
| - name: Show logs - Filter Response | ||
| if: always() | ||
| run: docker logs filter_response | ||
|
|
||
| - name: Stop Step - Filter Response | ||
| if: always() | ||
| run: | | ||
| docker stop filter_response | ||
| docker rm filter_response | ||
|
|
||
| - name: Run Naftiko with Multi Steps | ||
| run: | | ||
| docker run -d \ | ||
| -p 8081:8081 \ | ||
| -v ${{ github.workspace }}/src/main/resources/schemas/tutorial/step-5-multi-steps.yml:/app/step-5-multi-steps.yml \ | ||
| --env notion_api_key=$NOTION_API_KEY \ | ||
| --name multi_steps \ | ||
| ghcr.io/naftiko/framework:latest \ | ||
| /app/step-5-multi-steps.yml | ||
|
|
||
| - name: Consume /notion/my-full-user endpoint - Multi Steps | ||
| run: | | ||
| # Wait for the Naftiko framework to fully start before hitting the endpoint | ||
| sleep 2 | ||
| RESPONSE=$(curl -s -f http://localhost:8081/notion/my-full-user || true) | ||
| if [[ -z "$RESPONSE" ]]; then | ||
| echo "Multi Steps endpoint did not respond in time" | ||
| exit 1 | ||
| fi | ||
| echo "Response: $RESPONSE" | ||
|
|
||
| - name: Show logs - Multi Steps | ||
| if: always() | ||
| run: docker logs multi_steps | ||
|
|
||
| - name: Stop Multi Steps container | ||
| if: always() | ||
| run: | | ||
| docker stop multi_steps | ||
| docker rm multi_steps | ||
|
|
||
| - name: Run Naftiko with MCP Server | ||
| run: | | ||
| docker run -d \ | ||
| -p 9091:9091 \ | ||
| -v ${{ github.workspace }}/src/main/resources/schemas/tutorial/step-6-mcp.yml:/app/step-6-mcp.yml \ | ||
| --env notion_api_key=$NOTION_API_KEY \ | ||
| --name mcp_server \ | ||
| ghcr.io/naftiko/framework:latest \ | ||
| /app/step-6-mcp.yml | ||
|
|
||
| - name: Calling MCP server | ||
| run: | | ||
| # Wait for the Naftiko framework to fully start before hitting the endpoint | ||
| sleep 2 | ||
| if ! nc -z localhost 9091; then | ||
| echo "MCP server did not start in time" | ||
| exit 1 | ||
| fi | ||
| echo "MCP server ready" | ||
| - name: Install yq | ||
| run: | | ||
| sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 | ||
| sudo chmod +x /usr/local/bin/yq | ||
| - name: Test MCP tools/list | ||
| run: | | ||
| RESPONSE=$(curl -s -f -X POST http://localhost:9091 \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' || true) | ||
| if [[ -z "$RESPONSE" ]]; then | ||
| echo "MCP tools/list did not respond" | ||
| exit 1 | ||
| fi | ||
| echo "Response: $RESPONSE" | ||
| CAPABILITY_FILE="${{ github.workspace }}/src/main/resources/schemas/tutorial/step-6-mcp.yml" | ||
| EXPECTED_COUNT=$(yq '.capability.exposes[0].tools | length' "$CAPABILITY_FILE") | ||
| EXPECTED_NAMES=$(yq '.capability.exposes[0].tools[].name' "$CAPABILITY_FILE") | ||
| ACTUAL_COUNT=$(echo "$RESPONSE" | jq '.result.tools | length') | ||
| if [[ "$ACTUAL_COUNT" != "$EXPECTED_COUNT" ]]; then | ||
| echo "Expected $EXPECTED_COUNT tool(s), got $ACTUAL_COUNT" | ||
| exit 1 | ||
| fi | ||
| while IFS= read -r EXPECTED_NAME; do | ||
| FOUND=$(echo "$RESPONSE" | jq -r --arg name "$EXPECTED_NAME" '.result.tools[] | select(.name == $name) | .name') | ||
| if [[ -z "$FOUND" ]]; then | ||
| echo "Expected tool '$EXPECTED_NAME' not found in response" | ||
| exit 1 | ||
| fi | ||
| done <<< "$EXPECTED_NAMES" | ||
| echo "tools/list validation passed: $ACTUAL_COUNT tool(s) matched" | ||
|
|
||
| - name: Show logs MCP Server | ||
| if: always() | ||
| run: docker logs mcp_server | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are missing an actual test here of the tools here. A list "tools/list" seems to be sufficient for now, please add it =) |
||
| - name: Stop MCP Server container | ||
| if: always() | ||
| run: | | ||
| docker stop mcp_server | ||
| docker rm mcp_server | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add comment explaining we need to wait for the framework to start. Also I ma wondering : should not we put the sleep at the end of the Run action rather than the wait one. What do you think ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping it in the wait step is better because the run step has one job which is to start the container. The wait step has one job: ensure it's ready
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means if we setup the run once but perform 70 tests on it, we will wait 70 times for 2 seconds ? If we know we need 2 seconds for the docker to be up and running, it feels more efficient to sleep when we setup it rather than every time we will call it, don't you think ?