From 3f8105de17dedf7c68747564e8fc831954513c7b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 16:38:32 +0000 Subject: [PATCH] ci: stop updating the ollama.com pages from the workflow ollama.com answers 401 to page edits with an API key, the same as with no key or an invalid one: it accepts them only from a signed-in browser. Remove the page step, its script and the OLLAMA_API_KEY secret; the pages in docs/ollama/ are pasted by hand. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Cw7NFZ1kjsaaLELfRZLFv9 --- .github/workflows/publish-ollama.yml | 28 +++++++--------------------- Documentation.md | 18 +++++++----------- readme.md | 4 ++-- scripts/update-ollama-pages.sh | 24 ------------------------ tests/modelfile.test.mjs | 7 +++---- 5 files changed, 19 insertions(+), 62 deletions(-) delete mode 100755 scripts/update-ollama-pages.sh diff --git a/.github/workflows/publish-ollama.yml b/.github/workflows/publish-ollama.yml index 69c819d..158f864 100644 --- a/.github/workflows/publish-ollama.yml +++ b/.github/workflows/publish-ollama.yml @@ -1,22 +1,20 @@ name: publish-ollama -# Every change to main that touches a Modelfile or an Ollama page is published on ollama.com: -# the changed models are rebuilt and pushed as Tromset/, then the pages are updated from docs/ollama/. -# Needs two repository secrets (Settings > Secrets and variables > Actions): -# OLLAMA_KEY the private key ~/.ollama/id_ed25519 of a machine linked to the Tromset account (`ollama signin`) -# OLLAMA_API_KEY an API key from https://ollama.com/settings/keys +# Every change to main that touches a Modelfile is published on ollama.com: +# the changed models are rebuilt and pushed as Tromset/. +# The model pages are pasted by hand from docs/ollama/: ollama.com refuses page edits made with an API key. +# Needs one repository secret (Settings > Secrets and variables > Actions): +# OLLAMA_KEY the private key ~/.ollama/id_ed25519 of a machine linked to the Tromset account (`ollama signin`) on: push: branches: [main] paths: - 'Modelfile*' - - 'docs/ollama/**' - 'scripts/publish.sh' - - 'scripts/update-ollama-pages.sh' - '.github/workflows/publish-ollama.yml' workflow_dispatch: inputs: models: - description: 'Models to publish (space-separated names, "all", or "none" for pages only)' + description: 'Models to publish (space-separated names, or "all")' default: all concurrency: group: publish-ollama @@ -28,7 +26,6 @@ jobs: timeout-minutes: 120 env: OLLAMA_KEY: ${{ secrets.OLLAMA_KEY }} - OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }} steps: - uses: actions/checkout@v4 with: @@ -61,10 +58,9 @@ jobs: echo "Models to publish: $models" echo "models=$models" >> "$GITHUB_OUTPUT" - - name: Check the secrets + - name: Check the secret run: | [ -n "$OLLAMA_KEY" ] || { echo "::error::Add the OLLAMA_KEY secret (contents of ~/.ollama/id_ed25519 from a machine signed in to the Tromset account)."; exit 1; } - [ -n "$OLLAMA_API_KEY" ] || echo "::warning::OLLAMA_API_KEY is not set: the model pages will not be updated." - name: Free disk space for the base models if: steps.pick.outputs.models != 'none' @@ -96,16 +92,6 @@ jobs: # shellcheck disable=SC2086 if [ "$MODELS" = all ]; then sh scripts/publish.sh Tromset; else sh scripts/publish.sh Tromset $MODELS; fi - - name: Update the model pages - if: env.OLLAMA_API_KEY != '' - run: | - if sh scripts/update-ollama-pages.sh Tromset; then - echo "Model pages updated from docs/ollama/." >> "$GITHUB_STEP_SUMMARY" - else - echo "::warning::Some ollama.com pages were not updated (see the log). Paste docs/ollama/.md into the page by hand." - echo "Some ollama.com pages were not updated: paste docs/ollama/.md by hand." >> "$GITHUB_STEP_SUMMARY" - fi - - name: Remove the key if: always() run: rm -f ~/.ollama/id_ed25519 ~/.ollama/id_ed25519.pub diff --git a/Documentation.md b/Documentation.md index 58c58c7..5f5921a 100644 --- a/Documentation.md +++ b/Documentation.md @@ -352,23 +352,19 @@ With one attempt per problem, a gap of one problem is noise; the gap to the firs ## 8. Publishing on ollama.com -Publishing is automatic. On every change to `main` that touches a Modelfile, a page in `docs/ollama/` or the publishing scripts, the [publish-ollama](.github/workflows/publish-ollama.yml) workflow: +Publishing is automatic. On every change to `main` that touches a Modelfile or the publishing script, the [publish-ollama](.github/workflows/publish-ollama.yml) workflow rebuilds the changed models from their Modelfiles and pushes them as `Tromset/flycoder0.3`, `Tromset/flycoder0.3fast`, `Tromset/flycoder0.3pro`, `Tromset/flycoder0.3:lite` and `Tromset/flycoder0.3:router`. -1. rebuilds the changed models from their Modelfiles and pushes them as `Tromset/flycoder0.3`, `Tromset/flycoder0.3fast`, `Tromset/flycoder0.3pro`, `Tromset/flycoder0.3:lite` and `Tromset/flycoder0.3:router`; -2. updates each model page on ollama.com from `docs/ollama/.md`. - -It can also be started by hand from the Actions tab (Run workflow), with a list of models or `none` to update only the pages. +It can also be started by hand from the Actions tab (Run workflow), with a list of models or `all`. One-time setup, in the repository's Settings > Secrets and variables > Actions: | Secret | Value | |---|---| | `OLLAMA_KEY` | the private key `~/.ollama/id_ed25519` of a machine linked to the Tromset account (`ollama signin` on that machine first) | -| `OLLAMA_API_KEY` | an API key created at https://ollama.com/settings/keys, used to update the pages | -Updating a page uses the same request as the page's Edit button; Ollama does not document it. If it is refused, the workflow shows a warning and the page can still be pasted by hand. +The model pages are not published automatically: ollama.com accepts page edits only from a signed-in browser and refuses API keys. After changing `docs/ollama/.md`, open the model's page on ollama.com, click Edit and paste the file. -By hand, from any machine signed in to the account: `sh scripts/publish.sh` (all models) or `sh scripts/publish.sh Tromset flycoder0.3fast` (one model), then `OLLAMA_API_KEY=... sh scripts/update-ollama-pages.sh`. +By hand, from any machine signed in to the account: `sh scripts/publish.sh` (all models) or `sh scripts/publish.sh Tromset flycoder0.3fast` (one model). For a new version, update the version in `package.json`, `install.sh`, `scripts/publish.sh`, `scripts/publish-hf.sh`, the system prompt of the Modelfiles and the pages. `npm test` checks that they agree. @@ -408,7 +404,7 @@ By hand: `pip install huggingface_hub`, then `HF_TOKEN=... sh scripts/publish-hf | Thinking takes too long | simple question handled in thinking mode | `--think=false` or `/set nothink` | | Endless repetition | temperature changed to a value that is too low | go back to the Modelfile's settings | | `npm run bench`: "Reference solution failed" | `python3` or `node` missing, or sandbox refused | `xcode-select --install`, Node 22, or `--no-sandbox` | -| The publish workflow fails at "Check the secrets" | `OLLAMA_KEY` is missing | add it (section 8) | +| The publish workflow fails at "Check the secret" | `OLLAMA_KEY` is missing | add it (section 8) | | publish-huggingface warns "HF_TOKEN is not set" and publishes nothing | `HF_TOKEN` is missing | add it (section 8.1) | ## 10. Development @@ -422,8 +418,8 @@ By hand: `pip install huggingface_hub`, then `HF_TOKEN=... sh scripts/publish-hf | `brain/flybrain.mjs`, `brain/router.mjs` | FlyBrain server and routing rules | | `brain/eval-router.mjs`, `tests/fixtures/route-prompts.json` | router accuracy measurement | | `install.sh` | one-command installer | -| `scripts/publish.sh`, `scripts/update-ollama-pages.sh` | publishing models and pages on ollama.com | -| `docs/ollama/` | the ollama.com pages, one file per model | +| `scripts/publish.sh` | publishing the models on ollama.com | +| `docs/ollama/` | the ollama.com pages, one file per model, pasted by hand | | `docs/huggingface/`, `scripts/publish-hf.sh` | the Hugging Face model cards and their publisher | | `bench/bench.mjs`, `bench/problems.mjs` | benchmark and problems | | `bench/baselines/` | 0.1 profile, for comparison | diff --git a/readme.md b/readme.md index 6d3e4d5..9cd11e8 100644 --- a/readme.md +++ b/readme.md @@ -63,7 +63,7 @@ Details: [Documentation.md, section 5.5](Documentation.md#55-flybrain-the-router ## Publishing -Every change to `main` that touches a Modelfile or a page in `docs/ollama/` is published on ollama.com by the [publish-ollama](.github/workflows/publish-ollama.yml) workflow: models first, then their pages. It needs two repository secrets, `OLLAMA_KEY` and `OLLAMA_API_KEY` ([Documentation.md, section 8](Documentation.md#8-publishing-on-ollamacom)). +Every change to `main` that touches a Modelfile is published on ollama.com by the [publish-ollama](.github/workflows/publish-ollama.yml) workflow. It needs the repository secret `OLLAMA_KEY` ([Documentation.md, section 8](Documentation.md#8-publishing-on-ollamacom)). The model pages are pasted by hand from `docs/ollama/`. Each publication is then mirrored on Hugging Face by the [publish-huggingface](.github/workflows/publish-huggingface.yml) workflow: the same GGUF weights, vision projector, system prompt and sampling settings, with a model card from `docs/huggingface/`, under [huggingface.co/Tromset](https://huggingface.co/Tromset). It needs the `HF_TOKEN` secret ([Documentation.md, section 8.1](Documentation.md#81-publishing-on-hugging-face)). @@ -72,7 +72,7 @@ Each publication is then mirrored on Hugging Face by the [publish-huggingface](. - `Modelfile`, `Modelfile.fast`, `Modelfile.pro`: the three variants. `Modelfile.lite`, `Modelfile.router`: FlyBrain's experts. - `docs/ollama/`: the ollama.com page of each model. `docs/huggingface/`: the Hugging Face model card of each model. - `brain/`: the FlyBrain server and its routing rules. -- `install.sh`: one-command install. `scripts/publish.sh`, `scripts/update-ollama-pages.sh`, `scripts/publish-hf.sh`: publishing. +- `install.sh`: one-command install. `scripts/publish.sh`, `scripts/publish-hf.sh`: publishing. - `bench/`: quality and speed benchmark. `tests/`: `npm test`. - `training/`, `scripts/build_language_dataset.js`, `server/fly-language.js`: the former FlyBrain voice pipeline, independent of FlyCoder. diff --git a/scripts/update-ollama-pages.sh b/scripts/update-ollama-pages.sh deleted file mode 100755 index bf9578a..0000000 --- a/scripts/update-ollama-pages.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# Updates the model pages on ollama.com from docs/ollama/.md. -# OLLAMA_API_KEY=... sh scripts/update-ollama-pages.sh [] -# Uses the same request as the page's Edit button (POST https://ollama.com//, field readme), -# authenticated with an ollama.com API key (https://ollama.com/settings/keys). -# A page that cannot be updated is reported, and the script exits with status 1 at the end. -set -eu - -user=${1:-Tromset} -[ -n "${OLLAMA_API_KEY:-}" ] || { printf 'FlyCoder: OLLAMA_API_KEY is not set.\n' >&2; exit 1; } -here=$(cd "$(dirname "$0")/.." && pwd) - -failed=0 -for page in "$here"/docs/ollama/*.md; do - model=$(basename "$page" .md) - # No redirect following: a redirect to the sign-in page means the key was refused. - status=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "https://ollama.com/$user/$model" \ - -H "Authorization: Bearer $OLLAMA_API_KEY" --data-urlencode "readme@$page") || status=000 - case $status in - 2??) printf 'Updated https://ollama.com/%s/%s\n' "$user" "$model" ;; - *) printf 'FlyCoder: could not update https://ollama.com/%s/%s (HTTP %s)\n' "$user" "$model" "$status" >&2; failed=1 ;; - esac -done -exit "$failed" diff --git a/tests/modelfile.test.mjs b/tests/modelfile.test.mjs index 2aed028..51f5509 100644 --- a/tests/modelfile.test.mjs +++ b/tests/modelfile.test.mjs @@ -91,12 +91,11 @@ test('every published model has a short, up-to-date Ollama page', () => { } }); -test('the publish workflow runs the publisher and updates every page', () => { +test('the publish workflow runs the publisher with the Tromset key', () => { const workflow = read('.github/workflows/publish-ollama.yml'); assert.match(workflow, /branches: \[main\]/); assert.match(workflow, /sh scripts\/publish\.sh Tromset/); - for (const v of VARIANTS.filter(v => v.page)) assert.ok(workflow.includes(v.page.split('/').pop()) || workflow.includes('docs/ollama/'), `workflow uploads ${v.page}`); - for (const secret of ['OLLAMA_KEY', 'OLLAMA_API_KEY']) assert.ok(workflow.includes(`secrets.${secret}`), `workflow uses ${secret}`); + assert.ok(workflow.includes('secrets.OLLAMA_KEY'), 'workflow uses OLLAMA_KEY'); }); test('every published model has a Hugging Face model card and is mirrored by the Hugging Face publisher', () => { @@ -117,5 +116,5 @@ test('every published model has a Hugging Face model card and is mirrored by the }); test('shell scripts parse with POSIX sh', () => { - for (const file of ['install.sh', 'scripts/publish.sh', 'scripts/publish-hf.sh', 'scripts/update-ollama-pages.sh']) execFileSync('sh', ['-n', new URL(`../${file}`, import.meta.url).pathname]); + for (const file of ['install.sh', 'scripts/publish.sh', 'scripts/publish-hf.sh']) execFileSync('sh', ['-n', new URL(`../${file}`, import.meta.url).pathname]); });