From 48456caeb3cc701cc0d0e15091a42c5b5cb540d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89milien=20=28perso=29?=
<4016501+unixfox@users.noreply.github.com>
Date: Fri, 9 May 2025 18:46:20 +0000
Subject: [PATCH 01/21] chore: docker + github-actions dependabot (#4754)
* chore: docker dependabot
* Add github actions too
---
.github/dependabot.yml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4128911f3..a106397f3 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -20,3 +20,21 @@ updates:
target-branch: "master"
commit-message:
prefix: "[upd] web-client (simple):"
+
+ - package-ecosystem: "docker"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "friday"
+ target-branch: "master"
+ commit-message:
+ prefix: "[upd] docker:"
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "friday"
+ target-branch: "master"
+ commit-message:
+ prefix: "[upd] github-actions:"
From e982b9f73205dec9da2c5c1fc757bb40c605c899 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Fri, 9 May 2025 23:05:20 +0200
Subject: [PATCH 02/21] [fix] documentation should run on push/pr
Instead of executing the workflow after integration.yml completes correctly, let's run this workflow parallel to integration.yml restoring the original behaviour.
---
.github/workflows/documentation.yml | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index 6d9f2cac5..629d9a272 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -4,11 +4,10 @@ name: Documentation
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
- workflow_run:
- workflows:
- - Integration
- types:
- - completed
+ push:
+ branches:
+ - master
+ pull_request:
branches:
- master
@@ -24,7 +23,6 @@ env:
jobs:
release:
- if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
name: Release
runs-on: ubuntu-24.04-arm
permissions:
@@ -56,7 +54,8 @@ jobs:
- name: Build documentation
run: make V=1 docs.clean docs.html
- - name: Release
+ - if: github.ref_name == 'master'
+ name: Release
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: "dist/docs"
From 8e2e7774d7aeb13eac29c4dc16d65a2051ca250d Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Sat, 10 May 2025 13:08:20 +0200
Subject: [PATCH 03/21] [mod] new l10n.yml workflow (#4734)
l10n.yml will run after integration.yml finishes successfully (will defer anything depending on integration.yml until heavy loads like container building are moved to separate workflows) and in master branch.
* After every integration.yml workflow completes successfully, only the `update` job runs.
* Dispatch and Crontab triggers only the `pr` job.
Style changes, cleanup and improved integration with CI by leveraging the use of shared cache between all workflows (not functional until all workflows have been refactored).
---
.github/workflows/integration.yml | 42 -------
.github/workflows/l10n.yml | 136 ++++++++++++++++++++++
.github/workflows/translations-update.yml | 59 ----------
3 files changed, 136 insertions(+), 101 deletions(-)
create mode 100644 .github/workflows/l10n.yml
delete mode 100644 .github/workflows/translations-update.yml
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 9ca96bf69..eb4f458d7 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -47,48 +47,6 @@ jobs:
- name: Build themes
run: make themes.all
- babel:
- name: Update translations branch
- runs-on: ubuntu-24.04
- if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
- needs:
- - python
- - themes
- permissions:
- contents: write # for make V=1 weblate.push.translations
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: '0'
- token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.12'
- architecture: 'x64'
- - name: Cache Python dependencies
- id: cache-python
- uses: actions/cache@v4
- with:
- path: |
- ./local
- ./.nvm
- ./node_modules
- key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- - name: weblate & git setup
- env:
- WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
- run: |
- mkdir -p ~/.config
- echo "${WEBLATE_CONFIG}" > ~/.config/weblate
- git config --global user.email "searxng-bot@users.noreply.github.com"
- git config --global user.name "searxng-bot"
- - name: Update transations
- id: update
- run: |
- make V=1 weblate.push.translations
-
dockers:
name: Docker
if: github.ref == 'refs/heads/master'
diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml
new file mode 100644
index 000000000..4220c5c65
--- /dev/null
+++ b/.github/workflows/l10n.yml
@@ -0,0 +1,136 @@
+---
+name: Translation
+
+# yamllint disable-line rule:truthy
+on:
+ workflow_dispatch:
+ workflow_run:
+ workflows:
+ - Integration
+ types:
+ - completed
+ branches:
+ - master
+ schedule:
+ - cron: "05 07 * * 5"
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref_name }}
+ cancel-in-progress: false
+
+permissions:
+ contents: read
+
+env:
+ PYTHON_VERSION: "3.13"
+
+jobs:
+ update:
+ if: github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success'
+ name: Update
+ runs-on: ubuntu-24.04-arm
+ permissions:
+ # For "make V=1 weblate.push.translations"
+ contents: write
+
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "${{ env.PYTHON_VERSION }}"
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
+ fetch-depth: "0"
+
+ - name: Setup cache Python
+ uses: actions/cache@v4
+ with:
+ key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
+ restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
+ path: "./local/"
+
+ - name: Setup venv
+ run: make V=1 install
+
+ - name: Setup Weblate
+ run: |
+ mkdir -p ~/.config
+ echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
+
+ - name: Setup Git
+ run: |
+ git config --global user.email "searxng-bot@users.noreply.github.com"
+ git config --global user.name "searxng-bot"
+
+ - name: Update translations
+ run: make V=1 weblate.push.translations
+
+ pr:
+ if: |
+ github.repository_owner == 'searxng'
+ && (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
+ name: Pull Request
+ runs-on: ubuntu-24.04-arm
+ permissions:
+ # For "make V=1 weblate.translations.commit"
+ contents: write
+ # For action "peter-evans/create-pull-request"
+ pull-requests: write
+
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "${{ env.PYTHON_VERSION }}"
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
+ fetch-depth: "0"
+
+ - name: Setup cache Python
+ uses: actions/cache@v4
+ with:
+ key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
+ restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
+ path: "./local/"
+
+ - name: Setup venv
+ run: make V=1 install
+
+ - name: Setup Weblate
+ run: |
+ mkdir -p ~/.config
+ echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
+
+ - name: Setup Git
+ run: |
+ git config --global user.email "searxng-bot@users.noreply.github.com"
+ git config --global user.name "searxng-bot"
+
+ - name: Merge and push translation updates
+ run: make V=1 weblate.translations.commit
+
+ - name: Create PR
+ id: cpr
+ uses: peter-evans/create-pull-request@v7
+ with:
+ author: "${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>"
+ committer: "searxng-bot "
+ title: "[l10n] update translations from Weblate"
+ commit-message: "[l10n] update translations from Weblate"
+ branch: "translations_update"
+ delete-branch: "true"
+ draft: "false"
+ signoff: "false"
+ labels: |
+ translation
+
+ - name: Display information
+ run: |
+ echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
+ echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
diff --git a/.github/workflows/translations-update.yml b/.github/workflows/translations-update.yml
deleted file mode 100644
index 85e141e7f..000000000
--- a/.github/workflows/translations-update.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-name: "Update translations"
-on: # yamllint disable-line rule:truthy
- schedule:
- - cron: "05 07 * * 5"
- workflow_dispatch:
-
-jobs:
- babel:
- name: "create PR for additions from weblate"
- runs-on: ubuntu-24.04
- if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: '0'
- token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.12'
- architecture: 'x64'
- - name: Cache Python dependencies
- id: cache-python
- uses: actions/cache@v4
- with:
- path: |
- ./local
- ./.nvm
- ./node_modules
- key: python-ubuntu-24.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- - name: weblate & git setup
- env:
- WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
- run: |
- mkdir -p ~/.config
- echo "${WEBLATE_CONFIG}" > ~/.config/weblate
- git config --global user.email "searxng-bot@users.noreply.github.com"
- git config --global user.name "searxng-bot"
- - name: Merge and push transation updates
- run: |
- make V=1 weblate.translations.commit
- - name: Create Pull Request
- id: cpr
- uses: peter-evans/create-pull-request@v3
- with:
- token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- commit-message: '[l10n] update translations from Weblate'
- committer: searxng-bot
- author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
- signoff: false
- branch: translations_update
- delete-branch: true
- draft: false
- title: '[l10n] update translations from Weblate'
- body: |
- update translations from Weblate
- labels: |
- translation
From 1b787ed35e9c51e335c42faee1f76695780ba4cb Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Sat, 10 May 2025 13:59:31 +0200
Subject: [PATCH 04/21] [mod] refactor integration.yml (#4763)
Style changes, cleanup and improved integration with CI by leveraging the use of
shared cache between all workflows.
---
.github/workflows/integration.yml | 102 ++++++++++++++++++++++--------
1 file changed, 75 insertions(+), 27 deletions(-)
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index eb4f458d7..abdaf0c18 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -1,58 +1,106 @@
+---
name: Integration
-on: # yamllint disable-line rule:truthy
+# yamllint disable-line rule:truthy
+on:
push:
- branches: ["master"]
+ branches:
+ - master
pull_request:
- branches: ["master"]
+ branches:
+ - master
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref_name }}
+ cancel-in-progress: false
permissions:
contents: read
+env:
+ PYTHON_VERSION: "3.13"
+
jobs:
- python:
+ test:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-24.04
strategy:
matrix:
- os: [ubuntu-24.04]
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+ python-version:
+ - "3.9"
+ - "3.10"
+ - "3.11"
+ - "3.12"
+ - "3.13"
+
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Install Ubuntu packages
- run: |
- sudo ./utils/searxng.sh install packages
- - name: Set up Python
+ - name: Setup Python
uses: actions/setup-python@v5
with:
- python-version: ${{ matrix.python-version }}
- architecture: 'x64'
+ python-version: "${{ matrix.python-version }}"
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: "false"
+
+ - name: Setup cache Python
+ uses: actions/cache@v4
+ with:
+ key: "python-${{ matrix.python-version }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
+ restore-keys: "python-${{ matrix.python-version }}-${{ runner.arch }}-"
+ path: "./local/"
+
+ - name: Setup venv
+ run: make V=1 install
+
- name: Run tests
run: make V=1 ci.test
- themes:
- name: Themes
- runs-on: ubuntu-24.04
+ theme:
+ name: Theme
+ runs-on: ubuntu-24.04-arm
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Install Ubuntu packages
- run: sudo ./utils/searxng.sh install buildhost
- - name: Set up Python
+ - name: Setup Python
uses: actions/setup-python@v5
with:
- python-version: '3.12'
- architecture: 'x64'
- - name: Build themes
+ python-version: "${{ env.PYTHON_VERSION }}"
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: "false"
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: "./.nvmrc"
+
+ - name: Setup cache Node.js
+ uses: actions/cache@v4
+ with:
+ key: "nodejs-${{ runner.arch }}-${{ hashFiles('./.nvmrc', './package.json') }}"
+ path: "./client/simple/node_modules/"
+
+ - name: Setup cache Python
+ uses: actions/cache@v4
+ with:
+ key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
+ restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
+ path: "./local/"
+
+ - name: Setup venv
+ run: make V=1 install
+
+ - name: Build
run: make themes.all
dockers:
name: Docker
if: github.ref == 'refs/heads/master'
needs:
- - python
- - themes
+ - test
+ - theme
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
runs-on: ubuntu-24.04
From d16854e67a5bf2f640aabf119c9b50f5a1a3f24f Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Sun, 11 May 2025 18:12:51 +0200
Subject: [PATCH 05/21] [mod] rework container deployment (#4764)
container.yml will run after integration.yml COMPLETES successfully and in master branch.
Style changes, cleanup and improved integration with CI by leveraging the use of
shared cache between all workflows.
* Podman is now supported to build the container images (Docker also received a refactor, merging both build and buildx)
* Container images are being built by Buildah instead of Docker BuildKit.
* Container images are tested before release.
* Splitting "modern" (amd64 & arm64) and "legacy" (armv7) arches on different Dockerfiles allowing future optimizations.
---
.github/workflows/container.yml | 183 ++++++++++
.github/workflows/integration.yml | 46 ---
Makefile | 10 +-
container/Dockerfile | 100 ++++++
.../docker-entrypoint.sh | 4 +-
Dockerfile => container/legacy/Dockerfile | 13 +-
{dockerfiles => container}/uwsgi.ini | 0
docs/admin/installation-docker.rst | 11 +-
manage | 91 +----
searx/version.py | 6 +
utils/lib_sxng_container.sh | 319 ++++++++++++++++++
11 files changed, 628 insertions(+), 155 deletions(-)
create mode 100644 .github/workflows/container.yml
create mode 100644 container/Dockerfile
rename {dockerfiles => container}/docker-entrypoint.sh (97%)
rename Dockerfile => container/legacy/Dockerfile (90%)
rename {dockerfiles => container}/uwsgi.ini (100%)
create mode 100644 utils/lib_sxng_container.sh
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
new file mode 100644
index 000000000..d232a0737
--- /dev/null
+++ b/.github/workflows/container.yml
@@ -0,0 +1,183 @@
+---
+name: Container
+
+# yamllint disable-line rule:truthy
+on:
+ workflow_dispatch:
+ workflow_run:
+ workflows:
+ - Integration
+ types:
+ - completed
+ branches:
+ - master
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref_name }}
+ cancel-in-progress: false
+
+permissions:
+ contents: read
+ # Organization GHCR
+ packages: read
+
+env:
+ PYTHON_VERSION: "3.13"
+
+jobs:
+ build:
+ if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
+ name: Build (${{ matrix.arch }})
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - arch: amd64
+ os: ubuntu-24.04
+ emulation: false
+ - arch: arm64
+ os: ubuntu-24.04-arm
+ emulation: false
+ - arch: armv7
+ os: ubuntu-24.04-arm
+ emulation: true
+
+ permissions:
+ # Organization GHCR
+ packages: write
+
+ outputs:
+ version_string: ${{ steps.build.outputs.version_string }}
+ version_tag: ${{ steps.build.outputs.version_tag }}
+ docker_tag: ${{ steps.build.outputs.docker_tag }}
+ git_url: ${{ steps.build.outputs.git_url }}
+ git_branch: ${{ steps.build.outputs.git_branch }}
+
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "${{ env.PYTHON_VERSION }}"
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: "false"
+
+ - name: Setup cache Python
+ uses: actions/cache@v4
+ with:
+ key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
+ restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
+ path: "./local/"
+
+ - name: Setup cache container mounts
+ uses: actions/cache@v4
+ with:
+ # yamllint disable-line rule:line-length
+ key: "container-mounts-${{ matrix.arch }}-${{ hashFiles('./container/Dockerfile ./container/legacy/Dockerfile') }}"
+ restore-keys: "container-mounts-${{ matrix.arch }}-"
+ path: |
+ /var/tmp/buildah-cache/
+ /var/tmp/buildah-cache-*/
+
+ - if: ${{ matrix.emulation }}
+ name: Setup QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Login to GHCR
+ uses: docker/login-action@v3
+ with:
+ registry: "ghcr.io"
+ username: "${{ github.repository_owner }}"
+ password: "${{ secrets.GITHUB_TOKEN }}"
+
+ - name: Build
+ id: build
+ env:
+ OVERRIDE_ARCH: "${{ matrix.arch }}"
+ run: make podman.build
+
+ test:
+ name: Test (${{ matrix.arch }})
+ runs-on: ${{ matrix.os }}
+ needs: build
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - arch: amd64
+ os: ubuntu-24.04
+ emulation: false
+ - arch: arm64
+ os: ubuntu-24.04-arm
+ emulation: false
+ - arch: armv7
+ os: ubuntu-24.04-arm
+ emulation: true
+
+ permissions:
+ # Organization GHCR
+ packages: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: "false"
+
+ - if: ${{ matrix.emulation }}
+ name: Setup QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Login to GHCR
+ uses: docker/login-action@v3
+ with:
+ registry: "ghcr.io"
+ username: "${{ github.repository_owner }}"
+ password: "${{ secrets.GITHUB_TOKEN }}"
+
+ - name: Test
+ env:
+ OVERRIDE_ARCH: "${{ matrix.arch }}"
+ GIT_URL: "${{ needs.build.outputs.git_url }}"
+ run: make container.test
+
+ release:
+ if: github.repository_owner == 'searxng' && github.ref_name == 'master'
+ name: Release
+ runs-on: ubuntu-24.04-arm
+ needs:
+ - build
+ - test
+
+ steps:
+ - if: env.DOCKERHUB_USERNAME != ''
+ name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: "false"
+
+ - if: env.DOCKERHUB_USERNAME != ''
+ name: Login to GHCR
+ uses: docker/login-action@v3
+ with:
+ registry: "ghcr.io"
+ username: "${{ github.repository_owner }}"
+ password: "${{ secrets.GITHUB_TOKEN }}"
+
+ - if: env.DOCKERHUB_USERNAME != ''
+ name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ registry: "docker.io"
+ username: "${{ env.DOCKERHUB_USERNAME }}"
+ password: "${{ secrets.DOCKERHUB_TOKEN }}"
+
+ - if: env.DOCKERHUB_USERNAME != ''
+ name: Release
+ env:
+ GIT_URL: "${{ needs.build.outputs.git_url }}"
+ DOCKER_TAG: "${{ needs.build.outputs.docker_tag }}"
+ run: make container.push
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index abdaf0c18..b40ae26ab 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -94,49 +94,3 @@ jobs:
- name: Build
run: make themes.all
-
- dockers:
- name: Docker
- if: github.ref == 'refs/heads/master'
- needs:
- - test
- - theme
- env:
- DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
- runs-on: ubuntu-24.04
- steps:
- - name: Checkout
- if: env.DOCKERHUB_USERNAME != null
- uses: actions/checkout@v4
- with:
- # make sure "make docker.push" can get the git history
- fetch-depth: '0'
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.12'
- architecture: 'x64'
- - name: Cache Python dependencies
- id: cache-python
- uses: actions/cache@v4
- with:
- path: |
- ./local
- ./.nvm
- ./node_modules
- key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- - name: Set up QEMU
- if: env.DOCKERHUB_USERNAME != null
- uses: docker/setup-qemu-action@v1
- - name: Set up Docker Buildx
- if: env.DOCKERHUB_USERNAME != null
- uses: docker/setup-buildx-action@v1
- - name: Login to DockerHub
- if: env.DOCKERHUB_USERNAME != null
- uses: docker/login-action@v1
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Build and push
- if: env.DOCKERHUB_USERNAME != null
- run: make -e GIT_URL=$(git remote get-url origin) docker.buildx
diff --git a/Makefile b/Makefile
index c1c067149..15e43be08 100644
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,7 @@ ci.test: test.yamllint test.black test.types.ci test.pylint test.unit test.robo
test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell
test.shell:
$(Q)shellcheck -x -s dash \
- dockerfiles/docker-entrypoint.sh
+ container/docker-entrypoint.sh
$(Q)shellcheck -x -s bash \
utils/brand.sh \
$(MTOOLS) \
@@ -77,7 +77,9 @@ test.shell:
MANAGE += weblate.translations.commit weblate.push.translations
MANAGE += data.all data.traits data.useragents data.locales data.currencies
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
-MANAGE += docker.build docker.push docker.buildx
+MANAGE += podman.build
+MANAGE += docker.build docker.buildx
+MANAGE += container.build container.test container.push
MANAGE += gecko.driver
MANAGE += node.env node.env.dev node.clean
MANAGE += py.build py.clean
@@ -95,8 +97,8 @@ $(MANAGE):
# short hands of selected targets
-PHONY += docs docker themes
+PHONY += docs container themes
docs: docs.html
-docker: docker.build
+container: container.build
themes: themes.all
diff --git a/container/Dockerfile b/container/Dockerfile
new file mode 100644
index 000000000..b0530dfec
--- /dev/null
+++ b/container/Dockerfile
@@ -0,0 +1,100 @@
+FROM docker.io/library/python:3.13-slim AS builder
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ build-essential \
+ brotli \
+ # uwsgi
+ libpcre3-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /usr/local/searxng/
+
+COPY ./requirements.txt ./requirements.txt
+
+RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
+ && . ./venv/bin/activate \
+ && pip install -r requirements.txt \
+ && pip install "uwsgi~=2.0"
+
+COPY ./searx/ ./searx/
+
+ARG TIMESTAMP_SETTINGS=0
+ARG TIMESTAMP_UWSGI=0
+
+RUN python -m compileall -q searx \
+ && touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
+ && touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
+ && find /usr/local/searxng/searx/static \
+ \( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
+ -type f -exec gzip -9 -k {} + -exec brotli --best {} +
+
+ARG SEARXNG_UID=977
+ARG SEARXNG_GID=977
+
+RUN grep -m1 root /etc/group > /tmp/.searxng.group \
+ && grep -m1 root /etc/passwd > /tmp/.searxng.passwd \
+ && echo "searxng:x:$SEARXNG_GID:" >> /tmp/.searxng.group \
+ && echo "searxng:x:$SEARXNG_UID:$SEARXNG_GID:searxng:/usr/local/searxng:/bin/bash" >> /tmp/.searxng.passwd
+
+FROM docker.io/library/python:3.13-slim
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ # healthcheck
+ wget \
+ # uwsgi
+ libpcre3 \
+ libxml2 \
+ mailcap \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
+COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
+
+ARG LABEL_DATE="0001-01-01T00:00:00Z"
+ARG GIT_URL="unspecified"
+ARG SEARXNG_GIT_VERSION="unspecified"
+ARG LABEL_VCS_REF="unspecified"
+ARG LABEL_VCS_URL="unspecified"
+
+WORKDIR /usr/local/searxng/
+
+COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
+COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
+COPY --chown=searxng:searxng ./container/ ./container/
+
+LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
+ org.opencontainers.image.created=$LABEL_DATE \
+ org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
+ org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker" \
+ org.opencontainers.image.licenses="AGPL-3.0-or-later" \
+ org.opencontainers.image.revision=$LABEL_VCS_REF \
+ org.opencontainers.image.source=$LABEL_VCS_URL \
+ org.opencontainers.image.title="searxng" \
+ org.opencontainers.image.url=$LABEL_VCS_URL \
+ org.opencontainers.image.version=$SEARXNG_GIT_VERSION
+
+ENV CONFIG_PATH=/etc/searxng \
+ DATA_PATH=/var/cache/searxng
+
+ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
+ INSTANCE_NAME=searxng \
+ AUTOCOMPLETE="" \
+ BASE_URL="" \
+ BIND_ADDRESS=[::]:8080 \
+ MORTY_KEY="" \
+ MORTY_URL="" \
+ SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
+ UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
+ UWSGI_WORKERS=%k \
+ UWSGI_THREADS=4
+
+VOLUME $CONFIG_PATH
+VOLUME $DATA_PATH
+
+EXPOSE 8080
+
+HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
+
+ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]
diff --git a/dockerfiles/docker-entrypoint.sh b/container/docker-entrypoint.sh
similarity index 97%
rename from dockerfiles/docker-entrypoint.sh
rename to container/docker-entrypoint.sh
index 3668fb589..72d020dcf 100755
--- a/dockerfiles/docker-entrypoint.sh
+++ b/container/docker-entrypoint.sh
@@ -140,14 +140,14 @@ if [ "$SEARX_CONF" -eq "1" ]; then
cat << EOF > /etc/searx/deprecated_volume_read_me.txt
This Docker image uses the volume /etc/searxng
Update your configuration:
-* remove uwsgi.ini (or very carefully update your existing uwsgi.ini using https://github.com/searxng/searxng/blob/master/dockerfiles/uwsgi.ini )
+* remove uwsgi.ini (or very carefully update your existing uwsgi.ini using https://github.com/searxng/searxng/blob/master/container/uwsgi.ini )
* mount /etc/searxng instead of /etc/searx
EOF
fi
# end of searx compatibility
# make sure there are uwsgi settings
-update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/dockerfiles/uwsgi.ini" "patch_uwsgi_settings"
+update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/container/uwsgi.ini" "patch_uwsgi_settings"
# make sure there are searxng settings
update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings"
diff --git a/Dockerfile b/container/legacy/Dockerfile
similarity index 90%
rename from Dockerfile
rename to container/legacy/Dockerfile
index 9aeb28214..5436ea5da 100644
--- a/Dockerfile
+++ b/container/legacy/Dockerfile
@@ -1,3 +1,5 @@
+# For armv7 architecture
+
FROM docker.io/library/python:3.13-slim AS builder
RUN apt-get update \
@@ -16,8 +18,7 @@ WORKDIR /usr/local/searxng/
COPY ./requirements.txt ./requirements.txt
-# Readd on #4707 "--mount=type=cache,id=pip,target=/root/.cache/pip"
-RUN python -m venv ./venv \
+RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
&& . ./venv/bin/activate \
&& pip install -r requirements.txt \
&& pip install "uwsgi~=2.0"
@@ -29,7 +30,7 @@ ARG TIMESTAMP_UWSGI=0
RUN python -m compileall -q searx \
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
- && touch -c --date=@$TIMESTAMP_UWSGI ./dockerfiles/uwsgi.ini \
+ && touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
&& find /usr/local/searxng/searx/static \
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-type f -exec gzip -9 -k {} + -exec brotli --best {} +
@@ -69,7 +70,7 @@ WORKDIR /usr/local/searxng/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
-COPY --chown=searxng:searxng ./dockerfiles/ ./dockerfiles/
+COPY --chown=searxng:searxng ./container/ ./container/
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
org.opencontainers.image.created=$LABEL_DATE \
@@ -90,8 +91,6 @@ ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
AUTOCOMPLETE="" \
BASE_URL="" \
BIND_ADDRESS=[::]:8080 \
- MORTY_KEY="" \
- MORTY_URL="" \
SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
UWSGI_WORKERS=%k \
@@ -104,4 +103,4 @@ EXPOSE 8080
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
-ENTRYPOINT ["/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
+ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]
diff --git a/dockerfiles/uwsgi.ini b/container/uwsgi.ini
similarity index 100%
rename from dockerfiles/uwsgi.ini
rename to container/uwsgi.ini
diff --git a/docs/admin/installation-docker.rst b/docs/admin/installation-docker.rst
index 09471891b..06b3fe465 100644
--- a/docs/admin/installation-docker.rst
+++ b/docs/admin/installation-docker.rst
@@ -145,13 +145,6 @@ shell inside container
- `How to make bash scripts work in dash `_
- `Checking for Bashisms `_
-Like in many other distributions, Alpine's `/bin/sh
-`__ is :man:`dash`. Dash is meant to be
-`POSIX-compliant `__.
-Compared to debian, in the Alpine image :man:`bash` is not installed. The
-:origin:`dockerfiles/docker-entrypoint.sh` script is checked *against dash*
-(``make tests.shell``).
-
To open a shell inside the container:
.. code:: sh
@@ -188,10 +181,10 @@ Command line
`__.
In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as
-:origin:`dockerfiles/docker-entrypoint.sh`
+:origin:`container/docker-entrypoint.sh`
.. code:: sh
docker run --rm -it searxng/searxng -h
-.. program-output:: ../dockerfiles/docker-entrypoint.sh -h
+.. program-output:: ../container/docker-entrypoint.sh -h
diff --git a/manage b/manage
index 61bc68b74..ee2a29281 100755
--- a/manage
+++ b/manage
@@ -11,6 +11,9 @@ source "$(dirname "${BASH_SOURCE[0]}")/utils/lib.sh"
# shellcheck source=utils/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_nvm.sh"
+# shellcheck source=utils/lib_sxng_container.sh
+source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_container.sh"
+
# shellcheck source=utils/lib_sxng_data.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_data.sh"
@@ -77,9 +80,6 @@ docs.:
gh-pages : deploy on gh-pages branch
prebuild : build reST include files (./${DOCS_BUILD}/includes)
clean : clean documentation build
-docker.:
- build : build docker image
- push : build and push docker image
gecko.driver:
download & install geckodriver if not already installed (required for
robot_tests)
@@ -101,6 +101,7 @@ EOF
go.help
node.help
weblate.help
+ container.help
data.help
test.help
themes.help
@@ -136,90 +137,6 @@ webapp.run() {
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
}
-docker.push() {
- docker.build push
-}
-
-docker.buildx() {
- docker.build buildx
-}
-
-# shellcheck disable=SC2119
-docker.build() {
- pyenv.install
-
- local SEARXNG_GIT_VERSION
- local VERSION_GITCOMMIT
- local GITHUB_USER
- local SEARXNG_IMAGE_NAME
- local BUILD
-
- build_msg DOCKER build
- # run installation in a subprocess and activate pyenv
-
- # See https://www.shellcheck.net/wiki/SC1001 and others ..
- # shellcheck disable=SC2031,SC2230,SC2002,SC2236,SC2143,SC1001
- ( set -e
- pyenv.activate
-
- # Check if it is a git repository
- if [ ! -d .git ]; then
- die 1 "This is not Git repository"
- fi
- if [ ! -x "$(which git)" ]; then
- die 1 "git is not installed"
- fi
-
- if ! git remote get-url origin 2> /dev/null; then
- die 1 "there is no remote origin"
- fi
-
- # This is a git repository
- git update-index -q --refresh
- python -m searx.version freeze
- eval "$(python -m searx.version)"
-
- # Get the last git commit id
- VERSION_GITCOMMIT=$(echo "$VERSION_TAG" | cut -d+ -f2)
- build_msg DOCKER "Last commit : $VERSION_GITCOMMIT"
-
- # define the docker image name
- GITHUB_USER=$(echo "${GIT_URL}" | sed 's/.*github\.com\/\([^\/]*\).*/\1/')
- SEARXNG_IMAGE_NAME="${SEARXNG_IMAGE_NAME:-${GITHUB_USER:-searxng}/searxng}"
-
- BUILD="build"
- if [ "$1" = "buildx" ]; then
- # buildx includes the push option
- CACHE_TAG="${SEARXNG_IMAGE_NAME}:latest-build-cache"
- BUILD="buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push --cache-from=type=registry,ref=$CACHE_TAG --cache-to=type=registry,ref=$CACHE_TAG,mode=max"
- shift
- fi
- build_msg DOCKER "Build command: ${BUILD}"
-
- # build Docker image
- build_msg DOCKER "Building image ${SEARXNG_IMAGE_NAME}:${SEARXNG_GIT_VERSION}"
- # shellcheck disable=SC2086
- docker $BUILD \
- --build-arg BASE_IMAGE="${DEPENDENCIES_IMAGE_NAME}" \
- --build-arg GIT_URL="${GIT_URL}" \
- --build-arg SEARXNG_DOCKER_TAG="${DOCKER_TAG}" \
- --build-arg SEARXNG_GIT_VERSION="${VERSION_STRING}" \
- --build-arg VERSION_GITCOMMIT="${VERSION_GITCOMMIT}" \
- --build-arg LABEL_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
- --build-arg LABEL_VCS_REF="$(git rev-parse HEAD)" \
- --build-arg LABEL_VCS_URL="${GIT_URL}" \
- --build-arg TIMESTAMP_SETTINGS="$(git log -1 --format="%cd" --date=unix -- searx/settings.yml)" \
- --build-arg TIMESTAMP_UWSGI="$(git log -1 --format="%cd" --date=unix -- dockerfiles/uwsgi.ini)" \
- -t "${SEARXNG_IMAGE_NAME}:latest" -t "${SEARXNG_IMAGE_NAME}:${DOCKER_TAG}" .
-
- if [ "$1" = "push" ]; then
- docker push "${SEARXNG_IMAGE_NAME}:latest"
- docker push "${SEARXNG_IMAGE_NAME}:${DOCKER_TAG}"
- fi
- )
- dump_return $?
-}
-
# shellcheck disable=SC2119
gecko.driver() {
pyenv.install
diff --git a/searx/version.py b/searx/version.py
index d2013808b..565cc7e7a 100644
--- a/searx/version.py
+++ b/searx/version.py
@@ -41,6 +41,12 @@ def subprocess_run(args, **kwargs):
def get_git_url_and_branch():
+ # handle GHA directly
+ if "GITHUB_REPOSITORY" in os.environ and "GITHUB_REF_NAME" in os.environ:
+ git_url = f"https://github.com/{os.environ['GITHUB_REPOSITORY']}"
+ git_branch = os.environ["GITHUB_REF_NAME"]
+ return git_url, git_branch
+
try:
ref = subprocess_run("git rev-parse --abbrev-ref @{upstream}")
except subprocess.CalledProcessError:
diff --git a/utils/lib_sxng_container.sh b/utils/lib_sxng_container.sh
new file mode 100644
index 000000000..b3f84594f
--- /dev/null
+++ b/utils/lib_sxng_container.sh
@@ -0,0 +1,319 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+container.help() {
+ cat </dev/null; then
+ die 1 "Git is not installed"
+ fi
+
+ # Check if podman or docker is installed
+ if [ "$1" = "docker" ]; then
+ if command -v docker &>/dev/null; then
+ container_engine="docker"
+ else
+ die 1 "Docker is not installed"
+ fi
+ elif [ "$1" = "podman" ]; then
+ if command -v podman &>/dev/null; then
+ container_engine="podman"
+ else
+ die 1 "Podman is not installed"
+ fi
+ else
+ # If no explicit engine is passed, prioritize podman over docker
+ if command -v podman &>/dev/null; then
+ container_engine="podman"
+ elif command -v docker &>/dev/null; then
+ container_engine="docker"
+ else
+ die 1 "Podman/Docker is not installed"
+ fi
+ fi
+ info_msg "Selected engine: $container_engine"
+
+ # Setup arch specific
+ case $parch in
+ "X64" | "x86_64" | "amd64")
+ dockerfile="Dockerfile"
+ arch="amd64"
+ variant=""
+ platform="linux/$arch"
+ ;;
+ "ARM64" | "aarch64" | "arm64")
+ dockerfile="Dockerfile"
+ arch="arm64"
+ variant=""
+ platform="linux/$arch"
+ ;;
+ "ARMV7" | "armhf" | "armv7l" | "armv7")
+ dockerfile="legacy/Dockerfile"
+ arch="arm"
+ variant="v7"
+ platform="linux/$arch/$variant"
+ ;;
+ *)
+ err_msg "Unsupported architecture; $parch"
+ exit 1
+ ;;
+ esac
+ info_msg "Selected platform: $platform"
+
+ pyenv.install
+
+ (
+ set -e
+ pyenv.activate
+
+ # Check if it is a git repository
+ if [ ! -d .git ]; then
+ die 1 "This is not Git repository"
+ fi
+
+ if ! git remote get-url origin &>/dev/null; then
+ die 1 "There is no remote origin"
+ fi
+
+ # This is a git repository
+ git update-index -q --refresh
+ python -m searx.version freeze
+ eval "$(python -m searx.version)"
+
+ info_msg "Set \$VERSION_STRING: $VERSION_STRING"
+ info_msg "Set \$VERSION_TAG: $VERSION_TAG"
+ info_msg "Set \$DOCKER_TAG: $DOCKER_TAG"
+ info_msg "Set \$GIT_URL: $GIT_URL"
+ info_msg "Set \$GIT_BRANCH: $GIT_BRANCH"
+
+ if [ "$container_engine" = "podman" ]; then
+ params_build_builder="build --format=docker --platform=$platform --target=builder --layers --identity-label=false"
+ params_build="build --format=docker --platform=$platform --layers --squash-all --omit-history --identity-label=false"
+ else
+ params_build_builder="build --platform=$platform --target=builder"
+ params_build="build --platform=$platform --squash"
+ fi
+
+ if [ "$GITHUB_ACTIONS" = "true" ]; then
+ params_build_builder+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
+ params_build+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
+
+ # Tags
+ params_build+=" --tag=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
+ else
+ # Tags
+ params_build+=" --tag=localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:latest"
+ params_build+=" --tag=localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$DOCKER_TAG"
+ fi
+
+ # shellcheck disable=SC2086
+ "$container_engine" $params_build_builder \
+ --build-arg="TIMESTAMP_SETTINGS=$(git log -1 --format="%cd" --date=unix -- ./searx/settings.yml)" \
+ --build-arg="TIMESTAMP_UWSGI=$(git log -1 --format="%cd" --date=unix -- ./container/uwsgi.ini)" \
+ --tag="localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:builder" \
+ --file="./container/$dockerfile" \
+ .
+ build_msg CONTAINER "Image \"builder\" built"
+
+ # shellcheck disable=SC2086
+ "$container_engine" $params_build \
+ --build-arg="GIT_URL=$GIT_URL" \
+ --build-arg="SEARXNG_GIT_VERSION=$VERSION_STRING" \
+ --build-arg="LABEL_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
+ --build-arg="LABEL_VCS_REF=$(git rev-parse HEAD)" \
+ --build-arg="LABEL_VCS_URL=$GIT_URL" \
+ --file="./container/$dockerfile" \
+ .
+ build_msg CONTAINER "Image built"
+
+ if [ "$GITHUB_ACTIONS" = "true" ]; then
+ "$container_engine" push "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
+
+ # Output to GHA
+ {
+ echo "version_string=$VERSION_STRING"
+ echo "version_tag=$VERSION_TAG"
+ echo "docker_tag=$DOCKER_TAG"
+ echo "git_url=$GIT_URL"
+ echo "git_branch=$GIT_BRANCH"
+ } >>"$GITHUB_OUTPUT"
+ fi
+ )
+ dump_return $?
+}
+
+container.test() {
+ local parch=${OVERRIDE_ARCH:-$(uname -m)}
+ local arch
+ local variant
+ local platform
+
+ if [ "$GITHUB_ACTIONS" != "true" ]; then
+ die 1 "This command is intended to be run in GitHub Actions"
+ fi
+
+ # Check if podman is installed
+ if ! command -v podman &>/dev/null; then
+ die 1 "podman is not installed"
+ fi
+
+ # Setup arch specific
+ case $parch in
+ "X64" | "x86_64" | "amd64")
+ arch="amd64"
+ variant=""
+ platform="linux/$arch"
+ ;;
+ "ARM64" | "aarch64" | "arm64")
+ arch="arm64"
+ variant=""
+ platform="linux/$arch"
+ ;;
+ "ARMV7" | "armhf" | "armv7l" | "armv7")
+ arch="arm"
+ variant="v7"
+ platform="linux/$arch/$variant"
+ ;;
+ *)
+ err_msg "Unsupported architecture; $parch"
+ exit 1
+ ;;
+ esac
+ build_msg CONTAINER "Selected platform: $platform"
+
+ (
+ set -e
+
+ podman pull "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
+
+ name="$CONTAINER_IMAGE_NAME-$(date +%N)"
+
+ podman create --name="$name" --rm --timeout=60 --network="host" \
+ "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant" >/dev/null
+
+ podman start "$name" >/dev/null
+ podman logs -f "$name" &
+ pid_logs=$!
+
+ # Wait until container is ready
+ sleep 5
+
+ curl -vf --max-time 5 "http://localhost:8080/healthz"
+
+ kill $pid_logs &>/dev/null || true
+ podman stop "$name" >/dev/null
+ )
+ dump_return $?
+}
+
+container.push() {
+ # Architectures on manifest
+ local release_archs=("amd64" "arm64" "armv7")
+
+ local archs=()
+ local variants=()
+ local platforms=()
+
+ if [ "$GITHUB_ACTIONS" != "true" ]; then
+ die 1 "This command is intended to be run in GitHub Actions"
+ fi
+
+ # Check if podman is installed
+ if ! command -v podman &>/dev/null; then
+ die 1 "podman is not installed"
+ fi
+
+ for arch in "${release_archs[@]}"; do
+ case $arch in
+ "X64" | "x86_64" | "amd64")
+ archs+=("amd64")
+ variants+=("")
+ platforms+=("linux/${archs[-1]}")
+ ;;
+ "ARM64" | "aarch64" | "arm64")
+ archs+=("arm64")
+ variants+=("")
+ platforms+=("linux/${archs[-1]}")
+ ;;
+ "ARMV7" | "armv7" | "armhf" | "arm")
+ archs+=("arm")
+ variants+=("v7")
+ platforms+=("linux/${archs[-1]}/${variants[-1]}")
+ ;;
+ *)
+ err_msg "Unsupported architecture; $arch"
+ exit 1
+ ;;
+ esac
+ done
+
+ (
+ set -e
+
+ # Pull archs
+ for i in "${!archs[@]}"; do
+ podman pull "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-${archs[$i]}${variants[$i]}"
+ done
+
+ # Manifest tags
+ release_tags=("latest")
+ release_tags+=("$DOCKER_TAG")
+
+ # Create manifests
+ for tag in "${release_tags[@]}"; do
+ if ! podman manifest exists "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"; then
+ podman manifest create "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
+ fi
+
+ # Add archs to manifest
+ for i in "${!archs[@]}"; do
+ podman manifest add \
+ "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
+ "containers-storage:ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-${archs[$i]}${variants[$i]}"
+ done
+ done
+
+ podman image list
+
+ # Push manifests
+ for tag in "${release_tags[@]}"; do
+ build_msg CONTAINER "Pushing manifest with tag: $tag"
+
+ podman manifest push \
+ "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
+ "docker://docker.io/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
+ done
+ )
+ dump_return $?
+}
+
+# Alias
+podman.build() {
+ container.build podman
+}
+
+# Alias
+docker.build() {
+ container.build docker
+}
+
+# Alias
+docker.buildx() {
+ container.build docker
+}
From da3c640cef71032bced6f4e8baf1665801cdc4b9 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Sun, 11 May 2025 18:39:25 +0200
Subject: [PATCH 06/21] revert using null keyword
env.DOCKERHUB_USERNAME shouldn't be an empty string as it's defined and set (I think, I can't see this). Even if wasn't defined, GitHub Org/Repo wide envs/secrets should return an empty string (?)
---
.github/workflows/container.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index d232a0737..ee1093acb 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -153,13 +153,13 @@ jobs:
- test
steps:
- - if: env.DOCKERHUB_USERNAME != ''
+ - if: env.DOCKERHUB_USERNAME != null
name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- - if: env.DOCKERHUB_USERNAME != ''
+ - if: env.DOCKERHUB_USERNAME != null
name: Login to GHCR
uses: docker/login-action@v3
with:
@@ -167,7 +167,7 @@ jobs:
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- - if: env.DOCKERHUB_USERNAME != ''
+ - if: env.DOCKERHUB_USERNAME != null
name: Login to Docker Hub
uses: docker/login-action@v3
with:
@@ -175,7 +175,7 @@ jobs:
username: "${{ env.DOCKERHUB_USERNAME }}"
password: "${{ secrets.DOCKERHUB_TOKEN }}"
- - if: env.DOCKERHUB_USERNAME != ''
+ - if: env.DOCKERHUB_USERNAME != null
name: Release
env:
GIT_URL: "${{ needs.build.outputs.git_url }}"
From 750a7b4d6fba37f5d0d6bf42b99a865dc7e035e8 Mon Sep 17 00:00:00 2001
From: Markus Heiser
Date: Mon, 12 May 2025 08:27:16 +0200
Subject: [PATCH 07/21] [doc] add chapter on the purpose of (git) commits
(#4729)
Chapter on the purpose of (git) commits
The commits and their messages are elementary for the traceability of changes
and are unfortunately still too often given too little attention.
It therefore seems necessary to dedicate a chapter to this topic in the context
of development.
Signed-off-by: Markus Heiser
---
docs/dev/commits.rst | 108 ++++++++++++++++++++++++++++++++
docs/dev/contribution_guide.rst | 30 +++------
docs/dev/index.rst | 1 +
3 files changed, 116 insertions(+), 23 deletions(-)
create mode 100644 docs/dev/commits.rst
diff --git a/docs/dev/commits.rst b/docs/dev/commits.rst
new file mode 100644
index 000000000..e9b10fa2e
--- /dev/null
+++ b/docs/dev/commits.rst
@@ -0,0 +1,108 @@
+.. _create commit:
+
+===============================
+Git Commits & Change Management
+===============================
+
+.. sidebar:: Create good commits!
+
+ - `Conventional Commits`_
+ - `Structural split of changes`_
+ - `Git Commit Good Practice`_
+
+A commit and its commit message are among the most important information
+available to a developer for bug fixing and further development. A commit is a
+change and changes have a context (a change request).
+
+In a SCM system (git), the change history is derived from the commit history. A
+commit message is therefore part of the documentation for change management and
+thus elementary for the traceability of changes.
+
+**What a commit is not**: *A commit to an SCM system is not used to save files!*
+
+A commit should always have a context and the commit message describes what is
+to be changed in that context, just as a function description should describe
+what the intention and the goal of the function is, a commit message should
+describe what the intention and the goal of that commit is.
+
+The commit messages form the history and are the first and therefore most
+important information a developer has when he has to research when and why a
+change had to be made and how it was made (what the goal was).
+
+Like any text, a commit message should be written for the reader and not from
+the perspective of the author.
+
+When scrolling through the history, the first thing one see is the title of the
+commit message. Therefore the title should describe the change as briefly and
+precisely as possible ... followed by a blank line and then a somewhat detailed
+description of the change.
+
+----
+
+The follwing rules should be in mind, when creating a commit:
+
+- **Commit history should be read like a history book.**
+- **Commit messages are for the reader not for the author of the commit.**
+- **A commit is the atomic code-modification of a change in change management.**
+- **Think about which descriptions from your PR might belong in the commit message.**
+- **The maximum line length in a commit message is 80 characters.**
+
+----
+
+Choose meaningful commit messages:
+
+ .. code::
+
+ [type] optional scope: description
+
+ [body]
+
+ [optional trailers]
+
+``[type]``:
+ Commits MUST be prefixed with a type .. ``feat``, ``fix``, ``refactor``,
+ ``mod``, ``upd``, ``doc``, ``l10n``, ``build`` ..
+
+``[body]``
+ `Information in commit messages`_
+
+``[optional trailers]``:
+ - `Signed-off-by`_: certify that the committer has the rights to submit the
+ work under the project’s license. That the developer has this right is a
+ prerequisite for a merge. If the `Signed-off-by`_ is not set in the
+ commit, the contributor enters his `Developer's Certificate of Origin` at
+ the latest when creating a PR!
+ - Closes: Link to the bug report or the bug number (e.g. ``Closes: #10``)
+ - `Co-authored-by`_: email address of the co-author
+ - Reported-by: email address (if there is no bug report)
+ - Suggested-by: email address (if there is no bug report)
+
+----
+
+To give examples at hand, here are a few commits. Follow the links to see the
+full commit messages:
+
+:patch:`44d941c93`
+ ``[fix] mojeek web engine: don't add empty fmt argument for web searches``
+
+:patch:`feb15e387`
+ ``[fix] brave.news engine: response is HTML and no longer JSON``
+
+:patch:`bdfe1c2a1`
+ ``[mod] engines: migration of the individual cache solutions to EngineCache``
+
+
+.. _Conventional Commits:
+ https://www.conventionalcommits.org/
+.. _Structural split of changes:
+ https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes
+.. _Git Commit Good Practice:
+ https://wiki.openstack.org/wiki/GitCommitMessages
+.. _Information in commit messages:
+ https://wiki.openstack.org/wiki/GitCommitMessages#Information_in_commit_messages
+.. _`Developer's Certificate of Origin`:
+ https://developercertificate.org/
+.. _Signed-off-by:
+ https://git-scm.com/docs/git-commit#Documentation/git-commit.txt-code--signoffcode
+.. _Co-authored-by:
+ https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors
diff --git a/docs/dev/contribution_guide.rst b/docs/dev/contribution_guide.rst
index 61dd28c05..026cfbe73 100644
--- a/docs/dev/contribution_guide.rst
+++ b/docs/dev/contribution_guide.rst
@@ -30,15 +30,15 @@ SearXNG was born out of the need for a **privacy-respecting** search tool which
can be extended easily to maximize both its search and its privacy protecting
capabilities.
-Some widely used search engine features may work differently,
-may be turned off by default, or may not be implemented at all in SearXNG
+Some widely used search engine features may work differently,
+may be turned off by default, or may not be implemented at all in SearXNG
**as a consequence of a privacy-by-design approach**.
Following this approach, features reducing the privacy preserving aspects of SearXNG should be
switched off by default or should not be implemented at all. There are plenty of
search engines already providing such features. If a feature reduces
-SearXNG's efficacy in protecting a user's privacy, the user must be informed about
-the effect of choosing to enable it. Features that protect privacy but differ from the
+SearXNG's efficacy in protecting a user's privacy, the user must be informed about
+the effect of choosing to enable it. Features that protect privacy but differ from the
expectations of the user should also be carefully explained to them.
Also, if you think that something works weird with SearXNG, it might be because
@@ -56,20 +56,12 @@ Code
====
.. _PEP8: https://www.python.org/dev/peps/pep-0008/
-.. _Conventional Commits: https://www.conventionalcommits.org/
-.. _Git Commit Good Practice: https://wiki.openstack.org/wiki/GitCommitMessages
.. _Structural split of changes:
https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes
-.. _gitmoji: https://gitmoji.carloscuesta.me/
-.. _Semantic PR: https://github.com/zeke/semantic-pull-requests
.. sidebar:: Create good commits!
- - `Structural split of changes`_
- - `Conventional Commits`_
- - `Git Commit Good Practice`_
- - some like to use: gitmoji_
- - not yet active: `Semantic PR`_
+ - :ref:`create commit`
In order to submit a patch, please follow the steps below:
@@ -88,15 +80,7 @@ In order to submit a patch, please follow the steps below:
- Add yourself to the :origin:`AUTHORS.rst` file.
-- Choose meaningful commit messages, read `Conventional Commits`_
-
- .. code::
-
- [optional scope]:
-
- [optional body]
-
- [optional footer(s)]
+- Choose meaningful commit messages, see :ref:`create commit`
- Create a pull request.
@@ -161,7 +145,7 @@ changed (:ref:`make docs.clean`).
Live builds are implemented by sphinx-autobuild_. Use environment
``$(SPHINXOPTS)`` to pass arguments to the sphinx-autobuild_ command. You can
-pass any argument except for the ``--host`` option (which is always set to ``0.0.0.0``).
+pass any argument except for the ``--host`` option (which is always set to ``0.0.0.0``).
E.g., to find and use a free port, use:
.. code:: sh
diff --git a/docs/dev/index.rst b/docs/dev/index.rst
index 01a16ba80..6d601d166 100644
--- a/docs/dev/index.rst
+++ b/docs/dev/index.rst
@@ -6,6 +6,7 @@ Developer documentation
:maxdepth: 2
quickstart
+ commits
rtm_asdf
contribution_guide
extended_types
From 346d7fe0192ea180552adbd2877dc13b3dd4050e Mon Sep 17 00:00:00 2001
From: Markus Heiser
Date: Mon, 12 May 2025 16:42:43 +0200
Subject: [PATCH 08/21] [mod] CI: dependabot group updates by minor & patch and
major updates (#4773)
By default, Dependabot opens a new pull request to update each dependency and we
have a very large number of Dependabot pull requests to review and merge, which
can quickly become difficult to manage.
The intention of this patch to dependabot is to have:
- one PR for all minor & patch level updates
- one PR for every dependency with a major update
[1] https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/optimizing-pr-creation-version-updates
[2] https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#groups
Signed-off-by: Markus Heiser
---
.github/dependabot.yml | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index a106397f3..46e341362 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -10,6 +10,12 @@ updates:
target-branch: "master"
commit-message:
prefix: "[upd] pypi:"
+ groups:
+ minor:
+ applies-to: version-updates
+ update-types:
+ - "minor"
+ - "patch"
- package-ecosystem: "npm"
directory: "/client/simple"
@@ -20,6 +26,12 @@ updates:
target-branch: "master"
commit-message:
prefix: "[upd] web-client (simple):"
+ groups:
+ minor:
+ applies-to: version-updates
+ update-types:
+ - "minor"
+ - "patch"
- package-ecosystem: "docker"
directory: "/"
From 64a5b6920f1fd386d5ec8bce575b2ea0c82b2572 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Mon, 12 May 2025 10:36:04 +0200
Subject: [PATCH 09/21] [mod] lib_sxng_container.sh use required_commands()
helper
Suggested-by: @return42 https://github.com/searxng/searxng/pull/4764#discussion_r2083564489
---
utils/lib_sxng_container.sh | 32 ++++++++------------------------
1 file changed, 8 insertions(+), 24 deletions(-)
diff --git a/utils/lib_sxng_container.sh b/utils/lib_sxng_container.sh
index b3f84594f..1df9ef358 100644
--- a/utils/lib_sxng_container.sh
+++ b/utils/lib_sxng_container.sh
@@ -19,24 +19,14 @@ container.build() {
local variant
local platform
- # Check if git is installed
- if ! command -v git &>/dev/null; then
- die 1 "Git is not installed"
- fi
+ required_commands git
# Check if podman or docker is installed
- if [ "$1" = "docker" ]; then
- if command -v docker &>/dev/null; then
- container_engine="docker"
- else
- die 1 "Docker is not installed"
- fi
- elif [ "$1" = "podman" ]; then
- if command -v podman &>/dev/null; then
- container_engine="podman"
- else
- die 1 "Podman is not installed"
+ if [ "$1" = "podman" ] || [ "$1" = "docker" ]; then
+ if ! command -v "$1" &>/dev/null; then
+ die 42 "$1 is not installed"
fi
+ container_engine="$1"
else
# If no explicit engine is passed, prioritize podman over docker
if command -v podman &>/dev/null; then
@@ -44,7 +34,7 @@ container.build() {
elif command -v docker &>/dev/null; then
container_engine="docker"
else
- die 1 "Podman/Docker is not installed"
+ die 42 "no compatible container engine is installed (podman or docker)"
fi
fi
info_msg "Selected engine: $container_engine"
@@ -168,10 +158,7 @@ container.test() {
die 1 "This command is intended to be run in GitHub Actions"
fi
- # Check if podman is installed
- if ! command -v podman &>/dev/null; then
- die 1 "podman is not installed"
- fi
+ required_commands podman
# Setup arch specific
case $parch in
@@ -234,10 +221,7 @@ container.push() {
die 1 "This command is intended to be run in GitHub Actions"
fi
- # Check if podman is installed
- if ! command -v podman &>/dev/null; then
- die 1 "podman is not installed"
- fi
+ required_commands podman
for arch in "${release_archs[@]}"; do
case $arch in
From 945b30a1c459e6b437a3f379e638c2002a81fcab Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Mon, 12 May 2025 10:41:49 +0200
Subject: [PATCH 10/21] [mod] lib_sxng_container.sh: replace echo commands with
heredoc
Suggested-by: @return42 https://github.com/searxng/searxng/pull/4764#discussion_r2083571202
---
utils/lib_sxng_container.sh | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/utils/lib_sxng_container.sh b/utils/lib_sxng_container.sh
index 1df9ef358..f87b64e2b 100644
--- a/utils/lib_sxng_container.sh
+++ b/utils/lib_sxng_container.sh
@@ -136,13 +136,13 @@ container.build() {
"$container_engine" push "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
# Output to GHA
- {
- echo "version_string=$VERSION_STRING"
- echo "version_tag=$VERSION_TAG"
- echo "docker_tag=$DOCKER_TAG"
- echo "git_url=$GIT_URL"
- echo "git_branch=$GIT_BRANCH"
- } >>"$GITHUB_OUTPUT"
+ cat <>"$GITHUB_OUTPUT"
+version_string=$VERSION_STRING
+version_tag=$VERSION_TAG
+docker_tag=$DOCKER_TAG
+git_url=$GIT_URL
+git_branch=$GIT_BRANCH
+EOF
fi
)
dump_return $?
From 5d99373bc65c7087ee743a1fe44897bad6065338 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Mon, 12 May 2025 23:43:47 +0200
Subject: [PATCH 11/21] [fix] DOCKERHUB_USERNAME env reference (#4778)
When making the container rework, I unknowingly deleted the section where an env with the same name as the secret was defined on the job scope, making it look like it was originally defined as an organization env.
Since we can't validate the secrets in a condition directly, it's better to let docker/login-action take care of failing the entire job if the credentials are invalid.
Reported in: https://github.com/searxng/searxng/issues/4777
---
.github/workflows/container.yml | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index ee1093acb..ef92a0662 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -153,30 +153,26 @@ jobs:
- test
steps:
- - if: env.DOCKERHUB_USERNAME != null
- name: Checkout
+ - name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- - if: env.DOCKERHUB_USERNAME != null
- name: Login to GHCR
+ - name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- - if: env.DOCKERHUB_USERNAME != null
- name: Login to Docker Hub
+ - name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: "docker.io"
- username: "${{ env.DOCKERHUB_USERNAME }}"
+ username: "${{ secrets.DOCKERHUB_USERNAME }}"
password: "${{ secrets.DOCKERHUB_TOKEN }}"
- - if: env.DOCKERHUB_USERNAME != null
- name: Release
+ - name: Release
env:
GIT_URL: "${{ needs.build.outputs.git_url }}"
DOCKER_TAG: "${{ needs.build.outputs.docker_tag }}"
From 90068660196d898896219d1df7a088348c5d3d14 Mon Sep 17 00:00:00 2001
From: Markus Heiser
Date: Tue, 13 May 2025 10:18:28 +0200
Subject: [PATCH 12/21] [fix] engine archlinux: avoid Anubis challenge by
User-Agent "SearXNG" (#4779)
Of the archlinux wikis only wiki.archlinux.org has a has Anubis challenge.
About Anubis[1]:
> Anubis decides to present a challenge using this logic:
>
> - User-Agent contains "Mozilla"
> ...
> This should ensure that git clients, RSS readers, and other low-harm clients
> can get through without issue ..
[1] https://github.com/TecharoHQ/anubis/blob/6c0ff3f4d5e7a66ea85e5873e6ee4c28692091d7/docs/docs/design/how-anubis-works.mdx#challenge-presentation
Suggested-by: @unixfox https://github.com/searxng/searxng/issues/4646#issuecomment-2855322406
Closes: https://github.com/searxng/searxng/issues/4646
Signed-off-by: Markus Heiser
---
searx/engines/archlinux.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/searx/engines/archlinux.py b/searx/engines/archlinux.py
index 820b31799..63de157dc 100644
--- a/searx/engines/archlinux.py
+++ b/searx/engines/archlinux.py
@@ -51,6 +51,9 @@ def request(query, params):
if netloc == main_wiki:
eng_lang: str = traits.get_language(sxng_lang, 'English') # type: ignore
query += ' (' + eng_lang + ')'
+ # wiki.archlinux.org is protected by anubis
+ # - https://github.com/searxng/searxng/issues/4646#issuecomment-2817848019
+ params['headers']['User-Agent'] = "SearXNG"
elif netloc == 'wiki.archlinuxcn.org':
base_url = 'https://' + netloc + '/wzh/index.php?'
From 2cfd3fc44b16e7f3c6010c0ac1004efb6dacf382 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Sat, 5 Apr 2025 10:59:07 +0200
Subject: [PATCH 13/21] [enh] tidy: clean old morty, filtron, searx references
Everyone should have already switched from legacy methods
---
Makefile | 5 +-
container/docker-entrypoint.sh | 43 +-----
docs/admin/arch_public.dot | 2 +-
docs/admin/update-searxng.rst | 45 -------
docs/dev/lxcdev.rst | 5 +-
docs/own-instance.rst | 3 +-
docs/utils/searxng.sh.rst | 2 +-
searx/settings.yml | 12 --
searx/settings_defaults.py | 5 -
searx/templates/simple/macros.html | 4 +-
.../simple/result_templates/code.html | 2 +-
.../simple/result_templates/default.html | 2 +-
.../simple/result_templates/map.html | 2 +-
.../simple/result_templates/paper.html | 2 +-
.../simple/result_templates/products.html | 2 +-
.../simple/result_templates/torrent.html | 2 +-
.../simple/result_templates/videos.html | 2 +-
searx/webapp.py | 25 ----
tests/unit/settings/user_settings_simple.yml | 3 -
utils/filtron.sh | 125 ------------------
utils/lib.sh | 4 +-
utils/morty.sh | 124 -----------------
utils/searx.sh | 88 ------------
utils/searxng.sh | 9 --
.../lib/systemd/system/filtron.service | 29 ----
.../lib/systemd/system/morty.service | 29 ----
26 files changed, 18 insertions(+), 558 deletions(-)
delete mode 100755 utils/filtron.sh
delete mode 100755 utils/morty.sh
delete mode 100755 utils/searx.sh
delete mode 100644 utils/templates/lib/systemd/system/filtron.service
delete mode 100644 utils/templates/lib/systemd/system/morty.service
diff --git a/Makefile b/Makefile
index 15e43be08..917d3aeb4 100644
--- a/Makefile
+++ b/Makefile
@@ -65,10 +65,7 @@ test.shell:
utils/lib_redis.sh \
utils/searxng.sh \
utils/lxc.sh \
- utils/lxc-searxng.env \
- utils/searx.sh \
- utils/filtron.sh \
- utils/morty.sh
+ utils/lxc-searxng.env
$(Q)$(MTOOLS) build_msg TEST "$@ OK"
diff --git a/container/docker-entrypoint.sh b/container/docker-entrypoint.sh
index 72d020dcf..ee14b2f05 100755
--- a/container/docker-entrypoint.sh
+++ b/container/docker-entrypoint.sh
@@ -12,8 +12,7 @@ Environment variables:
INSTANCE_NAME settings.yml : general.instance_name
AUTOCOMPLETE settings.yml : search.autocomplete
BASE_URL settings.yml : server.base_url
- MORTY_URL settings.yml : result_proxy.url
- MORTY_KEY settings.yml : result_proxy.key
+
Volume:
/etc/searxng the docker entry point copies settings.yml and uwsgi.ini in
this directory (see the -f command line option)"
@@ -70,20 +69,6 @@ patch_searxng_settings() {
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
"${CONF}"
-
- # Morty configuration
-
- if [ -n "${MORTY_KEY}" ] && [ -n "${MORTY_URL}" ]; then
- sed -i -e "s/image_proxy: false/image_proxy: true/g" \
- "${CONF}"
- cat >> "${CONF}" <<-EOF
-
-# Morty configuration
-result_proxy:
- url: ${MORTY_URL}
- key: !!binary "${MORTY_KEY}"
-EOF
- fi
}
update_conf() {
@@ -122,30 +107,6 @@ update_conf() {
fi
}
-# searx compatibility: copy /etc/searx/* to /etc/searxng/*
-SEARX_CONF=0
-if [ -f "/etc/searx/settings.yml" ]; then
- if [ ! -f "${SEARXNG_SETTINGS_PATH}" ]; then
- printf '⚠️ /etc/searx/settings.yml is copied to /etc/searxng\n'
- cp "/etc/searx/settings.yml" "${SEARXNG_SETTINGS_PATH}"
- fi
- SEARX_CONF=1
-fi
-if [ -f "/etc/searx/uwsgi.ini" ]; then
- printf '⚠️ /etc/searx/uwsgi.ini is ignored. Use the volume /etc/searxng\n'
- SEARX_CONF=1
-fi
-if [ "$SEARX_CONF" -eq "1" ]; then
- printf '⚠️ The deprecated volume /etc/searx is mounted. Please update your configuration to use /etc/searxng ⚠️\n'
- cat << EOF > /etc/searx/deprecated_volume_read_me.txt
-This Docker image uses the volume /etc/searxng
-Update your configuration:
-* remove uwsgi.ini (or very carefully update your existing uwsgi.ini using https://github.com/searxng/searxng/blob/master/container/uwsgi.ini )
-* mount /etc/searxng instead of /etc/searx
-EOF
-fi
-# end of searx compatibility
-
# make sure there are uwsgi settings
update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/container/uwsgi.ini" "patch_uwsgi_settings"
@@ -158,8 +119,6 @@ if [ $DRY_RUN -eq 1 ]; then
exit
fi
-unset MORTY_KEY
-
printf 'Listen on %s\n' "${BIND_ADDRESS}"
# Start uwsgi
diff --git a/docs/admin/arch_public.dot b/docs/admin/arch_public.dot
index 526fb53da..49b03d157 100644
--- a/docs/admin/arch_public.dot
+++ b/docs/admin/arch_public.dot
@@ -6,7 +6,7 @@ digraph G {
browser [label="browser", shape=tab, fillcolor=aliceblue];
rp [label="reverse proxy"];
static [label="static files", shape=folder, href="url to configure static files", fillcolor=lightgray];
- uwsgi [label="uwsgi", shape=parallelogram href="https://docs.searxng.org/utils/searx.sh.html"]
+ uwsgi [label="uwsgi", shape=parallelogram href="https://docs.searxng.org/utils/searxng.sh.html"]
redis [label="redis DB", shape=cylinder];
searxng1 [label="SearXNG #1", fontcolor=blue3];
searxng2 [label="SearXNG #2", fontcolor=blue3];
diff --git a/docs/admin/update-searxng.rst b/docs/admin/update-searxng.rst
index b9d15c3f7..16715f00d 100644
--- a/docs/admin/update-searxng.rst
+++ b/docs/admin/update-searxng.rst
@@ -58,9 +58,6 @@ and then, to name just a few:
- Bot protection has been switched from filtron to SearXNG's :ref:`limiter
`, this requires a :ref:`Redis ` database.
-- The image proxy morty is no longer needed, it has been replaced by the
- :ref:`image proxy ` from SearXNG.
-
- To save bandwidth :ref:`cache busting ` has been implemented.
To get in use, the ``static-expires`` needs to be set in the :ref:`uwsgi
setup`.
@@ -71,12 +68,6 @@ examples show, this is not always enough, sometimes services have to be set up
or reconfigured and sometimes services that are no longer needed should be
uninstalled.
-.. hint::
-
- First of all: SearXNG is installed by the script :ref:`searxng.sh`. If you
- have old filtron, morty or searx setup you should consider complete
- uninstall/reinstall.
-
Here you will find a list of changes that affect the infrastructure. Please
check to what extent it is necessary to update your installations:
@@ -85,39 +76,6 @@ check to what extent it is necessary to update your installations:
file manually.
-remove obsolete services
-------------------------
-
-If your searx instance was installed *"Step by step"* or by the *"Installation
-scripts"*, you need to undo the installation procedure completely. If you have
-morty & filtron installed, it is recommended to uninstall these services also.
-In case of scripts, to uninstall use the scripts from the origin you installed
-searx from or try::
-
- $ sudo -H ./utils/filtron.sh remove all
- $ sudo -H ./utils/morty.sh remove all
- $ sudo -H ./utils/searx.sh remove all
-
-.. hint::
-
- If you are migrate from searx take into account that the ``.config.sh`` is no
- longer used.
-
-If you upgrade from searx or from before :pull:`1332` has been merged and you
-have filtron and/or morty installed, don't forget to remove HTTP sites.
-
-Apache::
-
- $ sudo -H ./utils/filtron.sh apache remove
- $ sudo -H ./utils/morty.sh apache remove
-
-nginx::
-
- $ sudo -H ./utils/filtron.sh nginx remove
- $ sudo -H ./utils/morty.sh nginx remove
-
-
-
Check after Installation
------------------------
@@ -130,9 +88,6 @@ to see if there are some left overs. In this example there exists a *old*
SearXNG checks
--------------
ERROR: settings.yml in /etc/searx/ is deprecated, move file to folder /etc/searxng/
- INFO: [OK] (old) account 'searx' does not exists
- INFO: [OK] (old) account 'filtron' does not exists
- INFO: [OK] (old) account 'morty' does not exists
...
INFO searx.redisdb : connecting to Redis db=0 path='/usr/local/searxng-redis/run/redis.sock'
INFO searx.redisdb : connected to Redis
diff --git a/docs/dev/lxcdev.rst b/docs/dev/lxcdev.rst
index 79716ae57..9edd9f672 100644
--- a/docs/dev/lxcdev.rst
+++ b/docs/dev/lxcdev.rst
@@ -319,13 +319,13 @@ To *inspect* the SearXNG instance (already described above):
.. code:: bash
- $ ./utils/searx.sh inspect service
+ $ ./utils/searxng.sh inspect service
.. group-tab:: desktop (HOST)
.. code:: bash
- $ sudo -H ./utils/lxc.sh cmd searxng-archlinux ./utils/searx.sh inspect service
+ $ sudo -H ./utils/lxc.sh cmd searxng-archlinux ./utils/searxng.sh inspect service
Run :ref:`makefile`, e.g. to test inside the container:
@@ -435,4 +435,3 @@ use:
[searxng-archlinux] SEARXNG_URL : http:///n.n.n.140/searxng
[searxng-archlinux] SEARXNG_PORT : 8888
[searxng-archlinux] SEARXNG_BIND_ADDRESS : 127.0.0.1
-
diff --git a/docs/own-instance.rst b/docs/own-instance.rst
index 7d79f26c2..8c0009aff 100644
--- a/docs/own-instance.rst
+++ b/docs/own-instance.rst
@@ -39,8 +39,7 @@ Removing private data means not sending cookies to external search engines and
generating a random browser profile for every request. Thus, it does not matter
if a public or private instance handles the request, because it is anonymized in
both cases. The IP address used will be the IP of the instance, but SearXNG can also be
-configured to use proxy or Tor. `Result proxy
-`__ is supported, too.
+configured to use proxy or Tor.
SearXNG does not serve ads or tracking content, unlike most search services. Therefore,
private data is not forwarded to third parties who might monetize it. Besides
diff --git a/docs/utils/searxng.sh.rst b/docs/utils/searxng.sh.rst
index bedc1ba4c..d45d7014f 100644
--- a/docs/utils/searxng.sh.rst
+++ b/docs/utils/searxng.sh.rst
@@ -28,7 +28,7 @@ In most cases you will install SearXNG simply by running the command:
.. code:: bash
- sudo -H ./utils/searx.sh install all
+ sudo -H ./utils/searxng.sh install all
The installation is described in chapter :ref:`installation basic`.
diff --git a/searx/settings.yml b/searx/settings.yml
index d756e9b1c..7e0455701 100644
--- a/searx/settings.yml
+++ b/searx/settings.yml
@@ -169,18 +169,6 @@ ui:
# - image_proxy
# - query_in_title
-# searx supports result proxification using an external service:
-# https://github.com/asciimoo/morty uncomment below section if you have running
-# morty proxy the key is base64 encoded (keep the !!binary notation)
-# Note: since commit af77ec3, morty accepts a base64 encoded key.
-#
-# result_proxy:
-# url: http://127.0.0.1:3000/
-# # the key is a base64 encoded string, the YAML !!binary prefix is optional
-# key: !!binary "your_morty_proxy_key"
-# # [true|false] enable the "proxy" button next to each result
-# proxify_results: true
-
# communication with search engines
#
outgoing:
diff --git a/searx/settings_defaults.py b/searx/settings_defaults.py
index b91657ff6..4cee7e345 100644
--- a/searx/settings_defaults.py
+++ b/searx/settings_defaults.py
@@ -230,11 +230,6 @@ SCHEMA = {
'extra_proxy_timeout': SettingsValue(int, 0),
'networks': {},
},
- 'result_proxy': {
- 'url': SettingsValue((None, str), None),
- 'key': SettingsBytesValue((None, bytes), None),
- 'proxify_results': SettingsValue(bool, False),
- },
'plugins': SettingsValue(dict, {}),
'checker': {
'off_when_debug': SettingsValue(bool, True, None),
diff --git a/searx/templates/simple/macros.html b/searx/templates/simple/macros.html
index 6010a5a3d..df8469d72 100644
--- a/searx/templates/simple/macros.html
+++ b/searx/templates/simple/macros.html
@@ -44,10 +44,10 @@
{%- endmacro -%}
-{%- macro result_sub_footer(result, proxify) -%}
+{%- macro result_sub_footer(result) -%}
{% for engine in result.engines %}{{ engine }}{% endfor %}
- {{ icon_small('ellipsis-vertical') + result_link(cache_url + result.url, _('cached'), "cache_link") }} {% if proxify and proxify_results %} {{ result_link(proxify(result.url), _('proxied'), "proxyfied_link") }} {% endif %}
+ {{ icon_small('ellipsis-vertical') + result_link(cache_url + result.url, _('cached'), "cache_link") }}
{{- '' -}}
{{- '' -}}
{%- endmacro -%}
diff --git a/searx/templates/simple/result_templates/code.html b/searx/templates/simple/result_templates/code.html
index 7d2c8ff79..49326aed5 100644
--- a/searx/templates/simple/result_templates/code.html
+++ b/searx/templates/simple/result_templates/code.html
@@ -28,5 +28,5 @@
{{- result.codelines|code_highlighter(result.code_language)|safe -}}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{{- result_footer(result) -}}
diff --git a/searx/templates/simple/result_templates/default.html b/searx/templates/simple/result_templates/default.html
index 263c19a36..8a6329248 100644
--- a/searx/templates/simple/result_templates/default.html
+++ b/searx/templates/simple/result_templates/default.html
@@ -14,7 +14,7 @@
{{ _('This site did not provide any description.')|safe }}
{% endif -%}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{% if result.iframe_src -%}
diff --git a/searx/templates/simple/result_templates/map.html b/searx/templates/simple/result_templates/map.html
index dc1f06dce..73a2701da 100644
--- a/searx/templates/simple/result_templates/map.html
+++ b/searx/templates/simple/result_templates/map.html
@@ -43,7 +43,7 @@
{{ icon_small( 'globe') }} {{ _('show map') }}
{%- endif -%}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{% if (result.latitude and result.longitude) or result.boundingbox -%}
diff --git a/searx/templates/simple/result_templates/paper.html b/searx/templates/simple/result_templates/paper.html
index dd610b903..7e94cf174 100644
--- a/searx/templates/simple/result_templates/paper.html
+++ b/searx/templates/simple/result_templates/paper.html
@@ -34,5 +34,5 @@
{%- if result.html_url -%}{{ result_link(result.html_url, _('HTML')) }}{%- endif -%}
{%- if result.doi %}{{ result_link('https://www.altmetric.com/details/doi/' + result.doi, 'Altmetric') }}{% endif -%}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{{- result_footer(result) }}
diff --git a/searx/templates/simple/result_templates/products.html b/searx/templates/simple/result_templates/products.html
index ce599aef7..b5404fd8d 100644
--- a/searx/templates/simple/result_templates/products.html
+++ b/searx/templates/simple/result_templates/products.html
@@ -10,5 +10,5 @@
{{ result.content|safe }}
{% endif -%}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{{- result_footer(result) }}
diff --git a/searx/templates/simple/result_templates/torrent.html b/searx/templates/simple/result_templates/torrent.html
index 0c870ae11..27e96dca4 100644
--- a/searx/templates/simple/result_templates/torrent.html
+++ b/searx/templates/simple/result_templates/torrent.html
@@ -19,5 +19,5 @@
{%- if result.files %}{{ icon_big('file') }}
{{ result.files }} {{ _('Number of Files') }}{%- endif -%}
{%- if result.content %}
{{ result.content|safe }}
{%- endif -%}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{{- result_footer(result) -}}
diff --git a/searx/templates/simple/result_templates/videos.html b/searx/templates/simple/result_templates/videos.html
index 23d4195ca..8771cea1f 100644
--- a/searx/templates/simple/result_templates/videos.html
+++ b/searx/templates/simple/result_templates/videos.html
@@ -15,7 +15,7 @@
{% endif -%}
-{{- result_sub_footer(result, proxify) -}}
+{{- result_sub_footer(result) -}}
{% if result.iframe_src -%}
diff --git a/searx/webapp.py b/searx/webapp.py
index 3b4cf1604..aaa2608c4 100755
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -7,8 +7,6 @@
from __future__ import annotations
import inspect
-import hashlib
-import hmac
import json
import os
import sys
@@ -261,24 +259,6 @@ def custom_url_for(endpoint: str, **values):
return url_for(endpoint, **values) + suffix
-def morty_proxify(url: str):
- if not url:
- return url
-
- if url.startswith('//'):
- url = 'https:' + url
-
- if not settings['result_proxy']['url']:
- return url
-
- url_params = dict(mortyurl=url)
-
- if settings['result_proxy']['key']:
- url_params['mortyhash'] = hmac.new(settings['result_proxy']['key'], url.encode(), hashlib.sha256).hexdigest()
-
- return '{0}?{1}'.format(settings['result_proxy']['url'], urlencode(url_params))
-
-
def image_proxify(url: str):
if not url:
return url
@@ -300,9 +280,6 @@ def image_proxify(url: str):
return url
return None
- if settings['result_proxy']['url']:
- return morty_proxify(url)
-
h = new_hmac(settings['server']['secret_key'], url.encode())
return '{0}?{1}'.format(url_for('image_proxy'), urlencode(dict(url=url.encode(), h=h)))
@@ -424,8 +401,6 @@ def render(template_name: str, **kwargs):
kwargs['url_for'] = custom_url_for # override url_for function in templates
kwargs['image_proxify'] = image_proxify
kwargs['favicon_url'] = favicons.favicon_url
- kwargs['proxify'] = morty_proxify if settings['result_proxy']['url'] is not None else None
- kwargs['proxify_results'] = settings['result_proxy']['proxify_results']
kwargs['cache_url'] = settings['ui']['cache_url']
kwargs['get_result_template'] = get_result_template
kwargs['opensearch_url'] = (
diff --git a/tests/unit/settings/user_settings_simple.yml b/tests/unit/settings/user_settings_simple.yml
index 6d6e73577..192c3a335 100644
--- a/tests/unit/settings/user_settings_simple.yml
+++ b/tests/unit/settings/user_settings_simple.yml
@@ -4,6 +4,3 @@ server:
bind_address: "[::]"
default_http_headers:
Custom-Header: Custom-Value
-result_proxy:
- url: https://localhost/morty
- key: "$ecretKey"
diff --git a/utils/filtron.sh b/utils/filtron.sh
deleted file mode 100755
index 2ac3b6dfd..000000000
--- a/utils/filtron.sh
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env bash
-# SPDX-License-Identifier: AGPL-3.0-or-later
-# shellcheck disable=SC2001
-
-# shellcheck source=utils/lib.sh
-source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
-
-# ----------------------------------------------------------------------------
-# config
-# ----------------------------------------------------------------------------
-
-PUBLIC_URL="${PUBLIC_URL:-${SEARXNG_URL}}"
-
-FILTRON_ETC="/etc/filtron"
-
-SERVICE_NAME="filtron"
-SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
-SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
-
-APACHE_FILTRON_SITE="searx.conf"
-NGINX_FILTRON_SITE="searx.conf"
-
-# ----------------------------------------------------------------------------
-usage() {
-# ----------------------------------------------------------------------------
-
- # shellcheck disable=SC1117
- cat <
&1 | prefix_stdout
- if service_is_available "${PUBLIC_URL}"; then
- MSG="** Don't forget to remove your public site! (${PUBLIC_URL}) **" wait_key 10
- fi
-}
-
-remove_apache_site() {
-
- rst_title "Remove Apache site $APACHE_FILTRON_SITE"
-
- rst_para "\
-This removes apache site ${APACHE_FILTRON_SITE}."
-
- ! apache_is_installed && err_msg "Apache is not installed."
-
- if ! ask_yn "Do you really want to continue?" Yn; then
- return
- fi
-
- apache_remove_site "$APACHE_FILTRON_SITE"
-
-}
-
-remove_nginx_site() {
-
- rst_title "Remove nginx site $NGINX_FILTRON_SITE"
-
- rst_para "\
-This removes nginx site ${NGINX_FILTRON_SITE}."
-
- ! nginx_is_installed && err_msg "nginx is not installed."
-
- if ! ask_yn "Do you really want to continue?" Yn; then
- return
- fi
-
- nginx_remove_app "$FILTRON_FILTRON_SITE"
-
-}
-
-# ----------------------------------------------------------------------------
-main "$@"
-# ----------------------------------------------------------------------------
diff --git a/utils/lib.sh b/utils/lib.sh
index ead4b0c61..d3d515c0a 100755
--- a/utils/lib.sh
+++ b/utils/lib.sh
@@ -1802,8 +1802,8 @@ url_replace_hostname(){
# to replace hostname by primary IP::
#
- # url_replace_hostname http://searx-ubu1604/morty $(primary_ip)
- # http://10.246.86.250/morty
+ # url_replace_hostname http://searx-ubu1604/example $(primary_ip)
+ # http://10.246.86.250/example
# shellcheck disable=SC2001
echo "$1" | sed "s|\(http[s]*://\)[^/]*\(.*\)|\1$2\2|"
diff --git a/utils/morty.sh b/utils/morty.sh
deleted file mode 100755
index 52f0fec31..000000000
--- a/utils/morty.sh
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/usr/bin/env bash
-# SPDX-License-Identifier: AGPL-3.0-or-later
-
-# shellcheck source=utils/lib.sh
-source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
-
-# ----------------------------------------------------------------------------
-# config
-# ----------------------------------------------------------------------------
-
-PUBLIC_URL="${PUBLIC_URL:-${SEARXNG_URL}}"
-
-MORTY_LISTEN="${MORTY_LISTEN:-127.0.0.1:3000}"
-PUBLIC_URL_PATH_MORTY="${PUBLIC_URL_PATH_MORTY:-/morty/}"
-PUBLIC_URL_MORTY="${PUBLIC_URL_MORTY:-$(echo "$PUBLIC_URL" | sed -e's,^\(.*://[^/]*\).*,\1,g')${PUBLIC_URL_PATH_MORTY}}"
-
-SERVICE_NAME="morty"
-SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
-SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
-
-# Apache Settings
-
-APACHE_MORTY_SITE="morty.conf"
-NGINX_MORTY_SITE="morty.conf"
-
-# ----------------------------------------------------------------------------
-usage() {
-# ----------------------------------------------------------------------------
-
- # shellcheck disable=SC1117
- cat <
Date: Tue, 13 May 2025 17:38:46 +0200
Subject: [PATCH 14/21] [upd] web-client (simple): Bump the minor group (#4775)
Bumps the minor group in /client/simple with 5 updates:
| Package | From | To |
| --- | --- | --- |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.25.1` | `9.26.0` |
| [eslint](https://github.com/eslint/eslint) | `9.25.1` | `9.26.0` |
| [globals](https://github.com/sindresorhus/globals) | `16.0.0` | `16.1.0` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `6.3.4` | `6.3.5` |
| [webpack](https://github.com/webpack/webpack) | `5.99.7` | `5.99.8` |
Updates `@eslint/js` from 9.25.1 to 9.26.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.26.0/packages/js)
Updates `eslint` from 9.25.1 to 9.26.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.25.1...v9.26.0)
Updates `globals` from 16.0.0 to 16.1.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v16.0.0...v16.1.0)
Updates `vite` from 6.3.4 to 6.3.5
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.3.5/packages/vite)
Updates `webpack` from 5.99.7 to 5.99.8
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.99.7...v5.99.8)
---
client/simple/package-lock.json | 977 +++++++++++++++++++++++++++++++-
client/simple/package.json | 10 +-
2 files changed, 957 insertions(+), 30 deletions(-)
diff --git a/client/simple/package-lock.json b/client/simple/package-lock.json
index 9ebd69257..1b4c423f7 100644
--- a/client/simple/package-lock.json
+++ b/client/simple/package-lock.json
@@ -11,13 +11,13 @@
"autocomplete-js": "^2.7.1"
},
"devDependencies": {
- "@eslint/js": "^9.25.1",
+ "@eslint/js": "^9.26.0",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"edge.js": "^6.2.1",
- "eslint": "^9.25.1",
+ "eslint": "^9.26.0",
"filemanager-webpack-plugin": "^8.0.0",
- "globals": "^16.0.0",
+ "globals": "^16.1.0",
"ionicons": "^8.0.8",
"leaflet": "^1.9.4",
"less": "^4.3.0",
@@ -31,10 +31,10 @@
"stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2",
"swiped-events": "^1.2.0",
- "vite": "^6.3.4",
+ "vite": "^6.3.5",
"vite-plugin-static-copy": "^2.3.1",
"vite-plugin-stylelint": "^6.0.0",
- "webpack": "^5.99.7",
+ "webpack": "^5.99.8",
"webpack-cli": "^6.0.1"
}
},
@@ -728,9 +728,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.25.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz",
- "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==",
+ "version": "9.26.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz",
+ "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1333,6 +1333,28 @@
"node": ">=8"
}
},
+ "node_modules/@modelcontextprotocol/sdk": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz",
+ "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^1.0.5",
+ "cors": "^2.8.5",
+ "cross-spawn": "^7.0.3",
+ "eventsource": "^3.0.2",
+ "express": "^5.0.1",
+ "express-rate-limit": "^7.5.0",
+ "pkce-challenge": "^5.0.0",
+ "raw-body": "^3.0.0",
+ "zod": "^3.23.8",
+ "zod-to-json-schema": "^3.24.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2213,6 +2235,43 @@
"dev": true,
"license": "Apache-2.0"
},
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/accepts/node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/accepts/node_modules/mime-types": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
@@ -2526,6 +2585,27 @@
"readable-stream": "^3.4.0"
}
},
+ "node_modules/body-parser": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
+ "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.0",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.6.3",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.0",
+ "raw-body": "^3.0.0",
+ "type-is": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@@ -2663,6 +2743,37 @@
"@keyv/serialize": "^1.0.3"
}
},
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -2909,6 +3020,49 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/content-disposition": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
+ "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
"node_modules/copy-anything": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz",
@@ -2953,6 +3107,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/cosmiconfig": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
@@ -3230,6 +3398,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
@@ -3322,6 +3500,21 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/edge-error": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/edge-error/-/edge-error-4.0.2.tgz",
@@ -3386,6 +3579,13 @@
"node": ">=18.16.0"
}
},
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.101",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz",
@@ -3400,6 +3600,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -3491,6 +3701,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-module-lexer": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
@@ -3498,6 +3728,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/esbuild": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
@@ -3562,6 +3805,13 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -3576,9 +3826,9 @@
}
},
"node_modules/eslint": {
- "version": "9.25.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz",
- "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==",
+ "version": "9.26.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz",
+ "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3588,11 +3838,12 @@
"@eslint/config-helpers": "^0.2.1",
"@eslint/core": "^0.13.0",
"@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.25.1",
+ "@eslint/js": "9.26.0",
"@eslint/plugin-kit": "^0.2.8",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
+ "@modelcontextprotocol/sdk": "^1.8.0",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
@@ -3616,7 +3867,8 @@
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
+ "optionator": "^0.9.3",
+ "zod": "^3.24.2"
},
"bin": {
"eslint": "bin/eslint.js"
@@ -3737,6 +3989,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@@ -3747,6 +4009,111 @@
"node": ">=0.8.x"
}
},
+ "node_modules/eventsource": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
+ "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eventsource-parser": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/eventsource-parser": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz",
+ "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
+ "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.0",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express-rate-limit": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz",
+ "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": "^4.11 || 5 || ^5.0.0-beta.1"
+ }
+ },
+ "node_modules/express/node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express/node_modules/mime-types": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -3891,6 +4258,24 @@
"node": ">=8"
}
},
+ "node_modules/finalhandler": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
+ "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -3949,6 +4334,26 @@
"node": ">=8"
}
},
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -4010,6 +4415,45 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -4094,9 +4538,9 @@
}
},
"node_modules/globals": {
- "version": "16.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-16.0.0.tgz",
- "integrity": "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==",
+ "version": "16.1.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
+ "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4113,6 +4557,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -4130,6 +4587,19 @@
"node": ">=8"
}
},
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -4173,13 +4643,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"license": "MIT",
- "optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
@@ -4348,6 +4834,16 @@
"@stencil/core": "^4.30.0"
}
},
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
@@ -4457,6 +4953,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/is-what": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
@@ -4843,6 +5346,16 @@
"semver": "bin/semver"
}
},
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/mathml-tag-names": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
@@ -4861,6 +5374,16 @@
"dev": true,
"license": "CC0-1.0"
},
+ "node_modules/media-typer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/meow": {
"version": "13.2.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
@@ -4874,6 +5397,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -5006,6 +5542,16 @@
"node": ">= 4.4.x"
}
},
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
@@ -5050,6 +5596,42 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -5178,6 +5760,16 @@
"node": ">= 0.10"
}
},
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -5215,6 +5807,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/path-to-regexp": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
+ "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -5246,6 +5848,16 @@
"node": ">=6"
}
},
+ "node_modules/pkce-challenge": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz",
+ "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -5543,6 +6155,20 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -5561,6 +6187,22 @@
"node": ">=6"
}
},
+ "node_modules/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -5592,6 +6234,32 @@
"safe-buffer": "^5.1.0"
}
},
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
+ "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.6.3",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -5798,6 +6466,23 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -5858,8 +6543,7 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
- "license": "MIT",
- "optional": true
+ "license": "MIT"
},
"node_modules/sax": {
"version": "1.4.1",
@@ -5956,6 +6640,52 @@
"node": ">=10"
}
},
+ "node_modules/send": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
+ "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.5",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "mime-types": "^3.0.1",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/send/node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/send/node_modules/mime-types": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
@@ -5966,6 +6696,29 @@
"randombytes": "^2.1.0"
}
},
+ "node_modules/serve-static": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
+ "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
@@ -6043,6 +6796,82 @@
"node": ">=8"
}
},
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
@@ -6135,6 +6964,16 @@
"source-map": "^0.6.0"
}
},
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -6836,6 +7675,16 @@
"node": ">=8.0"
}
},
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
"node_modules/truncatise": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/truncatise/-/truncatise-0.0.8.tgz",
@@ -6863,6 +7712,44 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/type-is": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
+ "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^1.0.5",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/type-is/node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/type-is/node_modules/mime-types": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
@@ -6880,6 +7767,16 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/update-browserslist-db": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
@@ -6928,10 +7825,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/vite": {
- "version": "6.3.4",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz",
- "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
+ "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7126,9 +8033,9 @@
}
},
"node_modules/webpack": {
- "version": "5.99.7",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.7.tgz",
- "integrity": "sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==",
+ "version": "5.99.8",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.8.tgz",
+ "integrity": "sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7378,6 +8285,26 @@
"engines": {
"node": ">= 10"
}
+ },
+ "node_modules/zod": {
+ "version": "3.24.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz",
+ "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.24.5",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz",
+ "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==",
+ "dev": true,
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.24.1"
+ }
}
}
}
diff --git a/client/simple/package.json b/client/simple/package.json
index 5eeffb688..f0cb956bb 100644
--- a/client/simple/package.json
+++ b/client/simple/package.json
@@ -9,13 +9,13 @@
"icons.html": "node theme_icons.js"
},
"devDependencies": {
- "@eslint/js": "^9.25.1",
+ "@eslint/js": "^9.26.0",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"edge.js": "^6.2.1",
- "eslint": "^9.25.1",
+ "eslint": "^9.26.0",
"filemanager-webpack-plugin": "^8.0.0",
- "globals": "^16.0.0",
+ "globals": "^16.1.0",
"ionicons": "^8.0.8",
"leaflet": "^1.9.4",
"less": "^4.3.0",
@@ -29,10 +29,10 @@
"stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2",
"swiped-events": "^1.2.0",
- "vite": "^6.3.4",
+ "vite": "^6.3.5",
"vite-plugin-static-copy": "^2.3.1",
"vite-plugin-stylelint": "^6.0.0",
- "webpack": "^5.99.7",
+ "webpack": "^5.99.8",
"webpack-cli": "^6.0.1"
},
"dependencies": {
From 4fb29aae812aa464c12fd959fc24dd91934f6a3b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 13 May 2025 17:44:10 +0200
Subject: [PATCH 15/21] [upd] pypi: Bump the minor group with 2 updates (#4776)
Bumps the minor group with 2 updates: [selenium](https://github.com/SeleniumHQ/Selenium) and [redis](https://github.com/redis/redis-py).
Updates `selenium` from 4.31.0 to 4.32.0
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.31.0...selenium-4.32.0)
Updates `redis` from 5.0.8 to 5.2.1
- [Release notes](https://github.com/redis/redis-py/releases)
- [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES)
- [Commits](https://github.com/redis/redis-py/compare/v5.0.8...v5.2.1)
---
requirements-dev.txt | 2 +-
requirements.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index d0e29867a..63c5fe842 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -4,7 +4,7 @@ cov-core==1.15.0
black==24.3.0
pylint==3.3.7
splinter==0.21.0
-selenium==4.31.0
+selenium==4.32.0
Pallets-Sphinx-Themes==2.3.0
Sphinx==7.4.7
sphinx-issues==5.0.1
diff --git a/requirements.txt b/requirements.txt
index f505e6b74..168d797b4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,7 +12,7 @@ Brotli==1.1.0
uvloop==0.21.0
httpx-socks[asyncio]==0.7.7
setproctitle==1.3.6
-redis==5.0.8
+redis==5.2.1
markdown-it-py==3.0.0
fasttext-predict==0.9.2.4
tomli==2.2.1; python_version < '3.11'
From c73b469ce74e7de01dab76f62346e732d1fcf933 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 14 May 2025 08:18:03 +0200
Subject: [PATCH 16/21] Bump flask from 3.1.0 to 3.1.1 (#4780)
Bumps [flask](https://github.com/pallets/flask) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/3.1.0...3.1.1)
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index 168d797b4..887e65202 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
certifi==2025.4.26
babel==2.17.0
flask-babel==4.0.0
-flask==3.1.0
+flask==3.1.1
jinja2==3.1.6
lxml==5.4.0
pygments==2.19.1
From b42f812c57b555d60a16cc64f16ccbb554b4ab91 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Wed, 14 May 2025 22:42:36 +0200
Subject: [PATCH 17/21] [fix] CI: handle old cache images from registry
Currently, we have 1100~ cache images uploaded to GHCR that weigh more than 300 MB each (most of them are layers from the second phase of the Dockerfile that were uploaded by mistake, read below). To avoid problems, I have set up a new job in a new workflow to be run weekly purging all images older than 1 week, but leaving always the 100 most recent ones.
Only the builder images should be uploaded to cache, the actual behaviour not only slows down the time for building the container, but also wastes lots of space by saving large and useless layers to GHCR that will never be used again.
---
.github/workflows/cleanup.yml | 34 ++++++++++++++++++++++++++++++++++
utils/lib_sxng_container.sh | 1 -
2 files changed, 34 insertions(+), 1 deletion(-)
create mode 100644 .github/workflows/cleanup.yml
diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml
new file mode 100644
index 000000000..d429e0ce3
--- /dev/null
+++ b/.github/workflows/cleanup.yml
@@ -0,0 +1,34 @@
+---
+name: Cleanup
+
+# yamllint disable-line rule:truthy
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "4 4 * * 0"
+
+concurrency:
+ group: ${{ github.workflow }}
+ cancel-in-progress: false
+
+permissions:
+ contents: read
+
+jobs:
+ container-cache:
+ name: Container cache
+ runs-on: ubuntu-24.04
+ permissions:
+ # Organization GHCR
+ packages: write
+
+ steps:
+ - name: Prune
+ uses: snok/container-retention-policy@v3.0.0
+ with:
+ account: "${{ github.repository_owner }}"
+ token: "${{ secrets.GITHUB_TOKEN }}"
+ image-names: "cache"
+ image-tags: "!searxng-*"
+ cut-off: "1w"
+ keep-n-most-recent: "100"
diff --git a/utils/lib_sxng_container.sh b/utils/lib_sxng_container.sh
index f87b64e2b..49ef1ef05 100644
--- a/utils/lib_sxng_container.sh
+++ b/utils/lib_sxng_container.sh
@@ -102,7 +102,6 @@ container.build() {
if [ "$GITHUB_ACTIONS" = "true" ]; then
params_build_builder+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
- params_build+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
# Tags
params_build+=" --tag=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
From d0b7f26f4bbe95a17a171ba77fbbed0b8427ce28 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Wed, 14 May 2025 23:05:08 +0200
Subject: [PATCH 18/21] [fix] CI: container-mounts bad hash
This is a typo, but if there are multiple patterns in hashFiles, they should be separated by commas.
https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#examples-with-multiple-patterns
---
.github/workflows/container.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index ef92a0662..22d1c0266 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -76,7 +76,7 @@ jobs:
uses: actions/cache@v4
with:
# yamllint disable-line rule:line-length
- key: "container-mounts-${{ matrix.arch }}-${{ hashFiles('./container/Dockerfile ./container/legacy/Dockerfile') }}"
+ key: "container-mounts-${{ matrix.arch }}-${{ hashFiles('./container/Dockerfile', './container/legacy/Dockerfile') }}"
restore-keys: "container-mounts-${{ matrix.arch }}-"
path: |
/var/tmp/buildah-cache/
From bec76bc2e3cfd8160de80fb924b058c0f10f0140 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Wed, 14 May 2025 23:43:38 +0200
Subject: [PATCH 19/21] [fix] CI: prevent race condition
`checker.yml` and `integration.yml` are the only workflows that are currently safe to be executed simultaneously, the others present a risk that the order of completion may not be expected. The ones that are chained from `integration.yml` can be called as many times as `integration.yml` workflows are running at that moment, the same with the trigger "workflow_dispatch".
This can be fatal for workflows like `container.yml` that use a centralized cache to store and load the candidate images in a common tag called "searxng-".
* For example, a `container.yml` workflow is executed after being chained from `integration.yml` (called "~1"), and seconds later it may be triggered again because another PR merged some breaking changes (called "~2"). While "~1" has already passed the test job successfully and is about to start the release job, "~2" finishes building the container and overwrites the references on the common tag. When "~1" in the release job loads the images using the common tag, it will load the container of "~2" instead of "~1" having skipped the whole test job process.
The example is only set for the container workflow, but the other workflows might occur in a similar way.
---
.github/workflows/checker.yml | 2 +-
.github/workflows/container.yml | 2 +-
.github/workflows/data-update.yml | 2 +-
.github/workflows/documentation.yml | 2 +-
.github/workflows/l10n.yml | 2 +-
.github/workflows/security.yml | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/checker.yml b/.github/workflows/checker.yml
index 2de3c9896..5383bbc21 100644
--- a/.github/workflows/checker.yml
+++ b/.github/workflows/checker.yml
@@ -8,7 +8,7 @@ on:
- cron: "0 4 * * 5"
concurrency:
- group: ${{ github.workflow }}-${{ github.ref_name }}
+ group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index 22d1c0266..93951674c 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -13,7 +13,7 @@ on:
- master
concurrency:
- group: ${{ github.workflow }}-${{ github.ref_name }}
+ group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
diff --git a/.github/workflows/data-update.yml b/.github/workflows/data-update.yml
index 1c7ff1c2d..37b226081 100644
--- a/.github/workflows/data-update.yml
+++ b/.github/workflows/data-update.yml
@@ -8,7 +8,7 @@ on:
- cron: "59 23 28 * *"
concurrency:
- group: ${{ github.workflow }}-${{ github.ref_name }}
+ group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index 629d9a272..05a507994 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -12,7 +12,7 @@ on:
- master
concurrency:
- group: ${{ github.workflow }}-${{ github.ref_name }}
+ group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml
index 4220c5c65..bba987d36 100644
--- a/.github/workflows/l10n.yml
+++ b/.github/workflows/l10n.yml
@@ -15,7 +15,7 @@ on:
- cron: "05 07 * * 5"
concurrency:
- group: ${{ github.workflow }}-${{ github.ref_name }}
+ group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
index d10d0c98b..e994306b8 100644
--- a/.github/workflows/security.yml
+++ b/.github/workflows/security.yml
@@ -8,7 +8,7 @@ on:
- cron: "42 05 * * *"
concurrency:
- group: ${{ github.workflow }}-${{ github.ref_name }}
+ group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
From 743f24d8c6b277191a915ef6f1558d6c33ee72c7 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Wed, 14 May 2025 23:51:22 +0200
Subject: [PATCH 20/21] [fix] CI: commit author should be `searxng-bot`
If the workflow is executed with the "workflow_dispatch" trigger, the user who executed the workflow becomes the author of the commit on the PR, this is not intended.
It also reverts the body param so that the default text of the action does not appear.
---
.github/workflows/data-update.yml | 4 +++-
.github/workflows/l10n.yml | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/data-update.yml b/.github/workflows/data-update.yml
index 37b226081..4deca2ffc 100644
--- a/.github/workflows/data-update.yml
+++ b/.github/workflows/data-update.yml
@@ -66,7 +66,7 @@ jobs:
id: cpr
uses: peter-evans/create-pull-request@v7
with:
- author: "${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>"
+ author: "searxng-bot "
committer: "searxng-bot "
title: "[data] update searx.data - ${{ matrix.fetch }}"
commit-message: "[data] update searx.data - ${{ matrix.fetch }}"
@@ -74,6 +74,8 @@ jobs:
delete-branch: "true"
draft: "false"
signoff: "false"
+ body: |
+ [data] update searx.data - ${{ matrix.fetch }}
labels: |
data
diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml
index bba987d36..0b23975d3 100644
--- a/.github/workflows/l10n.yml
+++ b/.github/workflows/l10n.yml
@@ -119,7 +119,7 @@ jobs:
id: cpr
uses: peter-evans/create-pull-request@v7
with:
- author: "${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>"
+ author: "searxng-bot "
committer: "searxng-bot "
title: "[l10n] update translations from Weblate"
commit-message: "[l10n] update translations from Weblate"
@@ -127,6 +127,8 @@ jobs:
delete-branch: "true"
draft: "false"
signoff: "false"
+ body: |
+ [l10n] update translations from Weblate
labels: |
translation
From cd64fb966e7e9d764e622e42b177a1f13dc65ec0 Mon Sep 17 00:00:00 2001
From: Ivan Gabaldon
Date: Mon, 12 May 2025 00:01:12 +0200
Subject: [PATCH 21/21] [enh] container: support multiple registries
Allows to push the manifests to other registries, this allows to push both docker.io and ghcr.io registries.
---
.github/workflows/container.yml | 8 ++++----
utils/lib_sxng_container.sh | 20 ++++++++++++--------
2 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index 93951674c..72e03be50 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -117,10 +117,6 @@ jobs:
os: ubuntu-24.04-arm
emulation: true
- permissions:
- # Organization GHCR
- packages: write
-
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -152,6 +148,10 @@ jobs:
- build
- test
+ permissions:
+ # Organization GHCR
+ packages: write
+
steps:
- name: Checkout
uses: actions/checkout@v4
diff --git a/utils/lib_sxng_container.sh b/utils/lib_sxng_container.sh
index 49ef1ef05..6e29a3809 100644
--- a/utils/lib_sxng_container.sh
+++ b/utils/lib_sxng_container.sh
@@ -255,8 +255,7 @@ container.push() {
done
# Manifest tags
- release_tags=("latest")
- release_tags+=("$DOCKER_TAG")
+ release_tags=("latest" "$DOCKER_TAG")
# Create manifests
for tag in "${release_tags[@]}"; do
@@ -274,13 +273,18 @@ container.push() {
podman image list
- # Push manifests
- for tag in "${release_tags[@]}"; do
- build_msg CONTAINER "Pushing manifest with tag: $tag"
+ # Remote registries
+ release_registries=("ghcr.io" "docker.io")
- podman manifest push \
- "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
- "docker://docker.io/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
+ # Push manifests
+ for registry in "${release_registries[@]}"; do
+ for tag in "${release_tags[@]}"; do
+ build_msg CONTAINER "Pushing manifest $tag to $registry"
+
+ podman manifest push \
+ "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
+ "docker://$registry/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
+ done
done
)
dump_return $?