name: Release

on:
  push:
    tags:
      - 'v*.*.*'
      - 'v*.*.*-*'
env:
  CARGO_INCREMENTAL: 0
  CARGO_NET_RETRY: 10
  RUSTUP_MAX_RETRIES: 10

jobs:
  npm:
    runs-on: ubuntu-24.04
    timeout-minutes: 60
    permissions:
      contents: write
      id-token: write  # Required for OIDC trusted publishing
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Install Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: 1.90.0
          # override: true # this is by default on
          rustflags: ""
          components: rustfmt
      - name: Install Node.js 24.x
        uses: actions/setup-node@v4
        with:
          node-version: 24.x
          registry-url: 'https://registry.npmjs.org/'
      - name: Upgrade npm for OIDC support
        run: npm install -g npm@11.7.0
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "dir=$(yarn cache dir)" >> "$GITHUB_OUTPUT"
        shell: bash
      - name: Restore yarn cache
        uses: actions/cache@v4
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Set Yarn version
        run: yarn policies set-version v1.22.22
      - name: Yarn install
        uses: nick-fields/retry@v3
        env:
          CUBESTORE_SKIP_POST_INSTALL: true
        with:
          max_attempts: 3
          retry_on: error
          retry_wait_seconds: 15
          timeout_minutes: 20
          command: yarn install --frozen-lockfile
      - name: Build Core Client libraries
        run: yarn build
      - name: Build other packages
        run: yarn lerna run --concurrency 1 build
        env:
          NODE_OPTIONS: --max_old_space_size=4096
      - name: NPM publish
        uses: nick-fields/retry@v3
        env:
          NPM_CONFIG_PROVENANCE: false
        with:
          max_attempts: 5
          retry_on: error
          retry_wait_seconds: 30
          timeout_minutes: 15
          command: ./node_modules/.bin/lerna publish from-package --yes

  native_linux:
    # Please use minimal possible version of ubuntu, because it produces constraint on glibc
    runs-on: ubuntu-22.04
    timeout-minutes: 60
    name: Build native Linux ${{ matrix.node-version }} ${{ matrix.target }} Python ${{ matrix.python-version }}
    strategy:
      matrix:
        node-version: [24]
        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "fallback"]
        target: ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]
        include:
          - target: x86_64-unknown-linux-gnu
            package_target_arch: x64
            package_target_platform: linux
            package_target_libc: glibc
          - target: aarch64-unknown-linux-gnu
            package_target_arch: arm64
            package_target_platform: linux
            package_target_libc: glibc
      fail-fast: false
    container:
      image: cubejs/rust-cross:${{ matrix.target }}-31072025${{ matrix.python-version != 'fallback' && format('-python-{0}', matrix.python-version) || '' }}
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Install Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: 1.90.0
          # override: true # this is by default on
          rustflags: ""
          components: rustfmt
          target: ${{ matrix.target }}
      - name: Install Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install Yarn
        run: npm install -g yarn
      - name: Set Yarn version
        run: yarn policies set-version v1.22.22
        # We don't need to install all yarn deps to build native
      - name: Install cargo-cp-artifact
        run: npm install -g cargo-cp-artifact@0.1
      - name: Build native (fallback)
        if: (matrix.python-version == 'fallback')
        env:
          CARGO_BUILD_TARGET: ${{ matrix.target }}
        run: cd packages/cubejs-backend-native && npm run native:build-release
      - name: Setup cross compilation
        if: (matrix.target == 'aarch64-unknown-linux-gnu')
        uses: allenevans/set-env@v4.0.0
        with:
          PYO3_CROSS_PYTHON_VERSION: ${{ matrix.python-version }}
      - name: Build native (with Python)
        if: (matrix.python-version != 'fallback')
        env:
          PYO3_PYTHON: python${{ matrix.python-version }}
          CARGO_BUILD_TARGET: ${{ matrix.target }}
        run: cd packages/cubejs-backend-native && npm run native:build-release-python
      - name: Archive release asset
        shell: bash
        run: |
          cd packages/cubejs-backend-native
          rm -rf native
          mkdir native
          cp index.node native/index.node
          tar czvf native.tar.gz native
      - name: Upload to Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: packages/cubejs-backend-native/native.tar.gz
          # Example: native-linux-arm64-glibc.tar.gz
          asset_name: native-${{ matrix.package_target_platform }}-${{ matrix.package_target_arch }}-${{ matrix.package_target_libc }}-${{ matrix.python-version }}.tar.gz
          tag: ${{ github.ref }}
          overwrite: true

  native_macos:
    runs-on: ${{ matrix.os-version }}
    timeout-minutes: 90
    name: Build ${{ matrix.os-version }} ${{ matrix.target }} ${{ matrix.node-version }} Python ${{ matrix.python-version }}
    strategy:
      matrix:
        node-version: [24.x]
        target: ["x86_64-apple-darwin", "aarch64-apple-darwin"]
        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "fallback"]
        include:
          - target: x86_64-apple-darwin
            os-version: macos-15-intel
            package_target_arch: x64
            package_target_platform: darwin
            package_target_libc: unknown
            tar_executable: gtar
          - target: aarch64-apple-darwin
            os-version: macos-14
            package_target_arch: arm64
            package_target_platform: darwin
            package_target_libc: unknown
            tar_executable: gtar
        exclude:
          # Disable python builds for aarch64 (not ready)
          - target: "aarch64-apple-darwin"
            python-version: "3.9"
          - target: "aarch64-apple-darwin"
            python-version: "3.10"
          - target: "aarch64-apple-darwin"
            python-version: "3.11"
          - target: "aarch64-apple-darwin"
            python-version: "3.12"
      fail-fast: false
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Install Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: 1.90.0
          # override: true # this is by default on
          rustflags: ""
          components: rustfmt
          target: ${{ matrix.target }}
      - name: Install Python
        uses: actions/setup-python@v5
        if: (matrix.python-version != 'fallback')
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Set Yarn version
        run: yarn policies set-version v1.22.22
        # We don't need to install all yarn deps to build native
      - name: Install cargo-cp-artifact
        run: npm install -g cargo-cp-artifact@0.1
      - name: Build native (fallback)
        if: (matrix.python-version == 'fallback')
        run: cd packages/cubejs-backend-native && npm run native:build-release
        env:
          CARGO_BUILD_TARGET: ${{ matrix.target }}
      - name: Build native (with Python)
        if: (matrix.python-version != 'fallback')
        env:
          PYO3_PYTHON: python${{ matrix.python-version }}
          CARGO_BUILD_TARGET: ${{ matrix.target }}
        run: cd packages/cubejs-backend-native && npm run native:build-release-python
      - name: Archive release asset
        shell: bash
        run: |
          cd packages/cubejs-backend-native
          rm -rf native
          mkdir native
          cp index.node native/index.node
          ${{ matrix.tar_executable }} -czvf native.tar.gz native
      - name: Upload to Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: packages/cubejs-backend-native/native.tar.gz
          # Example: native-linux-arm64-glibc.tar.gz
          asset_name: native-${{ matrix.package_target_platform }}-${{ matrix.package_target_arch }}-${{ matrix.package_target_libc }}-${{ matrix.python-version }}.tar.gz
          tag: ${{ github.ref }}
          overwrite: true

  native_windows:
    runs-on: ${{ matrix.os-version }}
    timeout-minutes: 90
    name: Build ${{ matrix.os-version }} ${{ matrix.node-version }} Python ${{ matrix.python-version }}
    strategy:
      matrix:
        node-version: [24.x]
        python-version: ["fallback"]
        os-version: [windows-2022]
        include:
          - os-version: windows-2022
            package_target_arch: x64
            package_target_platform: win32
            package_target_libc: unknown
            tar_executable: tar
      fail-fast: false
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Disable rustup update (issue workaround for Windows)
        run: rustup set auto-self-update disable
        shell: bash
      - name: Install Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: 1.90.0
          # override: true # this is by default on
          rustflags: ""
          components: rustfmt
      - name: Install Python
        uses: actions/setup-python@v5
        if: (matrix.python-version != 'fallback')
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Set Yarn version
        run: yarn policies set-version v1.22.22
        # We don't need to install all yarn deps to build native
      - name: Install cargo-cp-artifact
        run: npm install -g cargo-cp-artifact@0.1
      - name: Build native (fallback)
        if: (matrix.python-version == 'fallback')
        run: cd packages/cubejs-backend-native && npm run native:build-release
      - name: Build native (with Python)
        if: (matrix.python-version != 'fallback')
        env:
          PYO3_PYTHON: python${{ matrix.python-version }}
        run: cd packages/cubejs-backend-native && npm run native:build-release-python
      - name: Archive release asset
        shell: bash
        run: |
          cd packages/cubejs-backend-native
          rm -rf native
          mkdir native
          cp index.node native/index.node
          ${{ matrix.tar_executable }} -czvf native.tar.gz native
      - name: Upload to Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: packages/cubejs-backend-native/native.tar.gz
          # Example: native-linux-arm64-glibc.tar.gz
          asset_name: native-${{ matrix.package_target_platform }}-${{ matrix.package_target_arch }}-${{ matrix.package_target_libc }}-${{ matrix.python-version }}.tar.gz
          tag: ${{ github.ref }}
          overwrite: true

  docker-default:
    needs: [npm, cubestore_linux, native_linux, detect_branch]
    name: Debian docker image
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            platforms: linux/amd64,linux/arm64
    timeout-minutes: 90
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - name: Repo metadata
        id: repo
        uses: actions/github-script@v7
        with:
          script: |
            const { data } = await github.rest.repos.get(context.repo)
            const reg = new RegExp('📊 ', 'ug');
            data.description = data.description.replace(reg, "")
            return data
      - name: Prepare
        id: prep
        run: |
          DOCKER_IMAGE=cubejs/cube
          VERSION=noop

          if [ "${{ github.event_name }}" = "schedule" ]; then
            VERSION=nightly
          elif [[ $GITHUB_REF == refs/tags/* ]]; then
            VERSION=${GITHUB_REF#refs/tags/}
          fi

          TAGS="${DOCKER_IMAGE}:${VERSION}"

          if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            MINOR=${VERSION%.*}
            MAJOR=${MINOR%.*}
            TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR},${DOCKER_IMAGE}:${MAJOR}"
          fi

          if [ "${{ needs['detect_branch'].outputs.is_master }}" = "true" ]; then
            TAGS="$TAGS,${DOCKER_IMAGE}:latest"
          fi

          {
            echo "version=${VERSION}"
            echo "tags=${TAGS}"
            echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
          } >> "$GITHUB_OUTPUT"
      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Copy yarn.lock file
        run: cp yarn.lock packages/cubejs-docker
      - name: Push to Docker Hub
        uses: docker/build-push-action@v6
        with:
          context: ./packages/cubejs-docker
          file: ./packages/cubejs-docker/latest.Dockerfile
          platforms: ${{ matrix.platforms }}
          push: true
          tags: ${{ steps.prep.outputs.tags }}
          labels: |
            org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
            org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
            org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
            org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
            org.opencontainers.image.version=${{ steps.prep.outputs.version }}
            org.opencontainers.image.created=${{ steps.prep.outputs.created }}
            org.opencontainers.image.revision=${{ github.sha }}
            org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
          build-args: |
            IMAGE_VERSION=${{ steps.prep.outputs.version }}

  docker-debian-jdk:
    needs: [npm, cubestore_linux, native_linux, detect_branch]
    name: Debian with jdk docker image
    runs-on: ubuntu-24.04
    timeout-minutes: 30
    permissions:
      contents: write
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - name: Repo metadata
        id: repo
        uses: actions/github-script@v7
        with:
          script: |
            const { data } = await github.rest.repos.get(context.repo)
            const reg = new RegExp('📊 ', 'ug');
            data.description = data.description.replace(reg, "")
            return data
      - name: Prepare
        id: prep
        run: |
          DOCKER_IMAGE=cubejs/cube
          VERSION=noop

          if [ "${{ github.event_name }}" = "schedule" ]; then
            VERSION=nightly
          elif [[ $GITHUB_REF == refs/tags/* ]]; then
            VERSION=${GITHUB_REF#refs/tags/}
          fi

          TAGS="${DOCKER_IMAGE}:${VERSION}-jdk"

          if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            MINOR=${VERSION%.*}
            MAJOR=${MINOR%.*}
            TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR}-jdk,${DOCKER_IMAGE}:${MAJOR}-jdk"
          elif [ "${{ github.event_name }}" = "push" ]; then
            TAGS="$TAGS,${DOCKER_IMAGE}:sha-${GITHUB_SHA::8}-jdk"
          fi

          if [ "${{ needs['detect_branch'].outputs.is_master }}" = "true" ]; then
            TAGS="$TAGS,${DOCKER_IMAGE}:jdk"
          fi

          {
            echo "version=${VERSION}"
            echo "tags=${TAGS}"
            echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
          } >> "$GITHUB_OUTPUT"
      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Copy yarn.lock file
        run: cp yarn.lock packages/cubejs-docker
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Push to Docker Hub
        uses: docker/build-push-action@v6
        with:
          context: ./packages/cubejs-docker
          file: ./packages/cubejs-docker/latest-debian-jdk.Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ steps.prep.outputs.tags }}
          labels: |
            org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
            org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
            org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
            org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
            org.opencontainers.image.version=${{ steps.prep.outputs.version }}
            org.opencontainers.image.created=${{ steps.prep.outputs.created }}
            org.opencontainers.image.revision=${{ github.sha }}
            org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
          build-args: |
            IMAGE_VERSION=${{ steps.prep.outputs.version }}

  docker-cubestore:
    name: Cube Store Docker
    runs-on: ${{ matrix.os }}
    needs: [detect_branch]
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-24.04
            target: x86_64-unknown-linux-gnu
            platforms: linux/amd64
            build-args: WITH_AVX2=1
            postfix: ""
            tag: "latest"
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            platforms: linux/arm64
            build-args: WITH_AVX2=0
            postfix: "-arm64v8"
            tag: "arm64v8"
          # Non AVX build
          - os: ubuntu-24.04
            target: x86_64-unknown-linux-gnu
            platforms: linux/amd64
            build-args: WITH_AVX2=0
            postfix: "-non-avx"
            tag: "non-avx"
    timeout-minutes: 60
    permissions:
      contents: write
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - name: Repo metadata
        id: repo
        uses: actions/github-script@v7
        with:
          script: |
            const { data } = await github.rest.repos.get(context.repo)
            const reg = new RegExp('📊 ', 'ug');
            data.description = data.description.replace(reg, "")
            return data
      - name: Prepare
        id: prep
        env:
          GITHUB_SHA: ${{ github.sha }}
        run: |
          DOCKER_IMAGE=cubejs/cubestore
          VERSION=noop

          if [ "${{ github.event_name }}" = "schedule" ]; then
            VERSION=nightly
          elif [[ $GITHUB_REF == refs/tags/* ]]; then
            VERSION=${GITHUB_REF#refs/tags/}
          fi

          TAGS="${DOCKER_IMAGE}:${VERSION}${{ matrix.postfix }}"

          if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            MINOR=${VERSION%.*}
            MAJOR=${MINOR%.*}
            TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR}${{ matrix.postfix }},${DOCKER_IMAGE}:${MAJOR}${{ matrix.postfix }}"
          fi

          if [ "${{ needs['detect_branch'].outputs.is_master }}" = "true" ]; then
            TAGS="$TAGS,${DOCKER_IMAGE}:${{ matrix.tag }}"
          fi

          {
            echo "version=${VERSION}"
            echo "tags=${TAGS}"
            echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
          } >> "$GITHUB_OUTPUT"
      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Push to Docker Hub
        uses: docker/build-push-action@v6
        with:
          context: ./rust/
          file: ./rust/cubestore/Dockerfile
          platforms: ${{ matrix.platforms }}
          build-args: ${{ matrix.build-args }}
          push: true
          tags: ${{ steps.prep.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          labels: |
            org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
            org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
            org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
            org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
            org.opencontainers.image.version=${{ steps.prep.outputs.version }}
            org.opencontainers.image.created=${{ steps.prep.outputs.created }}
            org.opencontainers.image.revision=${{ github.sha }}
            org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
      - name: Update repo description
        uses: peter-evans/dockerhub-description@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          repository: cubejs/cubestore
          readme-filepath: ./rust/cubestore/README.md

  cubestore_linux:
    runs-on: ${{ matrix.os }}
    timeout-minutes: 90
    env:
      OPENSSL_STATIC: 1
    strategy:
      matrix:
        target:
          - x86_64-unknown-linux-gnu
          - x86_64-unknown-linux-musl
          - aarch64-unknown-linux-gnu
        include:
          # Please use minimal possible version of ubuntu, because it produces constraint on glibc
          - os: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            image: cubejs/rust-cross:x86_64-unknown-linux-gnu-31072025
            executable_name: cubestored
            strip: true
            compress: false
          - os: ubuntu-22.04
            target: x86_64-unknown-linux-musl
            image: cubejs/rust-cross:x86_64-unknown-linux-musl-31072025
            executable_name: cubestored
            strip: true
            # cubestored: CantPackException: bad DT_HASH nbucket=0x344  len=0x1890
            compress: false
          - os: ubuntu-24.04-arm
            image: cubejs/rust-builder:bullseye-llvm-18
            target: aarch64-unknown-linux-gnu
            executable_name: cubestored
            # Unable to recognise the format of the input file `rust/cubestore/target/aarch64-unknown-linux-gnu/release/cubestored'
            strip: false
            # UPX is broken, issue https://github.com/cube-js/cube/issues/4474
            compress: false
      fail-fast: false
    container:
      image: ${{ matrix.image }}
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: nightly-2025-08-01
          target: ${{ matrix.target }}
          # override: true # this is by default on
          rustflags: ""
          components: rustfmt
      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: ./rust/cubestore -> target
          prefix-key: v1-rust-cubestore-cross
          key: target-${{ matrix.target }}
      - name: Build with Cargo
        run: |
          cd rust/cubestore && cargo build --release --target=${{ matrix.target }} -p cubestore
      - name: Compress binaries
        uses: svenstaro/upx-action@v2
        if: ${{ matrix.compress }}
        with:
          file: rust/cubestore/target/${{ matrix.target }}/release/${{ matrix.executable_name }}
          args: --lzma
          strip: ${{ matrix.strip }}
      - name: Create folder for archive
        run: |
          mkdir cubestore-archive
          mkdir cubestore-archive/bin
      - name: Create archive for release
        run: |
          mv rust/cubestore/target/${{ matrix.target }}/release/${{ matrix.executable_name }} cubestore-archive/bin/${{ matrix.executable_name }}
          cd cubestore-archive
          tar -cvzf cubestored-${{ matrix.target }}.tar.gz ./*
      - name: Upload Binary to Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: cubestore-archive/cubestored-${{ matrix.target }}.tar.gz
          asset_name: cubestored-${{ matrix.target }}.tar.gz
          tag: ${{ github.ref }}
          overwrite: true

  cubestore:
    runs-on: ${{ matrix.os }}
    timeout-minutes: 90
    env:
      RUSTFLAGS: '-Ctarget-feature=+crt-static'
      OPENSSL_STATIC: 1
    strategy:
      matrix:
        target:
          - x86_64-pc-windows-msvc
          - x86_64-apple-darwin
          - aarch64-apple-darwin
        include:
          - target: x86_64-pc-windows-msvc
            os: windows-2022
            executable_name: cubestored.exe
            strip: true
            # cubestored.exe: CantPackException: superfluous data between sections
            compress: false
            tar_executable: tar
            # Please use minimal possible version of macOS, because it produces constraint on libstdc++
          - target: x86_64-apple-darwin
            os: macos-15-intel
            executable_name: cubestored
            # upx has been disabled because it is crashing for macOS Ventura or above! It was disabled on 2024-09-05.
            strip: false
            compress: false
            # bsd tar has a different format with Sparse files which breaks download script
            tar_executable: gtar
          - os: macos-14
            target: aarch64-apple-darwin
            executable_name: cubestored
            # upx has been disabled because it is crashing for macOS Ventura or above! It was disabled on 2024-09-05.
            strip: false
            compress: false
            # bsd tar has a different format with Sparse files which breaks download script
            tar_executable: gtar
      fail-fast: false
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - name: Disable rustup update (issue workaround for Windows)
        run: rustup set auto-self-update disable
        if: contains(runner.os, 'windows')
        shell: bash
      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: nightly-2025-08-01
          target: ${{ matrix.target }}
          # override: true # this is by default on
          rustflags: ""
          components: rustfmt
      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: ./rust/cubestore -> target
          prefix-key: v0-rust-cubestore-cross
          key: target-${{ matrix.target }}
      - uses: ilammy/msvc-dev-cmd@v1
        if: ${{ startsWith(matrix.os, 'windows') }}
      - name: Install OpenSSL for Windows
        if: ${{ startsWith(matrix.os, 'windows') }}
        run: vcpkg integrate install; vcpkg install openssl:x64-windows
      - name: Instal LLVM for Windows
        if: ${{ startsWith(matrix.os, 'windows') }}
        run: choco install -y --force llvm --version 22.1.0
      - name: Set Env Variables for Windows
        uses: allenevans/set-env@v4.0.0
        if: ${{ startsWith(matrix.os, 'windows') }}
        with:
          OPENSSL_DIR: 'C:/vcpkg/packages/openssl_x64-windows'
          # This paths are required to work with static linking
          OPENSSL_LIB_DIR: 'C:/vcpkg/packages/openssl_x64-windows/lib'
          OPENSSL_INCLUDE_DIR: 'C:/vcpkg/packages/openssl_x64-windows/include'
          LIBCLANG_PATH: 'C:\Program Files\LLVM\bin'
      - name: Build with Cargo
        run: |
          cd rust/cubestore && cargo build --release --target=${{ matrix.target }} -p cubestore
      - name: Compress binaries
        uses: svenstaro/upx-action@v2
        if: ${{ matrix.compress }}
        with:
          file: rust/cubestore/target/${{ matrix.target }}/release/${{ matrix.executable_name }}
          args: --lzma
          strip: ${{ matrix.strip }}
      - name: Create folder for archive
        run: |
          mkdir cubestore-archive
          mkdir cubestore-archive/bin
      - name: Copy/paste OpenSSL to Archive (hotfix for Windows)
        if: ${{ startsWith(matrix.os, 'windows') }}
        run: cp C:/vcpkg/packages/openssl_x64-windows/bin/*.dll cubestore-archive/bin
      - name: Create archive for release
        run: |
          mv rust/cubestore/target/${{ matrix.target }}/release/${{ matrix.executable_name }} cubestore-archive/bin/${{ matrix.executable_name }}
          cd cubestore-archive
          ${{ matrix.tar_executable }} -cvzf cubestored-${{ matrix.target }}.tar.gz ./*
      - name: Upload Binary to Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: cubestore-archive/cubestored-${{ matrix.target }}.tar.gz
          asset_name: cubestored-${{ matrix.target }}.tar.gz
          tag: ${{ github.ref }}
          overwrite: true

  cube-cli:
    name: Cube CLI ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    timeout-minutes: 60
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          # Linux — fully static single binaries (musl + rustls, no OpenSSL).
          - os: ubuntu-22.04
            target: x86_64-unknown-linux-musl
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-musl
          # macOS — Intel and Apple Silicon.
          - os: macos-15-intel
            target: x86_64-apple-darwin
          - os: macos-14
            target: aarch64-apple-darwin
          # Windows.
          - os: windows-2022
            target: x86_64-pc-windows-msvc
    steps:
      - uses: actions/checkout@v4
      - name: Install musl tools
        if: endsWith(matrix.target, '-musl')
        run: sudo apt-get update && sudo apt-get install -y musl-tools
      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: ${{ matrix.target }}
          cache-workspaces: rust/cube-cli
      # The CLI version comes from lerna.json at build time (see
      # rust/cube-cli/build.rs); just guard against tag/lerna drift.
      - name: Check release version matches lerna.json
        shell: bash
        run: |
          v="${GITHUB_REF_NAME#v}"
          l=$(jq -r .version lerna.json)
          if [ "$v" != "$l" ]; then
            echo "tag version $v does not match lerna.json version $l" >&2
            exit 1
          fi
      - name: Build
        working-directory: rust/cube-cli
        run: cargo build --release --target ${{ matrix.target }}
      - name: Create archive
        shell: bash
        run: |
          set -euo pipefail
          bindir="rust/cube-cli/target/${{ matrix.target }}/release"
          bin=cube
          [ "${{ runner.os }}" = "Windows" ] && bin=cube.exe
          tar -C "$bindir" -czf "cube-${{ matrix.target }}.tar.gz" "$bin"
      - name: Upload Binary to Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: cube-${{ matrix.target }}.tar.gz
          asset_name: cube-${{ matrix.target }}.tar.gz
          tag: ${{ github.ref }}
          overwrite: true

  trigger-test-suites:
    name: Trigger test suites run
    runs-on: ubuntu-24.04
    needs: [docker-default]
    timeout-minutes: 15
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Dispatch event
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GH_TRIGGER_TOKEN }}
          script: |
            const prUrl = context.payload.pull_request ? context.payload.pull_request.html_url : '';
            const commitUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.sha}`;

            await github.rest.actions.createWorkflowDispatch({
              owner: 'cubedevinc',
              repo: 'sql-api-test-suite',
              workflow_id: 'test_and_run_test_suites.yml',
              ref: 'main',
              inputs: {
                'cube-image': 'cubejs/cube:latest',
                'source-repo': context.repo.repo,
                'source-pr-url': prUrl,
                'source-commit-url': commitUrl,
                'initiator': '${{ github.actor }}'
              }
            })

  detect_branch:
    runs-on: ubuntu-24.04
    outputs:
      is_master: ${{ steps.detect_branch.outputs.is_master }}
      branch: ${{ steps.detect_branch.outputs.branch }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Detect branch name
        id: detect_branch
        run: |
          # Git & GitHub (for now) doesn't provide an easy/stable way to detect branch name from tag.
          echo "branch=master" >> "$GITHUB_OUTPUT"
          echo "is_master=true" >> "$GITHUB_OUTPUT"

  trigger-repo-sync:
    name: Trigger runtime repo
    runs-on: ubuntu-24.04
    needs: [docker-default, detect_branch]
    timeout-minutes: 15
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Trigger runtime
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GH_TRIGGER_TOKEN }}
          script: |
            const tagName = process.env.GITHUB_REF.replace('refs/tags/', '');
            const branchName = '${{ needs['detect_branch'].outputs.branch }}';

            await github.rest.actions.createWorkflowDispatch({
              owner: 'cubedevinc',
              repo: 'cube-runtime',
              workflow_id: 'sync.yml',
              ref: 'master',
              inputs: {
                'tag': tagName,
                'branch': branchName,
              }
            })
