name: "pull-request"

on:
  workflow_call:
    inputs:
      dry-run-flag:
        description: 'enable dry-run on artifact push'
        required: false
        type: boolean
        default: true
      devel:
        description: 'devel'
        required: false
        type: boolean
        default: false
      cron-run:
        description: 'disables jobs which should not run when cron runs e2es'
        required: false
        type: boolean
        default: false
  pull_request:
    types: [opened, synchronize, reopened]
    branches:
      - develop
      - master
      - develop-patch*
      - master-patch*

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  BASE_REF: ${{ github.base_ref }}
  HEAD_REF: ${{ github.head_ref }}
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  GITHUB_BRANCH: ${{ github.ref_name }}
  GH_BUILD_DIR: ${{ github.workspace }}
  GH_COMMIT: ${{ github.sha }}
  BUILD_ID: ${{ github.run_id }}
  GH_RUN_NUMBER: ${{ github.run_attempt }}
  GH_BUILD_NUMBER: ${{ github.run_id }}
  JOB_ID: ${{ github.run_id }}
  LOG_LEVEL: "ERROR"
  S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
  NODE_OPTIONS: "--max-old-space-size=5120"
  DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
  DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
  DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
  DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
  REPO_OWNER: "Alfresco"
  REPO_NAME: "alfresco-ng2-components"
  STORYBOOK_DIR: "./dist/storybook/stories"
  BUILT_LIBS_DIR: "./dist/libs"
  NODE_MODULES_DIR: "./node_modules"
  REDIRECT_URI: /

