From caf0acdec85bdc0bdb13b05b76cea47038b75932 Mon Sep 17 00:00:00 2001 From: Nick Sweeting Date: Thu, 4 Jun 2026 00:48:47 -0700 Subject: [PATCH] release: archivebox 0.9.34rc54 --- .github/workflows/debian.yml | 214 -------------------- .github/workflows/homebrew.yml | 233 ---------------------- .github/workflows/release.yml | 10 +- .github/workflows/update-homebrew-tap.yml | 35 ++++ README.md | 10 +- archivebox/tests/test_opencode_agent.py | 10 + bin/build.sh | 4 - bin/build_brew.sh | 112 ----------- bin/build_deb.sh | 43 ---- bin/release_brew.sh | 48 ----- bin/release_deb.sh | 33 --- brew_dist/archivebox.rb | 50 ----- docs/Install.md | 2 - docs/Troubleshooting.md | 11 +- etc/package.json | 2 +- pkg/debian/archivebox | 15 -- pkg/debian/archivebox.service | 20 -- pkg/debian/install.sh | 51 ----- pkg/debian/nfpm.yaml | 69 ------- pkg/debian/scripts/postinstall.sh | 32 --- pkg/debian/scripts/preremove.sh | 27 --- pyproject.toml | 9 +- 22 files changed, 62 insertions(+), 978 deletions(-) delete mode 100644 .github/workflows/debian.yml delete mode 100644 .github/workflows/homebrew.yml create mode 100644 .github/workflows/update-homebrew-tap.yml delete mode 100755 bin/build_brew.sh delete mode 100755 bin/build_deb.sh delete mode 100755 bin/release_brew.sh delete mode 100755 bin/release_deb.sh delete mode 100644 brew_dist/archivebox.rb delete mode 100755 pkg/debian/archivebox delete mode 100644 pkg/debian/archivebox.service delete mode 100755 pkg/debian/install.sh delete mode 100644 pkg/debian/nfpm.yaml delete mode 100755 pkg/debian/scripts/postinstall.sh delete mode 100755 pkg/debian/scripts/preremove.sh diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml deleted file mode 100644 index 800ce102..00000000 --- a/.github/workflows/debian.yml +++ /dev/null @@ -1,214 +0,0 @@ -name: Build Debian package - -on: - workflow_dispatch: - workflow_call: - push: - branches: ['**'] - paths: - - 'pkg/debian/**' - - 'bin/build_deb.sh' - - 'bin/release_deb.sh' - - '.github/workflows/debian.yml' - - 'pyproject.toml' - # release trigger is handled by release.yml to avoid double-runs - -permissions: - contents: write - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - matrix: - arch: [amd64, arm64] - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Get version - id: version - run: echo "version=$(grep '^version = ' pyproject.toml | awk -F'\"' '{print $2}')" >> "$GITHUB_OUTPUT" - - - name: Install nfpm - env: - NFPM_VERSION: "2.45.1" - run: | - curl -fsSL "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" \ - | sudo tar -xz -C /usr/local/bin nfpm - nfpm --version - - - name: Build .deb package - run: | - export VERSION="${{ steps.version.outputs.version }}" - export ARCH="${{ matrix.arch }}" - ./bin/build_deb.sh - - - name: Verify .deb package contents - run: | - DEB_FILE="$(ls dist/archivebox*.deb | head -1)" - echo "=== Package info ===" - dpkg-deb --info "$DEB_FILE" - echo "" - echo "=== Package contents ===" - dpkg-deb --contents "$DEB_FILE" - echo "" - echo "=== Control fields ===" - dpkg-deb --field "$DEB_FILE" - - - name: Upload .deb artifact - uses: actions/upload-artifact@v4 - with: - name: archivebox-${{ steps.version.outputs.version }}-${{ matrix.arch }}.deb - path: dist/*.deb - - test: - needs: build - strategy: - fail-fast: false - matrix: - include: - - arch: amd64 - runner: ubuntu-24.04 - - arch: arm64 - runner: ubuntu-24.04-arm - runs-on: ${{ matrix.runner }} - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Install uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: false - - - name: Install build dependencies - uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # v1.6.0 - with: - packages: build-essential python3-dev python3-setuptools libssl-dev libldap2-dev libsasl2-dev zlib1g-dev libatomic1 - version: 1.0 - - - name: Build local wheel - run: | - uv sync --all-extras --no-install-project --no-install-workspace --no-sources --no-cache - uv build --wheel --out-dir /tmp/wheels/ - - - name: Download .deb artifact - uses: actions/download-artifact@v4 - with: - pattern: archivebox-*-${{ matrix.arch }}.deb - merge-multiple: true - - - name: Install system dependencies - run: | - sudo apt-get install -y python3.13 python3.13-venv python3-pip git curl wget - - - name: Pre-seed virtualenv with local wheel before dpkg install - run: | - # CI-only: pre-seed the venv with a local wheel so we test the - # unreleased code, not whatever is on PyPI. We explicitly use python3.13 - # here (matching the system dep installed above) to ensure the venv is - # created with the correct Python version. On real installs, install.sh - # handles this by preferring python3.13 and failing if < 3.13. - # When postinstall.sh runs during dpkg -i, it finds the venv already - # populated and just upgrades deps. - sudo mkdir -p /opt/archivebox - sudo python3.13 -m venv /opt/archivebox/venv - sudo /opt/archivebox/venv/bin/python3 -m pip install --quiet --upgrade pip setuptools - sudo /opt/archivebox/venv/bin/pip install --quiet /tmp/wheels/archivebox-*.whl - echo "[√] Pre-seeded /opt/archivebox/venv with local wheel" - - - name: Install .deb package - run: | - # dpkg install will run postinstall which creates the user, - # sets up systemd, and tries pip install (which finds it already installed) - sudo dpkg -i archivebox*.deb || sudo apt-get install -f -y - - - name: Verify archivebox is installed - run: | - which archivebox - archivebox version - - - name: Verify wrapper script works - run: | - /usr/bin/archivebox version - /usr/bin/archivebox --help | head -5 - - - name: Test archivebox init as archivebox user - run: | - # The postinstall should have created the user - id archivebox - sudo mkdir -p /tmp/archivebox-test - sudo chown archivebox:archivebox /tmp/archivebox-test - sudo -u archivebox bash -c 'cd /tmp/archivebox-test && /opt/archivebox/venv/bin/archivebox init' - - - name: Test archivebox status - run: | - sudo -u archivebox bash -c 'cd /tmp/archivebox-test && /opt/archivebox/venv/bin/archivebox status' - - - name: Test archivebox add - run: | - sudo -u archivebox bash -c 'cd /tmp/archivebox-test && /opt/archivebox/venv/bin/archivebox add "https://example.com"' - - - name: Verify systemd service file exists - run: | - test -f /usr/lib/systemd/system/archivebox.service - cat /usr/lib/systemd/system/archivebox.service - - # Upload .deb to GitHub Release only after tests pass - release: - if: github.event_name == 'release' || github.event_name == 'workflow_call' - needs: [build, test] - runs-on: ubuntu-24.04 - permissions: - contents: write - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Determine release tag - id: tag - run: | - TAG="${{ github.event.release.tag_name }}" - if [ -z "$TAG" ]; then - TAG="v$(grep '^version = ' pyproject.toml | awk -F'\"' '{print $2}')" - echo "[i] No release tag in event context, using version from pyproject.toml: $TAG" - fi - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - - - name: Download all .deb artifacts - uses: actions/download-artifact@v4 - with: - pattern: archivebox-*.deb - merge-multiple: true - - - name: Upload .deb to GitHub Release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - TAG="${{ steps.tag.outputs.tag }}" - # Verify the release exists before uploading - if ! gh release view "$TAG" >/dev/null 2>&1; then - echo "[!] No GitHub Release found for tag $TAG." - if [ -n "${{ github.event.release.tag_name }}" ]; then - echo "[X] This was triggered by a release event — the release should exist. Failing." - exit 1 - fi - echo "[i] Skipping upload (workflow_dispatch without a release)." - echo " Create a release first or trigger via the release event." - exit 0 - fi - gh release upload "$TAG" *.deb --clobber diff --git a/.github/workflows/homebrew.yml b/.github/workflows/homebrew.yml deleted file mode 100644 index 10805ba1..00000000 --- a/.github/workflows/homebrew.yml +++ /dev/null @@ -1,233 +0,0 @@ -name: Build Homebrew formula - -on: - workflow_dispatch: - workflow_call: - push: - branches: ['**'] - paths: - - 'brew_dist/**' - - 'bin/build_brew.sh' - - 'bin/release_brew.sh' - - '.github/workflows/homebrew.yml' - - 'pyproject.toml' - # release trigger is handled by release.yml to avoid double-runs - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build-and-test: - strategy: - fail-fast: false - matrix: - os: [macos-latest, ubuntu-24.04] - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Get version - id: version - run: echo "version=$(grep '^version = ' pyproject.toml | awk -F'\"' '{print $2}')" >> "$GITHUB_OUTPUT" - - - name: Validate formula template syntax - run: ruby -c brew_dist/archivebox.rb - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Install uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: false - - - name: Install build dependencies (Linux) - if: runner.os == 'Linux' - uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # v1.6.0 - with: - packages: build-essential python3-dev python3-setuptools libssl-dev libldap2-dev libsasl2-dev zlib1g-dev libatomic1 - version: 1.0 - - - name: Build local sdist - run: | - uv sync --all-extras --no-install-project --no-install-workspace --no-sources --no-cache - uv build --sdist --out-dir /tmp/sdist/ - - - name: Generate formula from local sdist - run: | - VERSION="${{ steps.version.outputs.version }}" - SDIST_PATH="$(ls /tmp/sdist/archivebox-*.tar.gz | head -1)" - SDIST_SHA256="$(shasum -a 256 "$SDIST_PATH" | awk '{print $1}')" - - # Install archivebox + poet into a temp venv to generate resource stanzas - python3 -m venv /tmp/poet-venv - source /tmp/poet-venv/bin/activate - pip install --quiet "$SDIST_PATH" homebrew-pypi-poet - echo "[+] Generating resource stanzas with homebrew-pypi-poet..." - RESOURCES="$(poet archivebox)" - deactivate - - # For CI: use file:// URL pointing to local sdist - # For release: this gets overridden with the PyPI URL - SDIST_URL="file://${SDIST_PATH}" - - cat > /tmp/archivebox.rb << RUBY -class Archivebox < Formula - include Language::Python::Virtualenv - - desc "Self-hosted internet archiving solution" - homepage "https://github.com/ArchiveBox/ArchiveBox" - url "${SDIST_URL}" - sha256 "${SDIST_SHA256}" - license "MIT" - - depends_on "python@3.13" - -${RESOURCES} - - def install - virtualenv_install_with_resources - end - - def post_install - data_dir = var/"archivebox" - data_dir.mkpath - ENV["DATA_DIR"] = data_dir.to_s - system bin/"archivebox", "init" - end - - def caveats - <<~EOS - ArchiveBox data is stored in: - #{var}/archivebox - - To start archiving, run: - cd #{var}/archivebox && archivebox add 'https://example.com' - - To start the web UI: - cd #{var}/archivebox && archivebox server 0.0.0.0:8000 - EOS - end - - test do - assert_match version.to_s, shell_output("#{bin}/archivebox version") - end -end -RUBY - - echo "[√] Generated formula:" - ruby -c /tmp/archivebox.rb - cat /tmp/archivebox.rb - - - name: Install Homebrew (Linux only) - if: runner.os == 'Linux' - run: | - NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - echo "HOMEBREW_PREFIX=$HOMEBREW_PREFIX" >> "$GITHUB_ENV" - echo "HOMEBREW_CELLAR=$HOMEBREW_CELLAR" >> "$GITHUB_ENV" - echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >> "$GITHUB_ENV" - echo "$HOMEBREW_PREFIX/bin" >> "$GITHUB_PATH" - echo "$HOMEBREW_PREFIX/sbin" >> "$GITHUB_PATH" - - - name: Install brew dependencies - run: brew install python@3.13 - - - name: Install archivebox via brew from local formula - run: | - brew install --build-from-source --verbose /tmp/archivebox.rb - - - name: Verify archivebox version - run: archivebox version - - - name: Test archivebox init - run: | - mkdir -p /tmp/archivebox-test && cd /tmp/archivebox-test - archivebox init - - - name: Test archivebox status - run: | - cd /tmp/archivebox-test - archivebox status - - # On release only: generate the real formula with PyPI URL and push to tap - release: - if: github.event_name == 'release' || github.event_name == 'workflow_call' - needs: build-and-test - runs-on: macos-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Get version - id: version - run: echo "version=$(grep '^version = ' pyproject.toml | awk -F'\"' '{print $2}')" >> "$GITHUB_OUTPUT" - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Wait for PyPI package availability - run: | - VERSION="${{ steps.version.outputs.version }}" - echo "[+] Waiting for archivebox==${VERSION} to be available on PyPI..." - for i in $(seq 1 30); do - if pip index versions archivebox 2>/dev/null | grep -q "$VERSION"; then - echo "[√] archivebox==${VERSION} is available on PyPI" - break - fi - if [ "$i" -eq 30 ]; then - echo "[!] Timed out waiting for PyPI. Trying to install anyway..." - break - fi - echo " Attempt $i/30 - not yet available, waiting 30s..." - sleep 30 - done - - - name: Generate release formula via build_brew.sh - run: ./bin/build_brew.sh - - - name: Test formula install - run: | - brew install --build-from-source brew_dist/archivebox.rb - archivebox version - - - name: Upload formula artifact - uses: actions/upload-artifact@v4 - with: - name: archivebox.rb - path: brew_dist/archivebox.rb - - - name: Push to homebrew-archivebox tap - env: - GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} - run: | - VERSION="${{ steps.version.outputs.version }}" - git clone "https://x-access-token:${GH_TOKEN}@github.com/ArchiveBox/homebrew-archivebox.git" /tmp/tap - - cp brew_dist/archivebox.rb /tmp/tap/Formula/archivebox.rb 2>/dev/null || \ - cp brew_dist/archivebox.rb /tmp/tap/archivebox.rb - - cd /tmp/tap - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add -A - if git diff --cached --quiet; then - echo "[i] No changes to formula, skipping push." - else - git commit -m "Update archivebox to v${VERSION}" - git push origin HEAD - echo "[√] Formula pushed to homebrew-archivebox tap" - fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a16fba1b..41436c48 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,8 +2,8 @@ name: Release # Orchestrates the full release pipeline: # 1. Build and publish pip package to PyPI -# 2. Build .deb packages and Homebrew formula (in parallel, after pip) -# 3. Build Docker images (in parallel with deb/brew) +# 2. Build Homebrew formula after pip +# 3. Build Docker images in parallel # # Individual workflows also run on push for CI (see their own triggers). # Manual fallback for the hosted release pipeline. The normal prerelease loop @@ -28,12 +28,6 @@ jobs: uses: ./.github/workflows/pip.yml secrets: inherit - debian: - name: Build .deb packages - needs: pip - uses: ./.github/workflows/debian.yml - secrets: inherit - homebrew: name: Update Homebrew formula needs: pip diff --git a/.github/workflows/update-homebrew-tap.yml b/.github/workflows/update-homebrew-tap.yml new file mode 100644 index 00000000..ef2475ec --- /dev/null +++ b/.github/workflows/update-homebrew-tap.yml @@ -0,0 +1,35 @@ +name: Update Homebrew tap + +on: + push: + branches: [dev] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: update-homebrew-tap-${{ github.ref }} + cancel-in-progress: true + +jobs: + dispatch: + runs-on: ubuntu-latest + + steps: + - name: Dispatch tap update + env: + HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} + run: | + if [ -z "$HOMEBREW_TAP_TOKEN" ]; then + echo "HOMEBREW_TAP_TOKEN is not configured; tap hourly fallback will update the formula." + exit 0 + fi + + curl --fail-with-body \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${HOMEBREW_TAP_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ArchiveBox/homebrew-archivebox/dispatches \ + -d '{"event_type":"archivebox-dev-updated"}' diff --git a/README.md b/README.md index 019b06aa..7daf830b 100644 --- a/README.md +++ b/README.md @@ -295,12 +295,10 @@ See below for more usage examples using the C aptitude apt (Ubuntu/Debian/etc.)
    -
  1. Download and install the .deb package from the latest release. -
    # download the .deb for your architecture (amd64 or arm64)
    -ARCH="$(dpkg --print-architecture)"
    -VERSION="$(curl -fsSL https://api.github.com/repos/ArchiveBox/ArchiveBox/releases/latest | python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'].lstrip('v'))")"
    -curl -fsSL "https://github.com/ArchiveBox/ArchiveBox/releases/latest/download/archivebox_${VERSION}_${ARCH}.deb" -o /tmp/archivebox.deb
    -sudo apt install /tmp/archivebox.deb
    +
  2. Add the third-party ArchiveBox apt repo and install archivebox. +
    echo 'deb [trusted=yes] https://archivebox.github.io/debian-archivebox dev main' | sudo tee /etc/apt/sources.list.d/archivebox.list
    +sudo apt update
    +sudo apt install archivebox
     archivebox version                         # make sure all dependencies are installed
     
  3. diff --git a/archivebox/tests/test_opencode_agent.py b/archivebox/tests/test_opencode_agent.py index 5c6ad31b..7d3b2eec 100644 --- a/archivebox/tests/test_opencode_agent.py +++ b/archivebox/tests/test_opencode_agent.py @@ -1,5 +1,6 @@ import os import socket +import subprocess from pathlib import Path from types import SimpleNamespace from urllib.parse import quote @@ -97,6 +98,15 @@ def live_opencode(opencode_archive_config): settings["archivebox_base_url"] = "http://admin.archivebox.localhost:8000" settings["archivebox_admin_url"] = "http://admin.archivebox.localhost:8000/admin" settings["archivebox_api_url"] = "http://admin.archivebox.localhost:8000/api/" + binary, binary_env = views._resolve_binary(settings["binary"], settings["config"]) + version = subprocess.run( + [binary, "--version"], + env={**os.environ, **binary_env}, + text=True, + capture_output=True, + timeout=120, + ) + assert version.returncode == 0, version.stderr or version.stdout ok, error = views._ensure_opencode(settings) assert ok, error diff --git a/bin/build.sh b/bin/build.sh index 1ebf2d3d..a7f32a3e 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -19,13 +19,9 @@ cd "$REPO_DIR" # the order matters ./bin/build_docs.sh ./bin/build_pip.sh -./bin/build_deb.sh -./bin/build_brew.sh ./bin/build_docker.sh echo "[√] Done. Install the built package by running:" echo " pip install archivebox" echo " # or" -echo " sudo apt install ./dist/archivebox*.deb" -echo " # or" echo " brew tap archivebox/archivebox && brew install archivebox" diff --git a/bin/build_brew.sh b/bin/build_brew.sh deleted file mode 100755 index 80d4aa11..00000000 --- a/bin/build_brew.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash - -### Bash Environment Setup -# http://redsymbol.net/articles/unofficial-bash-strict-mode/ -# https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html -# set -o xtrace -set -o errexit -set -o errtrace -set -o nounset -set -o pipefail -IFS=$'\n' - -REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" -cd "$REPO_DIR" - -VERSION="$(grep '^version = ' "${REPO_DIR}/pyproject.toml" | awk -F'"' '{print $2}')" -FORMULA_FILE="$REPO_DIR/brew_dist/archivebox.rb" - -echo "[+] Building Homebrew formula for archivebox==${VERSION}..." - -# Create a temporary virtualenv for generating the formula -TMPDIR="$(mktemp -d)" -trap "rm -rf $TMPDIR" EXIT - -python3 -m venv "$TMPDIR/venv" -source "$TMPDIR/venv/bin/activate" - -pip install --quiet "archivebox==${VERSION}" homebrew-pypi-poet 2>/dev/null - -echo "[+] Generating resource stanzas with homebrew-pypi-poet..." -RESOURCES="$(poet archivebox)" - -# Get the sdist URL and SHA256 from PyPI JSON API (works on macOS and Linux) -SDIST_URL="" -SDIST_SHA256="" -PYPI_JSON="$(curl -fsSL "https://pypi.org/pypi/archivebox/${VERSION}/json" 2>/dev/null || echo '')" -if [ -n "$PYPI_JSON" ]; then - SDIST_URL="$(echo "$PYPI_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(next((u['url'] for u in d['urls'] if u['packagetype']=='sdist'), ''))" 2>/dev/null || echo '')" - SDIST_SHA256="$(echo "$PYPI_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(next((u['digests']['sha256'] for u in d['urls'] if u['packagetype']=='sdist'), ''))" 2>/dev/null || echo '')" -fi -if [ -z "$SDIST_URL" ]; then - SDIST_URL="https://files.pythonhosted.org/packages/source/a/archivebox/archivebox-${VERSION}.tar.gz" -fi -if [ -z "$SDIST_SHA256" ]; then - # Fallback: download and compute locally - mkdir -p "$TMPDIR/sdist" - pip download --no-binary :all: --no-deps -d "$TMPDIR/sdist" "archivebox==${VERSION}" 2>/dev/null || true - SDIST_SHA256="$(shasum -a 256 "$TMPDIR/sdist/"*.tar.gz 2>/dev/null | awk '{print $1}' || echo '')" -fi - -deactivate - -echo "[+] Updating formula file: $FORMULA_FILE" - -# Build the formula from the template -cat > "$FORMULA_FILE" << RUBY -# Auto-generated by bin/build_brew.sh using homebrew-pypi-poet. -# Users install with: brew tap archivebox/archivebox && brew install archivebox - -class Archivebox < Formula - include Language::Python::Virtualenv - - desc "Self-hosted internet archiving solution" - homepage "https://github.com/ArchiveBox/ArchiveBox" - url "${SDIST_URL}" - sha256 "${SDIST_SHA256}" - license "MIT" - head "https://github.com/ArchiveBox/ArchiveBox.git", branch: "dev" - - depends_on "python@3.13" - # All other runtime deps (node, chrome, yt-dlp, etc.) are installed - # on-demand by \`archivebox install\` and should NOT be declared here. - - # Python dependency resource blocks auto-generated by homebrew-pypi-poet - # AUTOGENERATED_RESOURCES_START -${RESOURCES} - # AUTOGENERATED_RESOURCES_END - - def install - virtualenv_install_with_resources - end - - def post_install - # Initialize ArchiveBox data in the Homebrew-managed var directory - data_dir = var/"archivebox" - data_dir.mkpath - ENV["DATA_DIR"] = data_dir.to_s - system bin/"archivebox", "init" - end - - def caveats - <<~EOS - ArchiveBox data is stored in: - #{var}/archivebox - - To start archiving, run: - cd #{var}/archivebox && archivebox add 'https://example.com' - - To start the web UI: - cd #{var}/archivebox && archivebox server 0.0.0.0:8000 - EOS - end - - test do - assert_match version.to_s, shell_output("#{bin}/archivebox version") - end -end -RUBY - -echo "[√] Formula updated: $FORMULA_FILE" -echo " Version: ${VERSION}" -echo " URL: ${SDIST_URL}" diff --git a/bin/build_deb.sh b/bin/build_deb.sh deleted file mode 100755 index 08c0950d..00000000 --- a/bin/build_deb.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -### Bash Environment Setup -# http://redsymbol.net/articles/unofficial-bash-strict-mode/ -# https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html -# set -o xtrace -set -o errexit -set -o errtrace -set -o nounset -set -o pipefail -IFS=$'\n' - -REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" -cd "$REPO_DIR" - -VERSION="$(grep '^version = ' "${REPO_DIR}/pyproject.toml" | awk -F'"' '{print $2}')" -export VERSION - -# Default to amd64, can be overridden with ARCH=arm64 -export ARCH="${ARCH:-amd64}" - -echo "[+] Building .deb package for archivebox_${VERSION}_${ARCH}..." - -# Check for nfpm -if ! command -v nfpm &>/dev/null; then - echo "[!] nfpm not found. Install it with one of:" - echo " go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest" - echo " uv tool install nfpm" - echo " brew install goreleaser/tap/nfpm" - echo " curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh" - exit 1 -fi - -mkdir -p "$REPO_DIR/dist" - -nfpm package \ - --config "$REPO_DIR/pkg/debian/nfpm.yaml" \ - --packager deb \ - --target "$REPO_DIR/dist/" - -echo -echo "[√] Built .deb package:" -ls -la "$REPO_DIR/dist/"archivebox*.deb diff --git a/bin/release_brew.sh b/bin/release_brew.sh deleted file mode 100755 index 19fbe90a..00000000 --- a/bin/release_brew.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -### Bash Environment Setup -# http://redsymbol.net/articles/unofficial-bash-strict-mode/ -# https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html -# set -o xtrace -set -o errexit -set -o errtrace -set -o nounset -set -o pipefail -IFS=$'\n' - -REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" -cd "$REPO_DIR" - -VERSION="$(grep '^version = ' "${REPO_DIR}/pyproject.toml" | awk -F'"' '{print $2}')" -FORMULA_FILE="$REPO_DIR/brew_dist/archivebox.rb" -TAP_REPO="ArchiveBox/homebrew-archivebox" - -if [ ! -f "$FORMULA_FILE" ]; then - echo "[!] Formula not found at $FORMULA_FILE" - echo " Run ./bin/build_brew.sh first to generate it." - exit 1 -fi - -echo "[+] Releasing Homebrew formula for archivebox==${VERSION} to ${TAP_REPO}..." - -# Clone the tap repo, update formula, commit, and push -TMPDIR="$(mktemp -d)" -trap "rm -rf $TMPDIR" EXIT - -git clone "https://github.com/${TAP_REPO}.git" "$TMPDIR/tap" -cp "$FORMULA_FILE" "$TMPDIR/tap/archivebox.rb" - -cd "$TMPDIR/tap" -git add archivebox.rb -if git diff --cached --quiet; then - echo "[i] No changes to formula, skipping release." - exit 0 -fi - -git commit -m "Update archivebox to v${VERSION}" -git push origin HEAD - -echo "[√] Homebrew formula pushed to ${TAP_REPO}" -echo " Users can install with:" -echo " brew tap archivebox/archivebox" -echo " brew install archivebox" diff --git a/bin/release_deb.sh b/bin/release_deb.sh deleted file mode 100755 index 45779f5c..00000000 --- a/bin/release_deb.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -### Bash Environment Setup -# http://redsymbol.net/articles/unofficial-bash-strict-mode/ -# https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html -# set -o xtrace -set -o errexit -set -o errtrace -set -o nounset -set -o pipefail -IFS=$'\n' - -REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" -cd "$REPO_DIR" - -VERSION="$(grep '^version = ' "${REPO_DIR}/pyproject.toml" | awk -F'"' '{print $2}')" - -echo "[+] Releasing .deb package for archivebox==${VERSION}..." - -DEB_FILE="$(ls -1 "$REPO_DIR/dist/"archivebox*.deb 2>/dev/null | head -1)" -if [ -z "$DEB_FILE" ]; then - echo "[!] No .deb file found in dist/. Run ./bin/build_deb.sh first." - exit 1 -fi - -echo "[+] Uploading $DEB_FILE to GitHub Release v${VERSION}..." -gh release upload "v${VERSION}" "$DEB_FILE" --clobber 2>/dev/null || \ - gh release create "v${VERSION}" "$DEB_FILE" --title "v${VERSION}" --generate-notes - -echo "[√] .deb package uploaded to GitHub Release v${VERSION}" -echo " Users can install with:" -echo " curl -fsSL https://github.com/ArchiveBox/ArchiveBox/releases/download/v${VERSION}/archivebox_${VERSION}_amd64.deb -o /tmp/archivebox.deb" -echo " sudo apt install /tmp/archivebox.deb" diff --git a/brew_dist/archivebox.rb b/brew_dist/archivebox.rb deleted file mode 100644 index 3e4d2f31..00000000 --- a/brew_dist/archivebox.rb +++ /dev/null @@ -1,50 +0,0 @@ -# Auto-generated by bin/build_brew.sh using homebrew-pypi-poet. -# Users install with: brew tap archivebox/archivebox && brew install archivebox - -class Archivebox < Formula - include Language::Python::Virtualenv - - desc "Self-hosted internet archiving solution" - homepage "https://github.com/ArchiveBox/ArchiveBox" - url "https://files.pythonhosted.org/packages/source/a/archivebox/archivebox-0.9.3.tar.gz" - sha256 "" # auto-filled by bin/build_brew.sh - license "MIT" - head "https://github.com/ArchiveBox/ArchiveBox.git", branch: "dev" - - depends_on "python@3.13" - # All other runtime deps (node, chrome, yt-dlp, etc.) are installed - # on-demand by `archivebox install` and should NOT be declared here. - - # Python dependency resource blocks auto-generated by homebrew-pypi-poet - # AUTOGENERATED_RESOURCES_START - # AUTOGENERATED_RESOURCES_END - - def install - virtualenv_install_with_resources - end - - def post_install - # Initialize ArchiveBox data in the Homebrew-managed var directory - data_dir = var/"archivebox" - data_dir.mkpath - ENV["DATA_DIR"] = data_dir.to_s - system bin/"archivebox", "init" - end - - def caveats - <<~EOS - ArchiveBox data is stored in: - #{var}/archivebox - - To start archiving, run: - cd #{var}/archivebox && archivebox add 'https://example.com' - - To start the web UI: - cd #{var}/archivebox && archivebox server 0.0.0.0:8000 - EOS - end - - test do - assert_match version.to_s, shell_output("#{bin}/archivebox version") - end -end diff --git a/docs/Install.md b/docs/Install.md index 80714ed4..71c31e93 100644 --- a/docs/Install.md +++ b/docs/Install.md @@ -86,8 +86,6 @@ curl -fsSL 'https://get.archivebox.io' | bash ``` The script explains what it installs beforehand, and will prompt for user confirmation before making any changes to your system. The script uses Docker if already installed, but you can decline and it will attempt to auto-install everything using `apt`/`brew`/`pkg` + `pip` instead. -Note: The script will currently still attempt to install via `brew` on macOS. This will fail as ArchiveBox is no longer distributed as a Homebrew formula. - After running the setup script, continue with the [Quickstart](https://github.com/ArchiveBox/ArchiveBox#%EF%B8%8F-next-steps) guide... ➡️ diff --git a/docs/Troubleshooting.md b/docs/Troubleshooting.md index 43c15e43..8d7d417c 100644 --- a/docs/Troubleshooting.md +++ b/docs/Troubleshooting.md @@ -34,15 +34,16 @@ archivebox version # shows lots of useful info about installed dependencie (ensure the version shown is the most recent available from [Releases](https://github.com/ArchiveBox/ArchiveBox/releases)) ### macOS -**✨ ArchiveBox no longer needs to be `brew`-installed:** -✅ ArchiveBox still fully supports macOS, don't worry! -📦 Just install it using `pip` (or `pipx`) instead now: +ArchiveBox can be installed with Homebrew or `pip`/`pipx` on macOS: ```bash +brew tap archivebox/archivebox +brew install archivebox + mkdir -p ~/archivebox/data cd ~/archivebox/data # (for example, can be anywhere) -pip install archivebox # just use pip to get archivebox -archivebox install # then finish installing dependencies +archivebox init +archivebox install # finish installing runtime dependencies ``` More info: https://github.com/ArchiveBox/homebrew-archivebox diff --git a/etc/package.json b/etc/package.json index aa51c438..8ed689a2 100644 --- a/etc/package.json +++ b/etc/package.json @@ -1,6 +1,6 @@ { "name": "archivebox", - "version": "0.9.34rc53", + "version": "0.9.34rc54", "repository": "github:ArchiveBox/ArchiveBox", "license": "MIT", "dependencies": { diff --git a/pkg/debian/archivebox b/pkg/debian/archivebox deleted file mode 100755 index 0ebccabc..00000000 --- a/pkg/debian/archivebox +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# /usr/bin/archivebox - wrapper script installed by the archivebox .deb package -# Activates the pip-installed virtualenv and runs archivebox CLI - -ARCHIVEBOX_VENV="/opt/archivebox/venv" - -if [ ! -f "$ARCHIVEBOX_VENV/bin/archivebox" ]; then - echo "Error: ArchiveBox is not installed in $ARCHIVEBOX_VENV" - echo "Try running: sudo /opt/archivebox/install.sh" - exit 1 -fi - -# Export venv bin to PATH so bundled console scripts (yt-dlp, etc.) are discoverable -export PATH="$ARCHIVEBOX_VENV/bin:$PATH" -exec "$ARCHIVEBOX_VENV/bin/archivebox" "$@" diff --git a/pkg/debian/archivebox.service b/pkg/debian/archivebox.service deleted file mode 100644 index af8b4500..00000000 --- a/pkg/debian/archivebox.service +++ /dev/null @@ -1,20 +0,0 @@ -# The archivebox user/group and /var/lib/archivebox directory are created by -# postinstall.sh (which runs after dpkg unpacks the package contents). - -[Unit] -Description=ArchiveBox Web Archiving Server -After=network.target - -[Service] -Type=simple -User=archivebox -Group=archivebox -WorkingDirectory=/var/lib/archivebox -Environment="PATH=/opt/archivebox/venv/bin:/usr/local/bin:/usr/bin:/bin" -ExecStartPre=/usr/bin/archivebox init -ExecStart=/usr/bin/archivebox server 0.0.0.0:8000 -Restart=on-failure -RestartSec=5 - -[Install] -WantedBy=multi-user.target diff --git a/pkg/debian/install.sh b/pkg/debian/install.sh deleted file mode 100755 index 1c72758e..00000000 --- a/pkg/debian/install.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -# /opt/archivebox/install.sh - installs/upgrades archivebox into its virtualenv -# Called by the postinstall script and can be run manually to upgrade - -set -e - -ARCHIVEBOX_VENV="/opt/archivebox/venv" -ARCHIVEBOX_VERSION="${ARCHIVEBOX_VERSION:-}" - -# ArchiveBox requires Python >= 3.13 (per pyproject.toml). -# Prefer python3.13 explicitly; fall back to python3 with a version check. -if command -v python3.13 >/dev/null 2>&1; then - PYTHON="python3.13" -elif command -v python3 >/dev/null 2>&1; then - PYTHON="python3" - PY_MAJOR="$("$PYTHON" -c 'import sys; print(sys.version_info.major)')" - PY_MINOR="$("$PYTHON" -c 'import sys; print(sys.version_info.minor)')" - if [ "$PY_MAJOR" -lt 3 ] || { [ "$PY_MAJOR" -eq 3 ] && [ "$PY_MINOR" -lt 13 ]; }; then - PY_VER="${PY_MAJOR}.${PY_MINOR}" - echo "[!] Error: ArchiveBox requires Python >= 3.13, but found Python $PY_VER" - echo " Install python3.13: sudo apt install python3.13 python3.13-venv" - exit 1 - fi -else - echo "[!] Error: python3 not found. Install python3.13: sudo apt install python3.13 python3.13-venv" - exit 1 -fi - -echo "[+] Setting up ArchiveBox virtualenv in $ARCHIVEBOX_VENV (using $PYTHON)..." - -# Create the virtualenv if it doesn't exist -if [ ! -d "$ARCHIVEBOX_VENV" ]; then - "$PYTHON" -m venv "$ARCHIVEBOX_VENV" -fi - -# Upgrade pip inside the virtualenv -"$ARCHIVEBOX_VENV/bin/python3" -m pip install --quiet --upgrade pip setuptools - -# Install or upgrade archivebox. -# ARCHIVEBOX_VERSION is set by postinstall.sh from the .deb package version. -# When run manually without it, install the latest release from PyPI. -if [ -n "$ARCHIVEBOX_VERSION" ]; then - echo "[+] Installing archivebox==$ARCHIVEBOX_VERSION..." - "$ARCHIVEBOX_VENV/bin/pip" install --quiet --upgrade "archivebox==$ARCHIVEBOX_VERSION" -else - echo "[+] Installing latest archivebox (no version pinned)..." - "$ARCHIVEBOX_VENV/bin/pip" install --quiet --upgrade archivebox -fi - -echo "[√] ArchiveBox installed successfully." -echo " Run 'archivebox version' to verify." diff --git a/pkg/debian/nfpm.yaml b/pkg/debian/nfpm.yaml deleted file mode 100644 index fa3df26c..00000000 --- a/pkg/debian/nfpm.yaml +++ /dev/null @@ -1,69 +0,0 @@ -# nFPM configuration for building ArchiveBox .deb packages -# Docs: https://nfpm.goreleaser.com/configuration/ -# Usage: nfpm package --config pkg/debian/nfpm.yaml --packager deb --target dist/ - -name: archivebox -arch: "${ARCH:-amd64}" -platform: linux -version: "${VERSION}" -version_schema: semver -maintainer: "Nick Sweeting " -description: | - Self-hosted internet archiving solution. - Save pages from the web including HTML, PDF, screenshots, media, and more. - Install with: sudo apt install archivebox && archivebox init --setup -vendor: "ArchiveBox" -homepage: "https://archivebox.io" -license: "MIT" -section: "web" -priority: "optional" - -depends: - # python3 >= 3.11 allows dpkg to install on more systems (e.g. Ubuntu 24.04). - # install.sh enforces the real >= 3.13 requirement at venv creation time, - # failing early with a clear error if only an older python3 is available. - - python3 (>= 3.11) - - python3-pip - - python3-venv - # All other runtime deps (node, chrome, yt-dlp, etc.) are installed on-demand - # by `archivebox install` and should NOT be declared as package dependencies. - -recommends: - # Common utilities used by archivebox extractors. Declared as recommends - # (not depends) so dpkg doesn't hard-fail if they're missing, but apt - # installs them by default so users have a working baseline out of the box. - - git - - curl - - wget - -contents: - # Wrapper script for /usr/bin/archivebox - - src: pkg/debian/archivebox - dst: /usr/bin/archivebox - file_info: - mode: 0755 - - # Install helper script - - src: pkg/debian/install.sh - dst: /opt/archivebox/install.sh - file_info: - mode: 0755 - - # Systemd service file - - src: pkg/debian/archivebox.service - dst: /usr/lib/systemd/system/archivebox.service - file_info: - mode: 0644 - - # Create data directory (unpacked as root; postinstall.sh chowns to archivebox user) - - dst: /var/lib/archivebox - type: dir - file_info: - mode: 0755 - -scripts: - postinstall: pkg/debian/scripts/postinstall.sh - preremove: pkg/debian/scripts/preremove.sh - -deb: - compression: zstd diff --git a/pkg/debian/scripts/postinstall.sh b/pkg/debian/scripts/postinstall.sh deleted file mode 100755 index a175c1b5..00000000 --- a/pkg/debian/scripts/postinstall.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# postinstall script for archivebox .deb package -set -e - -# Create archivebox system user if it doesn't exist -if ! id -u archivebox >/dev/null 2>&1; then - useradd --system --shell /bin/bash --home-dir /var/lib/archivebox --create-home archivebox - echo "[+] Created archivebox system user" -fi - -# Ensure data directory exists and is owned by archivebox -mkdir -p /var/lib/archivebox -chown archivebox:archivebox /var/lib/archivebox - -# Run the virtualenv install script, pinning to the .deb package version -ARCHIVEBOX_VERSION="$(dpkg-query -W -f='${Version}' archivebox 2>/dev/null || echo '')" -export ARCHIVEBOX_VERSION -/opt/archivebox/install.sh - -# Reload systemd to pick up the service file (skip if systemd is not running) -if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then - systemctl daemon-reload - - # On upgrade: restart the service if it was enabled (prerm stopped it) - if [ "$1" = "configure" ] && systemctl is-enabled archivebox >/dev/null 2>&1; then - systemctl start archivebox 2>/dev/null || true - echo "[+] Restarted archivebox service after upgrade" - else - echo "[i] To start ArchiveBox: sudo systemctl start archivebox" - echo "[i] To enable on boot: sudo systemctl enable archivebox" - fi -fi diff --git a/pkg/debian/scripts/preremove.sh b/pkg/debian/scripts/preremove.sh deleted file mode 100755 index 65fc7330..00000000 --- a/pkg/debian/scripts/preremove.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# preremove script for archivebox .deb package -set -e - -# dpkg passes "$1" as "remove", "purge", or "upgrade". - -# Always stop the service before removing or upgrading, because postinstall -# replaces the venv in-place — the running process would use stale binaries. -if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then - systemctl stop archivebox 2>/dev/null || true -fi - -# Only disable + clean up on full removal, not during upgrade. -if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then - if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then - systemctl disable archivebox 2>/dev/null || true - fi - - echo "[+] Removing ArchiveBox virtualenv..." - rm -rf /opt/archivebox/venv - - echo "[i] Your ArchiveBox data in /var/lib/archivebox has NOT been removed." - echo " The 'archivebox' system user has NOT been removed." - echo " Remove them manually if you no longer need them:" - echo " sudo rm -rf /var/lib/archivebox" - echo " sudo userdel archivebox" -fi diff --git a/pyproject.toml b/pyproject.toml index 57c82e87..d46bb13f 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "archivebox" -version = "0.9.34rc53" +version = "0.9.34rc54" requires-python = ">=3.13" description = "Self-hosted internet archiving solution." authors = [{name = "Nick Sweeting", email = "pyproject.toml@archivebox.io"}] @@ -79,9 +79,9 @@ dependencies = [ ### Extractor dependencies (optional binaries detected at runtime via shutil.which) ### Binary/Package Management "abxbus==2.5.10", # EventBus API - "abxpkg>=1.11.167", # for: detecting, versioning, and installing binaries via apt/brew/pip/npm - "abx-plugins>=1.11.171", # shared ArchiveBox plugin package with Chrome/Puppeteer dependency wiring - "abx-dl>=1.11.171", # shared ArchiveBox downloader package with blocking install preflight + "abxpkg>=1.11.169", # for: detecting, versioning, and installing binaries via apt/brew/pip/npm + "abx-plugins>=1.11.173", # shared ArchiveBox plugin package with Chrome/Puppeteer dependency wiring + "abx-dl>=1.11.173", # shared ArchiveBox downloader package with blocking install preflight ### UUID7 backport for Python <3.14 "uuid7>=0.1.0; python_version < '3.14'", # provides the uuid_extensions module on Python 3.13 ] @@ -119,7 +119,6 @@ dev = [ ### BUILD "uv>=0.11.3", "bumpver>=2023.1129", - #"homebrew-pypi-poet>=0.10.0", # for: generating archivebox.rb brewfile list of python packages ### DOCS "recommonmark>=0.7.1", "sphinx>=8.1.3",