This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/versioned-offline-docs-bundle in repository https://gitbox.apache.org/repos/asf/camel-website.git
commit 43212688470a74f294bcfed397f237ab51b07ecd Author: Claus Ibsen <[email protected]> AuthorDate: Wed Jun 17 12:29:52 2026 +0200 CAMEL-23788: Generate versioned offline documentation bundles Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .github/workflows/offline-bundle.yml | 69 +++++++++++++++++++++++++++ llms-txt-template.md | 8 ++++ scripts/generate-offline-bundle.js | 91 ++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) diff --git a/.github/workflows/offline-bundle.yml b/.github/workflows/offline-bundle.yml new file mode 100644 index 00000000..98d439b4 --- /dev/null +++ b/.github/workflows/offline-bundle.yml @@ -0,0 +1,69 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Generate Offline Documentation Bundle + +on: + workflow_dispatch: + inputs: + camel_version: + description: 'Camel version to bundle (e.g. 4.18)' + required: true + type: string + +jobs: + generate-bundle: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Install dependencies + run: yarn workspaces foreach --all install + + - name: Build site + run: yarn build + env: + CAMEL_ENV: production + HUGO_OPTIONS: --buildFuture + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate versioned bundle + run: node scripts/generate-offline-bundle.js ${{ inputs.camel_version }} + + - name: Create or update GitHub Release + run: | + TAG="docs-${{ inputs.camel_version }}" + FILE="public/camel-docs-${{ inputs.camel_version }}.zip" + TITLE="Apache Camel ${{ inputs.camel_version }} — Offline Documentation" + NOTES="Offline documentation bundle for Apache Camel ${{ inputs.camel_version }}. + + Contains all Markdown files for components, Spring Boot starters, Kamelets, and the user manual. + + Download and unzip locally for AI coding agents or environments with restricted internet access." + + # delete existing release if present so we can recreate it + gh release delete "$TAG" --yes 2>/dev/null || true + + gh release create "$TAG" "$FILE" \ + --title "$TITLE" \ + --notes "$NOTES" \ + --latest=false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/llms-txt-template.md b/llms-txt-template.md index badf76d9..e56d8fe5 100644 --- a/llms-txt-template.md +++ b/llms-txt-template.md @@ -7,6 +7,14 @@ For example: - HTML: `https://camel.apache.org/components/next/languages/simple-language.html` - Markdown: `https://camel.apache.org/components/next/languages/simple-language.md` +## Offline documentation bundles + +For agents or environments with no or restricted internet access, versioned offline documentation bundles are available as zip archives of all Markdown files: +- [Camel 4.18](https://github.com/apache/camel-website/releases/download/docs-4.18/camel-docs-4.18.zip) +- [Camel 4.14](https://github.com/apache/camel-website/releases/download/docs-4.14/camel-docs-4.14.zip) + +Download the zip matching your Camel version, unzip it locally, and read the `.md` files from there. Each bundle preserves the site directory structure and includes components, Spring Boot starters, Kamelets, and the user manual. + ## Key facts - Apache Camel is a **library**, not a platform — it embeds in your existing Spring Boot or Quarkus application diff --git a/scripts/generate-offline-bundle.js b/scripts/generate-offline-bundle.js new file mode 100644 index 00000000..abf2bd5d --- /dev/null +++ b/scripts/generate-offline-bundle.js @@ -0,0 +1,91 @@ +const fs = require('fs'); +const path = require('path'); +const { execFileSync } = require('child_process'); + +const PUBLIC_DIR = 'public'; + +const VERSION_DIRS = [ + 'components', + 'camel-spring-boot', + 'camel-kamelets' +]; + +const SHARED_DIRS = [ + 'manual' +]; + +function main() { + const version = process.argv[2]; + if (!version) { + console.error('Usage: node scripts/generate-offline-bundle.js <version>'); + console.error('Example: node scripts/generate-offline-bundle.js 4.18'); + process.exit(1); + } + + const versionDir = `${version}.x`; + const bundleName = `camel-docs-${version}.zip`; + const bundlePath = path.join(PUBLIC_DIR, bundleName); + + if (!fs.existsSync(PUBLIC_DIR)) { + console.error(`Cannot generate ${bundleName}: '${PUBLIC_DIR}' directory not found`); + process.exit(1); + } + + // collect paths to include (relative to public/) + const includePaths = []; + + for (const dir of VERSION_DIRS) { + const fullPath = path.join(PUBLIC_DIR, dir, versionDir); + if (fs.existsSync(fullPath)) { + includePaths.push(`${dir}/${versionDir}/*`); + console.log(` Including ${dir}/${versionDir}/`); + } else { + console.warn(` Skipping ${dir}/${versionDir}/ (not found)`); + } + } + + for (const dir of SHARED_DIRS) { + const fullPath = path.join(PUBLIC_DIR, dir); + if (fs.existsSync(fullPath)) { + includePaths.push(`${dir}/*`); + console.log(` Including ${dir}/`); + } + } + + if (includePaths.length === 0) { + console.error(`No documentation directories found for version ${version}`); + process.exit(1); + } + + // always include llms.txt if present + if (fs.existsSync(path.join(PUBLIC_DIR, 'llms.txt'))) { + includePaths.push('llms.txt'); + } + + // remove stale bundle + if (fs.existsSync(bundlePath)) { + fs.unlinkSync(bundlePath); + } + + // build zip: include only .md files from the selected directories, plus llms.txt + const zipArgs = ['-r', '-q', bundleName, '.']; + for (const p of includePaths) { + if (p === 'llms.txt') { + zipArgs.push('-i', 'llms.txt'); + } else { + zipArgs.push('-i', `${p}.md`); + } + } + + try { + execFileSync('zip', zipArgs, { cwd: PUBLIC_DIR, stdio: 'inherit' }); + + const sizeMb = (fs.statSync(bundlePath).size / (1024 * 1024)).toFixed(1); + console.log(`Generated ${bundleName} (${sizeMb} MB)`); + } catch (error) { + console.error(`Failed to generate ${bundleName}:`, error.message); + process.exit(1); + } +} + +main();
