# Copyright 2020 Signal Messenger, LLC
# SPDX-License-Identifier: AGPL-3.0-only

name: Benchmark
on:
  push:
    branches:
      - development
      - main
      - '[0-9]+.[0-9]+.x'
  pull_request:

jobs:
  linux:
    runs-on: ubuntu-latest-8-cores
    if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' }}
    timeout-minutes: 30

    steps:
    - name: Get system specs
      run: lsb_release -a
    - name: Get other system specs
      run: uname -a

    - name: Clone Desktop repo
      uses: actions/checkout@v3

    - name: Setup node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18.18.2'
    - name: Install global dependencies
      run: npm install -g yarn@1.22.10 npm@10.2.5

    - name: Install xvfb
      run: sudo apt-get install xvfb

    - name: Cache Desktop node_modules
      id: cache-desktop-modules
      uses: actions/cache@v3
      with:
        path: node_modules
        key: ${{ runner.os }}-${{ hashFiles('package.json', 'yarn.lock', 'patches/**') }}

    - name: Install Desktop node_modules
      if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
      run: yarn install --frozen-lockfile
      env:
        NPM_CONFIG_LOGLEVEL: verbose

    - name: Build typescript
      run: yarn generate
    - name: Bundle
      run: yarn build:esbuild:prod

    - name: Run startup benchmarks
      run: |
        set -o pipefail
        xvfb-run --auto-servernum node ts/test-mock/benchmarks/startup_bench.js |
          tee benchmark-startup.log
      timeout-minutes: 10
      env:
        NODE_ENV: production
        RUN_COUNT: 10
        ELECTRON_ENABLE_STACK_DUMPING: on
        ARTIFACTS_DIR: artifacts/startup

    - name: Run send benchmarks
      run: |
        set -o pipefail
        rm -rf /tmp/mock
        xvfb-run --auto-servernum node ts/test-mock/benchmarks/send_bench.js |
          tee benchmark-send.log
      timeout-minutes: 10
      env:
        NODE_ENV: production
        RUN_COUNT: 100
        ELECTRON_ENABLE_STACK_DUMPING: on
        ARTIFACTS_DIR: artifacts/send

    - name: Run group send benchmarks
      run: |
        set -o pipefail
        rm -rf /tmp/mock
        xvfb-run --auto-servernum node \
          ts/test-mock/benchmarks/group_send_bench.js | \
          tee benchmark-group-send.log
      timeout-minutes: 10
      env:
        NODE_ENV: production
        RUN_COUNT: 100
        CONVERSATION_SIZE: 500
        ELECTRON_ENABLE_STACK_DUMPING: on
        ARTIFACTS_DIR: artifacts/group-send

    - name: Run large group send benchmarks with delivery receipts
      run: |
        set -o pipefail
        rm -rf /tmp/mock
        xvfb-run --auto-servernum node \
          ts/test-mock/benchmarks/group_send_bench.js | \
          tee benchmark-large-group-send.log
      timeout-minutes: 10
      env:
        NODE_ENV: production
        GROUP_SIZE: 500
        CONTACT_COUNT: 500
        GROUP_DELIVERY_RECEIPTS: 500
        DISCARD_COUNT: 2
        RUN_COUNT: 20
        CONVERSATION_SIZE: 50
        ELECTRON_ENABLE_STACK_DUMPING: on
        ARTIFACTS_DIR: artifacts/large-group-send

    - name: Run conversation open benchmarks
      run: |
        set -o pipefail
        rm -rf /tmp/mock
        xvfb-run --auto-servernum node \
          ts/test-mock/benchmarks/convo_open_bench.js | \
          tee benchmark-convo-open.log
      timeout-minutes: 10
      env:
        NODE_ENV: production
        RUN_COUNT: 100
        ELECTRON_ENABLE_STACK_DUMPING: on
        ARTIFACTS_DIR: artifacts/convo-open

    - name: Upload benchmark logs on failure
      if: failure()
      uses: actions/upload-artifact@v3
      with:
        name: logs
        path: artifacts

    - name: Clone benchmark repo
      uses: actions/checkout@v3
      with:
        repository: 'signalapp/Signal-Desktop-Benchmarks-Private'
        path: 'benchmark-results'
        token: ${{ secrets.AUTOMATED_GITHUB_PAT }}

    - name: Push benchmark repo
      working-directory: benchmark-results
      run: |
        for attempt in {1..5}; do
          echo "Attempting to push to repository #$attempt"
          git fetch origin
          git reset --hard origin/main
          npm ci
          node ./bin/collect.js ../benchmark-startup.log data/startup.json
          node ./bin/collect.js ../benchmark-send.log data/send.json
          node ./bin/collect.js ../benchmark-group-send.log data/group-send.json
          node ./bin/collect.js ../benchmark-large-group-send.log data/large-group-send.json
          node ./bin/collect.js ../benchmark-convo-open.log data/convo-open.json
          npm run build
          git config --global user.email "no-reply@signal.org"
          git config --global user.name "Signal Bot"
          git add .
          git commit --message "${GITHUB_REF} ${GITHUB_SHA}"
          git push origin main && break || sleep "$((1 + RANDOM % 5))"
        done
