|
| 1 | +--- |
| 2 | +title: Configure GitHub Actions for CI/CD |
| 3 | +weight: 5 |
| 4 | + |
| 5 | +### FIXED, DO NOT MODIFY |
| 6 | +layout: learningpathall |
| 7 | +--- |
| 8 | + |
| 9 | +## Why use GitHub Actions for MCP testing? |
| 10 | + |
| 11 | +GitHub Actions provide automated CI/CD directly in your repository. For MCP server testing, it offers: |
| 12 | + |
| 13 | +- **Arm runner support**: GitHub provides native Arm64 runners for building and testing. |
| 14 | +- **Docker integration**: Runners come with Docker pre-installed. |
| 15 | +- **Automatic triggers**: Tests run on every push and pull request. |
| 16 | +- **Parallel execution**: Multiple jobs can run simultaneously. |
| 17 | + |
| 18 | +## Create the workflow file |
| 19 | + |
| 20 | +Create a GitHub Actions workflow file at `.github/workflows/integration-tests.yml`: |
| 21 | + |
| 22 | +```yaml |
| 23 | +name: Integration Tests |
| 24 | + |
| 25 | +on: |
| 26 | + push: |
| 27 | + pull_request: |
| 28 | + |
| 29 | +jobs: |
| 30 | + integration-tests: |
| 31 | + runs-on: ubuntu-24.04-arm |
| 32 | + steps: |
| 33 | + - name: Checkout |
| 34 | + uses: actions/checkout@v4 |
| 35 | + |
| 36 | + - name: Set up Python |
| 37 | + uses: actions/setup-python@v5 |
| 38 | + with: |
| 39 | + python-version: "3.11" |
| 40 | + cache: pip |
| 41 | + |
| 42 | + - name: Install test dependencies |
| 43 | + run: | |
| 44 | + python -m pip install --upgrade pip |
| 45 | + pip install -r mcp-local/tests/requirements.txt |
| 46 | +
|
| 47 | + - name: Build MCP Docker image |
| 48 | + run: docker buildx build -f mcp-local/Dockerfile -t arm-mcp . |
| 49 | + |
| 50 | + - name: Run integration tests |
| 51 | + env: |
| 52 | + MCP_IMAGE: arm-mcp:latest |
| 53 | + run: pytest -v mcp-local/tests/test_mcp.py |
| 54 | +``` |
| 55 | +
|
| 56 | +## Understand the workflow configuration |
| 57 | +
|
| 58 | +The workflow uses the `ubuntu-24.04-arm` runner, which is a GitHub-hosted Arm64 runner. This ensures that both the Docker build and the tests execute natively on Arm hardware. |
| 59 | + |
| 60 | +Key aspects of the configuration: |
| 61 | + |
| 62 | +### Trigger events |
| 63 | + |
| 64 | +```yaml |
| 65 | +on: |
| 66 | + push: |
| 67 | + pull_request: |
| 68 | +``` |
| 69 | + |
| 70 | +This configuration triggers the workflow on every push to any branch and on pull request events. You can restrict this to specific branches if needed: |
| 71 | + |
| 72 | +```yaml |
| 73 | +on: |
| 74 | + push: |
| 75 | + branches: [main, develop] |
| 76 | + pull_request: |
| 77 | + branches: [main] |
| 78 | +``` |
| 79 | + |
| 80 | +### Python caching |
| 81 | + |
| 82 | +```yaml |
| 83 | +- name: Set up Python |
| 84 | + uses: actions/setup-python@v5 |
| 85 | + with: |
| 86 | + python-version: "3.11" |
| 87 | + cache: pip |
| 88 | +``` |
| 89 | + |
| 90 | +The `cache: pip` option caches Python packages between runs, significantly speeding up subsequent workflow executions. |
| 91 | + |
| 92 | +### Environment variables |
| 93 | + |
| 94 | +```yaml |
| 95 | +- name: Run integration tests |
| 96 | + env: |
| 97 | + MCP_IMAGE: arm-mcp:latest |
| 98 | + run: pytest -v mcp-local/tests/test_mcp.py |
| 99 | +``` |
| 100 | + |
| 101 | +The `MCP_IMAGE` environment variable tells the test suite which Docker image to use. The test code reads this with: |
| 102 | + |
| 103 | +```python |
| 104 | +image = os.getenv("MCP_IMAGE", constants.MCP_DOCKER_IMAGE) |
| 105 | +``` |
| 106 | + |
| 107 | +## Add test result artifacts |
| 108 | + |
| 109 | +Enhance the workflow to save test results as artifacts for debugging: |
| 110 | + |
| 111 | +```yaml |
| 112 | + - name: Run integration tests |
| 113 | + env: |
| 114 | + MCP_IMAGE: arm-mcp:latest |
| 115 | + run: pytest -v mcp-local/tests/test_mcp.py --junitxml=test-results.xml |
| 116 | +
|
| 117 | + - name: Upload test results |
| 118 | + uses: actions/upload-artifact@v4 |
| 119 | + if: always() |
| 120 | + with: |
| 121 | + name: test-results |
| 122 | + path: test-results.xml |
| 123 | +``` |
| 124 | + |
| 125 | +The `if: always()` condition ensures test results upload even when tests fail. |
| 126 | + |
| 127 | +## Add a build matrix for multiple platforms |
| 128 | + |
| 129 | +To test on both Arm64 and x86_64, use a matrix strategy: |
| 130 | + |
| 131 | +```yaml |
| 132 | +jobs: |
| 133 | + integration-tests: |
| 134 | + strategy: |
| 135 | + matrix: |
| 136 | + runner: [ubuntu-24.04-arm, ubuntu-latest] |
| 137 | + runs-on: ${{ matrix.runner }} |
| 138 | + steps: |
| 139 | + # ... same steps as before |
| 140 | +``` |
| 141 | + |
| 142 | +This runs the integration tests in parallel on both architectures. |
| 143 | + |
| 144 | +## Monitor workflow runs |
| 145 | + |
| 146 | +After pushing the workflow file, navigate to the Actions tab in your GitHub repository. Each workflow run shows: |
| 147 | + |
| 148 | +- Build steps and their status |
| 149 | +- Execution time for each step |
| 150 | +- Log output for debugging failures |
| 151 | +- Artifacts for download |
| 152 | + |
| 153 | +## Troubleshoot common issues |
| 154 | + |
| 155 | +If the workflow fails, check these common causes: |
| 156 | + |
| 157 | +**Docker build timeout**: The initial image build can take 10+ minutes. GitHub Actions has a default timeout of 360 minutes per job, but individual steps might need explicit timeouts: |
| 158 | + |
| 159 | +```yaml |
| 160 | +- name: Build MCP Docker image |
| 161 | + timeout-minutes: 30 |
| 162 | + run: docker buildx build -f mcp-local/Dockerfile -t arm-mcp . |
| 163 | +``` |
| 164 | + |
| 165 | +**Container startup issues**: If tests fail with timeout errors, the MCP server might not be starting correctly. Add debug output: |
| 166 | + |
| 167 | +```yaml |
| 168 | +- name: Run integration tests |
| 169 | + env: |
| 170 | + MCP_IMAGE: arm-mcp:latest |
| 171 | + run: | |
| 172 | + docker run --rm arm-mcp:latest echo "Container starts successfully" |
| 173 | + pytest -v -s mcp-local/tests/test_mcp.py |
| 174 | +``` |
| 175 | + |
| 176 | +**Rate limiting**: If tests query external services, you might encounter rate limits. Consider adding retry logic or using mock responses for CI environments. |
| 177 | + |
| 178 | +## What you've accomplished and what's next |
| 179 | + |
| 180 | +In this section: |
| 181 | +- You created a GitHub Actions workflow for automated testing. |
| 182 | +- You learned how to use Arm64 runners for native execution. |
| 183 | +- You added test artifacts and multi-platform support. |
| 184 | +- You explored troubleshooting techniques for CI failures. |
| 185 | + |
| 186 | +You now have a complete CI/CD pipeline that automatically tests your MCP server on every code change. |
| 187 | + |
| 188 | +## Summary |
| 189 | + |
| 190 | +In this Learning Path, you learned how to: |
| 191 | + |
| 192 | +- Set up testcontainers for Docker-based integration testing. |
| 193 | +- Write pytest tests that communicate with MCP servers over stdio transport. |
| 194 | +- Parse MCP JSON-RPC responses and validate tool outputs. |
| 195 | +- Configure GitHub Actions with Arm64 runners for automated testing. |
| 196 | + |
| 197 | +These techniques apply to any MCP server implementation, not just the Arm MCP Server. Use this foundation to build comprehensive test suites that ensure your MCP tools work correctly across updates and deployments. |
0 commit comments