# This workflow relies on actions/cache to store the hak dependency artifacts as they take a long time to build
# Due to this extra care must be taken to only ever run all build_* scripts against the same branch to ensure
# the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch.
on:
    workflow_call:
        inputs:
            arch:
                type: string
                required: true
                description: "The architecture to build for, one of 'amd64' | 'arm64'"
            config:
                type: string
                required: true
                description: "The config directory to use"
            version:
                type: string
                required: false
                description: "Version string to override the one in package.json, used for non-release builds"
            sqlcipher:
                type: string
                required: true
                description: "How to link sqlcipher, one of 'system' | 'static'"
            docker-image:
                type: string
                required: false
                description: "The docker image to use for the build, defaults to ghcr.io/element-hq/element-desktop-dockerbuild"
jobs:
    build:
        runs-on: ubuntu-latest
        container:
            image: ${{ inputs.docker-image || format('ghcr.io/element-hq/element-desktop-dockerbuild:{0}', github.ref_name == 'master' && 'master' || 'develop') }}
        defaults:
            run:
                shell: bash
        steps:
            - uses: nbucic/variable-mapper@0673f6891a0619ba7c002ecfed0f9f4f39017b6f
              id: config
              with:
                  key: "${{ inputs.arch }}"
                  export_to: output
                  map: |
                      {
                        "amd64": {
                          "target": "x86_64-unknown-linux-gnu",
                          "arch": "x86-64"
                        },
                        "arm64": {
                          "target": "aarch64-unknown-linux-gnu",
                          "arch": "aarch64",
                          "build-args": "--arm64"
                        }
                      }

            - uses: actions/checkout@v4

            - uses: actions/download-artifact@v4
              with:
                  name: webapp

            - name: Cache .hak
              id: cache
              uses: actions/cache@v4
              with:
                  key: ${{ runner.os }}-${{ inputs.docker-image || github.ref_name }}-${{ inputs.sqlcipher }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion') }}
                  path: |
                      ./.hak

            - uses: actions/setup-node@v4
              with:
                  node-version-file: package.json
                  cache: "yarn"
              env:
                  # Workaround for https://github.com/actions/setup-node/issues/317
                  FORCE_COLOR: 0

            # Does not need branch matching as only analyses this layer
            - name: Install Deps
              run: "yarn install --frozen-lockfile"

            - name: Prepare for static sqlcipher build
              if: inputs.sqlcipher == 'static'
              run: |
                  echo "SQLCIPHER_BUNDLED=1" >> $GITHUB_ENV

            # Ideally the docker image would be ready for cross-compilation but libsqlcipher-dev is not Multi-Arch compatible
            # https://unix.stackexchange.com/a/349359
            - name: Prepare for cross compilation
              if: steps.cache.outputs.cache-hit != 'true' && inputs.arch == 'arm64'
              run: |
                  set -x
                  dpkg --add-architecture arm64
                  apt-get -qq update
                  apt-get -qq install --no-install-recommends crossbuild-essential-arm64 libsqlcipher-dev:arm64 libssl-dev:arm64 libsecret-1-dev:arm64
                  rustup target add aarch64-unknown-linux-gnu
                  mv dockerbuild/aarch64/.cargo .
                  cat dockerbuild/aarch64/.env >> $GITHUB_ENV

            - name: Build Natives
              if: steps.cache.outputs.cache-hit != 'true'
              run: "yarn build:native --target ${{ steps.config.outputs.target }}"

            - name: "[Nightly] Resolve version"
              if: inputs.version != ''
              run: |
                  echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV

            - name: Generate debian files and arguments
              run: |
                  if [ -f changelog.Debian ]; then
                      echo "ED_DEBIAN_CHANGELOG=changelog.Debian" >> $GITHUB_ENV
                  fi

            - name: Build App
              run: |
                  yarn build --publish never -l ${{ steps.config.outputs.build-args }}

            - name: Check native libraries
              run: |
                  set -x
                  shopt -s globstar

                  FILES=$(file dist/**/*.node)
                  echo "$FILES"

                  if [ grep -v "$ARCH" ]; then
                      exit 1
                  fi

                  LIBS=$(readelf -d dist/**/*.node | grep NEEDED)
                  echo "$LIBS"

                  set +x
                  assert_contains_string() { [[ "$1" == *"$2"* ]]; }
                  ! assert_contains_string "$LIBS" "libcrypto.so.1.1"
                  if [ "$SQLCIPHER_BUNDLED" == "1" ]; then
                      ! assert_contains_string "$LIBS" "libsqlcipher.so.0"
                  else
                      assert_contains_string "$LIBS" "libsqlcipher.so.0"
                  fi
              env:
                  ARCH: ${{ steps.config.outputs.arch }}

            # We exclude *-unpacked as it loses permissions and the tarball contains it with correct permissions
            - name: Upload Artifacts
              uses: actions/upload-artifact@v4
              with:
                  name: linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }}
                  path: |
                      dist
                      !dist/*-unpacked/**
                  retention-days: 1