mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-11-10 21:32:43 +08:00
393 lines
14 KiB
YAML
393 lines
14 KiB
YAML
name: release
|
|
|
|
on:
|
|
schedule:
|
|
- cron: '0 13 * * *' # This schedule runs every 13:00:00Z(21:00:00+08:00)
|
|
# https://github.com/orgs/community/discussions/26286?utm_source=chatgpt.com#discussioncomment-3251208
|
|
# "The create event does not support branch filter and tag filter."
|
|
# The "create tags" trigger is specifically focused on the creation of new tags, while the "push tags" trigger is activated when tags are pushed, including both new tag creations and updates to existing tags.
|
|
push:
|
|
tags:
|
|
- "v*.*.*" # normal release
|
|
- 'nightly' # mutable tag
|
|
|
|
permissions:
|
|
contents: write
|
|
actions: read
|
|
checks: read
|
|
statuses: read
|
|
|
|
# https://docs.github.com/en/actions/using-jobs/using-concurrency
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
prepare:
|
|
runs-on: ubuntu-24.04
|
|
outputs:
|
|
release_tag: ${{ steps.release.outputs.release_tag }}
|
|
prerelease: ${{ steps.release.outputs.prerelease }}
|
|
|
|
steps:
|
|
# https://github.com/actions/checkout/blob/v6/README.md
|
|
# Keep `token` so the move-mutable-tag step (schedule/nightly) can
|
|
# `git push -f` via the persisted GITHUB_TOKEN (persist-credentials
|
|
# defaults to true). Workflow-level `permissions: contents: write`
|
|
# grants the push.
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Prepare release metadata
|
|
id: release
|
|
run: |
|
|
if [[ ${GITHUB_EVENT_NAME} != "schedule" ]]; then
|
|
RELEASE_TAG=${GITHUB_REF#refs/tags/}
|
|
if [[ ${RELEASE_TAG} == v* ]]; then
|
|
PRERELEASE=false
|
|
else
|
|
PRERELEASE=true
|
|
fi
|
|
echo "Workflow triggered by create tag: ${RELEASE_TAG}"
|
|
else
|
|
RELEASE_TAG=nightly
|
|
PRERELEASE=true
|
|
echo "Workflow triggered by schedule"
|
|
fi
|
|
echo "RELEASE_TAG=${RELEASE_TAG}" >> ${GITHUB_ENV}
|
|
echo "PRERELEASE=${PRERELEASE}" >> ${GITHUB_ENV}
|
|
echo "release_tag=${RELEASE_TAG}" >> ${GITHUB_OUTPUT}
|
|
echo "prerelease=${PRERELEASE}" >> ${GITHUB_OUTPUT}
|
|
|
|
- name: Move the existing mutable tag
|
|
# https://github.com/softprops/action-gh-release/issues/171
|
|
run: |
|
|
git fetch --tags
|
|
if [[ ${GITHUB_EVENT_NAME} == "schedule" ]]; then
|
|
# Determine if a given tag exists and matches a specific Git commit.
|
|
# actions/checkout@v6 fetch-tags doesn't work when triggered by schedule
|
|
if [ "$(git rev-parse -q --verify "refs/tags/${RELEASE_TAG}")" = "${GITHUB_SHA}" ]; then
|
|
echo "mutable tag ${RELEASE_TAG} exists and matches ${GITHUB_SHA}"
|
|
else
|
|
git tag -f ${RELEASE_TAG} ${GITHUB_SHA}
|
|
git push -f origin ${RELEASE_TAG}:refs/tags/${RELEASE_TAG}
|
|
echo "created/moved mutable tag ${RELEASE_TAG} to ${GITHUB_SHA}"
|
|
fi
|
|
fi
|
|
|
|
build_cli:
|
|
needs: prepare
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- goos: linux
|
|
goarch: amd64
|
|
runner: ubuntu-24.04
|
|
- goos: linux
|
|
goarch: arm64
|
|
runner: ubuntu-24.04-arm
|
|
- goos: darwin
|
|
goarch: amd64
|
|
runner: macos-15-intel
|
|
- goos: darwin
|
|
goarch: arm64
|
|
runner: macos-14
|
|
- goos: windows
|
|
goarch: amd64
|
|
runner: windows-latest
|
|
output_ext: .exe
|
|
- goos: windows
|
|
goarch: arm64
|
|
runner: windows-11-arm
|
|
output_ext: .exe
|
|
runs-on: ${{ matrix.runner }}
|
|
env:
|
|
CLI_NAME: ragflow-cli
|
|
CLI_MAIN: ./cmd/ragflow-cli.go
|
|
DIST_DIR: dist/cli
|
|
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
|
|
|
|
steps:
|
|
# https://github.com/actions/checkout/blob/v6/README.md
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
# https://github.com/actions/setup-go
|
|
- name: Set up Go
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
|
|
- name: Build Go CLI release binaries on non-Windows
|
|
if: runner.os != 'Windows'
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
mkdir -p "${DIST_DIR}"
|
|
|
|
if [[ ! -e "${CLI_MAIN}" ]]; then
|
|
echo "::error::Go CLI entry does not exist: ${CLI_MAIN}"
|
|
echo "::error::Please update CLI_MAIN in .github/workflows/release.yml"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Building Go CLI release binaries"
|
|
echo "CLI name: ${CLI_NAME}"
|
|
echo "CLI main: ${CLI_MAIN}"
|
|
echo "Release tag: ${RELEASE_TAG}"
|
|
echo "Commit: ${GITHUB_SHA}"
|
|
|
|
output="${DIST_DIR}/${CLI_NAME}-${RELEASE_TAG}-${{ matrix.goos }}-${{ matrix.goarch }}"
|
|
echo "Building ${{ matrix.goos }}/${{ matrix.goarch }} -> ${output}"
|
|
|
|
CGO_ENABLED=0 \
|
|
GOOS="${{ matrix.goos }}" \
|
|
GOARCH="${{ matrix.goarch }}" \
|
|
go build \
|
|
-trimpath \
|
|
-ldflags="-s -w -X main.version=${RELEASE_TAG} -X main.commit=${GITHUB_SHA}" \
|
|
-o "${output}" \
|
|
"${CLI_MAIN}"
|
|
|
|
chmod +x "${output}"
|
|
|
|
- name: Build Go CLI release binaries on Windows
|
|
if: runner.os == 'Windows'
|
|
shell: pwsh
|
|
run: |
|
|
New-Item -ItemType Directory -Force -Path $env:DIST_DIR | Out-Null
|
|
|
|
if (-not (Test-Path $env:CLI_MAIN)) {
|
|
Write-Error "Go CLI entry does not exist: $env:CLI_MAIN"
|
|
exit 1
|
|
}
|
|
|
|
$output = Join-Path $env:DIST_DIR "${env:CLI_NAME}-${env:RELEASE_TAG}-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.output_ext }}"
|
|
Write-Host "Building ${{ matrix.goos }}/${{ matrix.goarch }} -> $output"
|
|
|
|
$env:CGO_ENABLED = "0"
|
|
$env:GOOS = "${{ matrix.goos }}"
|
|
$env:GOARCH = "${{ matrix.goarch }}"
|
|
|
|
go build `
|
|
-trimpath `
|
|
-ldflags="-s -w -X main.version=$env:RELEASE_TAG -X main.commit=$env:GITHUB_SHA" `
|
|
-o "$output" `
|
|
"$env:CLI_MAIN"
|
|
|
|
- name: Upload CLI artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: cli-${{ matrix.goos }}-${{ matrix.goarch }}
|
|
path: dist/cli/*
|
|
if-no-files-found: error
|
|
|
|
publish_cli_assets:
|
|
needs:
|
|
- prepare
|
|
- build_cli
|
|
runs-on: ubuntu-24.04
|
|
|
|
steps:
|
|
# https://github.com/actions/checkout/blob/v6/README.md
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Download CLI artifacts
|
|
uses: actions/download-artifact@v5
|
|
with:
|
|
pattern: cli-*
|
|
path: dist/cli
|
|
merge-multiple: true
|
|
|
|
- name: Prepare CLI release assets
|
|
env:
|
|
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
RELEASE_DATETIME=$(date --rfc-3339=seconds)
|
|
echo Release ${RELEASE_TAG} created from ${GITHUB_SHA} at ${RELEASE_DATETIME} > release_body.md
|
|
|
|
cd dist/cli
|
|
sha256sum * > SHA256SUMS
|
|
cd -
|
|
|
|
echo "Generated CLI release assets:"
|
|
ls -lh dist/cli
|
|
|
|
- name: Upload Go CLI release assets
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
prerelease: ${{ needs.prepare.outputs.prerelease }}
|
|
tag_name: ${{ needs.prepare.outputs.release_tag }}
|
|
body_path: release_body.md
|
|
files: |
|
|
dist/cli/*
|
|
tools/scripts/install.sh
|
|
tools/scripts/install.ps1
|
|
|
|
# Publish the ragflow Python SDK to PyPI. Runs on a GitHub-hosted runner so
|
|
# it no longer depends on the self-hosted release runner. Only stable v* tags
|
|
# (not nightly/prerelease) publish, gated by the `if` on this job.
|
|
publish_sdk:
|
|
needs:
|
|
- prepare
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
# https://github.com/actions/checkout/blob/v6/README.md
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v5
|
|
|
|
- name: Build and push ragflow-sdk
|
|
run: |
|
|
cd sdk/python && uv build && uv publish --token ${{ secrets.PYPI_API_TOKEN }}
|
|
|
|
# Build the linux/amd64 image on a GitHub-hosted runner, mirroring
|
|
# `build-arm64`. Pushes the version tag (amd64-only) so amd64 pulls always
|
|
# work even if the ARM64 job fails, plus the arch-specific -amd64/:amd64 tags
|
|
# for direct pulls. The multi-arch manifest is created by the `build-arm64`
|
|
# job once both arches are pushed.
|
|
build-amd64:
|
|
needs:
|
|
- prepare
|
|
runs-on: ubuntu-24.04
|
|
env:
|
|
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@v3
|
|
with:
|
|
username: infiniflow
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Build and push amd64 image
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: ./Dockerfile
|
|
platforms: linux/amd64
|
|
push: true
|
|
# Disable build attestations (provenance/SBOM) for the same reason as
|
|
# build-arm64: keep a clean manifest so the multi-arch index merged
|
|
# below contains only amd64 + arm64 image manifests.
|
|
provenance: false
|
|
sbom: false
|
|
# Use a Go proxy that is reliable from GitHub-hosted runners; the
|
|
# Dockerfile default (goproxy.cn) is flaky here (HTTP/2 GOAWAY).
|
|
build-args: |
|
|
GOPROXY=https://proxy.golang.org,direct
|
|
tags: |
|
|
infiniflow/ragflow:${{ needs.prepare.outputs.release_tag }}-amd64
|
|
infiniflow/ragflow:amd64
|
|
infiniflow/ragflow:${{ needs.prepare.outputs.release_tag }}
|
|
|
|
# Build the linux/arm64 image on a GitHub-hosted ARM64 runner and merge it
|
|
# with the amd64 image (pushed by the `build-amd64` job above) into a single
|
|
# multi-arch manifest list for infiniflow/ragflow:${RELEASE_TAG} and :latest,
|
|
# so `docker pull infiniflow/ragflow:${RELEASE_TAG}` resolves per-arch on both
|
|
# platforms. Runs after `build-amd64` so the amd64 (-amd64/:amd64) tags exist.
|
|
build-arm64:
|
|
needs:
|
|
- build-amd64
|
|
- prepare
|
|
runs-on: ubuntu-24.04-arm
|
|
env:
|
|
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
|
|
PRERELEASE: ${{ needs.prepare.outputs.prerelease }}
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@v3
|
|
with:
|
|
username: infiniflow
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Build and push arm64 image
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: ./Dockerfile
|
|
platforms: linux/arm64
|
|
push: true
|
|
# Disable build attestations (provenance/SBOM). build-push-action v6
|
|
# otherwise attaches an application/vnd.docker.attestation.manifest.v1+json
|
|
# artifact to the image. That artifact is not supported by some registries
|
|
# (e.g. Alibaba Cloud personal OCR), and skopeo sync then fails with
|
|
# "unsupported image-specific operation on artifact with type
|
|
# application/vnd.docker.attestation.manifest.v1+json". Disabling it keeps
|
|
# the pushed image a clean manifest so the multi-arch index merged below
|
|
# contains only amd64 + arm64 image manifests.
|
|
provenance: false
|
|
sbom: false
|
|
# Use a Go proxy that is reliable from GitHub-hosted runners; the
|
|
# Dockerfile default (goproxy.cn) is flaky here (HTTP/2 GOAWAY).
|
|
build-args: |
|
|
GOPROXY=https://proxy.golang.org,direct
|
|
tags: |
|
|
infiniflow/ragflow:${{ needs.prepare.outputs.release_tag }}-arm64
|
|
infiniflow/ragflow:arm64
|
|
|
|
# Create/upgrade the public multi-arch tags now that both arch-specific
|
|
# images (-amd64/:amd64 from the `build-amd64` job, -arm64/:arm64 from this
|
|
# job) are pushed. :${RELEASE_TAG} was already pushed amd64-only by the
|
|
# build-amd64 job (so amd64 pulls always work); this upgrades it to multi-arch.
|
|
# :latest is created here for the first time this release (it is NOT pushed
|
|
# by the build-amd64 job), so the previous, possibly multi-arch, :latest is
|
|
# never overwritten with an amd64-only image before ARM64 is ready.
|
|
- name: Create multi-arch manifest
|
|
run: |
|
|
docker buildx imagetools create --tag infiniflow/ragflow:${RELEASE_TAG} \
|
|
infiniflow/ragflow:${RELEASE_TAG}-amd64 \
|
|
infiniflow/ragflow:${RELEASE_TAG}-arm64
|
|
# Only stable (non-prerelease) v* tags should move the mutable :latest
|
|
# tag. Nightly and prerelease builds keep their own version tag but must
|
|
# not overwrite the stable :latest.
|
|
if [ "${PRERELEASE}" != "true" ]; then
|
|
docker buildx imagetools create --tag infiniflow/ragflow:latest \
|
|
infiniflow/ragflow:amd64 \
|
|
infiniflow/ragflow:arm64
|
|
else
|
|
echo "RELEASE_TAG=${RELEASE_TAG} is a prerelease/nightly build; skipping :latest update."
|
|
fi
|
|
|