# Tags used
#
# docker: Runner supports docker-in-docker.

workflow:
    rules:
        - if: $CI_MERGE_REQUEST_IID
        - if: $CI_COMMIT_TAG
        - if: $CI_COMMIT_BRANCH == "master"

variables:
  CARGO_HOME: $CI_PROJECT_DIR/cargo
  APT_CACHE_DIR: $CI_PROJECT_DIR/apt-cache

image: dagurval/rostrum-buildenv

cache:
  key:
    files:
      - Cargo.lock
    prefix: $CI_JOB_NAME
  paths:
    - $CARGO_HOME
    - $APT_CACHE_DIR
    - target
  when: always

.cleanup_common:
  after_script:
    # Make sure cached dirs exist, so that CI doesn't warn about them.
    - mkdir -p $CARGO_HOME
    - mkdir -p $APT_CACHE_DIR
    - mkdir -p target

    # Limit rust cache size to 500MB and build files to at most 4GB
    - if type cargo > /dev/null; then
        cargo cache trim --limit 500M;
        cargo sweep --maxsize 4000 > /dev/null;
      fi
  artifacts:
    expire_in: 1 week

.test_common:
  extends: .cleanup_common
  variables:
    RUSTC_BOOTSTRAP: 1 # required for cargo2junit

  before_script:
    - rustc --version
    - cargo --version
    - export PATH=$PATH:$CARGO_HOME/bin

  after_script:
    - |
      if grep -q "Unable to bind to\|Binding RPC on address.*failed" $CI_JOB_LOG_PATH; then
        echo "Tests failed due to port conflicts; flagging for retry"
        exit 75  # magic restart code
      fi

  # magic "port failure" exit code
  retry:
    max: 2
    when:
    exit_codes: 75

  artifacts:
    reports:
      junit: results.xml
    when: always

.install_dependencies_common:
  extends: .cleanup_common
  before_script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update
    - apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      clang cmake curl make llvm libclang-dev > /dev/null

    - export PATH=$PATH:$CARGO_HOME/bin
    - rustc --version
    - cargo --version
    - if [ $INSTALL_JUNIT ]; then
        cargo install cargo2junit;
      fi
    - cargo install cargo-cache
    - cargo install cargo-sweep

.nightly_common:
  extends: .install_dependencies_common
  image: rustlang/rust:nightly-buster-slim

.msvr_common:
  extends: .install_dependencies_common
  image: rust:1.88-bookworm

.python_common:
  image: python:slim-bookworm
  cache:
    key: $CI_JOB_NAME
    paths:
      - cache-pip
  variables:
    PIP_CACHE_DIR: $CI_PROJECT_DIR/cache-pip

.qa_common:
  extends: .python_common
  # allow qa tests to retry due to port conflicts
  retry: 2

.win64_common:
  extends: .cleanup_common
  variables:
    # Run tests using wine
    CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER: /usr/lib/wine64
    WINEPATH: "/usr/lib/gcc/x86_64-w64-mingw32/12-posix/;/usr/x86_64-w64-mingw32/lib/"
    RUST_BACKTRACE: full
  before_script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update > /dev/null
    # Set `variables: INSTALL_COMPILER: 1` in job if compiler is needed
    - if [ $INSTALL_COMPILER ]; then
        apt-get
        -o dir::cache::archives="$APT_CACHE_DIR" install
        -y --no-install-recommends
        gcc-mingw-w64-x86-64-posix
        g++-mingw-w64-x86-64-posix -y > /dev/null;
        rustup target add x86_64-pc-windows-gnu;
      fi

    # Set `variables: INSTALL_EMULATOR: 1` in job if emulator is needed
    - if [ $INSTALL_EMULATOR ]; then
        apt-get
        -o dir::cache::archives="$APT_CACHE_DIR" install
        -y --no-install-recommends
        wine64 -y > /dev/null;
      fi

