diff --git a/.github/workflows/benchmark-issue79.yml b/.github/workflows/benchmark-issue79.yml index ebf1626..022d430 100644 --- a/.github/workflows/benchmark-issue79.yml +++ b/.github/workflows/benchmark-issue79.yml @@ -70,7 +70,7 @@ jobs: - name: Build Docker image run: | docker build \ - --build-arg MYSQL_VERSION=8.4 \ + --build-arg MYSQL_VERSION=8.4.8 \ --build-arg TARGETARCH=amd64 \ -t ghcr.io/${{ github.repository }}:mysql8.4-fix-issue79 \ -f Dockerfile.oraclelinux9 \ diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8d75fbc..9398ba0 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -20,22 +20,30 @@ jobs: # Publish plugin images only from a dispatch that targets a VERSION tag # (refs/tags/v*). The version-tag guard stops a branch / non-version-tag # dispatch from overwriting the mutable public plugin tags - # (mysql8.0/8.4/9.7/latest). - if: github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/v') + # (mysql8.0/8.4/9.7/latest). A dry_run dispatch builds and tests without pushing. + if: >- + (github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/v')) || + (github.event_name == 'workflow_dispatch' && inputs.dry_run) runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - - mysql-tag: 'mysql-8.0.45' + # A plugin works only on the exact release it was built against, so each image + # is based on mysql:, the release of mysql-tag, and also tagged + # with it (mysql). + - mysql-tag: 'mysql-8.0.46' + mysql-release: '8.0.46' mysql-version: '8.0' dockerfile: Dockerfile.oraclelinux8 compiler: 10 - - mysql-tag: 'mysql-8.4.8' + - mysql-tag: 'mysql-8.4.13' + mysql-release: '8.4.13' mysql-version: '8.4' dockerfile: Dockerfile.oraclelinux9 compiler: 10 - - mysql-tag: 'mysql-9.7.0' + - mysql-tag: 'mysql-9.7.4' + mysql-release: '9.7.4' mysql-version: '9.7' dockerfile: Dockerfile.oraclelinux9 compiler: 11 @@ -162,7 +170,7 @@ jobs: docker buildx build \ --platform "linux/${arch}" \ --file ${{ matrix.dockerfile }} \ - --build-arg MYSQL_VERSION=${{ matrix.mysql-version }} \ + --build-arg MYSQL_VERSION=${{ matrix.mysql-release }} \ -t "myvector-smoke:${{ matrix.mysql-version }}-${arch}" \ --load \ . @@ -191,10 +199,13 @@ jobs: context: . file: ${{ matrix.dockerfile }} platforms: linux/amd64,linux/arm64 - push: true - tags: ghcr.io/${{ github.repository }}:mysql${{ matrix.mysql-version }} + # Never push on a dry_run dispatch — build only, to prove the pipeline. + push: ${{ !inputs.dry_run }} + tags: | + ghcr.io/${{ github.repository }}:mysql${{ matrix.mysql-version }} + ghcr.io/${{ github.repository }}:mysql${{ matrix.mysql-release }} build-args: | - MYSQL_VERSION=${{ matrix.mysql-version }} + MYSQL_VERSION=${{ matrix.mysql-release }} - name: Tag and push latest if: matrix.mysql-version == '8.0' @@ -203,10 +214,10 @@ jobs: context: . file: ${{ matrix.dockerfile }} platforms: linux/amd64,linux/arm64 - push: true + push: ${{ !inputs.dry_run }} tags: ghcr.io/${{ github.repository }}:latest build-args: | - MYSQL_VERSION=${{ matrix.mysql-version }} + MYSQL_VERSION=${{ matrix.mysql-release }} # Component-based images (INSTALL COMPONENT), distinct from the legacy plugin # images built above. mysql8.4/mysql9.7 already ship as plugin images with diff --git a/CHANGELOG.md b/CHANGELOG.md index 2245939..5cccacd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 and rebuild the index. See [Declaring a Vector Column](docs/usage.md#declaring-a-vector-column). ### Fixed +- **Plugin images pinned to their build release.** The plugin images were built for 8.0.45, 8.4.8 and 9.7.0 but based on the floating `mysql:8.0`/`mysql:8.4`/`mysql:9.7` (now 8.0.46, 8.4.13, 9.7.4), and a library built for one MySQL release can crash another. `docker-publish.yml` now builds them for **8.0.46, 8.4.13 and 9.7.4**, bases each image on `mysql:` and also tags it with the release (`mysql8.0.46`, `mysql8.4.13`, `mysql9.7.4`). The plugin job also runs on a `dry_run` dispatch, building and testing without pushing. `Dockerfile.oraclelinux8`/`9` now require `MYSQL_VERSION`. `scripts/build-docker-local.sh` builds 8.0, 8.4 or 9.7 on the same releases and rejects other versions (it used to map 9.0 to 9.0.0). - **Component images pinned to their build release.** A component works only on the exact MySQL release it was built against: in a dry run, a `component_mcp_guard` built for 8.4.8 crashed `mysql:8.4` (8.4.11). The images were built for 8.4.8 and 9.7.0 but ran on the floating `mysql:8.4`/`mysql:9.7`. `docker-publish.yml` now builds the component images for **8.4.13, 9.7.4 and 26.10.0** (the releases the floating tags now point to) and bases each one on `mysql:`. It also tags each image with its release (`mysql8.4.13-component`, `mysql9.7.4-component`, `mysql26.10.0`), and the artifact smoke test runs on the same release. `Dockerfile.component` now requires `MYSQL_VERSION` (no default). - **Component build scripts reconfigure the server tree after a failed configure.** A `.configure-ok` marker is written only after `cmake` succeeds; before, the scripts trusted `CMakeCache.txt`, which appears before configuration finishes, so a failed configure was skipped on the next run. - **Component build scripts no longer re-clone the MySQL source on every run.** Inside the build container, git refused the host-owned tree ("dubious ownership"), so the tag check always failed and the tree was deleted and cloned again, which also defeated the CI cache of the source tree. The scripts now mark the tree as a git safe directory. diff --git a/Dockerfile.oraclelinux8 b/Dockerfile.oraclelinux8 index 6e3e047..1e05d7a 100644 --- a/Dockerfile.oraclelinux8 +++ b/Dockerfile.oraclelinux8 @@ -1,4 +1,6 @@ -ARG MYSQL_VERSION=8.0 +# MYSQL_VERSION (required, no default) is the exact release the plugin was built against, +# for example 8.4.13: a plugin built for another release can crash the server. +ARG MYSQL_VERSION FROM mysql:${MYSQL_VERSION} ARG TARGETARCH diff --git a/Dockerfile.oraclelinux9 b/Dockerfile.oraclelinux9 index ad5d605..a90227a 100644 --- a/Dockerfile.oraclelinux9 +++ b/Dockerfile.oraclelinux9 @@ -1,4 +1,6 @@ -ARG MYSQL_VERSION=8.0 +# MYSQL_VERSION (required, no default) is the exact release the plugin was built against, +# for example 8.4.13: a plugin built for another release can crash the server. +ARG MYSQL_VERSION # Provide libstdc++ compatible with plugin (built with gcc-10). Use Ubuntu (lighter than Oracle Linux + gcc-toolset). FROM ubuntu:22.04 AS libstdcxx diff --git a/docs/DOCKER_IMAGES.md b/docs/DOCKER_IMAGES.md index 2b38733..07eaf7e 100644 --- a/docs/DOCKER_IMAGES.md +++ b/docs/DOCKER_IMAGES.md @@ -221,6 +221,11 @@ instructions in the main README: | `ghcr.io/askdba/myvector:mysql26.10` | 26.10.x (Innovation) | Component only (`INSTALL COMPONENT`) | | `ghcr.io/askdba/myvector:latest` | 8.0.x | Plugin (`INSTALL PLUGIN`) | +Each plugin image is based on the exact MySQL release its plugin was built against: a +plugin or component built for one release can crash another. The image is also +tagged with that release (`mysql8.0.46`, `mysql8.4.13`, `mysql9.7.4`); `mysql8.0`, +`mysql8.4`, `mysql9.7` and `latest` move to the new release when the build is updated. + Each component image is based on the exact MySQL release its component was built against: a component built for one patch release can crash another (an 8.4.8 build crashed 8.4.11). The image is also tagged with that release, e.g. diff --git a/scripts/build-docker-local.sh b/scripts/build-docker-local.sh index 2224d1e..643d927 100755 --- a/scripts/build-docker-local.sh +++ b/scripts/build-docker-local.sh @@ -4,7 +4,7 @@ # On x86_64: builds amd64 plugin and image. # # Usage: ./scripts/build-docker-local.sh [mysql-version] -# Example: ./scripts/build-docker-local.sh 8.4 +# Example: ./scripts/build-docker-local.sh 8.4 (8.0, 8.4 or 9.7) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -12,9 +12,18 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$REPO_ROOT" MYSQL_VERSION="${1:-8.4}" -MYSQL_TAG="mysql-8.4.8" -[ "$MYSQL_VERSION" = "8.0" ] && MYSQL_TAG="mysql-8.0.45" -[ "$MYSQL_VERSION" = "9.0" ] && MYSQL_TAG="mysql-9.0.0" +case "$MYSQL_VERSION" in +8.0) MYSQL_TAG="mysql-8.0.46" ;; +8.4) MYSQL_TAG="mysql-8.4.13" ;; +9.7) MYSQL_TAG="mysql-9.7.4" ;; +*) + echo "unsupported MySQL version: $MYSQL_VERSION (use 8.0, 8.4 or 9.7)" >&2 + exit 1 + ;; +esac +# The image is based on the release the plugin is built against (a plugin built for +# another release can crash the server). +MYSQL_RELEASE="${MYSQL_TAG#mysql-}" # Build for native arch on Apple Silicon; amd64 on x86 # Set MYVECTOR_ARCH=amd64 to force amd64 (QEMU) on arm64 - slower but avoids compiler bugs @@ -91,7 +100,7 @@ cp sql/myvectorplugin.sql . echo "Building Docker image ($PLATFORM)..." docker build -f Dockerfile.oraclelinux9 \ --platform "$PLATFORM" \ - --build-arg MYSQL_VERSION="$MYSQL_VERSION" \ + --build-arg MYSQL_VERSION="$MYSQL_RELEASE" \ -t "myvector:mysql${MYSQL_VERSION}-local" . echo ""