version: 2.1

orbs:
  go: circleci/go@1.8.0
  gcp-cli: circleci/gcp-cli@3.0.1
  slack: circleci/slack@4.10.1
commands:
  gcp-oidc-authenticate:
    description: "Authenticate with GCP using a CircleCI OIDC token."
    parameters:
      project_id:
        type: env_var_name
        default: GCP_PROJECT_ID
      workload_identity_pool_id:
        type: env_var_name
        default: GCP_WIP_ID
      workload_identity_pool_provider_id:
        type: env_var_name
        default: GCP_WIP_PROVIDER_ID
      service_account_email:
        type: env_var_name
        default: GCP_SERVICE_ACCOUNT_EMAIL
      gcp_cred_config_file_path:
        type: string
        default: /home/circleci/gcp_cred_config.json
      oidc_token_file_path:
        type: string
        default: /home/circleci/oidc_token.json
    steps:
      - run:
          name: "Create OIDC credential configuration"
          command: |
            # Store OIDC token in temp file
            echo $CIRCLE_OIDC_TOKEN > << parameters.oidc_token_file_path >>
            # Create a credential configuration for the generated OIDC ID Token
            gcloud iam workload-identity-pools create-cred-config \
                "projects/${<< parameters.project_id >>}/locations/global/workloadIdentityPools/${<< parameters.workload_identity_pool_id >>}/providers/${<< parameters.workload_identity_pool_provider_id >>}"\
                --output-file="<< parameters.gcp_cred_config_file_path >>" \
                --service-account="${<< parameters.service_account_email >>}" \
                --credential-source-file=<< parameters.oidc_token_file_path >>
      - run:
          name: "Authenticate with GCP using OIDC"
          command: |
            # Configure gcloud to leverage the generated credential configuration
            gcloud auth login --brief --cred-file "<< parameters.gcp_cred_config_file_path >>"
            # Configure ADC
            echo "export GOOGLE_APPLICATION_CREDENTIALS='<< parameters.gcp_cred_config_file_path >>'" | tee -a "$BASH_ENV"
  check-changed:
    description: "Conditionally halts a step if certain modules change"
    parameters:
      patterns:
        type: string
        description: "Comma-separated list of dependencies"
    steps:
      - run:
          name: "Check for changes"
          command: |
            cd ops/check-changed
            pip3 install -r requirements.txt
            python3 main.py "<<parameters.patterns>>"