.aarch64_common:
  extends: .cleanup_common
  before_script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update > /dev/null

    # Set `variables: INSTALL_COMPILER: 1` in job if compiler is needed
    #
    #
    # CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER:
    # For some reason we need to tell rust what is the correct linker.
    # Fixes linker error "Relocations in generic ELF (EM: 183)"
    - if [ $INSTALL_COMPILER ]; then
        apt-get
        -o dir::cache::archives="$APT_CACHE_DIR" install
        -y --no-install-recommends
        gcc-aarch64-linux-gnu
        g++-aarch64-linux-gnu
        libc6-dev-arm64-cross
        -y > /dev/null;
        rustup target add aarch64-unknown-linux-gnu;
        export CPATH=$CPATH:/usr/aarch64-linux-gnu/include;
        export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc;
      fi

    # Set `variables: INSTALL_EMULATOR: 1` in job if emulator is needed
    - if [ $INSTALL_EMULATOR ]; then
        export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64-static;
        export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/;
        apt-get
            -o dir::cache::archives="$APT_CACHE_DIR" install
            -y --no-install-recommends
            libc6-arm64-cross
            libstdc++6-arm64-cross
            qemu-user-static
            > /dev/null;
      fi

.musl_x86_64_common:
  extends: .cleanup_common
  cache:
    paths:
      - x86_64-linux-musl-cross.tgz
  before_script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget > /dev/null
    - wget --quiet --continue https://musl.cc/x86_64-linux-musl-cross.tgz
    - tar -xzf x86_64-linux-musl-cross.tgz -C /usr

    # Set `variables: INSTALL_COMPILER: 1` in job if compiler is needed
    #
    #
    # CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER:
    # For some reason we need to tell rust what is the correct linker.
    # Fixes linker error "Relocations in generic ELF (EM: 183)"
    - if [ $INSTALL_COMPILER ]; then
        rustup target add x86_64-unknown-linux-musl;
        export PATH=$PATH:/usr/x86_64-linux-musl-cross/bin
        export CPATH=$CPATH:/usr/x86_64-linux-musl-cross/include;
        export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-musl-gcc;
      fi

    # Set `variables: INSTALL_EMULATOR: 1` in job if emulator is needed
    - if [ $INSTALL_EMULATOR ]; then
        export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUNNER=qemu-x86_64-static;
        export QEMU_LD_PREFIX=/usr/x86_64-linux-musl-cross/;
        export PATH=$PATH:/usr/x86_64-linux-musl-cross/bin
        export CPATH=$CPATH:/usr/x86_64-linux-musl-cross/include;
        apt-get
            -o dir::cache::archives="$APT_CACHE_DIR" install
            -y --no-install-recommends
            qemu-user-static
            > /dev/null;
      fi

.musl_aarch64_common:
  extends: .cleanup_common
  cache:
    paths:
      - aarch64-linux-musl-cross.tgz
  before_script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget > /dev/null
    - wget --quiet --continue https://musl.cc/aarch64-linux-musl-cross.tgz
    - tar -xzf aarch64-linux-musl-cross.tgz -C /usr

    # Set `variables: INSTALL_COMPILER: 1` in job if compiler is needed
    #
    #
    # CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER:
    # For some reason we need to tell rust what is the correct linker.
    # Fixes linker error "Relocations in generic ELF (EM: 183)"
    - if [ $INSTALL_COMPILER ]; then
        rustup target add aarch64-unknown-linux-musl;
        export PATH=$PATH:/usr/aarch64-linux-musl-cross/bin
        export CPATH=/usr/aarch64-linux-musl-cross/include:/usr/aarch64-linux-musl-cross/aarch64-linux-musl/include:$CPATH;
        export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-musl-gcc;
      fi

    # Set `variables: INSTALL_EMULATOR: 1` in job if emulator is needed
    - if [ $INSTALL_EMULATOR ]; then
        export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUNNER=qemu-aarch64-static;
        export QEMU_LD_PREFIX=/usr/aarch64-linux-musl-cross/;
        export PATH=$PATH:/usr/aarch64-linux-musl-cross/bin
        export CPATH=/usr/aarch64-linux-musl-cross/include:/usr/aarch64-linux-musl-cross/aarch64-linux-musl/include:$CPATH;
        apt-get
            -o dir::cache::archives="$APT_CACHE_DIR" install
            -y --no-install-recommends
            qemu-user-static
            > /dev/null;
      fi

.docker_common:
  # Environment based on workarounds in this issue:
  # https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27300
  image: docker
  tags:
    - docker
  cache: {}
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ""
  services:
    - name: docker:dind
      alias: docker
      command: ["--tls=false"]
  rules:
    - if: $CI_COMMIT_BRANCH == "master"
  # Until issue #234 is resolved
  allow_failure: true

