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: [ "self-hosted", "ragflow-release" ] outputs: release_tag: ${{ steps.release.outputs.release_tag }} prerelease: ${{ steps.release.outputs.prerelease }} steps: - name: Ensure workspace ownership run: echo "chown -R ${USER} ${GITHUB_WORKSPACE}" && sudo chown -R ${USER} ${GITHUB_WORKSPACE} # https://github.com/actions/checkout/blob/v6/README.md - name: Check out code uses: actions/checkout@v6 with: token: ${{ secrets.GITHUB_TOKEN }} # Use the secret as an environment variable 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: 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: [ "self-hosted", "ragflow-release" ] steps: - name: Ensure workspace ownership run: echo "chown -R ${USER} ${GITHUB_WORKSPACE}" && sudo chown -R ${USER} ${GITHUB_WORKSPACE} # 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 - 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 release: needs: - prepare - publish_cli_assets runs-on: [ "self-hosted", "ragflow-release" ] env: RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} steps: - name: Ensure workspace ownership run: echo "chown -R ${USER} ${GITHUB_WORKSPACE}" && sudo chown -R ${USER} ${GITHUB_WORKSPACE} # 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 - name: Build and push image run: | sudo docker login --username infiniflow --password-stdin <<< ${{ secrets.DOCKERHUB_TOKEN }} sudo docker build -t infiniflow/ragflow:${RELEASE_TAG} -f Dockerfile . sudo docker tag infiniflow/ragflow:${RELEASE_TAG} infiniflow/ragflow:latest sudo docker push infiniflow/ragflow:${RELEASE_TAG} sudo docker push infiniflow/ragflow:latest - name: Build and push ragflow-sdk if: startsWith(github.ref, 'refs/tags/v') run: | cd sdk/python && uv build && uv publish --token ${{ secrets.PYPI_API_TOKEN }} - name: Build and push ragflow-cli if: startsWith(github.ref, 'refs/tags/v') run: | cd admin/client && uv build && uv publish --token ${{ secrets.PYPI_API_TOKEN }}