name: main

on:
  pull_request:
  push:
    branches:
      - main

permissions:
  contents: read
  actions: read
  security-events: write
  packages: write

jobs:
  store-image-name-and-tags:
    uses: ./.github/workflows/reuse-store-image-name-and-tags.yml

  filter-commit-changes:
    runs-on: gha-runner-scale-set-ubuntu-22.04-amd64-small
    name: Filter commit changes
    outputs:
      changed-file-count: ${{ steps.filter.outputs.all_count }}
      coordinator: ${{ steps.filter.outputs.coordinator }}
      staterecovery: ${{ steps.filter.outputs.staterecovery }}
      postman: ${{ steps.filter.outputs.postman }}
      prover: ${{ steps.filter.outputs.prover }}
      transaction-exclusion-api: ${{ steps.filter.outputs.transaction-exclusion-api }}
      has-changes-requiring-build: ${{ steps.exclusion-filter.outputs.has-changes-requiring-build }}
      contracts-excluding-local-deployment-artifacts: ${{ steps.exclusion-filter.outputs.contracts-excluding-local-deployment-artifacts }}
      contracts-excluding-local-deployment-artifacts-count: ${{ steps.exclusion-filter.outputs.contracts-excluding-local-deployment-artifacts_count }}
      smart-contracts: ${{ steps.filter.outputs.smart-contracts }}
      linea-sequencer-plugin: ${{ steps.filter.outputs.linea-sequencer-plugin }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Filter commit changes
        uses: dorny/paths-filter@v3
        id: filter
        with:
          base: ${{ github.ref }}
          list-files: "json"
          filters: |
            all:
              - '**/**'
            coordinator:
              - 'coordinator/**'
              - 'testdata/**'
              - 'buildSrc/**'
              - 'jvm-libs/**'
              - 'gradle/**'
              - 'build.gradle'
              - 'gradle.properties'
              - 'settings.gradle'
              - '.github/workflows/coordinator-*.yml'
              - '.github/workflows/build-and-publish.yml'
              - '.github/workflows/main.yml'
              - '.github/workflows/reuse-*.yml'
              - 'config/common/traces-limits-v2.toml'
              - 'config/coordinator/**'
              - 'e2e/**'
              - 'docker/compose-*.yml'
            staterecovery:
              - 'state-recovery/**'
              - 'buildSrc/**'
              - 'jvm-libs/**'
              - 'gradle/**'
              - 'build.gradle'
              - 'gradle.properties'
              - 'settings.gradle'
              - '.github/workflows/staterecovery-*.yml'
              - '.github/workflows/main.yml'
              - '.github/workflows/reuse-*.yml'
            postman:
              - 'postman/**'
              - 'sdk/**'
              - 'ts-libs/linea-native-libs/**'
              - '.github/workflows/postman-*.yml'
              - '.github/workflows/build-and-publish.yml'
              - '.github/workflows/main.yml'
              - '.github/workflows/reuse-*.yml'
            prover:
              - 'prover/**'
              - '.github/workflows/prover-*.yml'
              - '.github/workflows/build-and-publish.yml'
              - '.github/workflows/main.yml'
              - '.github/workflows/reuse-*.yml'
              - 'constraints'
            transaction-exclusion-api:
              - 'transaction-exclusion-api/**'
              - 'jvm-libs/generic/extensions/futures/**'
              - 'jvm-libs/generic/extensions/kotlin/**'
              - 'jvm-libs/generic/json-rpc/**'
              - 'jvm-libs/generic/persistence/**'
              - 'jvm-libs/generic/vertx-helper/**'
              - 'jvm-libs/linea/core/long-running-service/**'
              - 'jvm-libs/linea/core/metrics/**'
              - 'jvm-libs/linea/metrics/**'
              - '.github/workflows/transaction-exclusion-api-*.yml'
              - '.github/workflows/build-and-publish.yml'
              - '.github/workflows/main.yml'
              - '.github/workflows/reuse-*.yml'
              - 'buildSrc/**'
              - 'gradle/**'
              - 'build.gradle'
              - 'gradle.properties'
              - 'settings.gradle'
            smart-contracts:
              - 'contracts/**'
              - 'testdata/**'
              - 'prover/**'
              - '.github/workflows/main.yml'
              - '.github/workflows/run-smc-tests.yml'
            linea-sequencer-plugin:
              - 'besu-plugins/linea-sequencer/**'
              - '.github/workflows/linea-sequencer-plugin-testing.yml'

      - name: Filter out commit changes
        uses: dorny/paths-filter@v3
        id: exclusion-filter
        with:
          base: ${{ github.ref }}
          list-files: "json"
          filters: |
            has-changes-requiring-build:
              - '!**/*.md'
              - '!**/*.mdx'
              - '!**/docs/**'
              - '!docs/**'
            contracts-excluding-local-deployment-artifacts:
              - 'contracts/**'
              - '!contracts/local-deployments-artifacts/**'
          # Means that ALL (and not just one) filter patterns must match. In other words applies the 'AND' operator to filter patterns.
          # The default is 'some', which requires just one filter pattern match and applies the 'OR' operator.
          # For 'has-changes-requiring-build', it means we have an exclusion list that we can append to.
          predicate-quantifier: 'every'

  check-and-tag-images:
    needs: [ store-image-name-and-tags, filter-commit-changes ]
    uses: ./.github/workflows/reuse-check-images-tags-and-push.yml
    if: ${{ needs.filter-commit-changes.outputs.has-changes-requiring-build == 'true' }}
    with:
      commit_tag: ${{ needs.store-image-name-and-tags.outputs.commit_tag }}
      last_commit_tag: ${{ needs.store-image-name-and-tags.outputs.last_commit_tag }}
      develop_tag: ${{ needs.store-image-name-and-tags.outputs.develop_tag }}
      coordinator_changed: ${{ needs.filter-commit-changes.outputs.coordinator }}
      postman_changed: ${{ needs.filter-commit-changes.outputs.postman }}
      prover_changed: ${{ needs.filter-commit-changes.outputs.prover }}
      transaction_exclusion_api_changed: ${{ needs.filter-commit-changes.outputs.transaction-exclusion-api }}
    secrets: inherit

  code-analysis:
    uses: ./.github/workflows/codeql.yml

  testing:
    needs: [ store-image-name-and-tags, filter-commit-changes, check-and-tag-images ]
    if: ${{ always() && needs.filter-commit-changes.outputs.has-changes-requiring-build == 'true' }}
    uses: ./.github/workflows/testing.yml
    with:
      commit_tag: ${{ needs.store-image-name-and-tags.outputs.commit_tag }}
      coordinator_changed: ${{ needs.filter-commit-changes.outputs.coordinator }}
      linea_sequencer_changed: ${{ needs.filter-commit-changes.outputs.linea-sequencer-plugin }}
      postman_changed: ${{ needs.filter-commit-changes.outputs.postman }}
      prover_changed: ${{ needs.filter-commit-changes.outputs.prover }}
      smart_contracts_changed: ${{ needs.filter-commit-changes.outputs.smart-contracts }}
      staterecovery_changed: ${{ needs.filter-commit-changes.outputs.staterecovery }}
      transaction_exclusion_api_changed: ${{ needs.filter-commit-changes.outputs.transaction-exclusion-api }}
    secrets: inherit

  get-has-changes-requiring-e2e-testing:
    needs: [ filter-commit-changes ]
    uses: ./.github/workflows/get-has-changes-requiring-e2e-testing.yml
    with:
      has_changes_requiring_build: ${{ needs.filter-commit-changes.outputs.has-changes-requiring-build }}
      contracts_excluding_local_deployment_artifacts: ${{ needs.filter-commit-changes.outputs.contracts-excluding-local-deployment-artifacts }}
      changed_file_count: ${{ needs.filter-commit-changes.outputs.changed-file-count }}
      contracts_excluding_local_deployment_artifacts_count: ${{ needs.filter-commit-changes.outputs.contracts-excluding-local-deployment-artifacts-count }}

  manual-docker-build-and-e2e-tests:
    runs-on: gha-runner-scale-set-ubuntu-22.04-amd64-small
    needs: [ store-image-name-and-tags, check-and-tag-images, get-has-changes-requiring-e2e-testing ]
    if: ${{ needs.get-has-changes-requiring-e2e-testing.outputs.has-changes-requiring-e2e-testing == 'true' }}
    environment: ${{ github.ref != 'refs/heads/main' && 'docker-build-and-e2e' || '' }}
    concurrency:
      group: manual-docker-build-and-e2e-tests-${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
    steps:
      - name: Deploy environment
        run: |
          echo "Build and e2e test environment deployed"

  docker-build:
    needs: [ store-image-name-and-tags, filter-commit-changes, check-and-tag-images, manual-docker-build-and-e2e-tests ]
    uses: ./.github/workflows/build-and-publish.yml
    with:
      commit_tag: ${{ needs.store-image-name-and-tags.outputs.commit_tag }}
      develop_tag: ${{ needs.store-image-name-and-tags.outputs.develop_tag }}
      coordinator_changed: ${{ needs.filter-commit-changes.outputs.coordinator }}
      postman_changed: ${{ needs.filter-commit-changes.outputs.postman }}
      prover_changed: ${{ needs.filter-commit-changes.outputs.prover }}
      transaction_exclusion_api_changed: ${{ needs.filter-commit-changes.outputs.transaction-exclusion-api }}
      coordinator_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_coordinator }}
      postman_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_postman }}
      prover_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_prover }}
      transaction_exclusion_api_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_transaction_exclusion_api }}
    secrets: inherit

  run-e2e-tests:
    needs: [ store-image-name-and-tags, docker-build, get-has-changes-requiring-e2e-testing, manual-docker-build-and-e2e-tests ]
    # Make this execute for has-changes-requiring-e2e-testing == 'false' so that we can get to the required job @ which is in reuse-run-e2e-tests.yml
    if: ${{ always() && needs.get-has-changes-requiring-e2e-testing.outputs.has-changes-requiring-e2e-testing == 'false' || needs.docker-build.result == 'success' }}
    concurrency:
      group: run-e2e-tests-${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
    uses: ./.github/workflows/reuse-run-e2e-tests.yml
    with:
      commit_tag: ${{ needs.store-image-name-and-tags.outputs.commit_tag }}
      e2e-tests-logs-dump: true
      has-changes-requiring-e2e-testing: ${{ needs.get-has-changes-requiring-e2e-testing.outputs.has-changes-requiring-e2e-testing }}
    secrets: inherit

  publish-images-after-run-tests-success-on-main:
    needs: [ store-image-name-and-tags, testing, run-e2e-tests ]
    if: ${{ always() && github.ref == 'refs/heads/main' && needs.testing.result == 'success' && needs.run-e2e-tests.outputs.tests_outcome == 'success' }}
    uses: ./.github/workflows/build-and-publish.yml
    with:
      push_image: true
      commit_tag: ${{ needs.store-image-name-and-tags.outputs.commit_tag }}
      develop_tag: ${{ needs.store-image-name-and-tags.outputs.develop_tag }}
      coordinator_changed: ${{ needs.filter-commit-changes.outputs.coordinator }}
      postman_changed: ${{ needs.filter-commit-changes.outputs.postman }}
      prover_changed: ${{ needs.filter-commit-changes.outputs.prover }}
      transaction_exclusion_api_changed: ${{ needs.filter-commit-changes.outputs.transaction-exclusion-api }}
      coordinator_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_coordinator }}
      postman_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_postman }}
      prover_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_prover }}
      transaction_exclusion_api_image_tagged: ${{ needs.check-and-tag-images.outputs.image_tagged_transaction_exclusion_api }}
    secrets: inherit

  cleanup-deployments:
    needs: [ run-e2e-tests ]
    if: ${{ always() }}
    runs-on: gha-runner-scale-set-ubuntu-22.04-amd64-small
    steps:
      - uses: strumwolf/delete-deployment-environment@v3
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          environment: docker-build-and-e2e
          ref: ${{ github.ref_name }}
          onlyRemoveDeployments: true