#
# Builds
#
build-stable-bch-linux64:
  extends: .cleanup_common
  script:
    - cargo build --release --locked --features=fail-on-warnings,bch
      --target=x86_64-unknown-linux-gnu
  artifacts:
    paths:
      - target/x86_64-unknown-linux-gnu/release/rostrum

build-stable-nexa-linux64:
  extends: .cleanup_common
  script:
    - cargo build --release --locked --features=fail-on-warnings,nexa
      --target=x86_64-unknown-linux-gnu
  artifacts:
    paths:
      - target/x86_64-unknown-linux-gnu/release/rostrum

build-stable-nexa-linux64-musl:
  extends: .musl_x86_64_common
  variables:
    INSTALL_COMPILER: 1
  script:
    - cargo build --release --locked --features=fail-on-warnings,nexa
      --target=x86_64-unknown-linux-musl
  artifacts:
    paths:
      - target/x86_64-unknown-linux-musl/release/rostrum

build-stable-bch-win64:
  extends: .win64_common
  variables:
    INSTALL_COMPILER: 1
  script:
    - cargo build --release --locked
        --features=fail-on-warnings,bch --target=x86_64-pc-windows-gnu
    - cp /usr/lib/gcc/x86_64-w64-mingw32/12-posix/*.dll target/x86_64-pc-windows-gnu/release/
    - cp /usr/x86_64-w64-mingw32/lib/*.dll target/x86_64-pc-windows-gnu/release/
  artifacts:
    paths:
      - target/x86_64-pc-windows-gnu/release/rostrum.exe
      - target/x86_64-pc-windows-gnu/release/libwinpthread-1.dll
      - target/x86_64-pc-windows-gnu/release/libgcc_s_seh-1.dll
      - target/x86_64-pc-windows-gnu/release/libstdc++-6.dll

build-stable-nexa-win64:
  extends: .win64_common
  variables:
    INSTALL_COMPILER: 1
  script:
    - cargo build --release --locked
        --features=fail-on-warnings,nexa --target=x86_64-pc-windows-gnu
    - cp /usr/lib/gcc/x86_64-w64-mingw32/12-posix/*.dll target/x86_64-pc-windows-gnu/release/
    - cp /usr/x86_64-w64-mingw32/lib/*.dll target/x86_64-pc-windows-gnu/release/
  artifacts:
    paths:
      - target/x86_64-pc-windows-gnu/release/rostrum.exe
      - target/x86_64-pc-windows-gnu/release/*.dll

build-stable-bch-linux-aarch64:
  variables:
    INSTALL_COMPILER: 1
  extends: .aarch64_common
  script:
    - cargo build --release --locked
        --features=fail-on-warnings,bch --target=aarch64-unknown-linux-gnu
  artifacts:
    paths:
      - target/aarch64-unknown-linux-gnu/release/rostrum

build-stable-nexa-linux-aarch64:
  variables:
    INSTALL_COMPILER: 1
  extends: .aarch64_common
  script:
    - cargo build --release --locked
        --features=fail-on-warnings,nexa --target=aarch64-unknown-linux-gnu
  artifacts:
    paths:
      - target/aarch64-unknown-linux-gnu/release/rostrum

build-stable-nexa-linux-aarch64-musl:
  variables:
    INSTALL_COMPILER: 1
  extends: .musl_aarch64_common
  script:
    - cargo build --release --locked
        --features=fail-on-warnings,nexa --target=aarch64-unknown-linux-musl
  artifacts:
    paths:
      - target/aarch64-unknown-linux-musl/release/rostrum

build-stable-no-default:
  extends: .cleanup_common
  before_script:
    - rustc --version
    - cargo --version
  script:
    - cargo build --features=fail-on-warnings,bch --no-default-features
  artifacts:
    paths:
      - target/debug/rostrum
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

build-nightly:
  extends: .nightly_common
  script:
    - cargo build --features=fail-on-warnings,bch
  artifacts:
    paths:
      - target/debug/rostrum
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

# The minimum rust version rostrum can be built with
# If bumped, also update doc/build.md
build-msrv:
  extends: .msvr_common
  script:
    - cargo build

build-nightly-nexa:
  extends: .nightly_common
  script:
    - cargo build --features=fail-on-warnings,nexa
  artifacts:
    paths:
      - target/debug/rostrum
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

build-docker:
  extends: .docker_common
  script:
    - docker build --build-arg BUILD_FEATURES=bch -t rostrum-app .

build-docker-nexa:
  extends: .docker_common
  script:
    - docker build --build-arg BUILD_FEATURES=nexa -t rostrum-app .

#
# Linters
#
lint-code-style:
  image: rust:slim
  cache:
    paths:
      - $CARGO_HOME
  script:
    - time rustup component add rustfmt
    - cargo fmt --all -- --check

lint-clippy:
  extends: .cleanup_common
  before_script:
    - rustup component add clippy
  script:
    - cargo clippy --features=bch -- -D warnings

lint-clippy-nexa:
  extends: .cleanup_common
  before_script:
    - rustup component add clippy
  script:
    - cargo clippy --features=nexa -- -D warnings

lint-bloat:
  extends: .cleanup_common
  rules:
    - if: $CI_COMMIT_BRANCH == "master"
  script:
    # Biggest functions
    - cargo bloat --release

    # Biggest dependencies
    - cargo bloat --release --crates

    # Longest to compile
    - cargo bloat --time -j 1

lint-udeps:
  extends: .nightly_common
  script:
    - apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      pkg-config libssl-dev > /dev/null
    - cargo install cargo-udeps --locked
    - cargo +nightly udeps
  # Installing udeps failing (sometimes) on nightly
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

lint-audit:
  extends: .cleanup_common
  before_script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update > /dev/null
    - apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      pkg-config libssl-dev > /dev/null
    - cargo install cargo-audit
  script:
    # RUSTSEC-2023-0089: atomic-polyfill unmaintained, dependency of postcard via heapless
    # RUSTSEC-2024-0436: paste unmaintained, dependency of tikv-jemalloc-ctl
    - cargo audit
      --ignore RUSTSEC-2023-0089
      --ignore RUSTSEC-2024-0436
  rules:
    - if: $CI_COMMIT_BRANCH == "master"


lint-py-codestyle:
  extends: .python_common
  before_script:
    - pip install black
  script:
    - (cd test; black --check .)

lint-py-pylint:
  extends: .python_common
  before_script:
    - pip install pylint psutil
  script:
    - (cd test; pylint functional)
#
# Tests
#
test-stable-bch-linux64:
  extends: .test_common
  script:
    - cargo test
        --target=x86_64-unknown-linux-gnu
        --features=fail-on-warnings,bch
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-stable-nexa-linux64-musl:
  extends:
    - .test_common
    - .musl_x86_64_common
  variables:
    INSTALL_COMPILER: 1
    INSTALL_EMULATOR: 1
  script:
    - cargo test
        --target=x86_64-unknown-linux-musl
        --features=fail-on-warnings,nexa
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-stable-nexa-linux64:
  extends: .test_common
  script:
    - cargo test
        --target=x86_64-unknown-linux-gnu
        --features=fail-on-warnings,nexa
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-stable-bch-win64:
  extends:
    - .test_common
    - .win64_common
  variables:
    INSTALL_COMPILER: 1
    INSTALL_EMULATOR: 1
  script:
    - cargo test
        --target=x86_64-pc-windows-gnu
        --features=fail-on-warnings,bch
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

  # dep rocksdb 0.22 fails to build
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

test-stable-nexa-win64:
  extends:
    - .test_common
    - .win64_common
  variables:
    INSTALL_COMPILER: 1
    INSTALL_EMULATOR: 1
  script:
    - cargo test
        --target=x86_64-pc-windows-gnu
        --features=fail-on-warnings,nexa
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml
  # dep rocksdb 0.22 fails to build
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

test-stable-bch-linux-aarch64:
  variables:
    INSTALL_COMPILER: 1
    INSTALL_EMULATOR: 1
  extends:
    - .test_common
    - .aarch64_common
  script:
    - cargo test
        --target=aarch64-unknown-linux-gnu
        --features=fail-on-warnings,bch
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-stable-nexa-linux-aarch64:
  variables:
    INSTALL_COMPILER: 1
    INSTALL_EMULATOR: 1
  extends:
    - .test_common
    - .aarch64_common
  script:
    - cargo test
        --target=aarch64-unknown-linux-gnu
        --features=fail-on-warnings,nexa
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-stable-nexa-linux-aarch64-musl:
  variables:
    INSTALL_COMPILER: 1
    INSTALL_EMULATOR: 1
  extends:
    - .test_common
    - .musl_aarch64_common
  script:
    - cargo test
        --target=aarch64-unknown-linux-musl
        --features=fail-on-warnings,nexa
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-stable-no-default:
  extends: .test_common
  script:
    - cargo test
        --features=fail-on-warnings,bch
        --no-default-features
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

test-nightly-bch:
  variables:
    INSTALL_JUNIT: 1
  extends:
    - .test_common
    - .nightly_common
  script:
    - cargo test
        --features=fail-on-warnings,bch
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

test-nightly-nexa:
  variables:
    INSTALL_JUNIT: 1
  extends:
    - .test_common
    - .nightly_common
  script:
    - cargo test
        --features=fail-on-warnings,nexa
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

bench-nightly:
  extends:
    - .nightly_common
  script:
    - cargo bench
        --features=fail-on-warnings,with-benchmarks

  # Allow failure because it uses nightly
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

test-msrv:
  variables:
    INSTALL_JUNIT: 1
  extends:
    - .test_common
    - .msvr_common
  script:
    - cargo test
        --features=fail-on-warnings
        --
        -Z unstable-options --format json --report-time
        | cargo2junit > results.xml

test-qa-nexa-linux-x86_64:
  extends: .qa_common
  cache:
    paths:
      - nexa-2.0.0.0-linux64.tar.gz
  variables:
    RUST_BACKTRACE: 1
  dependencies:
    - build-stable-nexa-linux64
  needs: [build-stable-nexa-linux64]
  before_script:
    - pip install -q psutil websockets
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget > /dev/null
  script:
    # Download latest build from Nexa CI/CD
    - wget --quiet --continue
      "https://www.bitcoinunlimited.info/nexa/2.0.0.0/nexa-2.0.0.0-linux64.tar.gz"
    - tar -zvxf nexa-2.0.0.0-linux64.tar.gz

    # Run tests
    - export NODE_PATH=`pwd`/nexa-2.0.0.0/bin/nexad
    - export ROSTRUM_PATH=`pwd`/target/x86_64-unknown-linux-gnu/release/rostrum
    - ./test/functional/test_runner.py
        -parallel=`nproc`
        --no-ipv6-rpc-listen
        --gitlab

test-qa-nexa-linux-x86_64-tcpssl:
  extends: test-qa-nexa-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_TCP_SSL: 1

test-qa-nexa-linux-x86_64-websocket-ssl:
  extends: test-qa-nexa-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_WEBSOCKET_SSL: 1

test-qa-nexa-linux-x86_64-http:
  extends: test-qa-nexa-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_HTTP: 1

test-qa-nexa-linux-x86_64-https:
  extends: test-qa-nexa-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_HTTPS: 1

test-qa-bchn-linux-x86_64:
  cache:
    paths:
      - bitcoin-cash-node-28.0.1-x86_64-linux-gnu.tar.gz
  variables:
    RUST_BACKTRACE: 1
  extends: .qa_common
  dependencies:
    - build-stable-bch-linux64
  needs: [build-stable-bch-linux64]
  before_script:
    - pip install -q psutil websockets
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget > /dev/null
  script:
    - wget --quiet --continue
      "https://github.com/bitcoin-cash-node/bitcoin-cash-node/releases/download/v28.0.1/bitcoin-cash-node-28.0.1-x86_64-linux-gnu.tar.gz"
    - tar -zvxf bitcoin-cash-node-28.0.1-x86_64-linux-gnu.tar.gz

    - export NODE_PATH=`pwd`/bitcoin-cash-node-28.0.1/bin/bitcoind
    - export ROSTRUM_PATH=`pwd`/target/x86_64-unknown-linux-gnu/release/rostrum
    - ./test/functional/test_runner.py
      -parallel=`nproc`
      --gitlab

test-qa-bchn-linux-x86_64-tcpssl:
  extends: test-qa-bchn-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_TCP_SSL: 1

test-qa-bchn-linux-x86_64-websocket:
  extends: test-qa-bchn-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_WEBSOCKET: 1

test-qa-bchn-linux-x86_64-websocket-ssl:
  extends: test-qa-bchn-linux-x86_64
  variables:
    RUST_BACKTRACE: 1
    ROSTRUM_TEST_WEBSOCKET_SSL: 1

test-qa-bchn-linux-x86_64-http:
  extends: test-qa-bchn-linux-x86_64
  variables:
    ROSTRUM_TEST_HTTP: 1

test-qa-bchn-linux-x86_64-https:
  extends: test-qa-bchn-linux-x86_64
  variables:
    ROSTRUM_TEST_HTTPS: 1

# Run tests with aarch64 emulation
test-qa-bchn-linux-aarch64:
  cache:
    paths:
      - bitcoin-cash-node-28.0.1-aarch64-linux-gnu.tar.gz
  variables:
    RUST_BACKTRACE: 1
    INSTALL_EMULATOR: 1
  extends:
    - .qa_common
    - .aarch64_common
  dependencies:
    - build-stable-bch-linux-aarch64
  needs: [build-stable-bch-linux-aarch64]
  script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget > /dev/null
    - pip install -q psutil
    - wget --quiet --continue
      "https://github.com/bitcoin-cash-node/bitcoin-cash-node/releases/download/v28.0.1/bitcoin-cash-node-28.0.1-aarch64-linux-gnu.tar.gz"
    - tar -zvxf bitcoin-cash-node-28.0.1-aarch64-linux-gnu.tar.gz

      # Run tests
      # When spaned by bitcoind, QEMU_LD_PREFIX (set by aarch64_common) is no visible
      # in rostrums environment.
    - export NO_SPAWN_ROSTRUM=1
    - export PROCESS_WRAPPER=`which qemu-aarch64-static`
    - export NODE_PATH=`pwd`/bitcoin-cash-node-28.0.1/bin/bitcoind
    - export ROSTRUM_PATH=`pwd`/target/aarch64-unknown-linux-gnu/release/rostrum
    - ./test/functional/test_runner.py
        -parallel=`nproc`
        --no-ipv6-rpc-listen
        --gitlab

# Run tests with aarch64 emulation
test-qa-nexa-linux-aarch64:
  cache:
    paths:
      - nexa-2.0.0.0-arm64.tar.gz
  variables:
    RUST_BACKTRACE: 1
    INSTALL_EMULATOR: 1
  extends:
    - .qa_common
    - .aarch64_common
  dependencies:
    - build-stable-nexa-linux-aarch64
  needs: [build-stable-nexa-linux-aarch64]
  script:
    - pip install -q psutil
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget > /dev/null
    - wget --quiet --continue
      "https://www.bitcoinunlimited.info/nexa/2.0.0.0/nexa-2.0.0.0-arm64.tar.gz"
    - tar -zvxf nexa-2.0.0.0-arm64.tar.gz

      # Run tests
      # When spaned by bitcoind, QEMU_LD_PREFIX (set by aarch64_common) is no visible
      # in rostrums environment.
    - export NO_SPAWN_ROSTRUM=1
    - export PROCESS_WRAPPER=`which qemu-aarch64-static`
    - export NODE_PATH=`pwd`/nexa-2.0.0.0/bin/nexad
    - export ROSTRUM_PATH=`pwd`/target/aarch64-unknown-linux-gnu/release/rostrum
    - ./test/functional/test_runner.py
        -parallel=`nproc`
        --no-ipv6-rpc-listen
        --gitlab

# Run tests with win64 emulation
test-qa-nexa-win64:
  cache:
    paths:
      - nexa-2.0.0.0-win64.zip
  variables:
    INSTALL_EMULATOR: 1
  extends:
    - .qa_common
    - .win64_common
  dependencies:
    - build-stable-nexa-win64
  needs: [build-stable-nexa-win64]
  script:
    - pip install -q psutil
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      wget unzip > /dev/null
    - wget --quiet --continue "https://www.bitcoinunlimited.info/nexa/2.0.0.0/nexa-2.0.0.0-win64.zip"
    - unzip -x nexa-2.0.0.0-win64.zip

    - export NO_SPAWN_ROSTRUM=1
    - export PROCESS_WRAPPER=`which wine64-stable`
    - export NODE_PATH=`pwd`/nexa-2.0.0.0/bin/nexad.exe
    - export ROSTRUM_PATH=`pwd`/target/x86_64-pc-windows-gnu/release/rostrum.exe
    # Mitigate random disconencts / connection problems with parallel 1 and retry
    - ./test/functional/test_runner.py
        -parallel=1
        --no-ipv6-rpc-listen
        --gitlab
  # CI version of wine not compatible with tokio, see: https://github.com/tokio-rs/mio/issues/1444
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

#
# Published artifacts
#
generate-rustdoc:
  extends: .cleanup_common
  script:
    - cargo doc --no-deps -p rostrum
    - cargo rustdoc -p rostrum
  artifacts:
    paths:
      - target/doc
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

generate-mkdocs:
  extends: .python_common
  before_script:
    - pip install -q mkdocs
    - pip install -q mkdocs-material
    - pip install -q toml
    - pip install -q mkdocs-site-urls
  script:
    - ./contrib/build-docs.py
  artifacts:
    paths:
      - build-docs

archive-builds-bch:
  extends: .python_common
  needs:
    - build-stable-bch-linux64
    - build-stable-bch-win64
    - build-stable-bch-linux-aarch64
  before_script:
    - pip install -q toml
  script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      zip git -y > /dev/null
    - ROSTRUM_VERSION=`./contrib/read-version-number.py`
    - GIT_HEAD=`git rev-parse --short HEAD`
    - ROSTRUM_VERSION="$ROSTRUM_VERSION-$GIT_HEAD"
    - mkdir -p output
    - gzip -c target/x86_64-unknown-linux-gnu/release/rostrum
        > "output/rostrum-bitcoincash-linux-x86-64-$ROSTRUM_VERSION.gz"
    - gzip -c target/aarch64-unknown-linux-gnu/release/rostrum
        > "output/rostrum-bitcoincash-linux-arm64-$ROSTRUM_VERSION.gz"
    - zip
        "output/rostrum-bitcoincash-windows-x86-64-$ROSTRUM_VERSION.zip"
        target/x86_64-pc-windows-gnu/release/rostrum.exe
        target/x86_64-pc-windows-gnu/release/*.dll
  artifacts:
    paths:
      - output

archive-builds-nexa:
  extends: .python_common
  needs:
    - build-stable-nexa-linux64
    - build-stable-nexa-linux64-musl
    - build-stable-nexa-win64
    - build-stable-nexa-linux-aarch64
    - build-stable-nexa-linux-aarch64-musl
  before_script:
    - pip install -q toml
  script:
    - mkdir -pv $APT_CACHE_DIR
    - apt-get update && apt-get
      -o dir::cache::archives="$APT_CACHE_DIR" install
      -y --no-install-recommends
      zip git -y > /dev/null
    - ROSTRUM_VERSION=`./contrib/read-version-number.py`
    - GIT_HEAD=`git rev-parse --short HEAD`
    - ROSTRUM_VERSION="$ROSTRUM_VERSION-$GIT_HEAD"
    - mkdir -p output
    - gzip -c target/x86_64-unknown-linux-gnu/release/rostrum
        > "output/rostrum-nexa-linux-x86-64-$ROSTRUM_VERSION.gz"
    - gzip -c target/x86_64-unknown-linux-musl/release/rostrum
        > "output/rostrum-nexa-linux-x86-64-musl-$ROSTRUM_VERSION.gz"
    - gzip -c target/aarch64-unknown-linux-gnu/release/rostrum
        > "output/rostrum-nexa-linux-arm64-$ROSTRUM_VERSION.gz"
    - gzip -c target/aarch64-unknown-linux-musl/release/rostrum
        > "output/rostrum-nexa-linux-arm64-musl-$ROSTRUM_VERSION.gz"
    - zip
        "output/rostrum-nexa-windows-x86-64-$ROSTRUM_VERSION.zip"
        target/x86_64-pc-windows-gnu/release/rostrum.exe
        target/x86_64-pc-windows-gnu/release/*.dll
  artifacts:
    paths:
      - output


pages:
  image: alpine:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "master"
  dependencies:
    - generate-rustdoc
    - generate-mkdocs
    - archive-builds-bch
    - archive-builds-nexa
  needs: [
    generate-rustdoc, generate-mkdocs,
    archive-builds-bch, archive-builds-nexa
  ]
  before_script:
    apk update && apk add tree
  script:
    # from the generate-mkdocs job
    - mv build-docs public
    # from the generate-rustdoc job
    - mv target/doc public/rustdoc
    # from the archive-builds job
    - mv output public/nightly
    # create directory listing
    - (cd public/nightly;
        tree -H '.' -L 1 --noreport --charset utf-8 -o index.html)
    - sed -i 's|href="\.\.|href="/rostrum/nightly|g' public/nightly/index.html
  artifacts:
    paths:
      - public
  cache: {}
