name: Docker Build and Push on: pull_request: branches: [main] push: branches: [main] schedule: - cron: '0 0 * * *' jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: python-version: "3.15" - name: Install dependencies run: | pip install -r requirements.txt pytest - name: Run unit tests run: pytest tests/ -v --ignore=tests/test_integration.py integration-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Start Qdrant run: | docker rm -f qdrant-${{ github.run_id }} 2>/dev/null || true docker run -d --name qdrant-${{ github.run_id }} \ --network "container:$(hostname)" \ docker.io/qdrant/qdrant:v1.19 - name: Wait for Qdrant run: | # /healthz answers before the storage engine accepts writes, and a cold # container on a loaded host can take several seconds to create its # first collection. Gate on a real write round-trip, not on /healthz. ready="" for i in $(seq 1 60); do if curl -sf "http://localhost:6333/healthz" > /dev/null 2>&1 \ && curl -sf -X PUT "http://localhost:6333/collections/ci_readiness_probe?timeout=60" \ -H 'Content-Type: application/json' \ -d '{"vectors":{"size":4,"distance":"Cosine"}}' > /dev/null 2>&1; then curl -sf -X DELETE "http://localhost:6333/collections/ci_readiness_probe" > /dev/null 2>&1 || true ready="yes" echo "QDRANT ready: write path OK (attempt $i)" break fi echo "Waiting for Qdrant... ($i/60)" sleep 1 done if [ -z "$ready" ]; then echo "Qdrant write path never became ready" docker logs --tail 100 qdrant-${{ github.run_id }} || true exit 1 fi - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: python-version: "3.15" - name: Install dependencies run: | pip install -r requirements.txt pytest - name: Run integration tests run: pytest tests/ -v -m integration env: QDRANT_URL: http://localhost:6333 COLLECTION_NAME: test_mcp_maildir # The qdrant client defaults to a 5s request timeout, which a cold # collection on a shared runner can exceed; this job has no SLA. QDRANT_TIMEOUT: "60" - name: Qdrant diagnostics if: failure() run: | docker ps -a || true docker logs --tail 200 qdrant-${{ github.run_id }} || true - name: Cleanup Qdrant if: always() run: docker rm -f qdrant-${{ github.run_id }} 2>/dev/null || true build: runs-on: ubuntu-latest needs: [test, integration-test] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Docker Buildx uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4 - name: Login to Docker Hub if: github.event_name != 'pull_request' uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker metadata id: meta uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6 with: images: jcabillot/mcp-maildir tags: | type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7 with: context: . file: pkg/Dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} pull: true