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

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

jobs:
  lint:
    runs-on: ubuntu-22.04-8-cores
    timeout-minutes: 30

    steps:
    - run: lsb_release -a
    - run: uname -a
    - uses: actions/checkout@v4
    - name: Setup node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'
    - run: npm install -g npm@10.2.5

    - name: Restore cached .eslintcache and tsconfig.tsbuildinfo
      uses: actions/cache/restore@v4
      id: cache-lint
      with:
        path: |
          .eslintcache
          tsconfig.tsbuildinfo
        key: lint-${{ runner.os }}-${{ hashFiles('package.json', 'package-lock.json', 'patches/**', '.eslintrc.js', '.eslint/**', 'tsconfig.json') }}

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

    - name: Install Desktop node_modules
      if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
      run: npm ci
      env:
        NPM_CONFIG_LOGLEVEL: verbose

    - run: npm run generate
    - run: npm run lint
    - run: npm run lint-deps
    - run: npm run lint-license-comments

    - name: Check acknowledgments file is up to date
      run: npm run build:acknowledgments
      env:
        REQUIRE_SIGNAL_LIB_FILES: 1

    - run: git diff --exit-code

    - name: Update cached .eslintcache and tsconfig.tsbuildinfo
      uses: actions/cache/save@v4
      if: github.ref == 'refs/heads/main'
      with:
        path: |
          .eslintcache
          tsconfig.tsbuildinfo
        key: ${{ steps.cache-lint.outputs.cache-primary-key }}

  macos:
    needs: lint
    runs-on: macos-latest
    if: github.ref == 'refs/heads/main'
    timeout-minutes: 30

    steps:
    - run: uname -a
    - uses: actions/checkout@v4
    - name: Setup node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'

    - run: npm install -g npm@10.2.5

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

    - name: Install Desktop node_modules
      if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
      run: npm ci
      env:
        NPM_CONFIG_LOGLEVEL: verbose

    - run: npm run generate
    - run: npm run prepare-beta-build
    - run: npm run test-node
    - run: npm run test-electron
      env:
        ARTIFACTS_DIR: artifacts/macos
      timeout-minutes: 5
    - run: touch noop.sh && chmod +x noop.sh
    - run: npm run build
      env:
        DISABLE_INSPECT_FUSE: on
        SIGN_MACOS_SCRIPT: noop.sh
        ARTIFACTS_DIR: artifacts/macos
    - name: Upload installer size
      if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && github.ref == 'refs/heads/main' }}
      run: |
        node ts/scripts/dd-installer-size.js macos-arm64
        node ts/scripts/dd-installer-size.js macos-x64
        node ts/scripts/dd-installer-size.js macos-universal
      env:
        DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}
    - name: Rebuild native modules for x64
      run: npm run electron:install-app-deps
    - run: npm run test-release
      env:
        NODE_ENV: production
    - run: npm run test-eslint

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

  linux:
    needs: lint
    runs-on: ubuntu-22.04-8-cores
    timeout-minutes: 30

    steps:
    - run: lsb_release -a
    - run: uname -a
    - uses: actions/checkout@v4
    - name: Setup node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'
    - run: sudo apt-get install xvfb libpulse0

    - run: npm install -g npm@10.2.5

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

    - name: Install Desktop node_modules
      if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
      run: npm ci
      env:
        NPM_CONFIG_LOGLEVEL: verbose

    - run: npm run generate
    - run: npm run prepare-beta-build

    - name: Create bundle
      run: npm run build:esbuild:prod
    - name: Create preload cache
      run: xvfb-run --auto-servernum npm run build:preload-cache
      env:
        ARTIFACTS_DIR: artifacts/linux

    - name: Build with packaging .deb file
      run: npm run build:release -- --publish=never
      if: github.ref == 'refs/heads/main'
      env:
        DISABLE_INSPECT_FUSE: on
    - name: Build without packaging .deb file
      run: npm run build:release -- --linux dir
      if: github.ref != 'refs/heads/main'
      env:
        DISABLE_INSPECT_FUSE: on

    - name: Upload installer size
      if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && github.ref == 'refs/heads/main' }}
      run: node ts/scripts/dd-installer-size.js linux
      env:
        DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}

    - run: xvfb-run --auto-servernum npm run test-node

    - name: Clone backup integration tests
      uses: actions/checkout@v4
      with:
        repository: 'signalapp/Signal-Message-Backup-Tests'
        ref: '93a7d29527cb33e6bf23bc56fbf74d62cf682001'
        path: 'backup-integration-tests'

    - run: xvfb-run --auto-servernum npm run test-electron
      timeout-minutes: 5
      env:
        ARTIFACTS_DIR: artifacts/linux
        LANG: en_US
        LANGUAGE: en_US
        BACKUP_INTEGRATION_DIR: 'backup-integration-tests/test-cases'
    - run: xvfb-run --auto-servernum npm run test-release
      env:
        NODE_ENV: production

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

  windows:
    needs: lint
    runs-on: windows-2019
    timeout-minutes: 30

    env:
      BUILD_LOCATION: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Tools\\MSVC\\14.29.30133\\lib\\x86\\store\\references\\"
      SDK_LOCATION: "C:\\Program Files (x86)\\Windows Kits\\10\\UnionMetadata\\10.0.17134.0"

    steps:
    - run: systeminfo
    - run: git config --global core.autocrlf false
    - run: git config --global core.eol lf
    - uses: actions/checkout@v4
    - name: Setup node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'
    - run: npm install -g npm@10.2.5 node-gyp@10.0.1

    # Set things up so @nodert-win10-rs4 dependencies build properly
    - run: dir "$env:BUILD_LOCATION"
    - run: dir "$env:SDK_LOCATION"
    - run: "copy \"$env:BUILD_LOCATION\\platform.winmd\" \"$env:SDK_LOCATION\""
    - run: dir "$env:SDK_LOCATION"

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

    - name: Install Desktop node_modules
      if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
      run: npm ci
      env:
        CHILD_CONCURRENCY: 1
        NPM_CONFIG_LOGLEVEL: verbose

    - run: npm run generate
    - run: npm run test-node
    - run: copy package.json temp.json
    - run: del package.json
    - run: type temp.json | findstr /v certificateSubjectName | findstr /v certificateSha1 > package.json
    - run: npm run prepare-beta-build

    - name: Create bundle
      run: npm run build:esbuild:prod
    - name: Create preload cache
      run: npm run build:preload-cache
      env:
        ARTIFACTS_DIR: artifacts/win

    - name: Build with NSIS
      run: npm run build:release
      if: github.ref == 'refs/heads/main'
      env:
        DISABLE_INSPECT_FUSE: on
    - name: Build without NSIS
      run: npm run build:release -- --win dir
      if: github.ref != 'refs/heads/main'
      env:
        DISABLE_INSPECT_FUSE: on

    - name: Upload installer size
      if: ${{ github.repository == 'signalapp/Signal-Desktop-Private' && github.ref == 'refs/heads/main' }}
      run: node ts/scripts/dd-installer-size.js windows
      env:
        DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}

    - run: npm run test-electron
      env:
        ARTIFACTS_DIR: artifacts/windows
      timeout-minutes: 5
    - run: npm run test-release
      env:
        SIGNAL_ENV: production

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

  sticker-creator:
    name: Sticker Creator
    runs-on: ubuntu-22.04-8-cores
    timeout-minutes: 30

    defaults:
      run:
        working-directory: sticker-creator

    steps:
    - uses: actions/checkout@v4
    - name: Setup node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'
        cache: 'npm'
        cache-dependency-path: 'package-lock.json'

    - name: Install Sticker Creator node_modules
      run: npm ci

    - name: Build Sticker Creator
      run: npm run build

    - name: Check Sticker Creator types
      run: npm run check:types

    - name: Check Sticker Creator formatting
      run: npm run prettier:check

    - name: Check Sticker Creator linting
      run: npm run lint

    - name: Run tests
      run: npm test -- --run

  mock-tests:
    needs: lint
    runs-on: ubuntu-22.04-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@v4

    - name: Setup node.js
      uses: actions/setup-node@v4
      with:
        node-version-file: '.nvmrc'
    - name: Install global dependencies
      run: npm install -g npm@10.2.5

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

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

    - name: Install Desktop node_modules
      if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
      run: npm ci
      env:
        NPM_CONFIG_LOGLEVEL: verbose

    - name: Build typescript
      run: npm run generate
    - name: Bundle
      run: npm run build:esbuild:prod
    - name: Create preload cache
      run: xvfb-run --auto-servernum npm run build:preload-cache
      env:
        ARTIFACTS_DIR: artifacts/linux

    - name: Run mock server tests
      run: |
        set -o pipefail
        xvfb-run --auto-servernum npm run test-mock
      timeout-minutes: 10
      env:
        NODE_ENV: production
        DEBUG: mock:test:*
        ARTIFACTS_DIR: artifacts/startup

    - name: Upload mock server test logs on failure
      if: failure()
      uses: actions/upload-artifact@v4
      with:
        name: logs
        path: artifacts