jobs:
  cannon-go-lint-and-test:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: medium
    steps:
      - checkout
      - check-changed:
          patterns: cannon,packages/contracts-bedrock/src/cannon
      - run:
          name: prep Cannon results dir
          command: mkdir -p /tmp/test-results
      - run:
          name: build Cannon example binaries
          command: make elf # only compile ELF binaries with Go, we do not have MIPS GCC for creating the debug-dumps.
          working_directory: cannon/example
      - run:
          name: Cannon Go lint
          command: |
            make lint
          working_directory: cannon
      - run:
          name: Cannon Go tests
          command: |
            gotestsum --format=standard-verbose --junitfile=/tmp/test-results/cannon.xml \
            -- -parallel=2 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./...
          working_directory: cannon
      - run:
          name: upload Cannon coverage
          command: codecov --verbose --clean --flags cannon-go-tests
      - store_test_results:
          path: /tmp/test-results
  cannon-build-test-vectors:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: medium
    steps:
      - checkout
      - check-changed:
          patterns: cannon/mipsevm/open_mips_tests/test
      - run:
          name: Build MIPS test vectors
          command: python3 maketests.py && git diff --exit-code
          working_directory: cannon/mipsevm/open_mips_tests

  pnpm-monorepo:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: xlarge
    steps:
      - checkout
      - check-changed:
          patterns: op-chain-ops,packages/
      - restore_cache:
          name: Restore PNPM Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
      # Fetch node_modules into the pnpm store
      # This will cache node_modules based on pnpm-lock so other steps can instantly install them with `pnpm install --prefer-offline`
      # --prefer-offline installs node_modules instantly by just reading from cache if it exists rather than fetching from network
      # when installing node_modules pnpm simply adds symlinks instead of copying the files which is why it is pretty much instant to run --prefer-offline
      # this allows a caching strategy of only checking pnpm-lockfile so we don't have to keep it in sync with our packages
      # For more information see https://pnpm.io/cli/fetch
      - run:
          name: Fetch dependencies
          command: pnpm fetch --frozen-lockfile --prefer-offline
      - save_cache:
          name: Save PNPM Package Cache
          key: pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
          paths:
            - "node_modules"
      - run:
          name: Install dependencies
          command: pnpm install --frozen-lockfile --offline
      - run:
          name: print forge version
          command: forge --version
      - run:
          name: Build monorepo
          command: pnpm build
      - persist_to_workspace:
          root: "."
          paths:
            - "packages/**/dist"
            - "packages/contracts-bedrock/forge-artifacts"

  docker-build:
    environment:
      DOCKER_BUILDKIT: 1
    parameters:
      docker_name:
        description: Docker image name
        type: string
      docker_tags:
        description: Docker image tags as csv
        type: string
      docker_file:
        description: Path to Dockerfile
        type: string
      docker_context:
        description: Docker build context
        type: string
      registry:
        description: Docker registry
        type: string
        default: "us-docker.pkg.dev"
      repo:
        description: Docker repo
        type: string
        default: "oplabs-tools-artifacts/images"
    machine:
      image: ubuntu-2204:2022.07.1
      resource_class: medium
    steps:
      - checkout
      - run:
          command: mkdir -p /tmp/docker_images
      - run:
          name: Build
          command: |
            # Check to see if DOCKER_HUB_READ_ONLY_TOKEN is set (i.e. we are in repo) before attempting to use secrets.
            # Building should work without this read only login, but may get rate limited.
            if [[ -v DOCKER_HUB_READ_ONLY_TOKEN ]]; then
              echo "$DOCKER_HUB_READ_ONLY_TOKEN" | docker login -u "$DOCKER_HUB_READ_ONLY_USER" --password-stdin
            fi
            IMAGE_BASE="<<parameters.registry>>/<<parameters.repo>>/<<parameters.docker_name>>"
            DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
            docker build --progress plain \
            $(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
            -f <<parameters.docker_file>> \
            <<parameters.docker_context>>
      - run:
          name: Save
          command: |
            IMAGE_BASE="<<parameters.registry>>/<<parameters.repo>>/<<parameters.docker_name>>"
            DOCKER_LABELS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g")
            echo -ne $DOCKER_LABELS | tr ' ' '\n' | xargs -I {} docker save -o /tmp/docker_images/<<parameters.docker_name>>_{}.tar $IMAGE_BASE:{}
      - persist_to_workspace:
          root: /tmp/docker_images
          paths:
            - "."

  docker-publish:
    environment:
      DOCKER_BUILDKIT: 1
    parameters:
      docker_name:
        description: Docker image name
        type: string
      docker_tags:
        description: Docker image tags as csv
        type: string
      docker_file:
        description: Path to Dockerfile
        type: string
      docker_context:
        description: Docker build context
        type: string
        default: "."
      docker_target:
        description: "target build stage"
        type: string
        default: ""
      registry:
        description: Docker registry
        type: string
        default: "us-docker.pkg.dev"
      repo:
        description: Docker repo
        type: string
        default: "oplabs-tools-artifacts/images"
      platforms:
        description: Platforms to build for
        type: string
        default: "linux/amd64"
    machine:
      image: ubuntu-2204:2022.07.1
      resource_class: medium
    steps:
      - gcp-oidc-authenticate
      # Below is CircleCI recommended way of specifying nameservers on an Ubuntu box:
      # https://support.circleci.com/hc/en-us/articles/7323511028251-How-to-set-custom-DNS-on-Ubuntu-based-images-using-netplan
      - run: sudo sed -i '13 i \ \ \ \ \ \ \ \ \ \ \ \ nameservers:' /etc/netplan/50-cloud-init.yaml
      - run: sudo sed -i '14 i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ addresses:' /etc/netplan/50-cloud-init.yaml
      - run: sudo sed -i "s/addresses:/ addresses":" [8.8.8.8, 8.8.4.4] /g" /etc/netplan/50-cloud-init.yaml
      - run: cat /etc/netplan/50-cloud-init.yaml
      - run: sudo netplan apply
      - checkout
      - run:
          name: Build & Publish
          command: |
            gcloud auth configure-docker <<parameters.registry>>
            IMAGE_BASE="<<parameters.registry>>/<<parameters.repo>>/<<parameters.docker_name>>"
            DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
            docker context create buildx-build
            docker buildx create --use buildx-build
            docker buildx build --progress plain --platform=<<parameters.platforms>> --target "<<parameters.docker_target>>" --push \
              $(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
              -f <<parameters.docker_file>> \
              <<parameters.docker_context>>

  docker-release:
    environment:
      DOCKER_BUILDKIT: 1
    parameters:
      docker_name:
        description: Docker image name
        type: string
      docker_tags:
        description: Docker image tags as csv
        type: string
      docker_file:
        description: Path to Dockerfile
        type: string
      docker_context:
        description: Docker build context
        type: string
      docker_target:
        description: "target build stage"
        type: string
        default: ""
      registry:
        description: Docker registry
        type: string
        default: "us-docker.pkg.dev"
      repo:
        description: Docker repo
        type: string
        default: "oplabs-tools-artifacts/images"
      platforms:
        description: Platforms to build for
        type: string
        default: "linux/amd64"
    machine:
      image: ubuntu-2204:2022.07.1
      resource_class: medium
    steps:
      - gcp-cli/install
      - gcp-oidc-authenticate
      - checkout
      - run:
          name: Configure Docker
          command: |
            gcloud auth configure-docker <<parameters.registry>>
      - run:
          name: Build & Publish
          command: |
            IMAGE_BASE="<<parameters.registry>>/<<parameters.repo>>/<<parameters.docker_name>>"
            DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
            docker context create buildx-build
            docker buildx create --use buildx-build
            docker buildx build --progress plain --platform=<<parameters.platforms>> --target "<<parameters.docker_target>>" --push \
              $(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
              -f <<parameters.docker_file>> \
              <<parameters.docker_context>>
      - run:
          name: Tag
          command: |
            ./ops/scripts/ci-docker-tag-op-stack-release.sh <<parameters.registry>>/<<parameters.repo>> $CIRCLE_TAG $CIRCLE_SHA1

  contracts-bedrock-coverage:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: large
    steps:
      - checkout
      - check-changed:
          patterns: contracts-bedrock,op-node
      - run:
          name: print forge version
          command: forge --version
          working_directory: packages/contracts-bedrock
      - run:
          name: test and generate coverage
          command: pnpm coverage:lcov
          no_output_timeout: 18m
          environment:
            FOUNDRY_PROFILE: ci
          working_directory: packages/contracts-bedrock
      - run:
          name: upload coverage
          command: codecov --verbose --clean --flags contracts-bedrock-tests
          environment:
            FOUNDRY_PROFILE: ci

  contracts-bedrock-tests:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: xlarge
    steps:
      - checkout
      - check-changed:
          patterns: contracts-bedrock,op-node
      - run:
          name: print forge version
          command: forge --version
          working_directory: packages/contracts-bedrock
      - run:
          name: run tests
          command: pnpm test
          environment:
            FOUNDRY_PROFILE: ci
          working_directory: packages/contracts-bedrock
          no_output_timeout: 15m

  contracts-bedrock-checks:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: xlarge
    steps:
      - checkout
      - restore_cache:
          name: Restore PNPM Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
      - check-changed:
          patterns: contracts-bedrock,op-node
      # populate node modules from the cache
      - run:
          name: Install dependencies
          command: pnpm install --frozen-lockfile --prefer-offline
      - run:
          name: build contracts
          command: pnpm build
          working_directory: packages/contracts-bedrock
      - run:
          name: lint
          command: |
            pnpm lint:check || echo "export LINT_STATUS=1" >> "$BASH_ENV"
          working_directory: packages/contracts-bedrock
      - run:
          name: gas snapshot
          command: |
            forge --version
            pnpm gas-snapshot --check || echo "export GAS_SNAPSHOT_STATUS=1" >> "$BASH_ENV"
          environment:
            FOUNDRY_PROFILE: ci
          working_directory: packages/contracts-bedrock
          no_output_timeout: 15m
      - run:
          name: storage snapshot
          command: |
            pnpm storage-snapshot
            git diff --exit-code .storage-layout || echo "export STORAGE_SNAPSHOT_STATUS=1" >> "$BASH_ENV"
          working_directory: packages/contracts-bedrock
      - run:
          name: semver lock
          command: |
            pnpm semver-lock
            git diff --exit-code semver-lock.json || echo "export SEMVER_LOCK_STATUS=1" >> "$BASH_ENV"
          working_directory: packages/contracts-bedrock
      - run:
          name: invariant docs
          command: |
            pnpm autogen:invariant-docs
            git diff --exit-code ./invariant-docs/*.md || echo "export INVARIANT_DOCS_STATUS=1" >> "$BASH_ENV"
          working_directory: packages/contracts-bedrock
      - run:
          name: check deploy configs || echo "export DEPLOY_CONFIGS_STATUS=1" >> "$BASH_ENV"
          command: pnpm validate-deploy-configs
          working_directory: packages/contracts-bedrock
      - run:
          name: check statuses
          command: |
            if [[ "$LINT_STATUS" -ne 0 ]]; then
              FAILED=1
              echo "Linting failed, see job output for details."
            fi
            if [[ "$GAS_SNAPSHOT_STATUS" -ne 0 ]]; then
              FAILED=1
              echo "Gas snapshot failed, see job output for details."
            fi
            if [[ "$STORAGE_SNAPSHOT_STATUS" -ne 0 ]]; then
              echo "Storage snapshot failed, see job output for details."
              FAILED=1
            fi
            if [[ "$SEMVER_LOCK_STATUS" -ne 0 ]]; then
              echo "Semver lock failed, see job output for details."
              FAILED=1
            fi
            if [[ "$INVARIANT_DOCS_STATUS" -ne 0 ]]; then
              echo "Invariant docs failed, see job output for details."
              FAILED=1
            fi
            if [[ "$DEPLOY_CONFIGS_STATUS" -ne 0 ]]; then
              echo "Deploy config check failed, see job output for details."
              FAILED=1
            fi
            if [[ "$FAILED" -ne 0 ]]; then
              exit 1
            fi

  contracts-bedrock-slither:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: large
    steps:
      - checkout
      - check-changed:
          patterns: contracts-bedrock
      - run:
          name: slither
          command: |
            slither --version && pnpm slither || echo "Slither failed"

  contracts-bedrock-validate-spaces:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - attach_workspace: { at: "." }
      - restore_cache:
          name: Restore PNPM Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
      # populate node modules from the cache
      - run:
          name: Install dependencies
          command: pnpm install --frozen-lockfile --prefer-offline
      - check-changed:
          patterns: contracts-bedrock
      - run:
          name: validate spacers
          command: pnpm validate-spacers
          working_directory: packages/contracts-bedrock

  op-bindings-build:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: large
    steps:
      - checkout
      - run:
          name: check go bindings
          command: make && git diff --exit-code
          working_directory: op-bindings

  js-lint-test:
    parameters:
      package_name:
        description: Package name
        type: string
      dependencies:
        description: Regex matching dependent packages
        type: string
        default: this-package-does-not-exist
      coverage_flag:
        description: Coverage flag name
        type: string
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: large
    steps:
      - checkout
      - attach_workspace: { at: "." }
      - restore_cache:
          name: Restore PNPM Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
      - check-changed:
          patterns: <<parameters.package_name>>,<<parameters.dependencies>>
      # populate node modules from the cache
      - run:
          name: Install dependencies
          command: pnpm install --frozen-lockfile --prefer-offline
      - run:
          name: Lint
          command: pnpm lint && git diff --exit-code
          working_directory: packages/<<parameters.package_name>>
      - run:
          name: Test
          command: pnpm test:coverage
          working_directory: packages/<<parameters.package_name>>
      - run:
          name: Upload coverage
          command: codecov --verbose --clean --flags <<parameters.coverage_flag>>

  contracts-ts-tests:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: large
    steps:
      - checkout
      - attach_workspace: { at: "." }
      - restore_cache:
          name: Restore pnpm Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm.lock.yaml" }}
      - check-changed:
          patterns: sdk,contracts-bedrock,contracts
      # populate node modules from the cache
      - run:
          name: Install dependencies
          command: pnpm install --frozen-lockfile --prefer-offline
      - run:
          name: Check generated and build
          command: pnpm generate:check
          working_directory: packages/contracts-ts

  sdk-next-tests:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: large
    steps:
      - checkout
      - attach_workspace: { at: "." }
      - restore_cache:
          name: Restore pnpm Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm.lock.yaml" }}
      - check-changed:
          patterns: sdk,contracts-bedrock,contracts
      # populate node modules from the cache
      - run:
          name: Install dependencies
          command: pnpm install --frozen-lockfile --prefer-offline
      - run:
          name: anvil-l1
          background: true
          # atm this is goerli but we should use mainnet after bedrock is live
          command: anvil --fork-url $ANVIL_L1_FORK_URL --fork-block-number 9256679

      - run:
          name: anvil-l2
          background: true
          # atm this is goerli but we should use mainnet after bedrock is live
          command: anvil --fork-url $ANVIL_L2_FORK_URL --port 9545 --fork-block-number 11276409

      - run:
          name: build
          command: pnpm build
          working_directory: packages/sdk
      - run:
          name: lint
          command: pnpm lint:check
          working_directory: packages/sdk
      - run:
          name: make sure anvil l1 is up
          command: npx wait-on tcp:8545 && cast block-number --rpc-url http://localhost:8545
      - run:
          name: make sure anvil l2 is up
          command: npx wait-on tcp:9545 && cast block-number --rpc-url http://localhost:9545
      - run:
          name: test:next
          command: pnpm test:next:run
          no_output_timeout: 5m
          working_directory: packages/sdk
          environment:
            # anvil[0] test private key
            VITE_E2E_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
            VITE_E2E_RPC_URL_L1: http://localhost:8545
            VITE_E2E_RPC_URL_L2: http://localhost:9545

  todo-issues:
    machine:
      image: ubuntu-2204:2022.07.1
    steps:
      - checkout
      - run:
          name: Install ripgrep
          command: sudo apt-get install -y ripgrep
      - run:
          name: Check TODO issues
          command: ./ops/scripts/todo-checker.sh --verbose
      - slack/notify:
          channel: C03N11M0BBN
          event: fail
          template: basic_fail_1

  bedrock-markdown:
    machine:
      image: ubuntu-2204:2022.07.1
    steps:
      - checkout
      - check-changed:
          patterns: specs/(.*)\.md$
      - run:
          name: Install pnpm package manager
          command: |
            npm i pnpm --global
      - run:
          name: pnpm dev deps
          command: pnpm install --frozen-lockfile --prefer-offline
      - run:
          name: specs toc
          command: pnpm lint:specs:toc && git diff --exit-code ./specs
      - run:
          name: markdown lint
          command: pnpm lint:specs:check

  bedrock-markdown-links:
    machine:
      image: ubuntu-2204:2022.07.1
    steps:
      - checkout
      - run:
          name: Install pnpm package manager
          command: |
            npm i pnpm --global
      - run:
          name: Install node_modules
          command: |
            pnpm install --frozen-lockfile --prefer-offline
      - run:
          name: Lint check
          command: |
            pnpm lint:specs:check
      - run:
          name: link lint
          command: |
            make bedrock-markdown-links
      - slack/notify:
          channel: C055R639XT9 #notify-link-check
          event: fail
          template: basic_fail_1

  fuzz-op-node:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: op-node
      - run:
          name: Fuzz
          command: make fuzz
          working_directory: op-node

  fuzz-op-service:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: op-service
      - run:
          name: Fuzz
          command: make fuzz
          working_directory: op-service

  fuzz-op-chain-ops:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: op-chain-ops,op-bindings
      - run:
          name: Fuzz
          command: make fuzz
          working_directory: op-chain-ops

  fuzz-cannon:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: cannon,packages/contracts-bedrock/src/cannon
      - run:
          name: Fuzz
          command: make fuzz
          working_directory: cannon

  depcheck:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - attach_workspace: { at: "." }
      - restore_cache:
          name: Restore PNPM Package Cache
          keys:
            - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }}
      - check-changed:
          patterns: packages
      - run:
          name: Check common-ts
          command: npx depcheck
          working_directory: packages/common-ts
      - run:
          name: Check core-utils
          command: npx depcheck
          working_directory: packages/core-utils
      - run:
          name: Check sdk
          command: npx depcheck
          working_directory: packages/sdk

  go-lint:
    parameters:
      module:
        description: Go Module Name
        type: string
    docker:
      - image: cimg/go:1.21
    steps:
      - checkout
      - run:
          name: run lint
          command: make lint
          working_directory: <<parameters.module>>

  go-test:
    parameters:
      module:
        description: Go Module Name
        type: string
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest # only used to enable codecov.
    resource_class: xlarge
    steps:
      - checkout
      - run:
          name: prep results dir
          command: mkdir -p /tmp/test-results
      - run:
          name: run tests
          command: |
            gotestsum --format=standard-verbose --junitfile=/tmp/test-results/<<parameters.module>>.xml \
            -- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out ./...
          working_directory: <<parameters.module>>
      - run:
          name: upload coverage
          command: codecov --verbose --clean --flags bedrock-go-tests
      - store_test_results:
          path: /tmp/test-results

  go-e2e-test:
    parameters:
      module:
        description: Go Module Name
        type: string
      target:
        description: The make target to execute
        type: string
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    resource_class: xlarge
    steps:
      - checkout
      - check-changed:
          patterns: op-(.+),cannon,contracts-bedrock
      - run:
          name: prep results dir
          command: mkdir -p /tmp/test-results
      - run:
          name: install geth
          command: make install-geth
      - run:
          name: git submodules
          command: git submodule update --init --recursive
      - run:
          name: print go's available MIPS targets
          command: go tool dist list | grep mips
      - run:
          name: run tests
          command:
            # Note: We don't use circle CI test splits because we need to split by test name, not by package. There is an additional
            # constraint that gotestsum does not currently (nor likely will) accept files from different pacakges when building.
            JUNIT_FILE=/tmp/test-results/<<parameters.module>>_<<parameters.target>>.xml make <<parameters.target>>
          working_directory: <<parameters.module>>
      - store_test_results:
          path: /tmp/test-results

  go-lint-test-build:
    parameters:
      binary_name:
        description: Binary name to build
        type: string
      working_directory:
        description: Working directory
        type: string
      build:
        description: Whether or not to build the binary
        type: boolean
        default: true
      dependencies:
        description: Regex matching dependent packages
        type: string
        default: this-package-does-not-exist
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: <<parameters.working_directory>>,<<parameters.dependencies>>
      - run:
          name: Lint
          command: make lint
          working_directory: <<parameters.working_directory>>
      - store_test_results:
          path: /test-results
      - run:
          name: Test
          command: |
            mkdir -p /test-results
            gotestsum --junitfile /test-results/tests.xml
          working_directory: <<parameters.working_directory>>
      - when:
          condition:
            equal: [ true, <<parameters.build>> ]
          steps:
            - run:
                name: Build
                command: make <<parameters.binary_name>>
                working_directory: <<parameters.working_directory>>

  indexer-tests:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
      - image: cimg/postgres:14.1
    resource_class: large
    steps:
      - checkout
      - check-changed:
          patterns: indexer
      - run:
          name: Lint
          command: golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 4m -e "errors.As" -e "errors.Is" ./...
          working_directory: indexer
      - run:
          name: install geth
          command: make install-geth
      - run:
          name: git submodules
          command: git submodule update --init --recursive
      - run:
          name: generate cannon prestate
          command: make cannon-prestate
      - run:
          name: generate L1 state
          command: make devnet-allocs
      - run:
          name: Test
          command: |
            mkdir -p /test-results
            DB_USER=postgres gotestsum --format=standard-verbose --junitfile=/test-results/indexer_tests.xml -- -parallel=4 ./...
          working_directory: indexer
      - store_test_results:
          path: /test-results
      - run:
          name: Build
          command: make indexer
          working_directory: indexer
      - run:
          name: Install node_modules
          command: pnpm install --frozen-lockfile --prefer-offline
          working_directory: indexer/api-ts
      - run:
          name: Install tygo
          command: go install github.com/gzuidhof/tygo@latest
          working_directory: indexer/api-ts
      - run:
          name: Check generated code
          command: npm run generate && git diff --exit-code
          working_directory: indexer/api-ts

  devnet:
    machine:
      image: ubuntu-2204:2022.10.2
    environment:
      DOCKER_BUILDKIT: 1
    steps:
      - checkout
      - check-changed:
          patterns: op-(.+),packages,ops-bedrock
      - run:
          name: Install latest golang
          command: |
            wget https://go.dev/dl/go1.21.1.linux-amd64.tar.gz
            sudo rm -rf /usr/local/go
            sudo tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz
            export PATH=$PATH:/usr/local/go/bin
            go version
      - run:
          name: foundryup
          command: |
            curl -L https://foundry.paradigm.xyz | bash
            source $HOME/.bashrc
            foundryup
            echo 'export PATH=$HOME/.foundry/bin:$PATH' >> $BASH_ENV
            source $HOME/.bashrc
            forge --version
      - run:
          name: install geth
          command: make install-geth
      - run:
          name: Install NVM
          command: |
            curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
            source ~/.bashrc
            nvm --version
      - run:
          name: Install Node
          command: |
            nvm install
            nvm use && node --version && npm --version
      - run:
          name: Install pnpm
          command: |
            npm i pnpm --global
      - run:
          name: git submodules
          command: git submodule update --init --recursive
      - run:
          name: Install and build
          command: |
            pnpm install --frozen-lockfile --prefer-offline && pnpm build
      - run:
          name: generate cannon prestate
          command: make cannon-prestate
      - run:
          name: Bring up the stack
          command: make devnet-up
      - run:
          name: Test the stack
          command: make devnet-test
      - run:
          name: Dump op-node logs
          command: |
            docker logs ops-bedrock-op-node-1 || echo "No logs."
          when: on_fail
      - run:
          name: Dump op-geth logs
          command: |
            docker logs ops-bedrock-l2-1 || echo "No logs."
          when: on_fail
      - run:
          name: Dump l1 logs
          command: |
            docker logs ops-bedrock-l1-1 || echo "No logs."
          when: on_fail
      - run:
          name: Dump op-batcher logs
          command: |
            docker logs ops-bedrock-op-batcher-1 || echo "No logs."
          when: on_fail
      - run:
          name: Dump op-proposer logs
          command: |
            docker logs ops-bedrock-op-proposer-1 || echo "No logs."
          when: on_fail
      - run:
          name: Log deployment artifact
          command: |
            cat broadcast/Deploy.s.sol/900/run-latest.json || echo "No deployment file found"
          when: on_fail
          working_directory: packages/contracts-bedrock
      - run:
          name: Log artifacts directory
          command: |
            ls -R forge-artifacts || echo "No forge artifacts found"
          when: on_fail
          working_directory: packages/contracts-bedrock

  semgrep-scan:
    parameters:
      diff_branch:
        type: string
        default: develop
    environment:
      TEMPORARY_BASELINE_REF: << parameters.diff_branch >>
      SEMGREP_REPO_URL: << pipeline.project.git_url >>
      SEMGREP_BRANCH: << pipeline.git.branch >>
      SEMGREP_COMMIT: << pipeline.git.revision >>

      # Change job timeout (default is 1800 seconds; set to 0 to disable)
      SEMGREP_TIMEOUT: 3000

    docker:
      - image: returntocorp/semgrep
    resource_class: medium
    steps:
      - checkout
      - unless:
          condition:
            equal: [ "develop", << pipeline.git.branch >> ]
          steps:
            - run:
                # Scan changed files in PRs, block on new issues only (existing issues ignored)
                # Do a full scan when scanning develop, otherwise do an incremental scan.
                name: "Conditionally set BASELINE env var"
                command: |
                  echo 'export SEMGREP_BASELINE_REF=${TEMPORARY_BASELINE_REF}' >> $BASH_ENV
      - run:
          name: "Set environment variables" # for PR comments and in-app hyperlinks to findings
          command: |
            echo 'export SEMGREP_PR_ID=${CIRCLE_PULL_REQUEST##*/}' >> $BASH_ENV
            echo 'export SEMGREP_JOB_URL=$CIRCLE_BUILD_URL' >> $BASH_ENV
            echo 'export SEMGREP_REPO_NAME=$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME' >> $BASH_ENV
      - run:
          name: "Semgrep scan"
          command: semgrep ci

  go-mod-tidy:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - run:
          name: "Go mod tidy"
          command: make mod-tidy && git diff --exit-code

  bedrock-go-tests:
    docker:
      - image: cimg/go:1.21
    resource_class: medium
    steps:
      - run: echo Done

  fpp-verify:
    docker:
      - image: cimg/go:1.21
    steps:
      - checkout
      - run:
          name: verify-goerli
          command: |
            make verify-goerli
          working_directory: op-program
      - slack/notify:
          channel: C03N11M0BBN
          event: fail
          template: basic_fail_1

  check-generated-mocks-op-node:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: op-node
      - run:
          name: check-generated-mocks
          command: make generate-mocks-op-node && git diff --exit-code

  check-generated-mocks-op-service:
    docker:
      - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
    steps:
      - checkout
      - check-changed:
          patterns: op-service
      - run:
          name: check-generated-mocks
          command: make generate-mocks-op-service && git diff --exit-code

workflows:
  main:
    when:
      not:
        equal: [ scheduled_pipeline, << pipeline.trigger_source >> ]
    jobs:
      - pnpm-monorepo
      - js-lint-test:
          name: common-ts-tests
          coverage_flag: common-ts-tests
          package_name: common-ts
          requires:
            - pnpm-monorepo
      - js-lint-test:
          name: core-utils-tests
          coverage_flag: core-utils-tests
          package_name: core-utils
          requires:
            - pnpm-monorepo
      - contracts-bedrock-tests
      - contracts-bedrock-coverage
      - contracts-bedrock-checks:
          requires:
            - pnpm-monorepo
      - contracts-bedrock-slither
      - contracts-bedrock-validate-spaces:
          requires:
            - pnpm-monorepo
      - op-bindings-build
      - js-lint-test:
          name: chain-mon-tests
          coverage_flag: chain-mon-tests
          package_name: chain-mon
          dependencies: "(common-ts|contracts-bedrock|core-utils|sdk)"
          requires:
            - pnpm-monorepo
      - js-lint-test:
          name: contracts-ts-tests
          coverage_flag: contracts-ts-tests
          package_name: contracts-ts
          dependencies: '(contracts-bedrock|contracts-ts)'
          requires:
            - pnpm-monorepo
      - js-lint-test:
          name: sdk-next-tests
          coverage_flag: sdk-next-tests
          package_name: sdk
          dependencies: "(common-ts|contracts-bedrock|core-utils)"
          requires:
            - pnpm-monorepo
      - js-lint-test:
          name: sdk-tests
          coverage_flag: sdk-tests
          package_name: sdk
          dependencies: "(contracts-bedrock|core-utils)"
          requires:
            - pnpm-monorepo
      - depcheck:
          requires:
            - pnpm-monorepo
      - devnet
      - go-lint-test-build:
          name: proxyd-tests
          binary_name: proxyd
          working_directory: proxyd
      - indexer-tests
      - go-lint-test-build:
          name: op-heartbeat-tests
          binary_name: op-heartbeat
          working_directory: op-heartbeat
      - semgrep-scan
      - go-mod-tidy
      - fuzz-op-node
      - fuzz-op-service
      - fuzz-op-chain-ops
      - fuzz-cannon
      - bedrock-markdown
      - go-lint:
          name: op-batcher-lint
          module: op-batcher
      - go-lint:
          name: op-bootnode-lint
          module: op-bootnode
      - go-lint:
          name: op-bindings-lint
          module: op-bindings
      - go-lint:
          name: op-chain-ops-lint
          module: op-chain-ops
      - go-lint:
          name: op-e2e-lint
          module: op-e2e
      - go-lint:
          name: op-node-lint
          module: op-node
      - go-lint:
          name: op-proposer-lint
          module: op-proposer
      - go-lint:
          name: op-challenger-lint
          module: op-challenger
      - go-lint:
          name: op-program-lint
          module: op-program
      - go-lint:
          name: op-service-lint
          module: op-service
      - go-lint:
          name: op-wheel-lint
          module: op-wheel
      - go-test:
          name: op-batcher-tests
          module: op-batcher
      - go-test:
          name: op-bindings-tests
          module: op-bindings
      - go-test:
          name: op-chain-ops-tests
          module: op-chain-ops
      - go-test:
          name: op-node-tests
          module: op-node
          # TODO: override resource class
      - go-test:
          name: op-proposer-tests
          module: op-proposer
      - go-test:
          name: op-challenger-tests
          module: op-challenger
      - go-test:
          name: op-program-tests
          module: op-program
      - go-test:
          name: op-service-tests
          module: op-service
      - go-e2e-test:
          name: op-e2e-WS-tests
          module: op-e2e
          target: test-ws
      - go-e2e-test:
          name: op-e2e-HTTP-tests
          module: op-e2e
          target: test-http
      - go-e2e-test:
          name: op-e2e-ext-geth-tests
          module: op-e2e
          target: test-external-geth
      - bedrock-go-tests:
          requires:
            - go-mod-tidy
            - cannon-build-test-vectors
            - cannon-go-lint-and-test
            - check-generated-mocks-op-node
            - check-generated-mocks-op-service
            - op-batcher-lint
            - op-bootnode-lint
            - op-bindings-lint
            - op-chain-ops-lint
            - op-e2e-lint
            - op-node-lint
            - op-proposer-lint
            - op-challenger-lint
            - op-program-lint
            - op-service-lint
            - op-batcher-tests
            - op-bindings-tests
            - op-chain-ops-tests
            - op-heartbeat-tests
            - op-node-tests
            - op-proposer-tests
            - op-challenger-tests
            - op-program-tests
            - op-service-tests
            - op-e2e-WS-tests
            - op-e2e-HTTP-tests
            - op-e2e-ext-geth-tests
      - docker-build:
          name: op-node-docker-build
          docker_file: op-node/Dockerfile
          docker_name: op-node
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: op-batcher-docker-build
          docker_file: op-batcher/Dockerfile
          docker_name: op-batcher
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: op-program-docker-build
          docker_file: op-program/Dockerfile
          docker_name: op-program
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: op-proposer-docker-build
          docker_file: op-proposer/Dockerfile
          docker_name: op-proposer
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: op-challenger-docker-build
          docker_file: op-challenger/Dockerfile
          docker_name: op-challenger
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: op-heartbeat-docker-build
          docker_file: op-heartbeat/Dockerfile
          docker_name: op-heartbeat
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: indexer-docker-build
          docker_file: indexer/Dockerfile
          docker_name: indexer
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
      - docker-build:
          name: ufm-metamask-docker-build
          docker_file: ufm-test-services/metamask/Dockerfile
          docker_name: ufm-metamask
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: ufm-test-services/metamask
      - check-generated-mocks-op-node
      - check-generated-mocks-op-service
      - cannon-go-lint-and-test
      - cannon-build-test-vectors

  release:
    when:
      not:
        equal: [ scheduled_pipeline, << pipeline.trigger_source >> ]
    jobs:
      - hold:
          type: approval
          filters:
            tags:
              only: /^(proxyd|indexer|ci-builder|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/
            branches:
              ignore: /.*/
      - docker-release:
          name: op-heartbeat-release
          filters:
            tags:
              only: /^op-heartbeat\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-heartbeat/Dockerfile
          docker_name: op-heartbeat
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          platforms: "linux/amd64,linux/arm64"
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: op-node-docker-release
          filters:
            tags:
              only: /^op-node\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-node/Dockerfile
          docker_name: op-node
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          platforms: "linux/amd64,linux/arm64"
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: op-batcher-docker-release
          filters:
            tags:
              only: /^op-batcher\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-batcher/Dockerfile
          docker_name: op-batcher
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          platforms: "linux/amd64,linux/arm64"
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: op-proposer-docker-release
          filters:
            tags:
              only: /^op-proposer\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-proposer/Dockerfile
          docker_name: op-proposer
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          platforms: "linux/amd64,linux/arm64"
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: op-challenger-docker-release
          filters:
            tags:
              only: /^op-challenger\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-challenger/Dockerfile
          docker_name: op-challenger
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          platforms: "linux/amd64,linux/arm64"
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-build:
          name: op-migrate-docker-release
          filters:
            tags:
              only: /^op-migrate\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-chain-ops/Dockerfile
          docker_name: op-migrate
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: op-ufm-docker-release
          filters:
            tags:
              only: /^op-ufm\/v.*/
            branches:
              ignore: /.*/
          docker_file: op-ufm/Dockerfile
          docker_name: op-ufm
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: proxyd-docker-release
          filters:
            tags:
              only: /^proxyd\/v.*/
            branches:
              ignore: /.*/
          docker_file: proxyd/Dockerfile
          docker_name: proxyd
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: indexer-docker-release
          filters:
            tags:
              only: /^indexer\/v.*/
            branches:
              ignore: /.*/
          docker_file: indexer/Dockerfile
          docker_name: indexer
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_context: .
          context:
            - oplabs-gcr-release
          requires:
            - hold
      - docker-release:
          name: ci-builder-docker-release
          filters:
            tags:
              only: /^ci-builder\/v.*/
            branches:
              ignore: /.*/
          docker_file: ./ops/docker/ci-builder/Dockerfile
          docker_name: ci-builder
          docker_tags: <<pipeline.git.revision>>,latest
          docker_context: .
          context:
            - oplabs-gcr
          requires:
            - hold
      - docker-release:
          name: ufm-metamask-docker-release
          filters:
            tags:
              only: /^ufm-metamask\/v.*/
            branches:
              ignore: /.*/
          docker_file: ./ufm-test-services/metamask/Dockerfile
          docker_name: ufm-metamask
          docker_tags: <<pipeline.git.revision>>,latest
          docker_context: ./ufm-test-services/metamask
          context:
            - oplabs-gcr
          requires:
            - hold

  scheduled-todo-issues:
    when:
      equal: [ build_four_hours, <<pipeline.schedule.name>> ]
    jobs:
      - todo-issues:
          name: todo-issue-checks
          context:
            - slack

  scheduled-fpp:
    when:
      equal: [ build_four_hours, <<pipeline.schedule.name>> ]
    jobs:
      - fpp-verify:
          context:
            - slack
            - oplabs-fpp-nodes

  scheduled-link-check:
    when:
      equal: [ build_daily, <<pipeline.schedule.name>> ]
    jobs:
      - bedrock-markdown-links:
          context: slack

  scheduled-docker-publish:
    when:
      equal: [ build_hourly, <<pipeline.schedule.name>> ]
    jobs:
      - docker-publish:
          name: op-node-docker-publish
          docker_name: op-node
          docker_file: op-node/Dockerfile
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: op-batcher-docker-publish
          docker_file: op-batcher/Dockerfile
          docker_name: op-batcher
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: op-program-docker-publish
          docker_file: op-program/Dockerfile
          docker_name: op-program
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: op-proposer-docker-publish
          docker_file: op-proposer/Dockerfile
          docker_name: op-proposer
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: op-challenger-docker-publish
          docker_file: op-challenger/Dockerfile
          docker_name: op-challenger
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: op-heartbeat-docker-publish
          docker_file: op-heartbeat/Dockerfile
          docker_name: op-heartbeat
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: indexer-docker-publish
          docker_file: indexer/Dockerfile
          docker_name: indexer
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
          platforms: "linux/amd64,linux/arm64"
      - docker-publish:
          name: chain-mon-docker-publish
          docker_file: ./ops/docker/Dockerfile.packages
          docker_name: chain-mon
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          docker_target: wd-mon
          context:
            - oplabs-gcr
      - docker-publish:
          name: ufm-metamask-docker-publish
          docker_file: ufm-test-services/metamask/Dockerfile
          docker_name: ufm-metamask
          docker_context: ufm-test-services/metamask
          docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
          context:
            - oplabs-gcr
