diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 9b8a5cf42ab2..000000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,72 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ "master" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "master" ] - schedule: - - cron: '45 11 * * 5' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'javascript' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml deleted file mode 100644 index 4bb08276d06d..000000000000 --- a/.github/workflows/config.yml +++ /dev/null @@ -1,584 +0,0 @@ -name: Blockscout - -on: - push: - branches: - - master - pull_request: - branches: - - master - -env: - MIX_ENV: test - OTP_VERSION: '24.3.4.1' - ELIXIR_VERSION: '1.13.4' - ACCOUNT_AUTH0_DOMAIN: 'blockscoutcom.us.auth0.com' - ACCOUNT_AUTH0_LOGOUT_URL: 'https://blockscoutcom.us.auth0.com/v2/logout' - ACCOUNT_AUTH0_LOGOUT_RETURN_URL: 'https://blockscout.com/auth/logout' - -jobs: - build-and-cache: - name: Build and Cache deps - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: "ELIXIR_VERSION.lock" - run: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock - - - name: "OTP_VERSION.lock" - run: echo "${OTP_VERSION}" > OTP_VERSION.lock - - - name: Restore Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps- - - - name: Conditionally build Mix deps cache - if: steps.deps-cache.outputs.cache-hit != 'true' - run: | - mix local.hex --force - mix local.rebar --force - mix deps.get - mix deps.compile - cd deps/libsecp256k1 - make - - - name: Restore Explorer NPM Cache - uses: actions/cache@v2 - id: explorer-npm-cache - with: - path: apps/explorer/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm- - - - name: Conditionally build Explorer NPM Cache - if: steps.explorer-npm-cache.outputs.cache-hit != 'true' - run: npm install - working-directory: apps/explorer - - - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 - id: blockscoutweb-npm-cache - with: - path: apps/block_scout_web/assets/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm- - - - name: Conditionally build Blockscout Web NPM Cache - if: steps.blockscoutweb-npm-cache.outputs.cache-hit != 'true' - run: npm install - working-directory: apps/block_scout_web/assets - - credo: - name: Credo - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Restore Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - run: mix credo - - check_formatted: - name: Code formatting checks - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Restore Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - run: mix format --check-formatted - dialyzer: - name: Dialyzer static analysis - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Restore Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - name: Restore Dialyzer Cache - uses: actions/cache@v2 - id: dialyzer-cache - with: - path: priv/plts - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_15-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-" - - - name: Conditionally build Dialyzer Cache - if: steps.dialyzer-cache.output.cache-hit != 'true' - run: | - mkdir -p priv/plts - mix dialyzer --plt - - - name: Run Dialyzer - run: mix dialyzer --halt-exit-status - - gettext: - name: Missing translation keys check - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Restore Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - run: | - mix gettext.extract --merge | tee stdout.txt - ! grep "Wrote " stdout.txt - working-directory: "apps/block_scout_web" - sobelow: - name: Sobelow security analysis - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - name: Scan explorer for vulnerabilities - run: mix sobelow --config - working-directory: "apps/explorer" - - name: Scan block_scout_web for vulnerabilities - run: mix sobelow --config - working-directory: "apps/block_scout_web" - eslint: - name: ESLint - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - name: Restore Explorer NPM Cache - uses: actions/cache@v2 - id: explorer-npm-cache - with: - path: apps/explorer/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm- - - - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 - id: blockscoutweb-npm-cache - with: - path: apps/block_scout_web/assets/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm- - - - name: Build assets - run: node node_modules/webpack/bin/webpack.js --mode development - working-directory: "apps/block_scout_web/assets" - - - run: ./node_modules/.bin/eslint --format=junit --output-file="test/eslint/junit.xml" js/** - working-directory: apps/block_scout_web/assets - jest: - name: JS Tests - runs-on: ubuntu-latest - needs: build-and-cache - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 - id: blockscoutweb-npm-cache - with: - path: apps/block_scout_web/assets/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm- - - - name: Build assets - run: node node_modules/webpack/bin/webpack.js --mode development - working-directory: "apps/block_scout_web/assets" - - - run: ./node_modules/.bin/jest - working-directory: apps/block_scout_web/assets - - test_nethermind_mox_ethereum_jsonrpc: - name: EthereumJSONRPC Tests - runs-on: ubuntu-latest - needs: build-and-cache - services: - postgres: - image: postgres - env: - # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - POSTGRES_DB: explorer_test - # match PGPASSWORD for elixir image above - POSTGRES_PASSWORD: postgres - # match PGUSER for elixir image above - POSTGRES_USER: postgres - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - # Maps tcp port 5432 on service container to the host - - 5432:5432 - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - run: ./bin/install_chrome_headless.sh - - name: mix test --exclude no_nethermind - run: | - cd apps/ethereum_jsonrpc - mix compile - mix test --no-start --exclude no_nethermind - env: - # match POSTGRES_PASSWORD for postgres image below - PGPASSWORD: postgres - # match POSTGRES_USER for postgres image below - PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" - ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - test_nethermind_mox_explorer: - name: Explorer Tests - runs-on: ubuntu-latest - needs: build-and-cache - services: - postgres: - image: postgres - env: - # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - POSTGRES_DB: explorer_test - # match PGPASSWORD for elixir image above - POSTGRES_PASSWORD: postgres - # match PGUSER for elixir image above - POSTGRES_USER: postgres - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - # Maps tcp port 5432 on service container to the host - - 5432:5432 - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - name: Restore Explorer NPM Cache - uses: actions/cache@v2 - id: explorer-npm-cache - with: - path: apps/explorer/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm - - - run: ./bin/install_chrome_headless.sh - - name: mix test --exclude no_nethermind - run: | - mix ecto.create --quiet - mix ecto.migrate - cd apps/explorer - mix compile - mix test --no-start --exclude no_nethermind - env: - # match POSTGRES_PASSWORD for postgres image below - PGPASSWORD: postgres - # match POSTGRES_USER for postgres image below - PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" - ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - test_nethermind_mox_indexer: - name: Indexer Tests - runs-on: ubuntu-latest - needs: build-and-cache - services: - postgres: - image: postgres - env: - # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - POSTGRES_DB: explorer_test - # match PGPASSWORD for elixir image above - POSTGRES_PASSWORD: postgres - # match PGUSER for elixir image above - POSTGRES_USER: postgres - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - # Maps tcp port 5432 on service container to the host - - 5432:5432 - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - - run: ./bin/install_chrome_headless.sh - - - name: mix test --exclude no_nethermind - run: | - mix ecto.create --quiet - mix ecto.migrate - cd apps/indexer - mix compile - mix test --no-start --exclude no_nethermind - env: - # match POSTGRES_PASSWORD for postgres image below - PGPASSWORD: postgres - # match POSTGRES_USER for postgres image below - PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" - ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - - test_nethermind_mox_block_scout_web: - name: Blockscout Web Tests - runs-on: ubuntu-latest - needs: build-and-cache - services: - redis_db: - image: 'redis:alpine' - ports: - - 6379:6379 - - postgres: - image: postgres - env: - # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - POSTGRES_DB: explorer_test - # match PGPASSWORD for elixir image above - POSTGRES_PASSWORD: postgres - # match PGUSER for elixir image above - POSTGRES_USER: postgres - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - # Maps tcp port 5432 on service container to the host - - 5432:5432 - steps: - - uses: actions/checkout@v2 - - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ env.OTP_VERSION }} - elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV - - - name: Mix Deps Cache - uses: actions/cache@v2 - id: deps-cache - with: - path: | - deps - _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - - - - name: Restore Explorer NPM Cache - uses: actions/cache@v2 - id: explorer-npm-cache - with: - path: apps/explorer/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm- - - - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 - id: blockscoutweb-npm-cache - with: - path: apps/block_scout_web/assets/node_modules - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm- - - - name: Build assets - run: node node_modules/webpack/bin/webpack.js --mode development - working-directory: "apps/block_scout_web/assets" - - - run: ./bin/install_chrome_headless.sh - - - name: mix test --exclude no_nethermind - run: | - mix ecto.create --quiet - mix ecto.migrate - cd apps/block_scout_web - mix compile - mix test --no-start --exclude no_nethermind - env: - # match POSTGRES_PASSWORD for postgres image below - PGPASSWORD: postgres - # match POSTGRES_USER for postgres image below - PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" - ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - CHAIN_ID: "77" - ADMIN_PANEL_ENABLED: "true" - ACCOUNT_ENABLED: "true" - ACCOUNT_REDIS_URL: "redis://localhost:6379" diff --git a/.github/workflows/publish-docker-image-every-push-saas.yml b/.github/workflows/publish-docker-image-every-push-saas.yml new file mode 100644 index 000000000000..7df0aa258420 --- /dev/null +++ b/.github/workflows/publish-docker-image-every-push-saas.yml @@ -0,0 +1,85 @@ +name: Publish Docker image on every push to master branch + +on: + push: + branches: + - master +env: + OTP_VERSION: "24.3.4.1" + ELIXIR_VERSION: "1.13.4" + NEXT_RELEASE_VERSION: 4.1.11 + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + outputs: + release-version: ${{ steps.output-step.outputs.release-version }} + short-sha: ${{ steps.output-step.outputs.short-sha }} + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.PAT_TOKEN }} + + - run: docker context create gha${{ github.sha }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/settlemint/blockscout-saas + + - name: Add SHORT_SHA env property with commit short sha + run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV + + - name: Add outputs + run: | + echo "::set-output name=release-version::${{ env.NEXT_RELEASE_VERSION }}" + echo "::set-output name=short-sha::${{ env.SHORT_SHA }}" + id: output-step + + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + file: ./docker/Dockerfile + cache-from: type=registry,ref=ghcr.io/settlemint/blockscout:buildcache + cache-to: type=registry,ref=ghcr.io/settlemint/blockscout:buildcache,mode=max + push: true + platforms: | + linux/arm64 + linux/amd64 + tags: ghcr.io/settlemint/blockscout-saas:latest, ghcr.io/settlemint/blockscout-saas:${{ env.NEXT_RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}, ghcr.io/settlemint/blockscout-saas:${{ env.NEXT_RELEASE_VERSION }} + build-args: | + CACHE_EXCHANGE_RATES_PERIOD= + DISABLE_READ_API=false + DISABLE_WEBAPP=false + DISABLE_WRITE_API=false + CACHE_ENABLE_TOTAL_GAS_USAGE_COUNTER= + WOBSERVER_ENABLED=false + ADMIN_PANEL_ENABLED=true + CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= + DISABLE_BRIDGE_MARKET_CAP_UPDATER=true + CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL= + CHAIN_ID= + JSON_RPC= + COIN_NAME=Native Token + COIN=NT + SUBNETWORK= + DISABLE_EXCHANGE_RATES=true + SECRET_KEY_BASE=RMgI4C1HSkxsEjdhtGMfwAHfyT6CKWXOgzCboJflfSm4jeAlic52io05KB6mqzc5 + ENABLE_TXS_STATS=true + SHOW_TXS_CHART=true + LOGO=/images/blockscout_logo.svg diff --git a/.github/workflows/publish-docker-image-every-push.yml b/.github/workflows/publish-docker-image-every-push.yml index e15694d1a856..ed3c13fe1d4d 100644 --- a/.github/workflows/publish-docker-image-every-push.yml +++ b/.github/workflows/publish-docker-image-every-push.yml @@ -7,7 +7,7 @@ on: env: OTP_VERSION: '24.3.4.1' ELIXIR_VERSION: '1.13.4' - NEXT_RELEASE_VERSION: 5.0.0 + NEXT_RELEASE_VERSION: 4.1.11 jobs: push_to_registry: @@ -26,17 +26,20 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - name: Log in to Docker Hub + - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.PAT_TOKEN }} + + - run: docker context create gha${{ github.sha }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4 with: - images: blockscout/blockscout + images: ghcr.io/settlemint/blockscout - name: Add SHORT_SHA env property with commit short sha run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV @@ -53,28 +56,33 @@ jobs: context: . file: ./docker/Dockerfile push: true - cache-from: type=registry,ref=blockscout/blockscout:buildcache - cache-to: type=registry,ref=blockscout/blockscout:buildcache,mode=max - tags: blockscout/blockscout:latest, blockscout/blockscout:${{ env.NEXT_RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }} + cache-from: type=registry,ref=ghcr.io/settlemint/blockscout:buildcache + cache-to: type=registry,ref=ghcr.io/settlemint/blockscout:buildcache,mode=max + platforms: | + linux/arm64 + linux/amd64 + tags: ghcr.io/settlemint/blockscout:latest, ghcr.io/settlemint/blockscout:${{ env.NEXT_RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}, ghcr.io/settlemint/blockscout:${{ env.NEXT_RELEASE_VERSION }} build-args: | CACHE_EXCHANGE_RATES_PERIOD= DISABLE_READ_API=false - API_PATH= - NETWORK_PATH= + API_PATH=/explorer + NETWORK_PATH=/explorer DISABLE_WEBAPP=false DISABLE_WRITE_API=false CACHE_ENABLE_TOTAL_GAS_USAGE_COUNTER= WOBSERVER_ENABLED=false - ADMIN_PANEL_ENABLED=false + ADMIN_PANEL_ENABLED=true CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= - DISABLE_BRIDGE_MARKET_CAP_UPDATER=false + DISABLE_BRIDGE_MARKET_CAP_UPDATER=true CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL= - SOCKET_ROOT= - tests: - needs: push_to_registry - uses: blockscout/blockscout-ci-cd/.github/workflows/e2e_k8s.yaml@master - with: - blockscout_image: blockscout/blockscout:${{ needs.push_to_registry.outputs.release-version }}-prerelease-${{ needs.push_to_registry.outputs.short-sha }} - environment: 'test' - verification_image: 'ghcr.io/blockscout/verification:latest' - secrets: inherit + SOCKET_ROOT=/ + CHAIN_ID= + JSON_RPC= + COIN_NAME=Native Token + COIN=NT + SUBNETWORK= + DISABLE_EXCHANGE_RATES=true + SECRET_KEY_BASE=RMgI4C1HSkxsEjdhtGMfwAHfyT6CKWXOgzCboJflfSm4jeAlic52io05KB6mqzc5 + ENABLE_TXS_STATS=true + SHOW_TXS_CHART=true + LOGO=/explorer/images/blockscout_logo.svg diff --git a/.github/workflows/publish-docker-image-release.yml b/.github/workflows/publish-docker-image-release.yml deleted file mode 100644 index 05861878b950..000000000000 --- a/.github/workflows/publish-docker-image-release.yml +++ /dev/null @@ -1,111 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Publish Docker image - -on: - release: - types: [published] - -env: - OTP_VERSION: '24.3.4.1' - ELIXIR_VERSION: '1.13.4' - -jobs: - push_to_registry: - name: Push Docker image to Docker Hub - runs-on: ubuntu-latest - env: - RELEASE_VERSION: 4.1.8 - steps: - - name: Check out the repo - uses: actions/checkout@v3 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Log in to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: blockscout/blockscout - - - name: Build & Push Docker image - uses: docker/build-push-action@v3 - with: - context: . - file: ./docker/Dockerfile - push: true - cache-from: type=registry,ref=blockscout/blockscout:buildcache - cache-to: type=registry,ref=blockscout/blockscout:buildcache,mode=max - tags: blockscout/blockscout:latest, blockscout/blockscout:${{ env.RELEASE_VERSION }} - platforms: | - linux/arm64 - linux/amd64 - build-args: | - CACHE_EXCHANGE_RATES_PERIOD= - DISABLE_READ_API=false - API_PATH=/ - NETWORK_PATH=/ - DISABLE_WEBAPP=false - DISABLE_WRITE_API=false - CACHE_ENABLE_TOTAL_GAS_USAGE_COUNTER= - WOBSERVER_ENABLED=false - ADMIN_PANEL_ENABLED= - CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= - SOCKET_ROOT= - - merge-master-after-release: - name: Merge 'master' to specific branch after release - runs-on: ubuntu-latest - env: - BRANCHES: | - production-core-stg - production-eth-stg - production-harmony-mainnet-shard-0-stg - production-lukso-stg - production-optimism-goerli-stg - production-optimism-bedrock-goerli-stg - production-optimism-mainnet-stg - production-optimism-stg - production-rsk-stg - production-sokol-stg - production-xdai-stg - steps: - - uses: actions/checkout@v2 - - name: Set Git config - run: | - git config --local user.email "actions@github.com" - git config --local user.name "Github Actions" - - name: Merge master back after release - run: | - git fetch --unshallow - touch errors.txt - for branch in $BRANCHES; - do - git reset --merge - git checkout master - git fetch origin - echo $branch - git ls-remote --exit-code --heads origin $branch || { echo $branch >> errors.txt; continue; } - echo "Merge 'master' to $branch" - git checkout $branch - git pull || { echo $branch >> errors.txt; continue; } - git merge --no-ff master -m "Auto-merge master back to $branch" || { echo $branch >> errors.txt; continue; } - git push || { echo $branch >> errors.txt; continue; } - git checkout master; - done - [ -s errors.txt ] && echo "There are problems with merging 'master' to branches:" || echo "Errors file is empty" - cat errors.txt - [ ! -s errors.txt ] diff --git a/apps/block_scout_web/assets/js/pages/layout.js b/apps/block_scout_web/assets/js/pages/layout.js index 43fb5a2178f6..e572f0f39516 100644 --- a/apps/block_scout_web/assets/js/pages/layout.js +++ b/apps/block_scout_web/assets/js/pages/layout.js @@ -11,7 +11,7 @@ $(document).click(function (event) { const search = (value) => { if (value) { - window.location.href = `/search?q=${value}` + window.location.href = `/explorer/search?q=${value}` } } diff --git a/apps/block_scout_web/lib/block_scout_web/csp_header.ex b/apps/block_scout_web/lib/block_scout_web/csp_header.ex index cb81c9b22466..28f9c052c849 100644 --- a/apps/block_scout_web/lib/block_scout_web/csp_header.ex +++ b/apps/block_scout_web/lib/block_scout_web/csp_header.ex @@ -11,8 +11,8 @@ defmodule BlockScoutWeb.CSPHeader do def call(conn, _opts) do Controller.put_secure_browser_headers(conn, %{ "content-security-policy" => "\ - connect-src 'self' #{websocket_endpoints(conn)} wss://*.bridge.walletconnect.org/ https://request-global.czilladx.com/ https://raw.githubusercontent.com/trustwallet/assets/ https://registry.walletconnect.org/data/wallets.json https://*.poa.network;\ - default-src 'self';\ + connect-src 'self' #{websocket_endpoints(conn)} wss://*.bridge.walletconnect.org/ https://*.settlemint.com/ wss://*.settlemint.com/ https://request-global.czilladx.com/ https://raw.githubusercontent.com/trustwallet/assets/ https://registry.walletconnect.org/data/wallets.json https://*.poa.network;\ + default-src 'self' https://*.settlemint.com/;\ script-src 'self' 'unsafe-inline' 'unsafe-eval' https://coinzillatag.com https://www.google.com https://www.gstatic.com;\ style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com;\ img-src 'self' * data:;\ diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex index 78a3bb2cd826..c52bfbb4eedc 100644 --- a/apps/block_scout_web/lib/block_scout_web/router.ex +++ b/apps/block_scout_web/lib/block_scout_web/router.ex @@ -1,6 +1,7 @@ defmodule BlockScoutWeb.Router do use BlockScoutWeb, :router + alias BlockScoutWeb.Plug.AllowIframe alias BlockScoutWeb.Plug.GraphQL alias BlockScoutWeb.{ApiRouter, WebRouter} @@ -46,14 +47,14 @@ defmodule BlockScoutWeb.Router do ) else scope "/", BlockScoutWeb do - pipe_through(:browser) + pipe_through([:browser, BlockScoutWeb.Plug.AllowIframe]) get("/api-docs", PageNotFoundController, :index) get("/eth-rpc-api-docs", PageNotFoundController, :index) end end scope "/", BlockScoutWeb do - pipe_through(:browser) + pipe_through([:browser, BlockScoutWeb.Plug.AllowIframe]) get("/api-docs", APIDocsController, :index) get("/eth-rpc-api-docs", APIDocsController, :eth_rpc) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex index 429c4ee8bd77..2081a98b1e2c 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex @@ -1,93 +1 @@ - + \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex index 8347d71e3c56..355a3df2b6ab 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex @@ -1,7 +1,4 @@ <% apps_menu = Application.get_env(:block_scout_web, :apps_menu) %> -<% other_nets = dropdown_other_nets() %> -<% test_nets = test_nets(dropdown_nets()) %> -<% main_nets = dropdown_head_main_nets() %> + \ No newline at end of file diff --git a/apps/block_scout_web/mix.exs b/apps/block_scout_web/mix.exs index cd70d831562a..e5cde45eb050 100644 --- a/apps/block_scout_web/mix.exs +++ b/apps/block_scout_web/mix.exs @@ -97,7 +97,7 @@ defmodule BlockScoutWeb.Mixfile do {:number, "~> 1.0.1"}, {:phoenix, "== 1.5.13"}, {:phoenix_ecto, "~> 4.1"}, - {:phoenix_html, "== 3.0.4"}, + {:phoenix_html, "== 3.3.1"}, {:phoenix_live_reload, "~> 1.2", only: [:dev]}, {:phoenix_pubsub, "~> 2.0"}, # use `:cowboy` for WebServer with `:plug` diff --git a/apps/ethereum_jsonrpc/README.md b/apps/ethereum_jsonrpc/README.md index 945c793da83e..4b65295eeb39 100644 --- a/apps/ethereum_jsonrpc/README.md +++ b/apps/ethereum_jsonrpc/README.md @@ -1,6 +1,6 @@ # EthereumJSONRPC -Ethereum JSONRPC client. +Ethereum JSONRPC client ## Configuration diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/web_socket/web_socket_client.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/web_socket/web_socket_client.ex index baa4ce61c1fb..7892fa46234d 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/web_socket/web_socket_client.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/web_socket/web_socket_client.ex @@ -59,8 +59,7 @@ defmodule EthereumJSONRPC.WebSocket.WebSocketClient do :error -> :undefined end - %URI{host: host} = URI.parse(url) - host_charlist = String.to_charlist(host) + :ssl.start() # `:depth`, `:verify`, and `:verify_fun`, are based on `:hackney_connect.ssl_opts_1/2` as we use `:hackney` through # `:httpoison` and this keeps the SSL rules consistent between HTTP and WebSocket @@ -69,15 +68,8 @@ defmodule EthereumJSONRPC.WebSocket.WebSocketClient do url, __MODULE__, url, - ssl_verify: :verify_peer, - keepalive: keepalive, - socket_opts: [ - cacerts: :certifi.cacerts(), - depth: 99, - # SNI extension discloses host name in the clear, but allows for compatibility with Virtual Hosting for TLS - server_name_indication: host_charlist, - verify_fun: {&:ssl_verify_hostname.verify_fun/3, [check_hostname: host_charlist]} - ] + ssl_verify: :verify_none, + keepalive: keepalive ) end diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index c58d3bfd3741..3399d340a723 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -55,7 +55,7 @@ config :explorer, Explorer.Counters.AddressTokenUsdSum, enable_consolidation: true config :explorer, Explorer.Chain.Cache.TokenExchangeRate, - enabled: true, + enabled: false, enable_consolidation: true config :explorer, Explorer.Counters.TokenHoldersCounter, diff --git a/apps/explorer/mix.exs b/apps/explorer/mix.exs index b9217ddd0ad2..c038b7c86464 100644 --- a/apps/explorer/mix.exs +++ b/apps/explorer/mix.exs @@ -89,7 +89,7 @@ defmodule Explorer.Mixfile do {:math, "~> 0.7.0"}, {:mock, "~> 0.3.0", only: [:test], runtime: false}, {:mox, "~> 1.0", only: [:test]}, - {:phoenix_html, "== 3.0.4"}, + {:phoenix_html, "== 3.3.1"}, {:poison, "~> 4.0.1"}, {:nimble_csv, "~> 1.1"}, {:postgrex, ">= 0.0.0"}, diff --git a/docker-compose/envs/common-blockscout.env b/docker-compose/envs/common-blockscout.env index 6b157a2011eb..c8e90bbf7f5a 100644 --- a/docker-compose/envs/common-blockscout.env +++ b/docker-compose/envs/common-blockscout.env @@ -5,8 +5,8 @@ DATABASE_URL=postgresql://postgres:@host.docker.internal:7432/blockscout?ssl=fal ETHEREUM_JSONRPC_TRACE_URL=http://host.docker.internal:8545/ NETWORK= SUBNETWORK=Awesome chain -LOGO=/images/blockscout_logo.svg -LOGO_FOOTER=/images/blockscout_logo.svg +LOGO=/explorer/images/blockscout_logo.svg +LOGO_FOOTER=/explorer/images/blockscout_logo.svg # ETHEREUM_JSONRPC_WS_URL= ETHEREUM_JSONRPC_TRANSPORT=http ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=false diff --git a/docker/Dockerfile b/docker/Dockerfile index b0a6f0591b82..0265f8d1c823 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -43,7 +43,7 @@ ADD apps/explorer/mix.exs ./apps/explorer/ ADD apps/ethereum_jsonrpc/mix.exs ./apps/ethereum_jsonrpc/ ADD apps/indexer/mix.exs ./apps/indexer/ -RUN mix do deps.get, local.rebar --force, deps.compile +RUN mix do deps.get, local.rebar --force, deps.compile, deps.compile phoenix --force ADD . . @@ -82,3 +82,10 @@ WORKDIR /app COPY --from=builder /opt/release/blockscout . COPY --from=builder /app/apps/explorer/node_modules ./node_modules + +RUN chgrp -R 0 /app && \ + chmod -R g=u /app && \ + chown -R 1001:0 /app && \ + chmod 775 /app + +USER 1001 diff --git a/mix.lock b/mix.lock index 5514c9d7c1d2..05194b9a789a 100644 --- a/mix.lock +++ b/mix.lock @@ -100,10 +100,10 @@ "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "phoenix": {:hex, :phoenix, "1.5.13", "d4e0805ec0973bed80d67302631130fb47d75b1a0b7335a0b23c4432b6ce55ee", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1a7c4f1900e6e60bb60ae6680e48418e3f7c360d58bcb9f812487b6d0d281a0f"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, - "phoenix_html": {:hex, :phoenix_html, "3.0.4", "232d41884fe6a9c42d09f48397c175cd6f0d443aaa34c7424da47604201df2e1", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "ce17fd3cf815b2ed874114073e743507704b1f5288bb03c304a77458485efc8b"}, + "phoenix_html": {:hex, :phoenix_html, "3.3.1", "4788757e804a30baac6b3fc9695bf5562465dd3f1da8eb8460ad5b404d9a2178", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "bed1906edd4906a15fd7b412b85b05e521e1f67c9a85418c55999277e553d0d3"}, "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, - "plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"}, + "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"}, "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"},