jobs:
  pre-checks:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Ensure SHA pinned actions
        uses: zgosalvez/github-actions-ensure-sha-pinned-actions@0901cf7b71c7ea6261ec69a3dc2bd3f9264f893e # v3.0.12

      - name: Check package-lock.json version
        run: |
          if [[ $(jq '.lockfileVersion == 3' package-lock.json) == "true" ]] ; then
            echo "package-lock.json has a correct version"
          else
            echo "package-lock must be version 3"
            exit 1
          fi

  check-if-pr-is-approved:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
         fetch-depth: 0

      - name: Get branch name
        uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@a4013b7dfd8453ee94ec5d4eb8cb51d74654f770 # v7.0.0

      - name: Save commit message
        uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@a4013b7dfd8453ee94ec5d4eb8cb51d74654f770 # v7.0.0

      - name: ci:force flag parser
        shell: bash
        run: |
          if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.actor }}" == "dependabot[bot]" ]; then
            echo -e "\033[32mci:force check can be skipped\033[0m"
            skip_check="true"
          elif [[ "$COMMIT_MESSAGE" == *"[ci:force]"* ]]; then
              echo -e "\033[32m[ci:force] flag detected. No need for approval.\033[0m"
              skip_check="true"
          fi

      - name: Get PR number
        if: ${{ github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' }}
        uses: kamatama41/get-pr-number-action@0bcaab5752c0b699149e74667c8ce2f764cbb7fa # v0.9.1
        id: action
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

      - name: show pr number
        shell: bash
        run: |
          echo "PR: ${{ steps.action.outputs.number }}"

      - name: check if pr is approved
        env:
          DEVEL_FLAG: ${{ inputs.devel }}
          GH_TOKEN: ${{ github.token }}
          skip_check: "false"
        run: |
          if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.actor }}" == "dependabot[bot]" ]; then
            echo -e "\033[32mci:force check can be skipped\033[0m"
            skip_check="true"
          elif [[ "$COMMIT_MESSAGE" == *"[ci:force]"* ]]; then
            echo -e "\033[32m[ci:force] flag detected. No need for approval.\033[0m"
            skip_check="true"
          fi

          if [ "${{ github.actor }}" == "dependabot[bot]" ] || [ "${{ github.actor }}" == "alfresco-build" ]; then
            echo -e "\033[32mCommit by ${{ github.actor }}. No need for approval.\033[0m"
            skip_check="true"
          fi
          if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
            echo -e "\033[32mSchedule event\033[0m"
            skip_check="true"
          fi

          if [[ "$DEVEL_FLAG" == "true" ]]; then
            echo -e "\033[32mDevel flag\033[0m"
            skip_check="true"
          fi

          if [ "$skip_check" == "false" ]; then
            echo "Checking PR approval"
            prNumber=${{ steps.action.outputs.number }}
            echo "PR: $prNumber"
            checkApproval=$(gh api /repos/$GITHUB_REPOSITORY/pulls/$prNumber/reviews | jq '.[] | select(.state == "APPROVED") | .user.login')
            if [[ $checkApproval ]]; then
              echo -e "\033[32mPR approved\033[0m"
            else
              echo -e "\033[31mPR NOT approved\033[0m"
              exit 1
            fi
          fi

  setup:
    # long timeout required when cache has to be recreated
    timeout-minutes: 30
    name: "Setup"
    runs-on: ubuntu-latest
    needs: [check-if-pr-is-approved, pre-checks]
    steps:
      - name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          fetch-depth: 0 # Fetch all history for all tags and branches
      - uses: ./.github/actions/setup
      - name: install
        run: |
          npm ci
          npx nx run js-api:bundle
          npx nx run cli:bundle
          npx nx run testing:bundle
      - run: npx nx print-affected $NX_CALCULATION_FLAGS
      - uses: ./.github/actions/upload-node-modules-and-artifacts

  unit-tests:
    timeout-minutes: 30
    name: "Unit tests: ${{ matrix.unit-tests.name }}"
    runs-on: ubuntu-latest
    needs: [setup]
    strategy:
      fail-fast: false
      # max-parallel: 4
      matrix:
        unit-tests:
          - name: js-api
            exclude: "core,insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular"
          - name: content-services
            exclude: "insights,core,extensions,process-services,process-services-cloud,eslint-plugin-eslint-angular,js-api"
          - name: core
            exclude: "insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular,js-api"
          - name: insights
            exclude: "core,extensions,content-services,process-services-cloud,process-services,eslint-plugin-eslint-angular,js-api"
          - name: process-services
            exclude: "core,extensions,content-services,process-services-cloud,insights,eslint-plugin-eslint-angular,js-api"
          - name: process-cloud
            exclude: "insights,core,extensions,content-services,process-services,eslint-plugin-eslint-angular,js-api"
    steps:
      - name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          fetch-depth: 0 # Fetch all history for all tags and branches
      - uses: ./.github/actions/setup
      - uses: ./.github/actions/download-node-modules-and-artifacts
      - name: Run unit tests
        run: |
          /usr/bin/xvfb-run --auto-servernum npx nx affected:test $NX_CALCULATION_FLAGS --exclude=${{ matrix.unit-tests.exclude }}

  lint:
    # long timeout required when cache has to be recreated
    timeout-minutes: 30
    name: "Lint"
    runs-on: ubuntu-latest
    needs: [setup]
    steps:
      - name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          fetch-depth: 0 # Fetch all history for all tags and branches
      - uses: ./.github/actions/setup
      - uses: ./.github/actions/download-node-modules-and-artifacts
      - run: npx nx affected --target=lint $NX_CALCULATION_FLAGS

  build-libs:
    # long timeout required when cache has to be recreated
    timeout-minutes: 30
    name: "Build libs"
    runs-on: ubuntu-latest
    needs: [setup]
    steps:
      - name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          fetch-depth: 0 # Fetch all history for all tags and branches
      - uses: ./.github/actions/setup
      - uses: ./.github/actions/download-node-modules-and-artifacts
      - run: npx nx affected:build $NX_CALCULATION_FLAGS --prod
      - run: npx nx affected --target=build-storybook $NX_CALCULATION_FLAGS --configuration=ci --parallel=1
      - uses: ./.github/actions/upload-node-modules-and-artifacts

  PR-forbidden-labels:
    if: ${{ inputs.cron-run == '' || inputs.cron-run == 'false' }}
    runs-on: ubuntu-latest
    steps:
      - id: checkoutRepo
        name: Checkout repository
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        with:
          fetch-depth: 1
      - name: PR contains forbidden labels
        id: pr-forbidden
        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
        with:
          script: |
            const issueHasLabels = require('./scripts/github/update/check-issue-has-label.js');
            const checkLabels = ['next version ➡️', 'do not merge🙅🏻‍♂️'];

            const hasLabel = await issueHasLabels({github, context, checkLabels})

            if(hasLabel) {
              core.setFailed('The PR contains a forbidden label! You are not allowed to merge until the label is there.');
            }
      - name: Check value after
        run: |
          echo "result ${{ toJson(steps.pr-forbidden.*.result) }}" && echo "result ${{ steps.pr-forbidden.*.result }}"
          echo "result ${{ contains(toJson(steps.pr-forbidden.*.result), 'failure') }}"

  finalize:
    if: ${{ always() }}
    runs-on: ubuntu-latest
    name: Final Results
    needs: [check-if-pr-is-approved, pre-checks, setup, unit-tests, lint, build-libs]
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
      - name: identify-slack-group
        id: groups
        if: ${{ github.event_name == 'schedule' }}
        uses: ./.github/actions/slack-group-area
        with:
          affected: ${{ steps.e2e-result.outputs.result }}
      - uses: slackapi/slack-github-action@37ebaef184d7626c5f204ab8d3baff4262dd30f0 # v1.27.0
        name: Nofify QA failure
        if: ${{ github.event_name == 'schedule' && contains(needs.*.result, 'failure') }}
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
        with:
          channel-id: 'C016SMNNL8L' #guild-channel
          slack-message: "🔴 Warning: The daily ADF cronjob failed\nWorkflow run : <https://github.com/Alfresco/alfresco-ng2-components/actions/runs/${{ github.run_id }}| here>\nDetails: ${{ steps.e2e-result.outputs.result }}\nArea: ${{ steps.groups.outputs.groups}}"
      - name: workflow failure
        run: exit 1
        if: ${{ contains(needs.*.result, 'failure') }}
      - name: workflow canceled
        run: exit 1
        if: ${{ contains(needs.*.result, 'cancelled') }}
      - name: workflow success
        run: exit 0
        if: ${{ contains(needs.*.result, 'success') }}