🛟 Updated.
427799c parent: fa8a56d modified
.github/workflows/release.yml +0 -108 | @@ -97,111 +97,3 @@ jobs: | ||
| 97 | 97 | release/${{ github.ref_name }}/SHA256SUMS |
| 98 | 98 | release/${{ github.ref_name }}/README.md |
| 99 | 99 | fail_on_unmatched_files: true |
| 100 | - | |
| 101 | - # The Docker Sandbox template and its two kits, on Docker Hub, at the same | |
| 102 | - # version as the binaries: k33g/mm-sandbox:0.0.2 (the image, linux/amd64 + | |
| 103 | - # linux/arm64), k33g/mm-tui:0.0.2 and k33g/mm-acp:0.0.2 (the kits, OCI | |
| 104 | - # artifacts). The scripts are the ones a laptop runs — docker-sbx/build.sh | |
| 105 | - # with PUSH=1, then docker-sbx/push-kits.sh — so a local publish and a CI | |
| 106 | - # publish are the same pipeline. Runs after `release` so nothing is pushed | |
| 107 | - # to the Hub when the tests failed. | |
| 108 | - # | |
| 109 | - # Credentials: two repository secrets, DOCKER_HANDLE (the Docker Hub | |
| 110 | - # account, which is also the image owner) and DOCKER_PAT (an access token | |
| 111 | - # with read/write scope), exposed to the job as environment variables. | |
| 112 | - docker-sandbox: | |
| 113 | - # No expression in the name: Rickub shows it unexpanded. | |
| 114 | - name: publish the Docker Sandbox template and kits | |
| 115 | - runs-on: ubuntu-latest | |
| 116 | - needs: release | |
| 117 | - env: | |
| 118 | - DOCKER_HANDLE: ${{ secrets.DOCKER_HANDLE }} | |
| 119 | - DOCKER_PAT: ${{ secrets.DOCKER_PAT }} | |
| 120 | - # The sbx release whose CLI publishes the kits (docker/sbx-releases). | |
| 121 | - SBX_VERSION: v0.45.0 | |
| 122 | - steps: | |
| 123 | - - name: Checkout | |
| 124 | - uses: actions/checkout@v4 | |
| 125 | - | |
| 126 | - - name: Check the Docker Hub credentials | |
| 127 | - # Secrets pasted with a trailing newline or a stray CR are a classic; | |
| 128 | - # both are stripped before use. The handle must be the Docker ID, not | |
| 129 | - # the e-mail address: access tokens only pair with the username. | |
| 130 | - run: | | |
| 131 | - set -euo pipefail | |
| 132 | - handle="$(printf '%s' "${DOCKER_HANDLE}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 133 | - pat="$(printf '%s' "${DOCKER_PAT}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 134 | - if [ -z "${handle}" ] || [ -z "${pat}" ]; then | |
| 135 | - echo "❌ DOCKER_HANDLE and DOCKER_PAT must be set as repository secrets" | |
| 136 | - exit 1 | |
| 137 | - fi | |
| 138 | - case "${handle}" in | |
| 139 | - *@*|*:*) echo "❌ DOCKER_HANDLE must be the Docker ID (username), got something with @ or : in it"; exit 1 ;; | |
| 140 | - esac | |
| 141 | - echo "handle: ${handle} (${#handle} chars), token: ${#pat} chars" | |
| 142 | - echo "DOCKER_HANDLE=${handle}" >> "$GITHUB_ENV" | |
| 143 | - echo "::add-mask::${pat}" | |
| 144 | - echo "DOCKER_PAT=${pat}" >> "$GITHUB_ENV" | |
| 145 | - | |
| 146 | - - name: Diagnose the path to Docker Hub | |
| 147 | - # An anonymous GET on the registry must answer 401 with a Bearer | |
| 148 | - # challenge. A 400 "malformed HTTP Authorization header" there means | |
| 149 | - # something between this runner and the Hub (a proxy) adds its own | |
| 150 | - # Authorization header — the request below carries none. The token | |
| 151 | - # endpoint check then says whether the credentials themselves are | |
| 152 | - # accepted, without going through the Docker daemon. | |
| 153 | - run: | | |
| 154 | - set -uo pipefail | |
| 155 | - echo "--- anonymous GET https://registry-1.docker.io/v2/ (expect 401 + www-authenticate: Bearer)" | |
| 156 | - curl -sS -o /dev/null -D - https://registry-1.docker.io/v2/ | grep -i -E '^HTTP/|^www-authenticate|^docker-distribution' || true | |
| 157 | - echo "--- token for ${DOCKER_HANDLE}/mm-sandbox with the access token (expect 200)" | |
| 158 | - code="$(curl -sS -o /dev/null -w '%{http_code}' -u "${DOCKER_HANDLE}:${DOCKER_PAT}" \ | |
| 159 | - "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKER_HANDLE}/mm-sandbox:pull,push")" | |
| 160 | - echo "auth.docker.io answered ${code}" | |
| 161 | - env | grep -i -E '^(https?_proxy|no_proxy|DOCKER_)' | sed 's/=.*/=…/' || true | |
| 162 | - | |
| 163 | - - name: Set up QEMU | |
| 164 | - # The final image stage runs `mm --version` for linux/arm64 on an | |
| 165 | - # amd64 runner; the Go stage itself cross-compiles without emulation. | |
| 166 | - uses: docker/setup-qemu-action@v3 | |
| 167 | - | |
| 168 | - - name: Set up Docker Buildx | |
| 169 | - uses: docker/setup-buildx-action@v3 | |
| 170 | - | |
| 171 | - - name: Log in to Docker Hub | |
| 172 | - # Not `docker login`: its ping of the registry goes through the Docker | |
| 173 | - # daemon and failed on Rickub with "malformed HTTP Authorization | |
| 174 | - # header". Writing the credential store directly is the same result — | |
| 175 | - # buildx forwards it to BuildKit for the push, and `sbx kit push` | |
| 176 | - # reads it (credentials.NewStoreFromDocker) — without the ping. | |
| 177 | - run: | | |
| 178 | - set -euo pipefail | |
| 179 | - mkdir -p "${HOME}/.docker" | |
| 180 | - auth="$(printf '%s:%s' "${DOCKER_HANDLE}" "${DOCKER_PAT}" | base64 | tr -d '\n')" | |
| 181 | - if [ -f "${HOME}/.docker/config.json" ]; then | |
| 182 | - cp "${HOME}/.docker/config.json" "${RUNNER_TEMP}/docker-config.orig.json" | |
| 183 | - fi | |
| 184 | - printf '{"auths":{"https://index.docker.io/v1/":{"auth":"%s"}}}\n' "${auth}" > "${HOME}/.docker/config.json" | |
| 185 | - chmod 0600 "${HOME}/.docker/config.json" | |
| 186 | - echo "credential store written for ${DOCKER_HANDLE}" | |
| 187 | - | |
| 188 | - - name: Build and push the template image | |
| 189 | - run: PUSH=1 IMAGE_OWNER="${DOCKER_HANDLE}" bash ./docker-sbx/build.sh "${GITHUB_REF_NAME}" | |
| 190 | - | |
| 191 | - - name: Install the sbx CLI | |
| 192 | - # `sbx kit push` talks to the registry directly and reads the Docker | |
| 193 | - # credential store; no sandbox daemon is started here. | |
| 194 | - run: | | |
| 195 | - set -euo pipefail | |
| 196 | - mkdir -p "${RUNNER_TEMP}/sbx" | |
| 197 | - curl -fsSL -o "${RUNNER_TEMP}/sbx.tgz" \ | |
| 198 | - "https://github.com/docker/sbx-releases/releases/download/${SBX_VERSION}/DockerSandboxes-linux-amd64.tar.gz" | |
| 199 | - tar -xzf "${RUNNER_TEMP}/sbx.tgz" -C "${RUNNER_TEMP}/sbx" --strip-components=1 docker-sbx/sbx | |
| 200 | - "${RUNNER_TEMP}/sbx/sbx" version | |
| 201 | - | |
| 202 | - - name: Publish the kits | |
| 203 | - run: IMAGE_OWNER="${DOCKER_HANDLE}" SBX="${RUNNER_TEMP}/sbx/sbx" bash ./docker-sbx/push-kits.sh "${GITHUB_REF_NAME}" | |
| 204 | - | |
| 205 | - - name: Remove the credential store | |
| 206 | - if: always() | |
| 207 | - run: rm -f "${HOME}/.docker/config.json" | |
| @@ -97,111 +97,3 @@ jobs: | |||
| 97 | release/${{ github.ref_name }}/SHA256SUMS | 97 | release/${{ github.ref_name }}/SHA256SUMS |
| 98 | release/${{ github.ref_name }}/README.md | 98 | release/${{ github.ref_name }}/README.md |
| 99 | fail_on_unmatched_files: true | 99 | fail_on_unmatched_files: true |
| 100 | - | ||
| 101 | - # The Docker Sandbox template and its two kits, on Docker Hub, at the same | ||
| 102 | - # version as the binaries: k33g/mm-sandbox:0.0.2 (the image, linux/amd64 + | ||
| 103 | - # linux/arm64), k33g/mm-tui:0.0.2 and k33g/mm-acp:0.0.2 (the kits, OCI | ||
| 104 | - # artifacts). The scripts are the ones a laptop runs — docker-sbx/build.sh | ||
| 105 | - # with PUSH=1, then docker-sbx/push-kits.sh — so a local publish and a CI | ||
| 106 | - # publish are the same pipeline. Runs after `release` so nothing is pushed | ||
| 107 | - # to the Hub when the tests failed. | ||
| 108 | - # | ||
| 109 | - # Credentials: two repository secrets, DOCKER_HANDLE (the Docker Hub | ||
| 110 | - # account, which is also the image owner) and DOCKER_PAT (an access token | ||
| 111 | - # with read/write scope), exposed to the job as environment variables. | ||
| 112 | - docker-sandbox: | ||
| 113 | - # No expression in the name: Rickub shows it unexpanded. | ||
| 114 | - name: publish the Docker Sandbox template and kits | ||
| 115 | - runs-on: ubuntu-latest | ||
| 116 | - needs: release | ||
| 117 | - env: | ||
| 118 | - DOCKER_HANDLE: ${{ secrets.DOCKER_HANDLE }} | ||
| 119 | - DOCKER_PAT: ${{ secrets.DOCKER_PAT }} | ||
| 120 | - # The sbx release whose CLI publishes the kits (docker/sbx-releases). | ||
| 121 | - SBX_VERSION: v0.45.0 | ||
| 122 | - steps: | ||
| 123 | - - name: Checkout | ||
| 124 | - uses: actions/checkout@v4 | ||
| 125 | - | ||
| 126 | - - name: Check the Docker Hub credentials | ||
| 127 | - # Secrets pasted with a trailing newline or a stray CR are a classic; | ||
| 128 | - # both are stripped before use. The handle must be the Docker ID, not | ||
| 129 | - # the e-mail address: access tokens only pair with the username. | ||
| 130 | - run: | | ||
| 131 | - set -euo pipefail | ||
| 132 | - handle="$(printf '%s' "${DOCKER_HANDLE}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 133 | - pat="$(printf '%s' "${DOCKER_PAT}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 134 | - if [ -z "${handle}" ] || [ -z "${pat}" ]; then | ||
| 135 | - echo "❌ DOCKER_HANDLE and DOCKER_PAT must be set as repository secrets" | ||
| 136 | - exit 1 | ||
| 137 | - fi | ||
| 138 | - case "${handle}" in | ||
| 139 | - *@*|*:*) echo "❌ DOCKER_HANDLE must be the Docker ID (username), got something with @ or : in it"; exit 1 ;; | ||
| 140 | - esac | ||
| 141 | - echo "handle: ${handle} (${#handle} chars), token: ${#pat} chars" | ||
| 142 | - echo "DOCKER_HANDLE=${handle}" >> "$GITHUB_ENV" | ||
| 143 | - echo "::add-mask::${pat}" | ||
| 144 | - echo "DOCKER_PAT=${pat}" >> "$GITHUB_ENV" | ||
| 145 | - | ||
| 146 | - - name: Diagnose the path to Docker Hub | ||
| 147 | - # An anonymous GET on the registry must answer 401 with a Bearer | ||
| 148 | - # challenge. A 400 "malformed HTTP Authorization header" there means | ||
| 149 | - # something between this runner and the Hub (a proxy) adds its own | ||
| 150 | - # Authorization header — the request below carries none. The token | ||
| 151 | - # endpoint check then says whether the credentials themselves are | ||
| 152 | - # accepted, without going through the Docker daemon. | ||
| 153 | - run: | | ||
| 154 | - set -uo pipefail | ||
| 155 | - echo "--- anonymous GET https://registry-1.docker.io/v2/ (expect 401 + www-authenticate: Bearer)" | ||
| 156 | - curl -sS -o /dev/null -D - https://registry-1.docker.io/v2/ | grep -i -E '^HTTP/|^www-authenticate|^docker-distribution' || true | ||
| 157 | - echo "--- token for ${DOCKER_HANDLE}/mm-sandbox with the access token (expect 200)" | ||
| 158 | - code="$(curl -sS -o /dev/null -w '%{http_code}' -u "${DOCKER_HANDLE}:${DOCKER_PAT}" \ | ||
| 159 | - "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKER_HANDLE}/mm-sandbox:pull,push")" | ||
| 160 | - echo "auth.docker.io answered ${code}" | ||
| 161 | - env | grep -i -E '^(https?_proxy|no_proxy|DOCKER_)' | sed 's/=.*/=…/' || true | ||
| 162 | - | ||
| 163 | - - name: Set up QEMU | ||
| 164 | - # The final image stage runs `mm --version` for linux/arm64 on an | ||
| 165 | - # amd64 runner; the Go stage itself cross-compiles without emulation. | ||
| 166 | - uses: docker/setup-qemu-action@v3 | ||
| 167 | - | ||
| 168 | - - name: Set up Docker Buildx | ||
| 169 | - uses: docker/setup-buildx-action@v3 | ||
| 170 | - | ||
| 171 | - - name: Log in to Docker Hub | ||
| 172 | - # Not `docker login`: its ping of the registry goes through the Docker | ||
| 173 | - # daemon and failed on Rickub with "malformed HTTP Authorization | ||
| 174 | - # header". Writing the credential store directly is the same result — | ||
| 175 | - # buildx forwards it to BuildKit for the push, and `sbx kit push` | ||
| 176 | - # reads it (credentials.NewStoreFromDocker) — without the ping. | ||
| 177 | - run: | | ||
| 178 | - set -euo pipefail | ||
| 179 | - mkdir -p "${HOME}/.docker" | ||
| 180 | - auth="$(printf '%s:%s' "${DOCKER_HANDLE}" "${DOCKER_PAT}" | base64 | tr -d '\n')" | ||
| 181 | - if [ -f "${HOME}/.docker/config.json" ]; then | ||
| 182 | - cp "${HOME}/.docker/config.json" "${RUNNER_TEMP}/docker-config.orig.json" | ||
| 183 | - fi | ||
| 184 | - printf '{"auths":{"https://index.docker.io/v1/":{"auth":"%s"}}}\n' "${auth}" > "${HOME}/.docker/config.json" | ||
| 185 | - chmod 0600 "${HOME}/.docker/config.json" | ||
| 186 | - echo "credential store written for ${DOCKER_HANDLE}" | ||
| 187 | - | ||
| 188 | - - name: Build and push the template image | ||
| 189 | - run: PUSH=1 IMAGE_OWNER="${DOCKER_HANDLE}" bash ./docker-sbx/build.sh "${GITHUB_REF_NAME}" | ||
| 190 | - | ||
| 191 | - - name: Install the sbx CLI | ||
| 192 | - # `sbx kit push` talks to the registry directly and reads the Docker | ||
| 193 | - # credential store; no sandbox daemon is started here. | ||
| 194 | - run: | | ||
| 195 | - set -euo pipefail | ||
| 196 | - mkdir -p "${RUNNER_TEMP}/sbx" | ||
| 197 | - curl -fsSL -o "${RUNNER_TEMP}/sbx.tgz" \ | ||
| 198 | - "https://github.com/docker/sbx-releases/releases/download/${SBX_VERSION}/DockerSandboxes-linux-amd64.tar.gz" | ||
| 199 | - tar -xzf "${RUNNER_TEMP}/sbx.tgz" -C "${RUNNER_TEMP}/sbx" --strip-components=1 docker-sbx/sbx | ||
| 200 | - "${RUNNER_TEMP}/sbx/sbx" version | ||
| 201 | - | ||
| 202 | - - name: Publish the kits | ||
| 203 | - run: IMAGE_OWNER="${DOCKER_HANDLE}" SBX="${RUNNER_TEMP}/sbx/sbx" bash ./docker-sbx/push-kits.sh "${GITHUB_REF_NAME}" | ||
| 204 | - | ||
| 205 | - - name: Remove the credential store | ||
| 206 | - if: always() | ||
| 207 | - run: rm -f "${HOME}/.docker/config.json" | ||
modified
docker-sbx/README.md +14 -5 | @@ -6,6 +6,7 @@ The full guide, with the reasoning, is in [`docs/en/how-to/run-in-a-docker-sandb | ||
| 6 | 6 | |
| 7 | 7 | ``` |
| 8 | 8 | docker-sbx/ |
| 9 | +├── publish.sh build + push the image, then publish the kits — the one command to release | |
| 9 | 10 | ├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) |
| 10 | 11 | ├── sync-kits.sh points the kits at one image: owner + version |
| 11 | 12 | ├── push-kits.sh publishes the kits to Docker Hub as OCI artifacts (sbx kit push) |
| @@ -177,15 +178,23 @@ Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the agent' | ||
| 177 | 178 | |
| 178 | 179 | ## 4. Publishing a version |
| 179 | 180 | |
| 180 | -The Release workflow (`.github/workflows/release.yml`, job `docker-sandbox`) does this on every `v*` tag, after the binaries: it reads two repository secrets, `DOCKER_HANDLE` (the Docker Hub account, also the image owner) and `DOCKER_PAT` (an access token), logs in, then runs the same two scripts you can run from a laptop: | |
| 181 | +Publishing is done by hand, from a laptop with Docker Desktop (buildx and the `sbx` CLI). One command builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag: | |
| 181 | 182 | |
| 182 | 183 | ```bash |
| 183 | -docker login -u k33g # with an access token | |
| 184 | -PUSH=1 ./docker-sbx/build.sh v0.0.2 # buildx, linux/amd64 + linux/arm64, pushed as k33g/mm-sandbox:0.0.2 | |
| 185 | -./docker-sbx/push-kits.sh v0.0.2 # sbx kit validate + push → k33g/mm-tui:0.0.2, k33g/mm-acp:0.0.2 | |
| 184 | +export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner | |
| 185 | +export DOCKER_PAT=dckr_pat_… # an access token with read/write scope | |
| 186 | +./docker-sbx/publish.sh # TAG from release.env: v0.0.3 → k33g/mm-sandbox:0.0.3, k33g/mm-tui:0.0.3, k33g/mm-acp:0.0.3 | |
| 187 | +./docker-sbx/publish.sh v0.0.4 # another tag | |
| 186 | 188 | ``` |
| 187 | 189 | |
| 188 | -`push-kits.sh` needs the `sbx` CLI (the workflow downloads the Linux tarball from `docker/sbx-releases`); `sbx kit push` talks to the registry directly and authenticates from the Docker credential store, no sandbox daemon involved. Both scripts call `sync-kits.sh` first, so the published kits always name the image just pushed. `IMAGE_OWNER=<handle>` publishes under another account. | |
| 190 | +With the two variables set, the script logs in with them and logs out at the end; with neither, it reuses the `docker login` you already have. It is two steps you can also run alone: | |
| 191 | + | |
| 192 | +```bash | |
| 193 | +PUSH=1 ./docker-sbx/build.sh v0.0.3 # buildx multi-arch, pushed; proof: `imagetools inspect` lists both platforms | |
| 194 | +./docker-sbx/push-kits.sh v0.0.3 # sbx kit validate + sbx kit push, for each kit | |
| 195 | +``` | |
| 196 | + | |
| 197 | +Both call `sync-kits.sh` first, so the published kits always name the image just pushed, and the kits' `spec.yaml` end up saying the new version — commit them. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store; no sandbox daemon is involved. `IMAGE_OWNER=<handle>` publishes under another account. Nothing in CI publishes to the Hub: the Release workflow only builds the binaries. | |
| 189 | 198 | |
| 190 | 199 | ## The model server stays on the host |
| 191 | 200 | |
| @@ -6,6 +6,7 @@ The full guide, with the reasoning, is in [`docs/en/how-to/run-in-a-docker-sandb | |||
| 6 | 6 | ||
| 7 | ``` | 7 | ``` |
| 8 | docker-sbx/ | 8 | docker-sbx/ |
| 9 | +├── publish.sh build + push the image, then publish the kits — the one command to release | ||
| 9 | ├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) | 10 | ├── build.sh builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed) |
| 10 | ├── sync-kits.sh points the kits at one image: owner + version | 11 | ├── sync-kits.sh points the kits at one image: owner + version |
| 11 | ├── push-kits.sh publishes the kits to Docker Hub as OCI artifacts (sbx kit push) | 12 | ├── push-kits.sh publishes the kits to Docker Hub as OCI artifacts (sbx kit push) |
| @@ -177,15 +178,23 @@ Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the agent' | |||
| 177 | 178 | ||
| 178 | ## 4. Publishing a version | 179 | ## 4. Publishing a version |
| 179 | 180 | ||
| 180 | -The Release workflow (`.github/workflows/release.yml`, job `docker-sandbox`) does this on every `v*` tag, after the binaries: it reads two repository secrets, `DOCKER_HANDLE` (the Docker Hub account, also the image owner) and `DOCKER_PAT` (an access token), logs in, then runs the same two scripts you can run from a laptop: | 181 | +Publishing is done by hand, from a laptop with Docker Desktop (buildx and the `sbx` CLI). One command builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag: |
| 181 | 182 | ||
| 182 | ```bash | 183 | ```bash |
| 183 | -docker login -u k33g # with an access token | 184 | +export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner |
| 184 | -PUSH=1 ./docker-sbx/build.sh v0.0.2 # buildx, linux/amd64 + linux/arm64, pushed as k33g/mm-sandbox:0.0.2 | 185 | +export DOCKER_PAT=dckr_pat_… # an access token with read/write scope |
| 185 | -./docker-sbx/push-kits.sh v0.0.2 # sbx kit validate + push → k33g/mm-tui:0.0.2, k33g/mm-acp:0.0.2 | 186 | +./docker-sbx/publish.sh # TAG from release.env: v0.0.3 → k33g/mm-sandbox:0.0.3, k33g/mm-tui:0.0.3, k33g/mm-acp:0.0.3 |
| 187 | +./docker-sbx/publish.sh v0.0.4 # another tag | ||
| 186 | ``` | 188 | ``` |
| 187 | 189 | ||
| 188 | -`push-kits.sh` needs the `sbx` CLI (the workflow downloads the Linux tarball from `docker/sbx-releases`); `sbx kit push` talks to the registry directly and authenticates from the Docker credential store, no sandbox daemon involved. Both scripts call `sync-kits.sh` first, so the published kits always name the image just pushed. `IMAGE_OWNER=<handle>` publishes under another account. | 190 | +With the two variables set, the script logs in with them and logs out at the end; with neither, it reuses the `docker login` you already have. It is two steps you can also run alone: |
| 191 | + | ||
| 192 | +```bash | ||
| 193 | +PUSH=1 ./docker-sbx/build.sh v0.0.3 # buildx multi-arch, pushed; proof: `imagetools inspect` lists both platforms | ||
| 194 | +./docker-sbx/push-kits.sh v0.0.3 # sbx kit validate + sbx kit push, for each kit | ||
| 195 | +``` | ||
| 196 | + | ||
| 197 | +Both call `sync-kits.sh` first, so the published kits always name the image just pushed, and the kits' `spec.yaml` end up saying the new version — commit them. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store; no sandbox daemon is involved. `IMAGE_OWNER=<handle>` publishes under another account. Nothing in CI publishes to the Hub: the Release workflow only builds the binaries. | ||
| 189 | 198 | ||
| 190 | ## The model server stays on the host | 199 | ## The model server stays on the host |
| 191 | 200 | ||
modified
docker-sbx/build.sh +5 -4 | @@ -6,10 +6,10 @@ | ||
| 6 | 6 | # |
| 7 | 7 | # Usage: |
| 8 | 8 | # ./docker-sbx/build.sh # TAG from release.env, image for this machine |
| 9 | -# ./docker-sbx/build.sh v0.0.3 # override the tag for this run (what CI does) | |
| 9 | +# ./docker-sbx/build.sh v0.0.3 # override the tag for this run | |
| 10 | 10 | # PUSH=1 ./docker-sbx/build.sh # multi-arch (linux/amd64 + linux/arm64) built |
| 11 | 11 | # # with buildx and PUSHED to the registry — |
| 12 | -# # needs `docker login`; this is the CI path | |
| 12 | +# # needs `docker login`; publish.sh does this | |
| 13 | 13 | # IMAGE_OWNER=someone ./docker-sbx/build.sh # another image owner (default k33g) |
| 14 | 14 | # PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set |
| 15 | 15 | # SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh |
| @@ -19,7 +19,8 @@ | ||
| 19 | 19 | # |
| 20 | 20 | # Whatever the mode, the two kits under docker-sbx/kits/ are then pointed at |
| 21 | 21 | # the image just built (docker-sbx/sync-kits.sh), so kits and image move |
| 22 | -# together. Publishing the kits themselves is docker-sbx/push-kits.sh. | |
| 22 | +# together. Publishing the kits themselves is docker-sbx/push-kits.sh, and | |
| 23 | +# docker-sbx/publish.sh chains the two. | |
| 23 | 24 | set -euo pipefail |
| 24 | 25 | |
| 25 | 26 | cd "$(dirname "$0")/.." |
| @@ -52,7 +53,7 @@ if [ -n "${PUSH:-}" ]; then | ||
| 52 | 53 | # Multi-arch needs buildx's container driver: the classic builder can |
| 53 | 54 | # neither assemble a manifest list nor build for a foreign platform. The |
| 54 | 55 | # Go stage cross-compiles on the build platform; only the final stage's |
| 55 | - # `RUN mm --version` runs under emulation (QEMU, set up by the caller). | |
| 56 | + # `RUN mm --version` runs under emulation (Docker Desktop ships QEMU). | |
| 56 | 57 | echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" |
| 57 | 58 | if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then |
| 58 | 59 | docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null |
| @@ -6,10 +6,10 @@ | |||
| 6 | # | 6 | # |
| 7 | # Usage: | 7 | # Usage: |
| 8 | # ./docker-sbx/build.sh # TAG from release.env, image for this machine | 8 | # ./docker-sbx/build.sh # TAG from release.env, image for this machine |
| 9 | -# ./docker-sbx/build.sh v0.0.3 # override the tag for this run (what CI does) | 9 | +# ./docker-sbx/build.sh v0.0.3 # override the tag for this run |
| 10 | # PUSH=1 ./docker-sbx/build.sh # multi-arch (linux/amd64 + linux/arm64) built | 10 | # PUSH=1 ./docker-sbx/build.sh # multi-arch (linux/amd64 + linux/arm64) built |
| 11 | # # with buildx and PUSHED to the registry — | 11 | # # with buildx and PUSHED to the registry — |
| 12 | -# # needs `docker login`; this is the CI path | 12 | +# # needs `docker login`; publish.sh does this |
| 13 | # IMAGE_OWNER=someone ./docker-sbx/build.sh # another image owner (default k33g) | 13 | # IMAGE_OWNER=someone ./docker-sbx/build.sh # another image owner (default k33g) |
| 14 | # PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set | 14 | # PLATFORMS=linux/amd64 PUSH=1 … # narrower multi-arch set |
| 15 | # SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh | 15 | # SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh |
| @@ -19,7 +19,8 @@ | |||
| 19 | # | 19 | # |
| 20 | # Whatever the mode, the two kits under docker-sbx/kits/ are then pointed at | 20 | # Whatever the mode, the two kits under docker-sbx/kits/ are then pointed at |
| 21 | # the image just built (docker-sbx/sync-kits.sh), so kits and image move | 21 | # the image just built (docker-sbx/sync-kits.sh), so kits and image move |
| 22 | -# together. Publishing the kits themselves is docker-sbx/push-kits.sh. | 22 | +# together. Publishing the kits themselves is docker-sbx/push-kits.sh, and |
| 23 | +# docker-sbx/publish.sh chains the two. | ||
| 23 | set -euo pipefail | 24 | set -euo pipefail |
| 24 | 25 | ||
| 25 | cd "$(dirname "$0")/.." | 26 | cd "$(dirname "$0")/.." |
| @@ -52,7 +53,7 @@ if [ -n "${PUSH:-}" ]; then | |||
| 52 | # Multi-arch needs buildx's container driver: the classic builder can | 53 | # Multi-arch needs buildx's container driver: the classic builder can |
| 53 | # neither assemble a manifest list nor build for a foreign platform. The | 54 | # neither assemble a manifest list nor build for a foreign platform. The |
| 54 | # Go stage cross-compiles on the build platform; only the final stage's | 55 | # Go stage cross-compiles on the build platform; only the final stage's |
| 55 | - # `RUN mm --version` runs under emulation (QEMU, set up by the caller). | 56 | + # `RUN mm --version` runs under emulation (Docker Desktop ships QEMU). |
| 56 | echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" | 57 | echo "🐳 Building and pushing ${IMAGE} for ${PLATFORMS} (mm ${TAG}, base ${SHELL_TEMPLATE:-docker/sandbox-templates:shell})" |
| 57 | if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then | 58 | if ! docker buildx inspect mm-sandbox-builder >/dev/null 2>&1; then |
| 58 | docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null | 59 | docker buildx create --name mm-sandbox-builder --driver docker-container --bootstrap >/dev/null |
added
docker-sbx/publish.sh +82 -0 | new file mode 100755 | ||
| @@ -0,0 +1,82 @@ | ||
| 1 | +#!/usr/bin/env bash | |
| 2 | +# Build and publish everything to Docker Hub, by hand, in one go: | |
| 3 | +# <owner>/mm-sandbox:<version> the template image, linux/amd64 + linux/arm64 | |
| 4 | +# <owner>/mm-tui:<version> the window-mode kit | |
| 5 | +# <owner>/mm-acp:<version> the editor (ACP) kit | |
| 6 | +# | |
| 7 | +# Usage: | |
| 8 | +# ./docker-sbx/publish.sh # TAG from release.env (v0.0.3 → 0.0.3) | |
| 9 | +# ./docker-sbx/publish.sh v0.0.4 # another tag | |
| 10 | +# | |
| 11 | +# Credentials, two environment variables: | |
| 12 | +# DOCKER_HANDLE the Docker Hub account — also the image owner (default k33g) | |
| 13 | +# DOCKER_PAT an access token with read/write scope | |
| 14 | +# With both set, the script logs in with them (and out at the end). With | |
| 15 | +# neither, it uses the login you already have (`docker login` done earlier). | |
| 16 | +# | |
| 17 | +# Needs: docker with buildx (Docker Desktop has it), and the sbx CLI for the | |
| 18 | +# kits (`SBX=/path/to/sbx` if it is not on the PATH). Pieces, runnable alone: | |
| 19 | +# PUSH=1 ./docker-sbx/build.sh TAG image only | |
| 20 | +# ./docker-sbx/push-kits.sh TAG kits only | |
| 21 | +set -euo pipefail | |
| 22 | + | |
| 23 | +cd "$(dirname "$0")/.." | |
| 24 | + | |
| 25 | +if [ -f release.env ]; then | |
| 26 | + # shellcheck source=/dev/null | |
| 27 | + source release.env | |
| 28 | +fi | |
| 29 | +TAG="${1:-${TAG:-}}" | |
| 30 | +if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | |
| 31 | + echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/publish.sh v1.2.3)" | |
| 32 | + exit 1 | |
| 33 | +fi | |
| 34 | + | |
| 35 | +# Secrets pasted with a trailing newline or stray spaces are a classic. | |
| 36 | +DOCKER_HANDLE="$(printf '%s' "${DOCKER_HANDLE:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 37 | +DOCKER_PAT="$(printf '%s' "${DOCKER_PAT:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | |
| 38 | +case "${DOCKER_HANDLE}" in | |
| 39 | +*@* | *:*) | |
| 40 | + echo "❌ DOCKER_HANDLE must be the Docker ID (username), not an e-mail: access tokens only pair with the username" | |
| 41 | + exit 1 | |
| 42 | + ;; | |
| 43 | +esac | |
| 44 | +export IMAGE_OWNER="${IMAGE_OWNER:-${DOCKER_HANDLE:-k33g}}" | |
| 45 | +VERSION="${TAG#v}" | |
| 46 | + | |
| 47 | +SBX="${SBX:-sbx}" | |
| 48 | +if ! command -v "${SBX}" >/dev/null 2>&1; then | |
| 49 | + echo "❌ sbx not found (${SBX}): install Docker Sandboxes, or SBX=/path/to/sbx" | |
| 50 | + exit 1 | |
| 51 | +fi | |
| 52 | +export SBX | |
| 53 | + | |
| 54 | +logged_in_here="" | |
| 55 | +if [ -n "${DOCKER_HANDLE}" ] && [ -n "${DOCKER_PAT}" ]; then | |
| 56 | + echo "🔐 docker login as ${DOCKER_HANDLE}" | |
| 57 | + printf '%s' "${DOCKER_PAT}" | docker login --username "${DOCKER_HANDLE}" --password-stdin | |
| 58 | + logged_in_here=1 | |
| 59 | +elif [ -n "${DOCKER_HANDLE}${DOCKER_PAT}" ]; then | |
| 60 | + echo "❌ set both DOCKER_HANDLE and DOCKER_PAT, or neither (to reuse an existing docker login)" | |
| 61 | + exit 1 | |
| 62 | +else | |
| 63 | + echo "🔐 no DOCKER_HANDLE/DOCKER_PAT: using the existing docker login, publishing under ${IMAGE_OWNER}" | |
| 64 | +fi | |
| 65 | +# Whatever happens below, a login made here does not outlive the script. | |
| 66 | +cleanup() { | |
| 67 | + if [ -n "${logged_in_here}" ]; then | |
| 68 | + docker logout >/dev/null 2>&1 || true | |
| 69 | + fi | |
| 70 | +} | |
| 71 | +trap cleanup EXIT | |
| 72 | + | |
| 73 | +echo | |
| 74 | +echo "═══ 1/2 image ${IMAGE_OWNER}/mm-sandbox:${VERSION}" | |
| 75 | +PUSH=1 ./docker-sbx/build.sh "${TAG}" | |
| 76 | + | |
| 77 | +echo | |
| 78 | +echo "═══ 2/2 kits ${IMAGE_OWNER}/mm-tui:${VERSION} and ${IMAGE_OWNER}/mm-acp:${VERSION}" | |
| 79 | +./docker-sbx/push-kits.sh "${TAG}" | |
| 80 | + | |
| 81 | +echo | |
| 82 | +echo "✨ Published ${TAG}. The kits' spec.yaml now name version ${VERSION} — commit them." | |
| new file mode 100755 | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | +#!/usr/bin/env bash | ||
| 2 | +# Build and publish everything to Docker Hub, by hand, in one go: | ||
| 3 | +# <owner>/mm-sandbox:<version> the template image, linux/amd64 + linux/arm64 | ||
| 4 | +# <owner>/mm-tui:<version> the window-mode kit | ||
| 5 | +# <owner>/mm-acp:<version> the editor (ACP) kit | ||
| 6 | +# | ||
| 7 | +# Usage: | ||
| 8 | +# ./docker-sbx/publish.sh # TAG from release.env (v0.0.3 → 0.0.3) | ||
| 9 | +# ./docker-sbx/publish.sh v0.0.4 # another tag | ||
| 10 | +# | ||
| 11 | +# Credentials, two environment variables: | ||
| 12 | +# DOCKER_HANDLE the Docker Hub account — also the image owner (default k33g) | ||
| 13 | +# DOCKER_PAT an access token with read/write scope | ||
| 14 | +# With both set, the script logs in with them (and out at the end). With | ||
| 15 | +# neither, it uses the login you already have (`docker login` done earlier). | ||
| 16 | +# | ||
| 17 | +# Needs: docker with buildx (Docker Desktop has it), and the sbx CLI for the | ||
| 18 | +# kits (`SBX=/path/to/sbx` if it is not on the PATH). Pieces, runnable alone: | ||
| 19 | +# PUSH=1 ./docker-sbx/build.sh TAG image only | ||
| 20 | +# ./docker-sbx/push-kits.sh TAG kits only | ||
| 21 | +set -euo pipefail | ||
| 22 | + | ||
| 23 | +cd "$(dirname "$0")/.." | ||
| 24 | + | ||
| 25 | +if [ -f release.env ]; then | ||
| 26 | + # shellcheck source=/dev/null | ||
| 27 | + source release.env | ||
| 28 | +fi | ||
| 29 | +TAG="${1:-${TAG:-}}" | ||
| 30 | +if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then | ||
| 31 | + echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env or pass it: ./docker-sbx/publish.sh v1.2.3)" | ||
| 32 | + exit 1 | ||
| 33 | +fi | ||
| 34 | + | ||
| 35 | +# Secrets pasted with a trailing newline or stray spaces are a classic. | ||
| 36 | +DOCKER_HANDLE="$(printf '%s' "${DOCKER_HANDLE:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 37 | +DOCKER_PAT="$(printf '%s' "${DOCKER_PAT:-}" | tr -d '\r\n' | sed 's/^ *//; s/ *$//')" | ||
| 38 | +case "${DOCKER_HANDLE}" in | ||
| 39 | +*@* | *:*) | ||
| 40 | + echo "❌ DOCKER_HANDLE must be the Docker ID (username), not an e-mail: access tokens only pair with the username" | ||
| 41 | + exit 1 | ||
| 42 | + ;; | ||
| 43 | +esac | ||
| 44 | +export IMAGE_OWNER="${IMAGE_OWNER:-${DOCKER_HANDLE:-k33g}}" | ||
| 45 | +VERSION="${TAG#v}" | ||
| 46 | + | ||
| 47 | +SBX="${SBX:-sbx}" | ||
| 48 | +if ! command -v "${SBX}" >/dev/null 2>&1; then | ||
| 49 | + echo "❌ sbx not found (${SBX}): install Docker Sandboxes, or SBX=/path/to/sbx" | ||
| 50 | + exit 1 | ||
| 51 | +fi | ||
| 52 | +export SBX | ||
| 53 | + | ||
| 54 | +logged_in_here="" | ||
| 55 | +if [ -n "${DOCKER_HANDLE}" ] && [ -n "${DOCKER_PAT}" ]; then | ||
| 56 | + echo "🔐 docker login as ${DOCKER_HANDLE}" | ||
| 57 | + printf '%s' "${DOCKER_PAT}" | docker login --username "${DOCKER_HANDLE}" --password-stdin | ||
| 58 | + logged_in_here=1 | ||
| 59 | +elif [ -n "${DOCKER_HANDLE}${DOCKER_PAT}" ]; then | ||
| 60 | + echo "❌ set both DOCKER_HANDLE and DOCKER_PAT, or neither (to reuse an existing docker login)" | ||
| 61 | + exit 1 | ||
| 62 | +else | ||
| 63 | + echo "🔐 no DOCKER_HANDLE/DOCKER_PAT: using the existing docker login, publishing under ${IMAGE_OWNER}" | ||
| 64 | +fi | ||
| 65 | +# Whatever happens below, a login made here does not outlive the script. | ||
| 66 | +cleanup() { | ||
| 67 | + if [ -n "${logged_in_here}" ]; then | ||
| 68 | + docker logout >/dev/null 2>&1 || true | ||
| 69 | + fi | ||
| 70 | +} | ||
| 71 | +trap cleanup EXIT | ||
| 72 | + | ||
| 73 | +echo | ||
| 74 | +echo "═══ 1/2 image ${IMAGE_OWNER}/mm-sandbox:${VERSION}" | ||
| 75 | +PUSH=1 ./docker-sbx/build.sh "${TAG}" | ||
| 76 | + | ||
| 77 | +echo | ||
| 78 | +echo "═══ 2/2 kits ${IMAGE_OWNER}/mm-tui:${VERSION} and ${IMAGE_OWNER}/mm-acp:${VERSION}" | ||
| 79 | +./docker-sbx/push-kits.sh "${TAG}" | ||
| 80 | + | ||
| 81 | +echo | ||
| 82 | +echo "✨ Published ${TAG}. The kits' spec.yaml now name version ${VERSION} — commit them." | ||
modified
docker-sbx/push-kits.sh +2 -2 | @@ -4,7 +4,7 @@ | ||
| 4 | 4 | # |
| 5 | 5 | # Usage: |
| 6 | 6 | # ./docker-sbx/push-kits.sh # TAG from release.env |
| 7 | -# ./docker-sbx/push-kits.sh v0.0.3 # override the tag (what CI does) | |
| 7 | +# ./docker-sbx/push-kits.sh v0.0.3 # override the tag | |
| 8 | 8 | # IMAGE_OWNER=someone … # another owner (default k33g); the kits |
| 9 | 9 | # # are re-pointed at someone/mm-sandbox too |
| 10 | 10 | # REGISTRY=localhost:5000 … # another registry (default docker.io) |
| @@ -14,7 +14,7 @@ | ||
| 14 | 14 | # `sbx kit push` talks to the registry directly — no sandbox daemon involved — |
| 15 | 15 | # and falls back to the Docker credential store for authentication. |
| 16 | 16 | # |
| 17 | -# Push the image first (PUSH=1 ./docker-sbx/build.sh): a kit names | |
| 17 | +# publish.sh runs this after the image. Push the image first: a kit names | |
| 18 | 18 | # <owner>/mm-sandbox:<version>, and sbx pulls that image when the kit is used. |
| 19 | 19 | set -euo pipefail |
| 20 | 20 | |
| @@ -4,7 +4,7 @@ | |||
| 4 | # | 4 | # |
| 5 | # Usage: | 5 | # Usage: |
| 6 | # ./docker-sbx/push-kits.sh # TAG from release.env | 6 | # ./docker-sbx/push-kits.sh # TAG from release.env |
| 7 | -# ./docker-sbx/push-kits.sh v0.0.3 # override the tag (what CI does) | 7 | +# ./docker-sbx/push-kits.sh v0.0.3 # override the tag |
| 8 | # IMAGE_OWNER=someone … # another owner (default k33g); the kits | 8 | # IMAGE_OWNER=someone … # another owner (default k33g); the kits |
| 9 | # # are re-pointed at someone/mm-sandbox too | 9 | # # are re-pointed at someone/mm-sandbox too |
| 10 | # REGISTRY=localhost:5000 … # another registry (default docker.io) | 10 | # REGISTRY=localhost:5000 … # another registry (default docker.io) |
| @@ -14,7 +14,7 @@ | |||
| 14 | # `sbx kit push` talks to the registry directly — no sandbox daemon involved — | 14 | # `sbx kit push` talks to the registry directly — no sandbox daemon involved — |
| 15 | # and falls back to the Docker credential store for authentication. | 15 | # and falls back to the Docker credential store for authentication. |
| 16 | # | 16 | # |
| 17 | -# Push the image first (PUSH=1 ./docker-sbx/build.sh): a kit names | 17 | +# publish.sh runs this after the image. Push the image first: a kit names |
| 18 | # <owner>/mm-sandbox:<version>, and sbx pulls that image when the kit is used. | 18 | # <owner>/mm-sandbox:<version>, and sbx pulls that image when the kit is used. |
| 19 | set -euo pipefail | 19 | set -euo pipefail |
| 20 | 20 | ||
modified
docker-sbx/sync-kits.sh +1 -1 | @@ -9,7 +9,7 @@ | ||
| 9 | 9 | # sandbox.image: "<owner>/mm-sandbox:…" which owner the image lives under |
| 10 | 10 | # Everything else — comments included — is left byte-for-byte alone, so a |
| 11 | 11 | # kit that already matches is not changed at all. build.sh and push-kits.sh |
| 12 | -# call this; CI relies on it so the published kits name the image it pushed. | |
| 12 | +# call this, so the published kits always name the image just pushed. | |
| 13 | 13 | set -euo pipefail |
| 14 | 14 | |
| 15 | 15 | if [ $# -ne 2 ]; then |
| @@ -9,7 +9,7 @@ | |||
| 9 | # sandbox.image: "<owner>/mm-sandbox:…" which owner the image lives under | 9 | # sandbox.image: "<owner>/mm-sandbox:…" which owner the image lives under |
| 10 | # Everything else — comments included — is left byte-for-byte alone, so a | 10 | # Everything else — comments included — is left byte-for-byte alone, so a |
| 11 | # kit that already matches is not changed at all. build.sh and push-kits.sh | 11 | # kit that already matches is not changed at all. build.sh and push-kits.sh |
| 12 | -# call this; CI relies on it so the published kits name the image it pushed. | 12 | +# call this, so the published kits always name the image just pushed. |
| 13 | set -euo pipefail | 13 | set -euo pipefail |
| 14 | 14 | ||
| 15 | if [ $# -ne 2 ]; then | 15 | if [ $# -ne 2 ]; then |
modified
docs/en/how-to/run-in-a-docker-sandbox.md +5 -5 | @@ -113,15 +113,15 @@ Both kits allow ports 12434 and 8080 on the host in the sandbox's network policy | ||
| 113 | 113 | |
| 114 | 114 | ## Publishing a version |
| 115 | 115 | |
| 116 | -The Release workflow (`.github/workflows/release.yml`, job `docker-sandbox`) publishes the image and the kits on every `v*` tag, after the binaries job. It needs two repository secrets, exposed to the job as environment variables: `DOCKER_HANDLE`, the Docker Hub account (also the image owner), and `DOCKER_PAT`, an access token with read/write scope. It then runs the scripts a laptop would run: | |
| 116 | +Publishing is a manual step, from a machine with Docker Desktop (buildx and the `sbx` CLI); the Release workflow builds only the binaries. One script builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag: | |
| 117 | 117 | |
| 118 | 118 | ```bash |
| 119 | -docker login -u k33g # paste an access token | |
| 120 | -PUSH=1 ./docker-sbx/build.sh v0.0.2 # buildx, linux/amd64 + linux/arm64, pushed as k33g/mm-sandbox:0.0.2 | |
| 121 | -./docker-sbx/push-kits.sh v0.0.2 # sbx kit validate + sbx kit push → k33g/mm-tui:0.0.2, k33g/mm-acp:0.0.2 | |
| 119 | +export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner | |
| 120 | +export DOCKER_PAT=dckr_pat_… # an access token with read/write scope | |
| 121 | +./docker-sbx/publish.sh # TAG from release.env: v0.0.3 → k33g/mm-sandbox:0.0.3, k33g/mm-tui:0.0.3, k33g/mm-acp:0.0.3 | |
| 122 | 122 | ``` |
| 123 | 123 | |
| 124 | -`push-kits.sh` needs the `sbx` CLI on the PATH (or `SBX=/path/to/sbx`; the workflow downloads the Linux tarball of `docker/sbx-releases`). `sbx kit push` talks to the registry directly and authenticates from the Docker credential store — no sandbox daemon is involved, which is what makes it usable in CI. Both scripts call `sync-kits.sh` first, which rewrites the kits' `version`, default `tag` and image owner, so a published kit always names the image pushed with it. `IMAGE_OWNER=<handle>` publishes under another account. | |
| 124 | +With both variables set, the script logs in with them and logs out when it is done; with neither, it reuses your existing `docker login`. Its two halves run alone as `PUSH=1 ./docker-sbx/build.sh v0.0.3` (image) and `./docker-sbx/push-kits.sh v0.0.3` (kits, `SBX=/path/to/sbx` if the CLI is not on the PATH). Both call `sync-kits.sh` first, which rewrites the kits' `version`, default `tag` and image owner, so a published kit always names the image pushed with it — commit the two `spec.yaml` afterwards. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store, no sandbox daemon involved. `IMAGE_OWNER=<handle>` publishes under another account. | |
| 125 | 125 | |
| 126 | 126 | ## Variants |
| 127 | 127 | |
| @@ -113,15 +113,15 @@ Both kits allow ports 12434 and 8080 on the host in the sandbox's network policy | |||
| 113 | 113 | ||
| 114 | ## Publishing a version | 114 | ## Publishing a version |
| 115 | 115 | ||
| 116 | -The Release workflow (`.github/workflows/release.yml`, job `docker-sandbox`) publishes the image and the kits on every `v*` tag, after the binaries job. It needs two repository secrets, exposed to the job as environment variables: `DOCKER_HANDLE`, the Docker Hub account (also the image owner), and `DOCKER_PAT`, an access token with read/write scope. It then runs the scripts a laptop would run: | 116 | +Publishing is a manual step, from a machine with Docker Desktop (buildx and the `sbx` CLI); the Release workflow builds only the binaries. One script builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag: |
| 117 | 117 | ||
| 118 | ```bash | 118 | ```bash |
| 119 | -docker login -u k33g # paste an access token | 119 | +export DOCKER_HANDLE=k33g # the Docker Hub account, also the image owner |
| 120 | -PUSH=1 ./docker-sbx/build.sh v0.0.2 # buildx, linux/amd64 + linux/arm64, pushed as k33g/mm-sandbox:0.0.2 | 120 | +export DOCKER_PAT=dckr_pat_… # an access token with read/write scope |
| 121 | -./docker-sbx/push-kits.sh v0.0.2 # sbx kit validate + sbx kit push → k33g/mm-tui:0.0.2, k33g/mm-acp:0.0.2 | 121 | +./docker-sbx/publish.sh # TAG from release.env: v0.0.3 → k33g/mm-sandbox:0.0.3, k33g/mm-tui:0.0.3, k33g/mm-acp:0.0.3 |
| 122 | ``` | 122 | ``` |
| 123 | 123 | ||
| 124 | -`push-kits.sh` needs the `sbx` CLI on the PATH (or `SBX=/path/to/sbx`; the workflow downloads the Linux tarball of `docker/sbx-releases`). `sbx kit push` talks to the registry directly and authenticates from the Docker credential store — no sandbox daemon is involved, which is what makes it usable in CI. Both scripts call `sync-kits.sh` first, which rewrites the kits' `version`, default `tag` and image owner, so a published kit always names the image pushed with it. `IMAGE_OWNER=<handle>` publishes under another account. | 124 | +With both variables set, the script logs in with them and logs out when it is done; with neither, it reuses your existing `docker login`. Its two halves run alone as `PUSH=1 ./docker-sbx/build.sh v0.0.3` (image) and `./docker-sbx/push-kits.sh v0.0.3` (kits, `SBX=/path/to/sbx` if the CLI is not on the PATH). Both call `sync-kits.sh` first, which rewrites the kits' `version`, default `tag` and image owner, so a published kit always names the image pushed with it — commit the two `spec.yaml` afterwards. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store, no sandbox daemon involved. `IMAGE_OWNER=<handle>` publishes under another account. |
| 125 | 125 | ||
| 126 | ## Variants | 126 | ## Variants |
| 127 | 127 | ||
modified
docs/fr/how-to/run-in-a-docker-sandbox.md +5 -5 | @@ -113,15 +113,15 @@ Les deux kits autorisent les ports 12434 et 8080 de l'hôte dans la politique r | ||
| 113 | 113 | |
| 114 | 114 | ## Publier une version |
| 115 | 115 | |
| 116 | -Le workflow Release (`.github/workflows/release.yml`, job `docker-sandbox`) publie l'image et les kits à chaque tag `v*`, après le job des binaires. Il a besoin de deux secrets du dépôt, exposés au job comme variables d'environnement : `DOCKER_HANDLE`, le compte Docker Hub (aussi le propriétaire de l'image), et `DOCKER_PAT`, un jeton d'accès en lecture/écriture. Il lance ensuite les scripts qu'un portable lancerait : | |
| 116 | +La publication est une étape manuelle, depuis une machine avec Docker Desktop (buildx et la CLI `sbx`) ; le workflow Release ne construit que les binaires. Un script construit l'image pour linux/amd64 et linux/arm64, la pousse, puis valide et pousse les deux kits, le tout au tag de mm : | |
| 117 | 117 | |
| 118 | 118 | ```bash |
| 119 | -docker login -u k33g # coller un jeton d'accès | |
| 120 | -PUSH=1 ./docker-sbx/build.sh v0.0.2 # buildx, linux/amd64 + linux/arm64, poussée comme k33g/mm-sandbox:0.0.2 | |
| 121 | -./docker-sbx/push-kits.sh v0.0.2 # sbx kit validate + sbx kit push → k33g/mm-tui:0.0.2, k33g/mm-acp:0.0.2 | |
| 119 | +export DOCKER_HANDLE=k33g # le compte Docker Hub, aussi propriétaire de l'image | |
| 120 | +export DOCKER_PAT=dckr_pat_… # un jeton d'accès en lecture/écriture | |
| 121 | +./docker-sbx/publish.sh # TAG depuis release.env : v0.0.3 → k33g/mm-sandbox:0.0.3, k33g/mm-tui:0.0.3, k33g/mm-acp:0.0.3 | |
| 122 | 122 | ``` |
| 123 | 123 | |
| 124 | -`push-kits.sh` a besoin de la CLI `sbx` sur le PATH (ou `SBX=/chemin/vers/sbx` ; le workflow télécharge l'archive Linux de `docker/sbx-releases`). `sbx kit push` parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker — aucun démon sandbox n'intervient, c'est ce qui le rend utilisable en CI. Les deux scripts appellent d'abord `sync-kits.sh`, qui réécrit `version`, le `tag` par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui. `IMAGE_OWNER=<compte>` publie sous un autre compte. | |
| 124 | +Avec les deux variables, le script se connecte avec elles et se déconnecte à la fin ; sans elles, il réutilise votre `docker login` existant. Ses deux moitiés se lancent seules : `PUSH=1 ./docker-sbx/build.sh v0.0.3` (l'image) et `./docker-sbx/push-kits.sh v0.0.3` (les kits, `SBX=/chemin/vers/sbx` si la CLI n'est pas sur le PATH). Les deux appellent d'abord `sync-kits.sh`, qui réécrit `version`, le `tag` par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui — commitez ensuite les deux `spec.yaml`. `sbx kit push` parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker, sans démon sandbox. `IMAGE_OWNER=<compte>` publie sous un autre compte. | |
| 125 | 125 | |
| 126 | 126 | ## Variantes |
| 127 | 127 | |
| @@ -113,15 +113,15 @@ Les deux kits autorisent les ports 12434 et 8080 de l'hôte dans la politique r | |||
| 113 | 113 | ||
| 114 | ## Publier une version | 114 | ## Publier une version |
| 115 | 115 | ||
| 116 | -Le workflow Release (`.github/workflows/release.yml`, job `docker-sandbox`) publie l'image et les kits à chaque tag `v*`, après le job des binaires. Il a besoin de deux secrets du dépôt, exposés au job comme variables d'environnement : `DOCKER_HANDLE`, le compte Docker Hub (aussi le propriétaire de l'image), et `DOCKER_PAT`, un jeton d'accès en lecture/écriture. Il lance ensuite les scripts qu'un portable lancerait : | 116 | +La publication est une étape manuelle, depuis une machine avec Docker Desktop (buildx et la CLI `sbx`) ; le workflow Release ne construit que les binaires. Un script construit l'image pour linux/amd64 et linux/arm64, la pousse, puis valide et pousse les deux kits, le tout au tag de mm : |
| 117 | 117 | ||
| 118 | ```bash | 118 | ```bash |
| 119 | -docker login -u k33g # coller un jeton d'accès | 119 | +export DOCKER_HANDLE=k33g # le compte Docker Hub, aussi propriétaire de l'image |
| 120 | -PUSH=1 ./docker-sbx/build.sh v0.0.2 # buildx, linux/amd64 + linux/arm64, poussée comme k33g/mm-sandbox:0.0.2 | 120 | +export DOCKER_PAT=dckr_pat_… # un jeton d'accès en lecture/écriture |
| 121 | -./docker-sbx/push-kits.sh v0.0.2 # sbx kit validate + sbx kit push → k33g/mm-tui:0.0.2, k33g/mm-acp:0.0.2 | 121 | +./docker-sbx/publish.sh # TAG depuis release.env : v0.0.3 → k33g/mm-sandbox:0.0.3, k33g/mm-tui:0.0.3, k33g/mm-acp:0.0.3 |
| 122 | ``` | 122 | ``` |
| 123 | 123 | ||
| 124 | -`push-kits.sh` a besoin de la CLI `sbx` sur le PATH (ou `SBX=/chemin/vers/sbx` ; le workflow télécharge l'archive Linux de `docker/sbx-releases`). `sbx kit push` parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker — aucun démon sandbox n'intervient, c'est ce qui le rend utilisable en CI. Les deux scripts appellent d'abord `sync-kits.sh`, qui réécrit `version`, le `tag` par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui. `IMAGE_OWNER=<compte>` publie sous un autre compte. | 124 | +Avec les deux variables, le script se connecte avec elles et se déconnecte à la fin ; sans elles, il réutilise votre `docker login` existant. Ses deux moitiés se lancent seules : `PUSH=1 ./docker-sbx/build.sh v0.0.3` (l'image) et `./docker-sbx/push-kits.sh v0.0.3` (les kits, `SBX=/chemin/vers/sbx` si la CLI n'est pas sur le PATH). Les deux appellent d'abord `sync-kits.sh`, qui réécrit `version`, le `tag` par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui — commitez ensuite les deux `spec.yaml`. `sbx kit push` parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker, sans démon sandbox. `IMAGE_OWNER=<compte>` publie sous un autre compte. |
| 125 | 125 | ||
| 126 | ## Variantes | 126 | ## Variantes |
| 127 | 127 | ||