Merge pull request #172 from svc-design/codex/provide-offline-packages-for-dify,-n8n,-ragflow,-flowise,-au

Add workflows to build offline packages for new AI apps
This commit is contained in:
shenlan 2025-10-11 19:02:14 +08:00 committed by GitHub
commit 86e8fadf75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 1489 additions and 0 deletions

View File

@ -0,0 +1,159 @@
name: Build Offline AutoGen Studio Installer
on:
push:
paths:
- 'gitops/scripts/autogen-studio/**'
- '.github/workflows/offline-package-autogen-studio.yaml'
workflow_dispatch:
inputs:
tag:
description: "Release tag to use/sync (e.g., v0.1.0). Leave empty to use offline-autogen-studio-<run_number>"
required: false
type: string
autogen_tag:
description: "AutoGen Studio container tag (default: latest)"
required: false
type: string
permissions:
contents: write
concurrency:
group: build-offline-autogen-studio
cancel-in-progress: false
jobs:
build-offline-installer:
strategy:
matrix:
arch: [amd64, arm64]
runs-on: ubuntu-latest
outputs:
autogen_tag: ${{ steps.resolve.outputs.autogen_tag }}
steps:
- uses: actions/checkout@v4
- name: Resolve image tag
id: resolve
env:
INPUT_AUTOGEN_TAG: ${{ github.event.inputs.autogen_tag }}
run: |
set -euo pipefail
AUTOGEN_TAG=${INPUT_AUTOGEN_TAG:-latest}
echo "autogen_tag=${AUTOGEN_TAG}" >> "$GITHUB_OUTPUT"
- name: Prepare directories
run: |
set -euo pipefail
rm -rf offline-installer
mkdir -p offline-installer/{images,scripts}
- name: Stage compose file and scripts
env:
AUTOGEN_TAG: ${{ steps.resolve.outputs.autogen_tag }}
run: |
set -euo pipefail
cp gitops/scripts/autogen-studio/docker-compose.yaml offline-installer/docker-compose.yaml
sed -i "s/__AUTOGEN_TAG__/${AUTOGEN_TAG}/g" offline-installer/docker-compose.yaml
cp gitops/scripts/autogen-studio/deploy-autogen-studio.sh offline-installer/scripts/
chmod +x offline-installer/scripts/deploy-autogen-studio.sh
cat <<'README' > offline-installer/README.md
# Offline AutoGen Studio Installer
This archive contains container images and helper assets for deploying AutoGen Studio with Docker Compose.
## Contents
- `docker-compose.yaml`: Reference deployment manifest configured for the packaged images.
- `images/`: Pre-pulled container images saved as tar archives.
- `scripts/deploy-autogen-studio.sh`: Helper script to load the images and manage the compose stack.
## Usage
1. Extract the archive on a host with Docker/nerdctl available.
2. (Optional) Run `IMAGE_LOAD_TOOL=nerdctl ./scripts/deploy-autogen-studio.sh load-images` to import the images with nerdctl.
3. Start the stack: `./scripts/deploy-autogen-studio.sh up`.
4. Access AutoGen Studio at http://localhost:9090.
Adjust the compose file as needed before running the helper script.
README
- name: Pull & export container images
env:
AUTOGEN_TAG: ${{ steps.resolve.outputs.autogen_tag }}
run: |
set -euo pipefail
image="autogenstudio/autogen-studio:${AUTOGEN_TAG}"
docker pull "$image"
safe=$(echo "$image" | tr '/:' '-_')
docker save "$image" -o "offline-installer/images/${safe}.tar"
- name: Package offline installer
run: |
set -euo pipefail
tar -czf offline-package-autogen-studio-${{ matrix.arch }}.tar.gz -C offline-installer .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: offline-package-autogen-studio-${{ matrix.arch }}
path: offline-package-autogen-studio-${{ matrix.arch }}.tar.gz
test-offline-installer:
needs: build-offline-installer
strategy:
matrix:
arch: [amd64]
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: offline-package-autogen-studio-${{ matrix.arch }}
path: offline-test
- name: Verify archive integrity
run: |
set -euo pipefail
cd offline-test
tar -tzf offline-package-autogen-studio-${{ matrix.arch }}.tar.gz > /dev/null
publish-release:
needs: test-offline-installer
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.event.inputs.tag != '' && github.event.inputs.tag || format('offline-autogen-studio-{0}', github.run_number) }}
steps:
- uses: actions/checkout@v4
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
release_name: Build ${{ env.TAG_NAME }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download amd64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-autogen-studio-amd64
path: release-artifacts/amd64
- name: Download arm64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-autogen-studio-arm64
path: release-artifacts/arm64
- name: Upload offline installers to GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
files: |
release-artifacts/amd64/offline-package-autogen-studio-amd64.tar.gz
release-artifacts/arm64/offline-package-autogen-studio-arm64.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,192 @@
name: Build Offline Dify Installer
on:
push:
paths:
- 'gitops/scripts/dify/**'
- '.github/workflows/offline-package-dify.yaml'
workflow_dispatch:
inputs:
tag:
description: "Release tag to use/sync (e.g., v0.1.0). Leave empty to use offline-dify-<run_number>"
required: false
type: string
dify_tag:
description: "Dify container tag (default: latest)"
required: false
type: string
postgres_tag:
description: "Postgres image tag (default: 15-alpine)"
required: false
type: string
redis_tag:
description: "Redis image tag (default: 7-alpine)"
required: false
type: string
permissions:
contents: write
concurrency:
group: build-offline-dify
cancel-in-progress: false
jobs:
build-offline-installer:
strategy:
matrix:
arch: [amd64, arm64]
runs-on: ubuntu-latest
outputs:
dify_tag: ${{ steps.resolve.outputs.dify_tag }}
postgres_tag: ${{ steps.resolve.outputs.postgres_tag }}
redis_tag: ${{ steps.resolve.outputs.redis_tag }}
steps:
- uses: actions/checkout@v4
- name: Resolve image tags
id: resolve
env:
INPUT_DIFY_TAG: ${{ github.event.inputs.dify_tag }}
INPUT_POSTGRES_TAG: ${{ github.event.inputs.postgres_tag }}
INPUT_REDIS_TAG: ${{ github.event.inputs.redis_tag }}
run: |
set -euo pipefail
DIFY_TAG=${INPUT_DIFY_TAG:-latest}
POSTGRES_TAG=${INPUT_POSTGRES_TAG:-15-alpine}
REDIS_TAG=${INPUT_REDIS_TAG:-7-alpine}
{
echo "dify_tag=${DIFY_TAG}"
echo "postgres_tag=${POSTGRES_TAG}"
echo "redis_tag=${REDIS_TAG}"
} >> "$GITHUB_OUTPUT"
- name: Prepare directories
run: |
set -euo pipefail
rm -rf offline-installer
mkdir -p offline-installer/{images,scripts}
- name: Stage compose file and scripts
env:
DIFY_TAG: ${{ steps.resolve.outputs.dify_tag }}
POSTGRES_TAG: ${{ steps.resolve.outputs.postgres_tag }}
REDIS_TAG: ${{ steps.resolve.outputs.redis_tag }}
run: |
set -euo pipefail
cp gitops/scripts/dify/docker-compose.yaml offline-installer/docker-compose.yaml
sed -i "s/__DIFY_TAG__/${DIFY_TAG}/g" offline-installer/docker-compose.yaml
sed -i "s/__POSTGRES_TAG__/${POSTGRES_TAG}/g" offline-installer/docker-compose.yaml
sed -i "s/__REDIS_TAG__/${REDIS_TAG}/g" offline-installer/docker-compose.yaml
cp gitops/scripts/dify/deploy-dify.sh offline-installer/scripts/
chmod +x offline-installer/scripts/deploy-dify.sh
cat <<'README' > offline-installer/README.md
# Offline Dify Installer
This archive contains container images and helper assets for deploying Dify with Docker Compose.
## Contents
- `docker-compose.yaml`: Reference deployment manifest configured for the packaged images.
- `images/`: Pre-pulled container images saved as tar archives.
- `scripts/deploy-dify.sh`: Helper script to load the images and manage the compose stack.
## Usage
1. Extract the archive on a host with Docker/nerdctl available.
2. (Optional) Run `IMAGE_LOAD_TOOL=nerdctl ./scripts/deploy-dify.sh load-images` to import the images with nerdctl.
3. Start the stack: `./scripts/deploy-dify.sh up`.
4. Access the Dify web UI at http://localhost:8080.
Adjust the compose file as needed before running the helper script.
README
- name: Pull & export container images
env:
DIFY_TAG: ${{ steps.resolve.outputs.dify_tag }}
POSTGRES_TAG: ${{ steps.resolve.outputs.postgres_tag }}
REDIS_TAG: ${{ steps.resolve.outputs.redis_tag }}
run: |
set -euo pipefail
images=(
"langgenius/dify-api:${DIFY_TAG}"
"langgenius/dify-worker:${DIFY_TAG}"
"langgenius/dify-web:${DIFY_TAG}"
"langgenius/dify-nginx:${DIFY_TAG}"
"postgres:${POSTGRES_TAG}"
"redis:${REDIS_TAG}"
)
for image in "${images[@]}"; do
docker pull "$image"
safe=$(echo "$image" | tr '/:' '-_')
docker save "$image" -o "offline-installer/images/${safe}.tar"
done
- name: Package offline installer
run: |
set -euo pipefail
tar -czf offline-package-dify-${{ matrix.arch }}.tar.gz -C offline-installer .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: offline-package-dify-${{ matrix.arch }}
path: offline-package-dify-${{ matrix.arch }}.tar.gz
test-offline-installer:
needs: build-offline-installer
strategy:
matrix:
arch: [amd64]
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: offline-package-dify-${{ matrix.arch }}
path: offline-test
- name: Verify archive integrity
run: |
set -euo pipefail
cd offline-test
tar -tzf offline-package-dify-${{ matrix.arch }}.tar.gz > /dev/null
publish-release:
needs: test-offline-installer
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.event.inputs.tag != '' && github.event.inputs.tag || format('offline-dify-{0}', github.run_number) }}
steps:
- uses: actions/checkout@v4
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
release_name: Build ${{ env.TAG_NAME }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download amd64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-dify-amd64
path: release-artifacts/amd64
- name: Download arm64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-dify-arm64
path: release-artifacts/arm64
- name: Upload offline installers to GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
files: |
release-artifacts/amd64/offline-package-dify-amd64.tar.gz
release-artifacts/arm64/offline-package-dify-arm64.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,159 @@
name: Build Offline Flowise Installer
on:
push:
paths:
- 'gitops/scripts/flowise/**'
- '.github/workflows/offline-package-flowise.yaml'
workflow_dispatch:
inputs:
tag:
description: "Release tag to use/sync (e.g., v0.1.0). Leave empty to use offline-flowise-<run_number>"
required: false
type: string
flowise_tag:
description: "Flowise container tag (default: latest)"
required: false
type: string
permissions:
contents: write
concurrency:
group: build-offline-flowise
cancel-in-progress: false
jobs:
build-offline-installer:
strategy:
matrix:
arch: [amd64, arm64]
runs-on: ubuntu-latest
outputs:
flowise_tag: ${{ steps.resolve.outputs.flowise_tag }}
steps:
- uses: actions/checkout@v4
- name: Resolve image tag
id: resolve
env:
INPUT_FLOWISE_TAG: ${{ github.event.inputs.flowise_tag }}
run: |
set -euo pipefail
FLOWISE_TAG=${INPUT_FLOWISE_TAG:-latest}
echo "flowise_tag=${FLOWISE_TAG}" >> "$GITHUB_OUTPUT"
- name: Prepare directories
run: |
set -euo pipefail
rm -rf offline-installer
mkdir -p offline-installer/{images,scripts}
- name: Stage compose file and scripts
env:
FLOWISE_TAG: ${{ steps.resolve.outputs.flowise_tag }}
run: |
set -euo pipefail
cp gitops/scripts/flowise/docker-compose.yaml offline-installer/docker-compose.yaml
sed -i "s/__FLOWISE_TAG__/${FLOWISE_TAG}/g" offline-installer/docker-compose.yaml
cp gitops/scripts/flowise/deploy-flowise.sh offline-installer/scripts/
chmod +x offline-installer/scripts/deploy-flowise.sh
cat <<'README' > offline-installer/README.md
# Offline Flowise Installer
This archive contains container images and helper assets for deploying Flowise with Docker Compose.
## Contents
- `docker-compose.yaml`: Reference deployment manifest configured for the packaged images.
- `images/`: Pre-pulled container images saved as tar archives.
- `scripts/deploy-flowise.sh`: Helper script to load the images and manage the compose stack.
## Usage
1. Extract the archive on a host with Docker/nerdctl available.
2. (Optional) Run `IMAGE_LOAD_TOOL=nerdctl ./scripts/deploy-flowise.sh load-images` to import the images with nerdctl.
3. Start the stack: `./scripts/deploy-flowise.sh up`.
4. Access the Flowise UI at http://localhost:3000.
Adjust the compose file as needed before running the helper script.
README
- name: Pull & export container images
env:
FLOWISE_TAG: ${{ steps.resolve.outputs.flowise_tag }}
run: |
set -euo pipefail
image="flowiseai/flowise:${FLOWISE_TAG}"
docker pull "$image"
safe=$(echo "$image" | tr '/:' '-_')
docker save "$image" -o "offline-installer/images/${safe}.tar"
- name: Package offline installer
run: |
set -euo pipefail
tar -czf offline-package-flowise-${{ matrix.arch }}.tar.gz -C offline-installer .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: offline-package-flowise-${{ matrix.arch }}
path: offline-package-flowise-${{ matrix.arch }}.tar.gz
test-offline-installer:
needs: build-offline-installer
strategy:
matrix:
arch: [amd64]
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: offline-package-flowise-${{ matrix.arch }}
path: offline-test
- name: Verify archive integrity
run: |
set -euo pipefail
cd offline-test
tar -tzf offline-package-flowise-${{ matrix.arch }}.tar.gz > /dev/null
publish-release:
needs: test-offline-installer
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.event.inputs.tag != '' && github.event.inputs.tag || format('offline-flowise-{0}', github.run_number) }}
steps:
- uses: actions/checkout@v4
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
release_name: Build ${{ env.TAG_NAME }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download amd64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-flowise-amd64
path: release-artifacts/amd64
- name: Download arm64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-flowise-arm64
path: release-artifacts/arm64
- name: Upload offline installers to GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
files: |
release-artifacts/amd64/offline-package-flowise-amd64.tar.gz
release-artifacts/arm64/offline-package-flowise-arm64.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,177 @@
name: Build Offline n8n Installer
on:
push:
paths:
- 'gitops/scripts/n8n/**'
- '.github/workflows/offline-package-n8n.yaml'
workflow_dispatch:
inputs:
tag:
description: "Release tag to use/sync (e.g., v0.1.0). Leave empty to use offline-n8n-<run_number>"
required: false
type: string
n8n_tag:
description: "n8n container tag (default: latest)"
required: false
type: string
postgres_tag:
description: "Postgres image tag (default: 15-alpine)"
required: false
type: string
permissions:
contents: write
concurrency:
group: build-offline-n8n
cancel-in-progress: false
jobs:
build-offline-installer:
strategy:
matrix:
arch: [amd64, arm64]
runs-on: ubuntu-latest
outputs:
n8n_tag: ${{ steps.resolve.outputs.n8n_tag }}
postgres_tag: ${{ steps.resolve.outputs.postgres_tag }}
steps:
- uses: actions/checkout@v4
- name: Resolve image tags
id: resolve
env:
INPUT_N8N_TAG: ${{ github.event.inputs.n8n_tag }}
INPUT_POSTGRES_TAG: ${{ github.event.inputs.postgres_tag }}
run: |
set -euo pipefail
N8N_TAG=${INPUT_N8N_TAG:-latest}
POSTGRES_TAG=${INPUT_POSTGRES_TAG:-15-alpine}
{
echo "n8n_tag=${N8N_TAG}"
echo "postgres_tag=${POSTGRES_TAG}"
} >> "$GITHUB_OUTPUT"
- name: Prepare directories
run: |
set -euo pipefail
rm -rf offline-installer
mkdir -p offline-installer/{images,scripts}
- name: Stage compose file and scripts
env:
N8N_TAG: ${{ steps.resolve.outputs.n8n_tag }}
POSTGRES_TAG: ${{ steps.resolve.outputs.postgres_tag }}
run: |
set -euo pipefail
cp gitops/scripts/n8n/docker-compose.yaml offline-installer/docker-compose.yaml
sed -i "s/__N8N_TAG__/${N8N_TAG}/g" offline-installer/docker-compose.yaml
sed -i "s/__POSTGRES_TAG__/${POSTGRES_TAG}/g" offline-installer/docker-compose.yaml
cp gitops/scripts/n8n/deploy-n8n.sh offline-installer/scripts/
chmod +x offline-installer/scripts/deploy-n8n.sh
cat <<'README' > offline-installer/README.md
# Offline n8n Installer
This archive contains container images and helper assets for deploying n8n with Docker Compose.
## Contents
- `docker-compose.yaml`: Reference deployment manifest configured for the packaged images.
- `images/`: Pre-pulled container images saved as tar archives.
- `scripts/deploy-n8n.sh`: Helper script to load the images and manage the compose stack.
## Usage
1. Extract the archive on a host with Docker/nerdctl available.
2. (Optional) Run `IMAGE_LOAD_TOOL=nerdctl ./scripts/deploy-n8n.sh load-images` to import the images with nerdctl.
3. Start the stack: `./scripts/deploy-n8n.sh up`.
4. Access the n8n UI at http://localhost:5678.
Adjust the compose file as needed before running the helper script.
README
- name: Pull & export container images
env:
N8N_TAG: ${{ steps.resolve.outputs.n8n_tag }}
POSTGRES_TAG: ${{ steps.resolve.outputs.postgres_tag }}
run: |
set -euo pipefail
images=(
"n8nio/n8n:${N8N_TAG}"
"postgres:${POSTGRES_TAG}"
)
for image in "${images[@]}"; do
docker pull "$image"
safe=$(echo "$image" | tr '/:' '-_')
docker save "$image" -o "offline-installer/images/${safe}.tar"
done
- name: Package offline installer
run: |
set -euo pipefail
tar -czf offline-package-n8n-${{ matrix.arch }}.tar.gz -C offline-installer .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: offline-package-n8n-${{ matrix.arch }}
path: offline-package-n8n-${{ matrix.arch }}.tar.gz
test-offline-installer:
needs: build-offline-installer
strategy:
matrix:
arch: [amd64]
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: offline-package-n8n-${{ matrix.arch }}
path: offline-test
- name: Verify archive integrity
run: |
set -euo pipefail
cd offline-test
tar -tzf offline-package-n8n-${{ matrix.arch }}.tar.gz > /dev/null
publish-release:
needs: test-offline-installer
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.event.inputs.tag != '' && github.event.inputs.tag || format('offline-n8n-{0}', github.run_number) }}
steps:
- uses: actions/checkout@v4
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
release_name: Build ${{ env.TAG_NAME }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download amd64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-n8n-amd64
path: release-artifacts/amd64
- name: Download arm64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-n8n-arm64
path: release-artifacts/arm64
- name: Upload offline installers to GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
files: |
release-artifacts/amd64/offline-package-n8n-amd64.tar.gz
release-artifacts/arm64/offline-package-n8n-arm64.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,189 @@
name: Build Offline RAGFlow Installer
on:
push:
paths:
- 'gitops/scripts/ragflow/**'
- '.github/workflows/offline-package-ragflow.yaml'
workflow_dispatch:
inputs:
tag:
description: "Release tag to use/sync (e.g., v0.1.0). Leave empty to use offline-ragflow-<run_number>"
required: false
type: string
ragflow_tag:
description: "RAGFlow container tag (default: latest)"
required: false
type: string
postgres_tag:
description: "Postgres image tag (default: 15-alpine)"
required: false
type: string
redis_tag:
description: "Redis image tag (default: 7-alpine)"
required: false
type: string
permissions:
contents: write
concurrency:
group: build-offline-ragflow
cancel-in-progress: false
jobs:
build-offline-installer:
strategy:
matrix:
arch: [amd64, arm64]
runs-on: ubuntu-latest
outputs:
ragflow_tag: ${{ steps.resolve.outputs.ragflow_tag }}
postgres_tag: ${{ steps.resolve.outputs.postgres_tag }}
redis_tag: ${{ steps.resolve.outputs.redis_tag }}
steps:
- uses: actions/checkout@v4
- name: Resolve image tags
id: resolve
env:
INPUT_RAGFLOW_TAG: ${{ github.event.inputs.ragflow_tag }}
INPUT_POSTGRES_TAG: ${{ github.event.inputs.postgres_tag }}
INPUT_REDIS_TAG: ${{ github.event.inputs.redis_tag }}
run: |
set -euo pipefail
RAGFLOW_TAG=${INPUT_RAGFLOW_TAG:-latest}
POSTGRES_TAG=${INPUT_POSTGRES_TAG:-15-alpine}
REDIS_TAG=${INPUT_REDIS_TAG:-7-alpine}
{
echo "ragflow_tag=${RAGFLOW_TAG}"
echo "postgres_tag=${POSTGRES_TAG}"
echo "redis_tag=${REDIS_TAG}"
} >> "$GITHUB_OUTPUT"
- name: Prepare directories
run: |
set -euo pipefail
rm -rf offline-installer
mkdir -p offline-installer/{images,scripts}
- name: Stage compose file and scripts
env:
RAGFLOW_TAG: ${{ steps.resolve.outputs.ragflow_tag }}
POSTGRES_TAG: ${{ steps.resolve.outputs.postgres_tag }}
REDIS_TAG: ${{ steps.resolve.outputs.redis_tag }}
run: |
set -euo pipefail
cp gitops/scripts/ragflow/docker-compose.yaml offline-installer/docker-compose.yaml
sed -i "s/__RAGFLOW_TAG__/${RAGFLOW_TAG}/g" offline-installer/docker-compose.yaml
sed -i "s/__POSTGRES_TAG__/${POSTGRES_TAG}/g" offline-installer/docker-compose.yaml
sed -i "s/__REDIS_TAG__/${REDIS_TAG}/g" offline-installer/docker-compose.yaml
cp gitops/scripts/ragflow/deploy-ragflow.sh offline-installer/scripts/
chmod +x offline-installer/scripts/deploy-ragflow.sh
cat <<'README' > offline-installer/README.md
# Offline RAGFlow Installer
This archive contains container images and helper assets for deploying RAGFlow with Docker Compose.
## Contents
- `docker-compose.yaml`: Reference deployment manifest configured for the packaged images.
- `images/`: Pre-pulled container images saved as tar archives.
- `scripts/deploy-ragflow.sh`: Helper script to load the images and manage the compose stack.
## Usage
1. Extract the archive on a host with Docker/nerdctl available.
2. (Optional) Run `IMAGE_LOAD_TOOL=nerdctl ./scripts/deploy-ragflow.sh load-images` to import the images with nerdctl.
3. Start the stack: `./scripts/deploy-ragflow.sh up`.
4. Access the RAGFlow UI at http://localhost:3001.
Adjust the compose file as needed before running the helper script. Configure external vector stores or storage services as required by your deployment.
README
- name: Pull & export container images
env:
RAGFLOW_TAG: ${{ steps.resolve.outputs.ragflow_tag }}
POSTGRES_TAG: ${{ steps.resolve.outputs.postgres_tag }}
REDIS_TAG: ${{ steps.resolve.outputs.redis_tag }}
run: |
set -euo pipefail
images=(
"ragflow/ragflow:${RAGFLOW_TAG}"
"postgres:${POSTGRES_TAG}"
"redis:${REDIS_TAG}"
)
for image in "${images[@]}"; do
docker pull "$image"
safe=$(echo "$image" | tr '/:' '-_')
docker save "$image" -o "offline-installer/images/${safe}.tar"
done
- name: Package offline installer
run: |
set -euo pipefail
tar -czf offline-package-ragflow-${{ matrix.arch }}.tar.gz -C offline-installer .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: offline-package-ragflow-${{ matrix.arch }}
path: offline-package-ragflow-${{ matrix.arch }}.tar.gz
test-offline-installer:
needs: build-offline-installer
strategy:
matrix:
arch: [amd64]
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: offline-package-ragflow-${{ matrix.arch }}
path: offline-test
- name: Verify archive integrity
run: |
set -euo pipefail
cd offline-test
tar -tzf offline-package-ragflow-${{ matrix.arch }}.tar.gz > /dev/null
publish-release:
needs: test-offline-installer
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.event.inputs.tag != '' && github.event.inputs.tag || format('offline-ragflow-{0}', github.run_number) }}
steps:
- uses: actions/checkout@v4
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
release_name: Build ${{ env.TAG_NAME }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download amd64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-ragflow-amd64
path: release-artifacts/amd64
- name: Download arm64 artifact
uses: actions/download-artifact@v4
with:
name: offline-package-ragflow-arm64
path: release-artifacts/arm64
- name: Upload offline installers to GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.TAG_NAME }}
files: |
release-artifacts/amd64/offline-package-ragflow-amd64.tar.gz
release-artifacts/arm64/offline-package-ragflow-arm64.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="AutoGen Studio"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
OFFLINE_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
COMPOSE_FILE="${OFFLINE_ROOT}/docker-compose.yaml"
IMAGES_DIR="${OFFLINE_ROOT}/images"
IMAGE_LOAD_TOOL="${IMAGE_LOAD_TOOL:-docker}"
command_exists() {
command -v "$1" >/dev/null 2>&1
}
load_images() {
if ! command_exists "${IMAGE_LOAD_TOOL}"; then
echo "Error: image loader '${IMAGE_LOAD_TOOL}' not found in PATH" >&2
exit 1
fi
if [ ! -d "${IMAGES_DIR}" ]; then
echo "No images directory found at ${IMAGES_DIR}. Skipping image load." >&2
return
fi
shopt -s nullglob
local tarball
for tarball in "${IMAGES_DIR}"/*.tar; do
echo "Loading container images from ${tarball}"
"${IMAGE_LOAD_TOOL}" load -i "${tarball}"
done
shopt -u nullglob
}
compose() {
if command_exists docker && docker compose version >/dev/null 2>&1; then
docker compose "$@"
elif command_exists docker-compose; then
docker-compose "$@"
else
echo "Error: docker compose plugin or docker-compose binary is required" >&2
exit 1
fi
}
usage() {
cat <<USAGE
Usage: $(basename "$0") [command]
Commands:
up Load images (if available) and start ${APP_NAME}
down Stop ${APP_NAME}
load-images Only load container images from the images/ directory
status Show status of the compose application
Environment variables:
IMAGE_LOAD_TOOL Override the container image loader (default: docker)
COMPOSE_FILE Override docker compose file path (default: ${COMPOSE_FILE})
USAGE
}
cmd=${1:-up}
case "${cmd}" in
up)
load_images
compose -f "${COMPOSE_FILE}" up -d
;;
down)
compose -f "${COMPOSE_FILE}" down
;;
load-images)
load_images
;;
status)
compose -f "${COMPOSE_FILE}" ps
;;
-h|--help|help)
usage
;;
*)
echo "Unknown command: ${cmd}" >&2
usage
exit 1
;;
esac

View File

@ -0,0 +1,18 @@
version: "3.8"
services:
autogen-studio:
image: autogenstudio/autogen-studio:__AUTOGEN_TAG__
container_name: autogen-studio
restart: unless-stopped
ports:
- "9090:9090"
environment:
AUTOGEN_STUDIO_HOST: 0.0.0.0
AUTOGEN_STUDIO_PORT: 9090
AUTOGEN_STUDIO_LOG_LEVEL: info
volumes:
- autogen-data:/data
volumes:
autogen-data:

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="Dify"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
OFFLINE_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
COMPOSE_FILE="${OFFLINE_ROOT}/docker-compose.yaml"
IMAGES_DIR="${OFFLINE_ROOT}/images"
IMAGE_LOAD_TOOL="${IMAGE_LOAD_TOOL:-docker}"
command_exists() {
command -v "$1" >/dev/null 2>&1
}
load_images() {
if ! command_exists "${IMAGE_LOAD_TOOL}"; then
echo "Error: image loader '${IMAGE_LOAD_TOOL}' not found in PATH" >&2
exit 1
fi
if [ ! -d "${IMAGES_DIR}" ]; then
echo "No images directory found at ${IMAGES_DIR}. Skipping image load." >&2
return
fi
shopt -s nullglob
local tarball
for tarball in "${IMAGES_DIR}"/*.tar; do
echo "Loading container images from ${tarball}"
"${IMAGE_LOAD_TOOL}" load -i "${tarball}"
done
shopt -u nullglob
}
compose() {
if command_exists docker && docker compose version >/dev/null 2>&1; then
docker compose "$@"
elif command_exists docker-compose; then
docker-compose "$@"
else
echo "Error: docker compose plugin or docker-compose binary is required" >&2
exit 1
fi
}
usage() {
cat <<USAGE
Usage: $(basename "$0") [command]
Commands:
up Load images (if available) and start ${APP_NAME}
down Stop ${APP_NAME}
load-images Only load container images from the images/ directory
status Show status of the compose application
Environment variables:
IMAGE_LOAD_TOOL Override the container image loader (default: docker)
COMPOSE_FILE Override docker compose file path (default: ${COMPOSE_FILE})
USAGE
}
cmd=${1:-up}
case "${cmd}" in
up)
load_images
compose -f "${COMPOSE_FILE}" up -d
;;
down)
compose -f "${COMPOSE_FILE}" down
;;
load-images)
load_images
;;
status)
compose -f "${COMPOSE_FILE}" ps
;;
-h|--help|help)
usage
;;
*)
echo "Unknown command: ${cmd}" >&2
usage
exit 1
;;
esac

View File

@ -0,0 +1,72 @@
version: "3.8"
services:
postgres:
image: postgres:__POSTGRES_TAG__
container_name: dify-postgres
restart: unless-stopped
environment:
POSTGRES_DB: dify
POSTGRES_USER: dify
POSTGRES_PASSWORD: dify
volumes:
- dify-postgres:/var/lib/postgresql/data
redis:
image: redis:__REDIS_TAG__
container_name: dify-redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"]
volumes:
- dify-redis:/data
dify-api:
image: langgenius/dify-api:__DIFY_TAG__
container_name: dify-api
restart: unless-stopped
depends_on:
- postgres
- redis
environment:
DATABASE_URL: postgresql+psycopg://dify:dify@postgres:5432/dify
REDIS_URL: redis://redis:6379/0
WEB_URL: http://localhost:8080
WORKER_QUEUE_BROKER_URL: redis://redis:6379/1
WORKER_QUEUE_BACKEND_URL: redis://redis:6379/2
volumes:
- dify-storage:/app/storage
dify-worker:
image: langgenius/dify-worker:__DIFY_TAG__
container_name: dify-worker
restart: unless-stopped
depends_on:
- redis
- dify-api
environment:
REDIS_URL: redis://redis:6379/1
WORKER_QUEUE_BACKEND_URL: redis://redis:6379/2
API_URL: http://dify-api:5001
dify-web:
image: langgenius/dify-web:__DIFY_TAG__
container_name: dify-web
restart: unless-stopped
depends_on:
- dify-api
environment:
VITE_API_URL: http://dify-nginx
VITE_APP_ENV: production
dify-nginx:
image: langgenius/dify-nginx:__DIFY_TAG__
container_name: dify-nginx
restart: unless-stopped
ports:
- "8080:80"
depends_on:
- dify-api
- dify-web
environment:
API_HOST: dify-api:5001
WEB_HOST: dify-web:3000
volumes:
dify-postgres:
dify-redis:
dify-storage:

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="Flowise"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
OFFLINE_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
COMPOSE_FILE="${OFFLINE_ROOT}/docker-compose.yaml"
IMAGES_DIR="${OFFLINE_ROOT}/images"
IMAGE_LOAD_TOOL="${IMAGE_LOAD_TOOL:-docker}"
command_exists() {
command -v "$1" >/dev/null 2>&1
}
load_images() {
if ! command_exists "${IMAGE_LOAD_TOOL}"; then
echo "Error: image loader '${IMAGE_LOAD_TOOL}' not found in PATH" >&2
exit 1
fi
if [ ! -d "${IMAGES_DIR}" ]; then
echo "No images directory found at ${IMAGES_DIR}. Skipping image load." >&2
return
fi
shopt -s nullglob
local tarball
for tarball in "${IMAGES_DIR}"/*.tar; do
echo "Loading container images from ${tarball}"
"${IMAGE_LOAD_TOOL}" load -i "${tarball}"
done
shopt -u nullglob
}
compose() {
if command_exists docker && docker compose version >/dev/null 2>&1; then
docker compose "$@"
elif command_exists docker-compose; then
docker-compose "$@"
else
echo "Error: docker compose plugin or docker-compose binary is required" >&2
exit 1
fi
}
usage() {
cat <<USAGE
Usage: $(basename "$0") [command]
Commands:
up Load images (if available) and start ${APP_NAME}
down Stop ${APP_NAME}
load-images Only load container images from the images/ directory
status Show status of the compose application
Environment variables:
IMAGE_LOAD_TOOL Override the container image loader (default: docker)
COMPOSE_FILE Override docker compose file path (default: ${COMPOSE_FILE})
USAGE
}
cmd=${1:-up}
case "${cmd}" in
up)
load_images
compose -f "${COMPOSE_FILE}" up -d
;;
down)
compose -f "${COMPOSE_FILE}" down
;;
load-images)
load_images
;;
status)
compose -f "${COMPOSE_FILE}" ps
;;
-h|--help|help)
usage
;;
*)
echo "Unknown command: ${cmd}" >&2
usage
exit 1
;;
esac

View File

@ -0,0 +1,19 @@
version: "3.8"
services:
flowise:
image: flowiseai/flowise:__FLOWISE_TAG__
container_name: flowise-app
restart: unless-stopped
ports:
- "3000:3000"
environment:
PORT: 3000
FLOWISE_USERNAME: admin
FLOWISE_PASSWORD: changeme
DATABASE_PATH: /data/flowise.sqlite
volumes:
- flowise-data:/data
volumes:
flowise-data:

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="n8n"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
OFFLINE_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
COMPOSE_FILE="${OFFLINE_ROOT}/docker-compose.yaml"
IMAGES_DIR="${OFFLINE_ROOT}/images"
IMAGE_LOAD_TOOL="${IMAGE_LOAD_TOOL:-docker}"
command_exists() {
command -v "$1" >/dev/null 2>&1
}
load_images() {
if ! command_exists "${IMAGE_LOAD_TOOL}"; then
echo "Error: image loader '${IMAGE_LOAD_TOOL}' not found in PATH" >&2
exit 1
fi
if [ ! -d "${IMAGES_DIR}" ]; then
echo "No images directory found at ${IMAGES_DIR}. Skipping image load." >&2
return
fi
shopt -s nullglob
local tarball
for tarball in "${IMAGES_DIR}"/*.tar; do
echo "Loading container images from ${tarball}"
"${IMAGE_LOAD_TOOL}" load -i "${tarball}"
done
shopt -u nullglob
}
compose() {
if command_exists docker && docker compose version >/dev/null 2>&1; then
docker compose "$@"
elif command_exists docker-compose; then
docker-compose "$@"
else
echo "Error: docker compose plugin or docker-compose binary is required" >&2
exit 1
fi
}
usage() {
cat <<USAGE
Usage: $(basename "$0") [command]
Commands:
up Load images (if available) and start ${APP_NAME}
down Stop ${APP_NAME}
load-images Only load container images from the images/ directory
status Show status of the compose application
Environment variables:
IMAGE_LOAD_TOOL Override the container image loader (default: docker)
COMPOSE_FILE Override docker compose file path (default: ${COMPOSE_FILE})
USAGE
}
cmd=${1:-up}
case "${cmd}" in
up)
load_images
compose -f "${COMPOSE_FILE}" up -d
;;
down)
compose -f "${COMPOSE_FILE}" down
;;
load-images)
load_images
;;
status)
compose -f "${COMPOSE_FILE}" ps
;;
-h|--help|help)
usage
;;
*)
echo "Unknown command: ${cmd}" >&2
usage
exit 1
;;
esac

View File

@ -0,0 +1,37 @@
version: "3.8"
services:
postgres:
image: postgres:__POSTGRES_TAG__
container_name: n8n-postgres
restart: unless-stopped
environment:
POSTGRES_DB: n8n
POSTGRES_USER: n8n
POSTGRES_PASSWORD: n8n
volumes:
- n8n-postgres:/var/lib/postgresql/data
n8n:
image: n8nio/n8n:__N8N_TAG__
container_name: n8n-app
restart: unless-stopped
depends_on:
- postgres
ports:
- "5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: n8n
N8N_BASIC_AUTH_ACTIVE: "true"
N8N_BASIC_AUTH_USER: admin
N8N_BASIC_AUTH_PASSWORD: changeme
volumes:
- n8n-data:/home/node/.n8n
volumes:
n8n-postgres:
n8n-data:

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="RAGFlow"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
OFFLINE_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
COMPOSE_FILE="${OFFLINE_ROOT}/docker-compose.yaml"
IMAGES_DIR="${OFFLINE_ROOT}/images"
IMAGE_LOAD_TOOL="${IMAGE_LOAD_TOOL:-docker}"
command_exists() {
command -v "$1" >/dev/null 2>&1
}
load_images() {
if ! command_exists "${IMAGE_LOAD_TOOL}"; then
echo "Error: image loader '${IMAGE_LOAD_TOOL}' not found in PATH" >&2
exit 1
fi
if [ ! -d "${IMAGES_DIR}" ]; then
echo "No images directory found at ${IMAGES_DIR}. Skipping image load." >&2
return
fi
shopt -s nullglob
local tarball
for tarball in "${IMAGES_DIR}"/*.tar; do
echo "Loading container images from ${tarball}"
"${IMAGE_LOAD_TOOL}" load -i "${tarball}"
done
shopt -u nullglob
}
compose() {
if command_exists docker && docker compose version >/dev/null 2>&1; then
docker compose "$@"
elif command_exists docker-compose; then
docker-compose "$@"
else
echo "Error: docker compose plugin or docker-compose binary is required" >&2
exit 1
fi
}
usage() {
cat <<USAGE
Usage: $(basename "$0") [command]
Commands:
up Load images (if available) and start ${APP_NAME}
down Stop ${APP_NAME}
load-images Only load container images from the images/ directory
status Show status of the compose application
Environment variables:
IMAGE_LOAD_TOOL Override the container image loader (default: docker)
COMPOSE_FILE Override docker compose file path (default: ${COMPOSE_FILE})
USAGE
}
cmd=${1:-up}
case "${cmd}" in
up)
load_images
compose -f "${COMPOSE_FILE}" up -d
;;
down)
compose -f "${COMPOSE_FILE}" down
;;
load-images)
load_images
;;
status)
compose -f "${COMPOSE_FILE}" ps
;;
-h|--help|help)
usage
;;
*)
echo "Unknown command: ${cmd}" >&2
usage
exit 1
;;
esac

View File

@ -0,0 +1,37 @@
version: "3.8"
services:
postgres:
image: postgres:__POSTGRES_TAG__
container_name: ragflow-postgres
restart: unless-stopped
environment:
POSTGRES_DB: ragflow
POSTGRES_USER: ragflow
POSTGRES_PASSWORD: ragflow
volumes:
- ragflow-postgres:/var/lib/postgresql/data
redis:
image: redis:__REDIS_TAG__
container_name: ragflow-redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"]
volumes:
- ragflow-redis:/data
ragflow:
image: ragflow/ragflow:__RAGFLOW_TAG__
container_name: ragflow-app
restart: unless-stopped
depends_on:
- postgres
- redis
ports:
- "3001:3000"
environment:
DATABASE_URL: postgresql://ragflow:ragflow@postgres:5432/ragflow
REDIS_URL: redis://redis:6379/0
SECRET_KEY: changeme
volumes:
ragflow-postgres:
ragflow-redis: