|
| 1 | +name: Build experimental Docker image |
| 2 | + |
| 3 | +# Builds ghcr.io/boettiger-lab/mcp-data-server:experimental from |
| 4 | +# Dockerfile.experimental — the default image plus the `raster` and `zarr` |
| 5 | +# community extensions (issue #354). |
| 6 | +# |
| 7 | +# Deliberately NOT triggered by pushes to main. This tag backs a single testing |
| 8 | +# endpoint (experimental-duckdb-mcp) and is meant to move only when someone is |
| 9 | +# actually exercising it; an automatic rebuild on every main push would swap the |
| 10 | +# image under a live test session. |
| 11 | +# |
| 12 | +# BASE_TAG selects which default image to layer on. It defaults to :main, so the |
| 13 | +# experimental build inherits main's dependency and stock-extension layers while |
| 14 | +# `COPY . /app` overlays the code from *this* ref — that is what lets the tag carry |
| 15 | +# server changes before they merge. When main's deps move, re-run this workflow. |
| 16 | +on: |
| 17 | + push: |
| 18 | + branches: ['experimental/**'] |
| 19 | + workflow_dispatch: |
| 20 | + inputs: |
| 21 | + base_tag: |
| 22 | + description: 'Default image tag to layer on (e.g. main, v0.8.12, or a sha)' |
| 23 | + required: false |
| 24 | + default: 'main' |
| 25 | + |
| 26 | +jobs: |
| 27 | + build: |
| 28 | + runs-on: ubuntu-latest |
| 29 | + permissions: |
| 30 | + contents: read |
| 31 | + packages: write |
| 32 | + steps: |
| 33 | + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 |
| 34 | + |
| 35 | + - name: Log in to GHCR |
| 36 | + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 |
| 37 | + with: |
| 38 | + registry: ghcr.io |
| 39 | + username: ${{ github.actor }} |
| 40 | + password: ${{ secrets.GITHUB_TOKEN }} |
| 41 | + |
| 42 | + - name: Set up Buildx |
| 43 | + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 |
| 44 | + |
| 45 | + - name: Build and push |
| 46 | + id: build |
| 47 | + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 |
| 48 | + with: |
| 49 | + context: . |
| 50 | + file: Dockerfile.experimental |
| 51 | + push: true |
| 52 | + tags: ghcr.io/boettiger-lab/mcp-data-server:experimental |
| 53 | + build-args: | |
| 54 | + BASE_TAG=${{ github.event.inputs.base_tag || 'main' }} |
| 55 | + APP_VERSION=experimental |
| 56 | + GIT_SHA=${{ github.sha }} |
| 57 | + # Always pull, so a moving BASE_TAG (:main) is actually re-resolved |
| 58 | + # rather than served from a stale local base. |
| 59 | + pull: true |
| 60 | + cache-from: type=gha |
| 61 | + cache-to: type=gha,mode=max |
| 62 | + |
| 63 | + - name: Smoke-test image |
| 64 | + run: | |
| 65 | + image="ghcr.io/boettiger-lab/mcp-data-server@${{ steps.build.outputs.digest }}" |
| 66 | + docker pull "$image" |
| 67 | + # Stock extensions must still work, and both extras must load and expose |
| 68 | + # their entry points — a silently-missing extension would otherwise only |
| 69 | + # surface as a confusing "function does not exist" at query time. |
| 70 | + docker run --rm "$image" python -c " |
| 71 | + import duckdb |
| 72 | + c = duckdb.connect() |
| 73 | + for e in ('httpfs', 'spatial', 'h3', 'raster', 'zarr'): |
| 74 | + c.sql(f'LOAD {e}') |
| 75 | + c.sql('SELECT h3_latlng_to_cell(37.8, -122.4, 5)') |
| 76 | + c.sql('SELECT ST_Point(0, 0)') |
| 77 | + for fn in ('RT_ReadCells', 'read_zarr'): |
| 78 | + n = c.sql(f\"SELECT count(*) FROM duckdb_functions() WHERE function_name ILIKE '{fn}'\").fetchone()[0] |
| 79 | + assert n, f'{fn} missing' |
| 80 | + print('OK: httpfs/spatial/h3 + raster/zarr loaded and functional') |
| 81 | + " |
| 82 | +
|
| 83 | + - name: Report image digest |
| 84 | + run: | |
| 85 | + { |
| 86 | + echo '### Experimental image digest' |
| 87 | + echo '```' |
| 88 | + echo "${{ steps.build.outputs.digest }}" |
| 89 | + echo '```' |
| 90 | + } >> "$GITHUB_STEP_SUMMARY" |
0 commit comments