Skip to content

Commit 7d3ceba

Browse files
feat: replace Elasticsearch search with Pagefind (#5106)
* feat: replace Elasticsearch search with Pagefind Migrate documentation search from a self-hosted Elasticsearch index to Pagefind, a static search library that crawls the built HTML in public/ and writes a chunked index into public/pagefind/. This removes the need for an Elasticsearch server, local docker container, CORS workarounds, and the ELASTICSEARCH_* CI secrets. - package.json: drop @elastic/elasticsearch, cheerio, html-entities and lodash; add pagefind dev dependency and a `pagefind` npm script - site.yml / extensions.md: remove the generate-index.js Antora extension - delete ext-antora/generate-index.js and es-docker-compose.yml - ci.yml: drop ELASTICSEARCH_* env/secrets, run `npm run pagefind` after the Antora build so the deployed site always ships a fresh index - build-the-docs.md: rewrite the Search section for the Pagefind workflow Verified locally: `npm run antora` builds cleanly with no reference to the removed extension, and `npm run pagefind` indexes 1359 pages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com> * ci: fail build on empty Pagefind index; require pagefind >= 1.5.0 Address review feedback on the Elasticsearch -> Pagefind migration: - CI ran `npm run pagefind` unconditionally. pagefind exits 0 even when it indexes nothing (e.g. the output dir moves or no indexable pages are emitted), so a broken index would deploy with silently empty search. Tee the output and fail the build unless at least 10 pages were indexed. - Bump the pagefind floor from ^1.3.0 to ^1.5.0. The docs-ui search markup uses the Component UI web components (pagefind-modal, pagefind-modal-trigger), which were introduced in Pagefind 1.5.0; ^1.3.0 declared compatibility with releases that lack them. The lockfile already resolved 1.5.2, so this only corrects the declared range (no dependency change). Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com> --------- Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 6ceaf02 commit 7d3ceba

8 files changed

Lines changed: 150 additions & 661 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,18 @@ jobs:
3232
run: npm install
3333

3434
- name: Build docs
35-
env:
36-
UPDATE_SEARCH_INDEX: ${{ github.ref == 'refs/heads/master' }}
37-
ELASTICSEARCH_NODE: ${{ secrets.ELASTICSEARCH_NODE }}
38-
ELASTICSEARCH_INDEX: ${{ secrets.ELASTICSEARCH_INDEX }}
39-
ELASTICSEARCH_READ_AUTH: ${{ secrets.ELASTICSEARCH_READ_AUTH }}
40-
ELASTICSEARCH_WRITE_AUTH: ${{ secrets.ELASTICSEARCH_WRITE_AUTH }}
4135
run: |
4236
npm run antora
37+
# Build the Pagefind search index and fail the build if it is empty.
38+
# pagefind exits 0 even when it indexes nothing (e.g. the output dir
39+
# moved or no indexable pages were emitted), which would deploy a site
40+
# with silently broken search. Require a non-trivial page count.
41+
npm run pagefind | tee pagefind.log
42+
grep -qE 'Indexed [1-9][0-9]+ pages' pagefind.log || {
43+
echo '::error::Pagefind indexed fewer than 10 pages - search index looks broken'
44+
exit 1
45+
}
46+
rm -f pagefind.log
4347
echo 'doc.owncloud.com' > public/CNAME
4448
4549
- name: Save cache

docs/build-the-docs.md

Lines changed: 10 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -392,88 +392,30 @@ Though components get sourced locally when running `npm run antora-dev-xxx`, som
392392

393393
The search bar is the component on the top right of the documentation where one can enter a term and get matches. If something is found, the matches are displayed as suggestions that can be clicked.
394394

395-
For "normal" changes, search is not necessary and may only complicate building commands and delay building times. To use the search functionality during production or development, see [Prepared npm Commands](#prepared-npm-commands) for details, some prerequisites apply. This is not only true for changes in the documentation, but also for UI changes.
395+
Search is powered by [Pagefind](https://pagefind.app), a static search library. There is no server, container, or secret to set up: Pagefind crawls the already-built HTML in `public/` and writes a static, chunked index into `public/pagefind/`. Because it runs over the build output, the index automatically covers every component and version included in that build.
396396

397-
Note that ownCloud currently uses Elasticsearch version 7.x. All internal scripts and builds are therefore aligned to it and *must not* be changed, though you can use any latest minor/patch release.
397+
Follow this procedure to build and use search locally:
398398

399-
Follow this procedure to show and use search and populate an index:
400-
401-
1. Create an `es-docker-compose.yml` file with the following content. Note that no security or passwords is needed to be set up as it is only used locally:
402-
403-
```
404-
services:
405-
elasticsearch:
406-
image: elasticsearch:7.17.15
407-
ports:
408-
- 9200:9200
409-
- 9300:9300
410-
environment:
411-
- discovery.type=single-node
412-
- xpack.security.enabled=false
413-
```
414-
415-
2. Start the container with the `up -d` command, use `down` to stop it.
416-
417-
```
418-
docker compose -f es-docker-compose.yml up -d
419-
```
420-
421-
3. To avoid a CORS Policy error, the browser must be prepared to allow access to the local Elasticsearch container. If this is not prepared, no search is possible and the browser console will return the following error:
399+
1. Build the site as usual with any `npm run antora-xxx` command, for example:
422400
```
423-
Access to XMLHttpRequest at 'http://localhost:9200/' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
424-
```
425-
There are several ways to fix this, only one is shown when using Chrome browsers. Install the plugin named [Allow CORS: Access-Control-Allow-Origin](https://chrome.google.com/webstore/detail/lhobafahddgcelffkeicbaginigeejlf).
426-
427-
4. When building docs, the following environment variables must be added to the build process. Note that you can use any `npm run antora-xxx` command:
428-
```
429-
UPDATE_SEARCH_INDEX=true \
430-
ELASTICSEARCH_NODE=http://localhost:9200 \
431-
ELASTICSEARCH_INDEX=docs \
432-
ELASTICSEARCH_WRITE_AUTH=x:y \
433401
npm run antora-local
434402
```
435-
Note that `ELASTICSEARCH_WRITE_AUTH` is necessary for building though it does not do any authentication. A value for that envvar must not be omitted but can be any dummy value you like in the format of at minimum two characters separated by a colon.
436403
437-
Running the build now also returns on the console:
404+
2. Index the built site. This reads `public/` and writes `public/pagefind/`:
438405
```
439-
elastic: generate search index
440-
elastic: rebuild search index
441-
elastic: remove old search index
442-
elastic: create empty search index
443-
elastic: upload search index
406+
npm run pagefind
444407
```
445408
446-
5. Optionally, the status of Elasticsearch can be monitored:
447-
`http://localhost:9200/_cat/indices?v=`
448-
```
449-
green open .geoip_databases Ygj4WI-STGmJrSeCfep7Tg 1 0 41 0 38.3mb 38.3mb
450-
yellow open docs oag2dCMnS4CiSXX0Ul8plA 1 1 163 0 1.4mb 1.4mb
451-
```
452-
To make a dummy query after the index has been created, type the following as URL in the browser and replace `term` with what you want to search for:
453-
`http://localhost:9200/_search?q=term`
454-
```
455-
{"took":45,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}, ...
456-
```
457-
458-
6. To view the build result either with `npm run serve` (Antora build) or `npm run preview` (UI build) run:
409+
The command prints a short summary of how many pages and words were indexed.
410+
411+
3. Serve the build and open it in the browser:
459412
```
460-
ELASTICSEARCH_NODE=http://localhost:9200 \
461-
ELASTICSEARCH_INDEX=docs \
462-
ELASTICSEARCH_READ_AUTH=x:y \
463413
npm run serve
464414
```
465415
466-
Note that for `ELASTICSEARCH_READ_AUTH`, the same applies as for `ELASTICSEARCH_WRITE_AUTH`.
416+
4. Enter any search term into the search field to see matches returned.
467417
468-
7. Open the build via the browser and enter any search term as required into the search field to see matches returned.
469-
470-
8. Note that building against ownCloud's hosted Elasticsearch is not possible locally though you can use it for previewing the build. To do so, type the following:
471-
```
472-
ELASTICSEARCH_NODE=https://search.owncloud.com \
473-
ELASTICSEARCH_INDEX=docs \
474-
ELASTICSEARCH_READ_AUTH=docs:cADL6DDAKEBrkFMrvfxXEtYm \
475-
npm run serve
476-
```
418+
In CI, the production build runs `npm run antora` followed by `npm run pagefind` before deploying `public/`, so the deployed site always ships a fresh index. Re-run `npm run pagefind` whenever the HTML changes; serving a build without indexing it first yields an empty search.
477419
478420
## Resolving Edit-this-page in Development
479421

docs/extensions.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ The documentation uses extensions that are added via the `site.yml` file. Some e
1212

1313
**Antora**
1414

15-
* Create an Elastic Search Index: `./ext-antora/generate-index.js`
1615
* Load Global Site Attributes: `./ext-antora/load-global-site-attributes.js`
1716

1817
## Optional Extensions

es-docker-compose.yml

Lines changed: 0 additions & 9 deletions
This file was deleted.

ext-antora/generate-index.js

Lines changed: 0 additions & 192 deletions
This file was deleted.

0 commit comments

Comments
 (0)