RFC: Plugin Extension System — runtime intelligence, hosted MCP, and plugin ecosystem #2
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
| name: Build and Publish Plugin Images | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_PREFIX: ${{ github.repository_owner }} | |
| jobs: | |
| # ── Read the service matrix from services.json ────────────────────────── | |
| setup: | |
| name: Load service matrix | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.load.outputs.matrix }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Load services.json into matrix | |
| id: load | |
| run: | | |
| # Filter to plugin services only (skip cgc-core — handled by docker-publish.yml) | |
| MATRIX=$(cat .github/services.json | jq -c '[.[] | select(.name != "cgc-core")]') | |
| echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT" | |
| # ── Build, smoke-test, and optionally push each plugin image ──────────── | |
| build-plugins: | |
| name: Build ${{ matrix.name }} | |
| needs: setup | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| include: ${{ fromJson(needs.setup.outputs.matrix) }} | |
| fail-fast: false | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/${{ matrix.image }} | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=semver,pattern={{major}} | |
| type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }} | |
| type=ref,event=pr | |
| type=sha,prefix=sha- | |
| labels: | | |
| org.opencontainers.image.title=${{ matrix.name }} | |
| org.opencontainers.image.description=${{ matrix.description }} | |
| org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} | |
| - name: Build image (load locally for smoke test) | |
| id: build-local | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ${{ matrix.path }} | |
| file: ${{ matrix.path }}/${{ matrix.dockerfile }} | |
| push: false | |
| load: true | |
| tags: smoke-test/${{ matrix.image }}:ci | |
| cache-from: type=gha,scope=${{ matrix.name }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.name }} | |
| - name: Smoke test — gRPC import | |
| if: matrix.health_check == 'grpc_ping' | |
| run: docker run --rm smoke-test/${{ matrix.image }}:ci python -c "import grpc; print('gRPC OK')" | |
| - name: Smoke test — Python import | |
| if: matrix.health_check == 'http_health' | |
| run: docker run --rm smoke-test/${{ matrix.image }}:ci python -c "import cgc_plugin_memory; print('memory OK')" | |
| - name: Smoke test — socket | |
| if: matrix.health_check == 'tcp_connect' | |
| run: docker run --rm smoke-test/${{ matrix.image }}:ci python -c "import socket; socket.socket(); print('socket OK')" | |
| - name: Push image to GHCR | |
| if: github.event_name != 'pull_request' | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ${{ matrix.path }} | |
| file: ${{ matrix.path }}/${{ matrix.dockerfile }} | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=${{ matrix.name }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.name }} | |
| platforms: linux/amd64,linux/arm64 | |
| # ── Summary ────────────────────────────────────────────────────────────── | |
| build-summary: | |
| name: Plugin build summary | |
| needs: build-plugins | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Report overall status | |
| run: | | |
| if [ "${{ needs.build-plugins.result }}" = "success" ]; then | |
| echo "✅ All plugin images built successfully." | |
| else | |
| echo "⚠️ One or more plugin images failed. Check individual job logs." | |
| exit 1 | |
| fi |