on:
  push:
  pull_request:
  workflow_dispatch:

permissions:
  contents: read

name: Test
jobs:
  test:
    runs-on: ${{ matrix.os }}
    name: "Test Plugin on NodeBB ${{ matrix.nodebb }} (Node.js ${{ matrix.node }}, ${{ matrix.database }}${{ matrix.lint && ', linting enabled' }})"  
    strategy:
      matrix:
        os: [ubuntu-latest]
        node: [20, 22] # versions currently supported by NodeBB
        database: [mongo] # you can add redis and postgres here if you're touching the database more directly
        nodebb: [master, v4.x, v3.x] # branches or tags
        include:
          - os: ubuntu-latest
            node: 22
            database: mongo
            nodebb: master
            lint: true # we only want to lint once
        exclude:
          # pre-release means living on the edge... of LTS releases too I guess
          - nodebb: master
            node: 20
    services:
      postgres:
        image: ${{ startsWith(matrix.database, 'postgres') && 'postgres:15-alpine' || '' }}
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps port 5432 on service container to the host
          - 5432:5432

      redis:
        image: ${{ startsWith(matrix.database, 'redis') && 'redis:7.0.11' || '' }}
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps port 6379 on service container to the host
          - 6379:6379

      mongo:
        image: ${{ startsWith(matrix.database, 'mongo') && 'mongo:3.7' || ''}}
        ports:
          # Maps port 27017 on service container to the host
          - 27017:27017
      meilisearch:
        image: getmeili/meilisearch:latest
        ports:
          - 7700:7700
    steps:
      - uses: actions/checkout@v4
        with:
          repository: NodeBB/NodeBB
          ref: ${{ matrix.nodebb }}
          path: nodebb
      - uses: actions/checkout@v4
        with:
          path: tested-plugin
      - name: Prepare NodeBB package.json
        run: cp install/package.json package.json
        working-directory: nodebb
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - name: Install plugin dependencies
        working-directory: tested-plugin
        run: yarn
      - name: Run ESLint
        if: matrix.lint
        working-directory: tested-plugin
        run: yarn lint
      - name: Get npm cache directory
        id: npm-cache-dir
        shell: bash
        run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}
      - uses: actions/cache@v4
        id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
        with:
          path: ${{ steps.npm-cache-dir.outputs.dir }}
          key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
          restore-keys: |
            ${{ runner.os }}-node-
      - name: Get plugin name
        id: pluginName
        run: echo "NAME=$(node -e "console.log(require('./tested-plugin/package.json').name)")" >> "$GITHUB_OUTPUT"
      - name: Install dependencies
        run: yarn
        working-directory: nodebb
      - name: Install tested plugin
        run: yarn add $GITHUB_WORKSPACE/tested-plugin
        working-directory: nodebb
      - name: Setup on MongoDB
        if: startsWith(matrix.database, 'mongo')
        env:
          SETUP: >-
            {
              "url": "http://127.0.0.1:4567",
              "secret": "abcdef",
              "admin:username": "admin",
              "admin:email": "test@example.org",
              "admin:password": "hAN3Eg8W",
              "admin:password:confirm": "hAN3Eg8W",

              "database": "mongo",
              "mongo:host": "127.0.0.1",
              "mongo:port": 27017,
              "mongo:username": "",
              "mongo:password": "",
              "mongo:database": "nodebb"
            }
          CI: >-
            {
              "host": "127.0.0.1",
              "port": 27017,
              "database": "ci_test"
            }
        run: |
          node app --setup="${SETUP}" --ci="${CI}"
        working-directory: nodebb
      - name: Setup on PostgreSQL
        if: startsWith(matrix.database, 'postgres')
        env:
          SETUP: >-
            {
              "url": "http://127.0.0.1:4567",
              "secret": "abcdef",
              "admin:username": "admin",
              "admin:email": "test@example.org",
              "admin:password": "hAN3Eg8W",
              "admin:password:confirm": "hAN3Eg8W",

              "database": "postgres",
              "postgres:host": "127.0.0.1",
              "postgres:port": 5432,
              "postgres:username": "postgres",
              "postgres:password": "postgres",
              "postgres:database": "nodebb"
            }
          CI: >-
            {
              "host": "127.0.0.1",
              "database": "ci_test",
              "port": 5432,
              "username": "postgres",
              "password": "postgres"
            }
        run: |
          node -e "const { Client } = require('pg'); const c = new Client({ host: '127.0.0.1', port: 5432, user: 'postgres', password: 'postgres' }); c.connect().then(() => c.query('CREATE DATABASE nodebb')).then(() => c.query('CREATE DATABASE ci_test')).then(() => c.end())"
          node app --setup="${SETUP}" --ci="${CI}"
        working-directory: nodebb
      - name: Setup on Redis
        if: startsWith(matrix.database, 'redis')
        env:
          SETUP: >-
            {
              "url": "http://127.0.0.1:4567/forum",
              "secret": "abcdef",
              "admin:username": "admin",
              "admin:email": "test@example.org",
              "admin:password": "hAN3Eg8W",
              "admin:password:confirm": "hAN3Eg8W",
              "database": "redis",
              "redis:host": "127.0.0.1",
              "redis:port": 6379,
              "redis:password": "",
              "redis:database": 0
            }
          CI: >-
            {
              "host": "127.0.0.1",
              "database": 1,
              "port": 6379
            }
        run: |
          node app --setup="${SETUP}" --ci="${CI}"
        working-directory: nodebb
      - name: Add tested plugin to config
        run: jq '.test_plugins = ["${{ steps.pluginName.outputs.NAME }}"]' config.json > config.json.tmp && mv config.json.tmp config.json
        working-directory: nodebb
      - name: Run tests
        run: npm test test/plugins-installed.js
        working-directory: nodebb
