name: Update Plugin and Run Tests

on:
  pull_request:
    branches: ["main", "stable-*"]
    types:
      - opened
      - reopened
      - ready_for_review
  workflow_dispatch: # Allows manual triggering from the GitHub Actions interface
    inputs:
      trigger_api_tests_workflow:
        description: "Set to false if you want to skip running api tests. Set to true by default"
        required: false
        default: true
      trigger_playwright_workflow:
        description: "Trigger Playwright workflow once complete"
        required: false
        default: true

# permissions: read-all

jobs:
  update-plugin:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    permissions:
      actions: read
      attestations: read
      checks: read
      contents: read
      deployments: read
      id-token: write
      issues: read
      discussions: read
      packages: read
      pages: read
      pull-requests: read
      repository-projects: read
      security-events: read
      statuses: read
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          ref: ${{ github.head_ref || github.ref }}
          submodules: recursive # Fetch the submodules
          token: ${{ secrets.TESTS_REPOS_ACCESS_PAT }}
          fetch-depth: 0     # Fetch the full history to access submodules
      - name: Wait for other instances of `Update Plugin and Run Tests` Workflow to complete
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OWNER: ${{ github.repository_owner }}
          REPO: ${{ github.event.repository.name }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          CURRENT_RUN_ID: ${{ github.run_id }}
        run: |
          WORKFLOW_ID=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
            https://api.github.com/repos/$OWNER/$REPO/actions/workflows | jq -r '.workflows[] | select(.name == "Update Plugin and Run Tests") | .id')
          if [ -z "$WORKFLOW_ID" ]; then
            echo " `Update Plugin and Run Tests` Workflow not found"
            exit 1
          fi

          echo "Current run id: $CURRENT_RUN_ID"
          while :
          do
            # Get the running workflows with the same workflow ID and exclude the current run
              RUNNING_WORKFLOWS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
                https://api.github.com/repos/$OWNER/$REPO/actions/runs?status=in_progress | grep -B 20 "\"workflow_id\": $WORKFLOW_ID" | grep '"id":' | grep -v "\"id\": $CURRENT_RUN_ID" | awk '{print $2}' | tr -d ',')
            if [ -z "$RUNNING_WORKFLOWS" ]; then
              echo "No other running instances of `Update Plugin and Run Tests` workflow is found, proceeding..."
              break
            else
              echo "Another instance of `Update Plugin and Run Tests` workflow is currently running, waiting..."
              echo "$RUNNING_WORKFLOWS"
              sleep 30
            fi
          done
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.10"

      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "22.13.1"
          registry-url: 'https://npm.pkg.github.com'
          always-auth: true
          scope: '@dataiku'
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Install dependencies
        run: |
          pip install dataiku-api-client
      
      - name: Create .npmrc
        run: |
          echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > ./resource/frontend/.npmrc

      - name: Test delete yarn.lock
        run: rm ./resource/frontend/yarn.lock

      - name: Build plugin from current branch
        run: make dev

      - name: Update Answers Plugin in Test instance
        env:
          DSS_HOST: ${{ secrets.tests_integrations_url }}
          DSS_API_KEY: ${{ secrets.tests_integrations_api_key }}
          PLUGIN_ID: agent-connect
          DSS_PROJECT_KEY: TESTINTEGRATIONPORTALPLUGIN
          DSS_WEBAPP_IDS: "1dFpV4r"
        run: python tests/update_plugin.py

  trigger-api-tests:
    runs-on: ubuntu-latest
    needs: update-plugin
    if: ${{ github.event.inputs.trigger_api_tests_workflow != 'false' }}
    steps:
      - name: Trigger API tests workflow
        id: trigger_api_tests
        run: |
          WORKFLOW_ID="api-tests.yml"
          GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
          OWNER=${{ github.repository_owner }}
          REPO=${{ github.event.repository.name }}
          REF=${{ github.head_ref || github.event.ref }}
          echo "Triggering API tests workflow"
          response=$(curl -s -X POST \
            -H "Accept: application/vnd.github+json" \
            -H "Authorization: Bearer $GITHUB_TOKEN" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            "https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_ID/dispatches" \
            -d "{\"ref\": \"$REF\"}")

          echo "REF: $REF, WORKFLOW_ID: $WORKFLOW_ID"
          echo "Trigger response: $response"

  trigger-playwright-tests:
    runs-on: ubuntu-latest
    needs: update-plugin
    if: ${{ github.event.inputs.trigger_playwright_workflow != 'false' }}
    steps:
      - name: Trigger Playwright tests workflow
        id: trigger_playwright_tests
        run: |
          WORKFLOW_ID="playwright.yml"
          GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
          OWNER=${{ github.repository_owner }}
          REPO=${{ github.event.repository.name }}
          REF=${{ github.head_ref || github.event.ref }}
          echo "Triggering Playwright tests workflow"
          response=$(curl -s -X POST \
            -H "Accept: application/vnd.github+json" \
            -H "Authorization: Bearer $GITHUB_TOKEN" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            "https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_ID/dispatches" \
            -d "{\"ref\": \"$REF\"}")

          echo "REF: $REF, WORKFLOW_ID: $WORKFLOW_ID"
          echo "Trigger response: $response"

  wait-for-api-tests:
    runs-on: ubuntu-latest
    needs: trigger-api-tests
    if: ${{ github.event.inputs.trigger_api_tests_workflow != 'false' }}
    steps:
      - name: Wait for API tests to complete
        id: wait_for_api_tests
        run: |
          # Define variables
          OWNER="${{ github.repository_owner }}"
          REPO="${{ github.event.repository.name }}"
          REF=${{ github.head_ref || github.event.ref }}
          BRANCH=$REF
          if [[ "$BRANCH" == refs/heads/* ]]; then
            BRANCH=${REF#refs/heads/}
          fi
          WORKFLOW_NAME="Run API tests"
          echo "Owner: $OWNER, Repo: $REPO, REF: $REF, BRANCH: $BRANCH"

          WORKFLOW_ID=

          get_workflow_id() {
            echo "Getting workflow Id..."
            WORKFLOW_DISPATCH_RUNS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              "https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&status=in_progress")
            echo "workflow_dispatch_runs runs: $WORKFLOW_DISPATCH_RUNS"
            # Extract the ID of the specific workflow run
            WORKFLOW_ID=$(echo "$WORKFLOW_DISPATCH_RUNS" | jq -r --arg WORKFLOW_NAME "$WORKFLOW_NAME" '.workflow_runs | map(select(.name == $WORKFLOW_NAME)) | .[0].id')

            echo "Workflow ID: $WORKFLOW_ID"
          }

          # Function to poll the status of the workflow run
          poll_workflow_status() {
            sleep 30
            get_workflow_id
            if [ -z "$WORKFLOW_ID" ] || [ "$WORKFLOW_ID" = "null" ]; then
              sleep 60
              # retry
              get_workflow_id
              if [ -z "$WORKFLOW_ID" ] || [ "$WORKFLOW_ID" = "null" ]; then
                sleep 180
                # retry
                get_workflow_id
                if [ -z "$WORKFLOW_ID" ] || [ "$WORKFLOW_ID" = "null" ]; then
                  echo "Workflow not found"
                  exit 1
                fi
              fi
            fi
            status=""
            conclusion=""
            while [[ "$status" != "completed" ]]; do
              sleep 30
              echo "Checking workflow status..."
              response=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              "https://api.github.com/repos/$OWNER/$REPO/actions/runs/$WORKFLOW_ID")
              echo "Response to https://api.github.com/repos/$OWNER/$REPO/actions/runs/$WORKFLOW_ID from GitHub API: $response"

              # Extract the status and conclusion of the workflow run
              status=$(echo "$response" | jq -r '.status')
              conclusion=$(echo "$response" | jq -r '.conclusion')
              echo "Current Workflow Status: $status, Conclusion: $conclusion"

            done

            echo "Workflow concluded with status: $conclusion"
            echo "::set-output name=status::$conclusion"
            if [ "$conclusion" != "success" ]; then
              echo "API tests failed"
              exit 1
            fi
          }

          # Poll the workflow status
          poll_workflow_status

  wait-for-playwright-tests:
    runs-on: ubuntu-latest
    needs: trigger-playwright-tests
    if: ${{ github.event.inputs.trigger_playwright_workflow != 'false' }}
    steps:
      - name: Wait for Playwright tests to complete
        id: wait_for_playwright_tests
        run: |
          # Define variables
          OWNER="${{ github.repository_owner }}"
          REPO="${{ github.event.repository.name }}"
          REF=${{ github.head_ref || github.event.ref }}
          BRANCH=$REF
          if [[ "$BRANCH" == refs/heads/* ]]; then
            BRANCH=${REF#refs/heads/}
          fi
          WORKFLOW_NAME="Run Playwright Tests"
          echo "Owner: $OWNER, Repo: $REPO, REF: $REF, BRANCH: $BRANCH"

          WORKFLOW_ID=

          get_workflow_id() {
            echo "Getting workflow Id..."
            WORKFLOW_DISPATCH_RUNS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              "https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&status=in_progress")
            echo "workflow_dispatch_runs runs: $WORKFLOW_DISPATCH_RUNS"
            # Extract the ID of the specific workflow run
            WORKFLOW_ID=$(echo "$WORKFLOW_DISPATCH_RUNS" | jq -r --arg WORKFLOW_NAME "$WORKFLOW_NAME" '.workflow_runs | map(select(.name == $WORKFLOW_NAME)) | .[0].id')

            echo "Workflow ID: $WORKFLOW_ID"
          }

          # Function to poll the status of the workflow run
          poll_workflow_status() {
            sleep 30
            get_workflow_id
            if [ -z "$WORKFLOW_ID" ] || [ "$WORKFLOW_ID" = "null" ]; then
              sleep 60
              # retry
              get_workflow_id
              if [ -z "$WORKFLOW_ID" ] || [ "$WORKFLOW_ID" = "null" ]; then
                sleep 300
                # retry
                get_workflow_id
                if [ -z "$WORKFLOW_ID" ] || [ "$WORKFLOW_ID" = "null" ]; then
                  echo "Workflow not found"
                  exit 1
                fi
              fi
            fi
            status=""
            conclusion=""
            while [[ "$status" != "completed" ]]; do
              sleep 30
              echo "Checking workflow status..."
              response=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              "https://api.github.com/repos/$OWNER/$REPO/actions/runs/$WORKFLOW_ID")
              echo "Response to https://api.github.com/repos/$OWNER/$REPO/actions/runs/$WORKFLOW_ID from GitHub API: $response"

              # Extract the status and conclusion of the workflow run
              status=$(echo "$response" | jq -r '.status')
              conclusion=$(echo "$response" | jq -r '.conclusion')
              echo "Current Workflow Status: $status, Conclusion: $conclusion"

            done

            echo "Workflow concluded with status: $conclusion"
            echo "::set-output name=status::$conclusion"
            if [ "$conclusion" != "success" ]; then
              echo "Playwright tests failed"
              exit 1
            fi
          }

          # Poll the workflow status
          poll_workflow_status
