name: 'Run Benchmark'

on:
  workflow_dispatch:
    inputs:
      bench-file:
        required: true
        type: string
      node-versions:
        required: true
        type: string
        default: '["18.0.0","18.20.1","18.20.2","20.0.0","20.12.1","20.12.2","21.0.0","21.7.2","21.7.3","22.0.0","22.1.0"]'
        description: 'The Node.js Versions (should be a JSON array)'
      node-opts:
        required: false
        type: string
        description: 'Flags to be used in the Node.js binary'
      run-start-stop:
        required: false
        type: boolean
        default: true
        description: 'When false, starting and stopping the runner machine is skipped'
  workflow_call:
    inputs:
      bench-file:
        required: true
        type: string
      node-versions:
        required: true
        type: string
        default: '["18.0.0","18.20.1","18.20.2","20.0.0","20.12.1","20.12.2","21.0.0","21.7.2","21.7.3","22.0.0","22.1.0"]'
        description: 'The Node.js Versions (should be a JSON array)'
      node-opts:
        required: false
        type: string
        description: 'Flags to be used in the Node.js binary'
      run-start-stop:
        required: false
        type: boolean
        default: true
        description: 'When false, starting and stopping the runner machine is skipped'

permissions:
  issues: write
  contents: read
  id-token: write

jobs:
  runner-start:
    if: ${{ inputs.run-start-stop == true }}
    runs-on: ubuntu-latest
    steps:
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: us-west-2
          role-to-assume: arn:aws:iam::800406105498:role/RafaelGSS-nodejs-bench-operations
      - name: Checkout
        uses: actions/checkout@v4

      - name: Start Runner
        uses: ./.github/workflows/runner-starter
        with:
          instance_id: 'i-065f0f848eb1615ae'
          action: 'start'
          aws_default_region: 'us-west-2'

  benchmark:
    continue-on-error: true
    runs-on: self-hosted
    # needs: runner-start
    if: always()
    strategy:
      matrix:
        node-version: ${{ fromJson(inputs.node-versions) }}
      fail-fast: true

    steps:
      - uses: actions/checkout@v3

      - name: Use Node.js v${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

      - name: NPM Install
        run: npm install

      - name: Report Filename
        run: echo "BENCH_REPORT_FILE=report-${{github.run_id}}-${{ matrix.node-version }}-${{ inputs.bench-file }}.md" >> $GITHUB_ENV

      - name: Run Benchmark
        run: node ${{ inputs.node-opts }} bench/${{ inputs.bench-file }} > ./${{ env.BENCH_REPORT_FILE }}
        env:
          CI: true

      - name: Notify on Error
        if: ${{ failure() }}
        uses: dacbd/create-issue-action@main
        with:
          token: ${{ github.token }}
          title: Benchmark ${{ inputs.bench-file }} failed on v${{ matrix.node-version }}
          body: |
            ### Context
            [Failed Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
            [Codebase](https://github.com/${{ github.repository }}/tree/${{ github.sha }})
            Workflow name - `${{ github.workflow }}`
            Job -           `${{ github.job }}`
            status -        `${{ job.status }}`
          assignees: RafaelGSS
          labels: bug

      - name: Output Failure
        if: ${{ failure() }}
        uses: cloudposse/github-action-matrix-outputs-write@main
        with:
          matrix-step-name: benchmark-${{ inputs.bench-file }}
          matrix-key: ${{ matrix.node-version }}
          outputs: |-
            failure: 'true'
            result: ''

      - name: Add Job Summary
        run: |
          result=$(cat ./${{ env.BENCH_REPORT_FILE }})
          echo "$result" >> $GITHUB_STEP_SUMMARY

      - name: Upload Bench Result
        uses: actions/upload-artifact@v3
        with:
          name: benchmark-artifacts-${{github.run_id}}
          retention-days: 1
          if-no-files-found: error
          path: ./${{ env.BENCH_REPORT_FILE }}

      ## Write for matrix outputs workaround
      - uses: cloudposse/github-action-matrix-outputs-write@main
        id: out
        with:
          matrix-step-name: benchmark-${{ inputs.bench-file }}
          matrix-key: ${{ matrix.node-version }}
          outputs: |-
            failure: 'false'
            result: ${{ env.BENCH_REPORT_FILE }}

  ## Read matrix outputs
  read:
    runs-on: ubuntu-latest
    continue-on-error: true
    needs: [benchmark]

    steps:
      - uses: cloudposse/github-action-matrix-outputs-read@main
        id: read
        with:
          matrix-step-name: benchmark-${{ inputs.bench-file }}

    outputs:
      result: '${{ steps.read.outputs.result }}'

  commit:
    runs-on: ubuntu-latest
    continue-on-error: true
    if: ${{ needs.read.outputs.failure != 'true' }}
    needs: [read]

    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v3
        with:
          ref: main

      - name: Use Node.js v20.x
        uses: actions/setup-node@v3
        with:
          node-version: 20.x

      - name: Create temporary report folder
        run: mkdir ./temp-reports

      - uses: actions/download-artifact@v3
        with:
          name: benchmark-artifacts-${{github.run_id}}
          path: ./temp-reports

      - name: Write Benchmark Reports
        run: |
          node scripts/write-bench-results.mjs
          node scripts/generate-reports.mjs
        env:
          BENCH_FILE: ${{ inputs.bench-file }}
          BENCH_ARTIFACTS: ${{ needs.read.outputs.result }}

      - name: Clean temporary report folder
        run: rm -r ./temp-reports

      - name: Commit and Push Updated Results
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          branch: 'main'
          commit_message: 'chore(${{ inputs.bench-file }}): update benchmark results'
          commit_author: Github Actions <actions@github.com> 

  ## Stop Runner
  runner-stop:
    if: ${{ inputs.run-start-stop == true }}
    runs-on: ubuntu-latest
    needs: [benchmark]
    steps:
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Stop Runner
        uses: ./.github/workflows/runner-starter
        with:
          instance_id: 'i-065f0f848eb1615ae'
          action: 'stop'
          aws_default_region: 'us-west-2'
