From 01fc1ba6de66ed29848aa794e9a814908d129ef9 Mon Sep 17 00:00:00 2001 From: Amos Kibet Date: Thu, 19 Sep 2024 02:29:17 +0300 Subject: [PATCH 1/6] Update installation scripts (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Erlang, Elixir, Phoenix, and PostgreSQL. Remove unnecessary dependencies. Use existing shell (bash or zsh) instead of forcing usage of zsh. Switch from asdf to mise. Refactor scripts. Co-authored-by: James Rowa Co-authored-by: James Rowa <76947107+rowah@users.noreply.github.com> Co-authored-by: Almir Sarajčić --- .github/github_workflows.ex | 157 +++++--- .github/workflows/main.yml | 148 ++++++-- .github/workflows/pr.yml | 148 ++++++-- .tool-versions | 4 +- Dockerfile | 6 +- README.md | 12 +- .../components/seo_meta_tag_component.ex | 12 +- .../live/phx_tools_live/index.html.heex | 4 +- priv/static/Linux.sh | 352 ++++++------------ priv/static/macOS.sh | 323 ++++++---------- test/scripts/Makefile | 17 +- test/scripts/script.exp | 2 - 12 files changed, 595 insertions(+), 590 deletions(-) diff --git a/.github/github_workflows.ex b/.github/github_workflows.ex index 40272d4ef..3d4dc1487 100644 --- a/.github/github_workflows.ex +++ b/.github/github_workflows.ex @@ -9,6 +9,7 @@ defmodule GithubWorkflows do @preview_app_name "#{@app_name_prefix}-#{@environment_name}" @preview_app_host "#{@preview_app_name}.fly.dev" @repo_name "phx_tools" + @shells ["bash", "zsh"] def get do %{ @@ -28,7 +29,7 @@ defmodule GithubWorkflows do ] ], jobs: - elixir_ci_jobs() ++ + ci_jobs() ++ [ deploy_production_app: deploy_production_app_job() ] @@ -47,7 +48,7 @@ defmodule GithubWorkflows do ] ], jobs: - elixir_ci_jobs() ++ + ci_jobs() ++ [ deploy_preview_app: deploy_preview_app_job() ] @@ -72,7 +73,7 @@ defmodule GithubWorkflows do ] end - defp elixir_ci_jobs do + defp ci_jobs do [ compile: compile_job(), credo: credo_job(), @@ -83,10 +84,8 @@ defmodule GithubWorkflows do prettier: prettier_job(), sobelow: sobelow_job(), test: test_job(), - test_linux_script_job: test_linux_script_job(), - test_macos_script_job: test_macos_script_job(), unused_deps: unused_deps_job() - ] + ] ++ test_scripts_jobs() end defp compile_job do @@ -162,7 +161,7 @@ defmodule GithubWorkflows do defp deploy_job(env, opts) do [ name: "Deploy #{env} app", - needs: Enum.map(elixir_ci_jobs(), &elem(&1, 0)), + needs: Enum.map(ci_jobs(), &elem(&1, 0)), "runs-on": "ubuntu-latest" ] ++ opts end @@ -372,66 +371,112 @@ defmodule GithubWorkflows do ) end - defp test_linux_script_job do - test_shell_script_job( - "Linux", - "ubuntu-latest", - "sudo apt-get update && sudo apt-get install -y expect" - ) + defp test_scripts_jobs do + Enum.reduce(@shells, [], fn shell, jobs -> + jobs ++ + [ + {:"test_linux_#{shell}", test_linux_script_job(shell)}, + {:"test_macos_#{shell}", test_macos_script_job(shell)} + ] + end) end - defp test_macos_script_job do - test_shell_script_job("macOS", "macos-latest", "brew install expect") - end + defp test_shell_script_job(opts) do + os = Keyword.fetch!(opts, :os) + runs_on = Keyword.fetch!(opts, :runs_on) + shell = Keyword.fetch!(opts, :shell) + shell_install_command = Keyword.fetch!(opts, :shell_install_command) + expect_install_command = Keyword.fetch!(opts, :expect_install_command) - defp test_shell_script_job(os, runs_on, expect_install_command) do [ - name: "Test #{os} script", + name: "Test #{os} script with #{shell} shell", "runs-on": runs_on, - env: [TZ: "America/New_York"], - steps: [ - checkout_step(), + env: [ + SHELL: "/bin/#{shell}", + TZ: "America/New_York" + ], + steps: [ - name: "Restore script result cache", - uses: "actions/cache@v3", - id: "result_cache", - with: [ - key: - "${{ runner.os }}-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/#{os}.sh') }}", - path: "priv/static/#{os}.sh" + checkout_step(), + [ + name: "Restore script result cache", + uses: "actions/cache@v3", + id: "result_cache", + with: [ + key: + "${{ runner.os }}-#{shell}-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/#{os}.sh') }}", + path: "priv/static/#{os}.sh" + ] ] - ], - [ - name: "Install expect tool", - if: "steps.result_cache.outputs.cache-hit != 'true'", - run: expect_install_command - ], - [ - name: "Test the script", - if: "steps.result_cache.outputs.cache-hit != 'true'", - run: "cd test/scripts && expect script.exp #{os}.sh" - ], - [ - name: "Generate an app and start the server", - if: "steps.result_cache.outputs.cache-hit != 'true'", - run: "/bin/zsh -c 'source ~/.zshrc && make -f test/scripts/Makefile'" - ], - [ - name: "Check HTTP status code", - if: "steps.result_cache.outputs.cache-hit != 'true'", - uses: "nick-fields/retry@v2", - with: [ - command: - "INPUT_SITES='[\"http://localhost:4000\"]' INPUT_EXPECTED='[200]' ./test/scripts/check_status_code.sh", - max_attempts: 7, - retry_wait_seconds: 5, - timeout_seconds: 1 + ] ++ + if(shell == "bash", + do: [], + else: [ + [ + name: "Install shell", + if: "steps.result_cache.outputs.cache-hit != 'true'", + run: shell_install_command + ] + ] + ) ++ + [ + [ + name: "Install expect tool", + if: "steps.result_cache.outputs.cache-hit != 'true'", + run: expect_install_command + ], + [ + name: "Remove mise config files", + run: "rm -f .mise.toml .tool-versions" + ], + [ + name: "Test the script", + if: "steps.result_cache.outputs.cache-hit != 'true'", + run: "cd test/scripts && expect script.exp #{os}.sh", + shell: "/bin/#{shell} -l {0}" + ], + [ + name: "Generate an app and start the server", + if: "steps.result_cache.outputs.cache-hit != 'true'", + run: "make -f test/scripts/Makefile serve", + shell: "/bin/#{shell} -l {0}" + ], + [ + name: "Check HTTP status code", + if: "steps.result_cache.outputs.cache-hit != 'true'", + uses: "nick-fields/retry@v2", + with: [ + command: + "INPUT_SITES='[\"http://localhost:4000\"]' INPUT_EXPECTED='[200]' ./test/scripts/check_status_code.sh", + max_attempts: 7, + retry_wait_seconds: 5, + timeout_seconds: 1 + ] + ] ] - ] - ] ] end + defp test_linux_script_job(shell) do + test_shell_script_job( + expect_install_command: "sudo apt-get update && sudo apt-get install -y expect", + os: "Linux", + runs_on: "ubuntu-latest", + shell: shell, + shell_install_command: "sudo apt-get update && sudo apt-get install -y #{shell}" + ) + end + + defp test_macos_script_job(shell) do + test_shell_script_job( + expect_install_command: "brew install expect", + os: "macOS", + runs_on: "macos-latest", + shell: shell, + shell_install_command: "brew install #{shell}" + ) + end + defp unused_deps_job do elixir_job("Check unused deps", needs: :compile, diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 77ce46588..85d34e2a0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -237,10 +237,36 @@ jobs: env: MIX_ENV: test run: mix test --cover --warnings-as-errors - test_linux_script_job: - name: Test Linux script + unused_deps: + needs: compile + name: Check unused deps + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: setup-beam + name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + version-file: .tool-versions + version-type: strict + - uses: actions/cache@v3 + with: + path: | + _build + deps + key: ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix- + - name: Check for unused Mix dependencies + env: + MIX_ENV: test + run: mix deps.unlock --check-unused + test_linux_bash: + name: Test Linux script with bash shell runs-on: ubuntu-latest env: + SHELL: /bin/bash TZ: America/New_York steps: - name: Checkout @@ -249,17 +275,21 @@ jobs: uses: actions/cache@v3 id: result_cache with: - key: ${{ runner.os }}-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/Linux.sh') }} + key: ${{ runner.os }}-bash-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/Linux.sh') }} path: priv/static/Linux.sh - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: sudo apt-get update && sudo apt-get install -y expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions - name: Test the script if: steps.result_cache.outputs.cache-hit != 'true' run: cd test/scripts && expect script.exp Linux.sh + shell: /bin/bash -l {0} - name: Generate an app and start the server if: steps.result_cache.outputs.cache-hit != 'true' - run: /bin/zsh -c 'source ~/.zshrc && make -f test/scripts/Makefile' + run: make -f test/scripts/Makefile serve + shell: /bin/bash -l {0} - name: Check HTTP status code if: steps.result_cache.outputs.cache-hit != 'true' uses: nick-fields/retry@v2 @@ -268,10 +298,11 @@ jobs: max_attempts: 7 retry_wait_seconds: 5 timeout_seconds: 1 - test_macos_script_job: - name: Test macOS script + test_macos_bash: + name: Test macOS script with bash shell runs-on: macos-latest env: + SHELL: /bin/bash TZ: America/New_York steps: - name: Checkout @@ -280,17 +311,21 @@ jobs: uses: actions/cache@v3 id: result_cache with: - key: ${{ runner.os }}-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} + key: ${{ runner.os }}-bash-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} path: priv/static/macOS.sh - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: brew install expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions - name: Test the script if: steps.result_cache.outputs.cache-hit != 'true' run: cd test/scripts && expect script.exp macOS.sh + shell: /bin/bash -l {0} - name: Generate an app and start the server if: steps.result_cache.outputs.cache-hit != 'true' - run: /bin/zsh -c 'source ~/.zshrc && make -f test/scripts/Makefile' + run: make -f test/scripts/Makefile serve + shell: /bin/bash -l {0} - name: Check HTTP status code if: steps.result_cache.outputs.cache-hit != 'true' uses: nick-fields/retry@v2 @@ -299,31 +334,84 @@ jobs: max_attempts: 7 retry_wait_seconds: 5 timeout_seconds: 1 - unused_deps: - needs: compile - name: Check unused deps + test_linux_zsh: + name: Test Linux script with zsh shell runs-on: ubuntu-latest + env: + SHELL: /bin/zsh + TZ: America/New_York steps: - name: Checkout uses: actions/checkout@v4 - - id: setup-beam - name: Set up Elixir - uses: erlef/setup-beam@v1 + - name: Restore script result cache + uses: actions/cache@v3 + id: result_cache with: - version-file: .tool-versions - version-type: strict - - uses: actions/cache@v3 + key: ${{ runner.os }}-zsh-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/Linux.sh') }} + path: priv/static/Linux.sh + - name: Install shell + if: steps.result_cache.outputs.cache-hit != 'true' + run: sudo apt-get update && sudo apt-get install -y zsh + - name: Install expect tool + if: steps.result_cache.outputs.cache-hit != 'true' + run: sudo apt-get update && sudo apt-get install -y expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions + - name: Test the script + if: steps.result_cache.outputs.cache-hit != 'true' + run: cd test/scripts && expect script.exp Linux.sh + shell: /bin/zsh -l {0} + - name: Generate an app and start the server + if: steps.result_cache.outputs.cache-hit != 'true' + run: make -f test/scripts/Makefile serve + shell: /bin/zsh -l {0} + - name: Check HTTP status code + if: steps.result_cache.outputs.cache-hit != 'true' + uses: nick-fields/retry@v2 with: - path: | - _build - deps - key: ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix- - - name: Check for unused Mix dependencies - env: - MIX_ENV: test - run: mix deps.unlock --check-unused + command: INPUT_SITES='["http://localhost:4000"]' INPUT_EXPECTED='[200]' ./test/scripts/check_status_code.sh + max_attempts: 7 + retry_wait_seconds: 5 + timeout_seconds: 1 + test_macos_zsh: + name: Test macOS script with zsh shell + runs-on: macos-latest + env: + SHELL: /bin/zsh + TZ: America/New_York + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Restore script result cache + uses: actions/cache@v3 + id: result_cache + with: + key: ${{ runner.os }}-zsh-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} + path: priv/static/macOS.sh + - name: Install shell + if: steps.result_cache.outputs.cache-hit != 'true' + run: brew install zsh + - name: Install expect tool + if: steps.result_cache.outputs.cache-hit != 'true' + run: brew install expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions + - name: Test the script + if: steps.result_cache.outputs.cache-hit != 'true' + run: cd test/scripts && expect script.exp macOS.sh + shell: /bin/zsh -l {0} + - name: Generate an app and start the server + if: steps.result_cache.outputs.cache-hit != 'true' + run: make -f test/scripts/Makefile serve + shell: /bin/zsh -l {0} + - name: Check HTTP status code + if: steps.result_cache.outputs.cache-hit != 'true' + uses: nick-fields/retry@v2 + with: + command: INPUT_SITES='["http://localhost:4000"]' INPUT_EXPECTED='[200]' ./test/scripts/check_status_code.sh + max_attempts: 7 + retry_wait_seconds: 5 + timeout_seconds: 1 deploy_production_app: name: Deploy production app needs: @@ -336,9 +424,11 @@ jobs: - prettier - sobelow - test - - test_linux_script_job - - test_macos_script_job - unused_deps + - test_linux_bash + - test_macos_bash + - test_linux_zsh + - test_macos_zsh runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a53e76b48..e20228977 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -241,10 +241,36 @@ jobs: env: MIX_ENV: test run: mix test --cover --warnings-as-errors - test_linux_script_job: - name: Test Linux script + unused_deps: + needs: compile + name: Check unused deps + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: setup-beam + name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + version-file: .tool-versions + version-type: strict + - uses: actions/cache@v3 + with: + path: | + _build + deps + key: ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix- + - name: Check for unused Mix dependencies + env: + MIX_ENV: test + run: mix deps.unlock --check-unused + test_linux_bash: + name: Test Linux script with bash shell runs-on: ubuntu-latest env: + SHELL: /bin/bash TZ: America/New_York steps: - name: Checkout @@ -253,17 +279,21 @@ jobs: uses: actions/cache@v3 id: result_cache with: - key: ${{ runner.os }}-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/Linux.sh') }} + key: ${{ runner.os }}-bash-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/Linux.sh') }} path: priv/static/Linux.sh - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: sudo apt-get update && sudo apt-get install -y expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions - name: Test the script if: steps.result_cache.outputs.cache-hit != 'true' run: cd test/scripts && expect script.exp Linux.sh + shell: /bin/bash -l {0} - name: Generate an app and start the server if: steps.result_cache.outputs.cache-hit != 'true' - run: /bin/zsh -c 'source ~/.zshrc && make -f test/scripts/Makefile' + run: make -f test/scripts/Makefile serve + shell: /bin/bash -l {0} - name: Check HTTP status code if: steps.result_cache.outputs.cache-hit != 'true' uses: nick-fields/retry@v2 @@ -272,10 +302,11 @@ jobs: max_attempts: 7 retry_wait_seconds: 5 timeout_seconds: 1 - test_macos_script_job: - name: Test macOS script + test_macos_bash: + name: Test macOS script with bash shell runs-on: macos-latest env: + SHELL: /bin/bash TZ: America/New_York steps: - name: Checkout @@ -284,17 +315,21 @@ jobs: uses: actions/cache@v3 id: result_cache with: - key: ${{ runner.os }}-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} + key: ${{ runner.os }}-bash-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} path: priv/static/macOS.sh - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: brew install expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions - name: Test the script if: steps.result_cache.outputs.cache-hit != 'true' run: cd test/scripts && expect script.exp macOS.sh + shell: /bin/bash -l {0} - name: Generate an app and start the server if: steps.result_cache.outputs.cache-hit != 'true' - run: /bin/zsh -c 'source ~/.zshrc && make -f test/scripts/Makefile' + run: make -f test/scripts/Makefile serve + shell: /bin/bash -l {0} - name: Check HTTP status code if: steps.result_cache.outputs.cache-hit != 'true' uses: nick-fields/retry@v2 @@ -303,31 +338,84 @@ jobs: max_attempts: 7 retry_wait_seconds: 5 timeout_seconds: 1 - unused_deps: - needs: compile - name: Check unused deps + test_linux_zsh: + name: Test Linux script with zsh shell runs-on: ubuntu-latest + env: + SHELL: /bin/zsh + TZ: America/New_York steps: - name: Checkout uses: actions/checkout@v4 - - id: setup-beam - name: Set up Elixir - uses: erlef/setup-beam@v1 + - name: Restore script result cache + uses: actions/cache@v3 + id: result_cache with: - version-file: .tool-versions - version-type: strict - - uses: actions/cache@v3 + key: ${{ runner.os }}-zsh-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/Linux.sh') }} + path: priv/static/Linux.sh + - name: Install shell + if: steps.result_cache.outputs.cache-hit != 'true' + run: sudo apt-get update && sudo apt-get install -y zsh + - name: Install expect tool + if: steps.result_cache.outputs.cache-hit != 'true' + run: sudo apt-get update && sudo apt-get install -y expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions + - name: Test the script + if: steps.result_cache.outputs.cache-hit != 'true' + run: cd test/scripts && expect script.exp Linux.sh + shell: /bin/zsh -l {0} + - name: Generate an app and start the server + if: steps.result_cache.outputs.cache-hit != 'true' + run: make -f test/scripts/Makefile serve + shell: /bin/zsh -l {0} + - name: Check HTTP status code + if: steps.result_cache.outputs.cache-hit != 'true' + uses: nick-fields/retry@v2 with: - path: | - _build - deps - key: ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ steps.setup-beam.outputs.otp-version }}-mix- - - name: Check for unused Mix dependencies - env: - MIX_ENV: test - run: mix deps.unlock --check-unused + command: INPUT_SITES='["http://localhost:4000"]' INPUT_EXPECTED='[200]' ./test/scripts/check_status_code.sh + max_attempts: 7 + retry_wait_seconds: 5 + timeout_seconds: 1 + test_macos_zsh: + name: Test macOS script with zsh shell + runs-on: macos-latest + env: + SHELL: /bin/zsh + TZ: America/New_York + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Restore script result cache + uses: actions/cache@v3 + id: result_cache + with: + key: ${{ runner.os }}-zsh-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} + path: priv/static/macOS.sh + - name: Install shell + if: steps.result_cache.outputs.cache-hit != 'true' + run: brew install zsh + - name: Install expect tool + if: steps.result_cache.outputs.cache-hit != 'true' + run: brew install expect + - name: Remove mise config files + run: rm -f .mise.toml .tool-versions + - name: Test the script + if: steps.result_cache.outputs.cache-hit != 'true' + run: cd test/scripts && expect script.exp macOS.sh + shell: /bin/zsh -l {0} + - name: Generate an app and start the server + if: steps.result_cache.outputs.cache-hit != 'true' + run: make -f test/scripts/Makefile serve + shell: /bin/zsh -l {0} + - name: Check HTTP status code + if: steps.result_cache.outputs.cache-hit != 'true' + uses: nick-fields/retry@v2 + with: + command: INPUT_SITES='["http://localhost:4000"]' INPUT_EXPECTED='[200]' ./test/scripts/check_status_code.sh + max_attempts: 7 + retry_wait_seconds: 5 + timeout_seconds: 1 deploy_preview_app: name: Deploy preview app needs: @@ -340,9 +428,11 @@ jobs: - prettier - sobelow - test - - test_linux_script_job - - test_macos_script_job - unused_deps + - test_linux_bash + - test_macos_bash + - test_linux_zsh + - test_macos_zsh runs-on: ubuntu-latest permissions: write-all concurrency: diff --git a/.tool-versions b/.tool-versions index d836019a7..5ad81876b 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -elixir 1.17.1-otp-27 -erlang 27.0 +elixir 1.17.2-otp-27 +erlang 27.0.1 nodejs 20.14.0 diff --git a/Dockerfile b/Dockerfile index e0ef3d17c..d355ed0db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,9 +11,9 @@ # - https://pkgs.org/ - resource for finding needed packages # - Ex: hexpm/elixir:1.17.1-erlang-27.0-debian-bullseye-20240612-slim # -ARG ELIXIR_VERSION=1.17.1 -ARG OTP_VERSION=27.0 -ARG DEBIAN_VERSION=bullseye-20240612-slim +ARG ELIXIR_VERSION=1.17.2 +ARG OTP_VERSION=27.0.1 +ARG DEBIAN_VERSION=bullseye-20240904-slim ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}" ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}" diff --git a/README.md b/README.md index 5c1d096ee..5cea9cd28 100644 --- a/README.md +++ b/README.md @@ -9,21 +9,13 @@ Here are the tools that `phx.tools` will install for you, if not already install _Required_ - Build dependencies -- Zsh -- Homebrew -- asdf +- Homebrew (only on macOS) +- mise - Erlang - Elixir - Phoenix - PostgreSQL -_Optional_ - -- Chrome -- Node.js -- ChromeDriver -- Docker - ## Setup To start your Phoenix server: diff --git a/lib/phx_tools_web/components/seo_meta_tag_component.ex b/lib/phx_tools_web/components/seo_meta_tag_component.ex index efa2a543e..b5578e3dd 100644 --- a/lib/phx_tools_web/components/seo_meta_tag_component.ex +++ b/lib/phx_tools_web/components/seo_meta_tag_component.ex @@ -15,6 +15,8 @@ defmodule PhxToolsWeb.SeoMetaTagComponent do create a new Phoenix application, and launch the server... """ + @keywords "elixir, erlang, homebrew, mise, phoenix, postgres, postgresql" + attr :attributes, :map @spec seo_meta_tags(assigns()) :: rendered() @@ -23,6 +25,7 @@ defmodule PhxToolsWeb.SeoMetaTagComponent do assigns |> assign_new(:description, fn -> String.trim(@default_description) end) |> assign_new(:image_url, fn -> static_url(Endpoint, ~p"/images/phx_tools.png") end) + |> assign_new(:keywords, fn -> @keywords end) |> assign_new(:url, fn %{attributes: %{url: url}} -> url _assigns -> url(~p"/") @@ -30,10 +33,7 @@ defmodule PhxToolsWeb.SeoMetaTagComponent do ~H""" <.open_graph_meta_tags description={@description} image_url={@image_url} url={@url} /> - <.other_meta_tags - description={@description} - keywords="elixir, erlang, homebrew, mise, phoenix, postgres, postgresql" - /> + <.other_meta_tags description={@description} keywords={@keywords} /> <.twitter_meta_tags description={@description} image_url={@image_url} url={@url} /> """ end @@ -56,9 +56,11 @@ defmodule PhxToolsWeb.SeoMetaTagComponent do attr :keywords, :string, required: true defp other_meta_tags(assigns) do + assigns = assign_new(assigns, :keywords, fn -> @keywords end) + ~H""" - + """ end diff --git a/lib/phx_tools_web/live/phx_tools_live/index.html.heex b/lib/phx_tools_web/live/phx_tools_live/index.html.heex index bb610a450..d9dbd8be1 100644 --- a/lib/phx_tools_web/live/phx_tools_live/index.html.heex +++ b/lib/phx_tools_web/live/phx_tools_live/index.html.heex @@ -8,7 +8,7 @@ <:installation_command> - <%= "/bin/bash -c \"$(curl -fsSL #{Endpoint.url() <> "/Linux.sh"})\"" %> + <%= "$SHELL -c \"$(curl -fsSL #{Endpoint.url() <> "/Linux.sh"})\"" %> <:instruction> @@ -30,7 +30,7 @@ <:installation_command> - <%= "/bin/bash -c \"$(curl -fsSL #{Endpoint.url() <> "/macOS.sh"})\"" %> + <%= "$SHELL -c \"$(curl -fsSL #{Endpoint.url() <> "/macOS.sh"})\"" %> <:instruction> diff --git a/priv/static/Linux.sh b/priv/static/Linux.sh index a9bef8947..94bf71b42 100755 --- a/priv/static/Linux.sh +++ b/priv/static/Linux.sh @@ -1,4 +1,6 @@ -#! /bin/bash +#!/bin/sh + +set -eu # Make sure important variables exist if not already defined # @@ -12,8 +14,8 @@ HOME="${HOME:-$(getent passwd $USER 2>/dev/null | cut -d: -f6)}" # macOS does not have getent, but this works even if $HOME is unset HOME="${HOME:-$(eval echo ~$USER)}" -bold=$(tput bold) -normal=$(tput sgr0) +bold='\033[1m' +normal='\033[0m' red='\033[0;31m' blue='\033[0;34m' bblue='\033[1;34m' @@ -21,232 +23,133 @@ white='\033[0;37m' green='\033[0;32m' cyan='\033[0;36m' -function already_installed() { - case $1 in - "Git") - which git >/dev/null 2>&1 - ;; - "Zsh") - dpkg -l | grep -q zsh - ;; - "oh-my-zsh") - [ -d ~/.oh-my-zsh ] - ;; - "wget") - dpkg -l | grep -q wget - ;; - "Homebrew") - which brew >/dev/null 2>&1 - ;; - "asdf") - brew list | grep -q asdf +elixir_version=1.17.2-otp-27 +erlang_version=27.0.1 +phoenix_version=1.7.14 +postgres_version=15.1 + +case "${SHELL:-}" in +*/bash) + current_shell="bash" + config_file="$HOME/.bashrc" + ;; +*/zsh) + current_shell="zsh" + config_file="$HOME/.zshrc" + ;; +*) + printf "Unsupported shell: $SHELL\n" + exit 1 + ;; +esac + +already_installed() { + case "$1" in + "Elixir") + mise which elixir >/dev/null 2>&1 ;; "Erlang") - command -v erl >/dev/null 2>&1 + mise which erl >/dev/null 2>&1 ;; - "Elixir") - which elixir >/dev/null 2>&1 + "mise") + which mise >/dev/null 2>&1 ;; "Phoenix") mix phx.new --version >/dev/null 2>&1 ;; "PostgreSQL") - which pg_ctl >/dev/null 2>&1 - ;; - "Chrome") - dpkg -l | grep -q google-chrome-stable - ;; - "Node.js") - which node >/dev/null 2>&1 - ;; - "ChromeDriver") - npm list -g | grep -q chromedriver - ;; - "Docker") - which docker >/dev/null 2>&1 + mise which initdb >/dev/null 2>&1 ;; *) - echo "Invalid name argument on checking" + printf "Invalid name argument on checking: $1\n" + exit 1 ;; esac } -function install() { - case $1 in - "Git") - sudo apt-get install -y git - ;; - "Zsh") - sudo apt-get install -y zsh - ;; - "oh-my-zsh") - sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended - ;; - "wget") - sudo apt-get install -y wget - ;; - "Homebrew") - NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - echo '# Set PATH, MANPATH, etc., for Homebrew.' >>~/.zshrc - ( - echo - echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' - ) >>~/.zshrc - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - ;; - "asdf") - brew install asdf - ( - echo - echo '. $(brew --prefix asdf)/libexec/asdf.sh' - ) >>~/.zshrc - source ~/.zshrc >/dev/null 2>&1 +install() { + case "$1" in + "Elixir") + mise use -g -y elixir@$elixir_version ;; "Erlang") - sudo apt-get update - sudo apt-get -y install build-essential autoconf m4 libncurses5-dev libwxgtk3.0-gtk3-dev libwxgtk-webview3.0-gtk3-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-11-jdk - asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git - asdf install erlang 27.0 - asdf global erlang 27.0 - asdf reshim erlang 27.0 + if [ ! -f ~/.kerlrc ]; then + printf "KERL_CONFIGURE_OPTIONS=\"--without-javac\"\n" >~/.kerlrc + fi + mise use -g -y erlang@$erlang_version ;; - "Elixir") - asdf plugin add elixir https://github.com/asdf-vm/asdf-elixir.git - asdf install elixir 1.17.1-otp-27 - asdf global elixir 1.17.1-otp-27 - asdf reshim elixir 1.17.1-otp-27 + "mise") + curl https://mise.run | sh + + case $current_shell in + "bash") + echo 'eval "$(~/.local/bin/mise activate bash)"' >>$config_file + ;; + "zsh") + echo 'eval "$(~/.local/bin/mise activate zsh)"' >>$config_file + ;; + esac + + export PATH="$HOME/.local/bin:$PATH" ;; "Phoenix") - source ~/.zshrc >/dev/null 2>&1 - mix local.hex --force - mix archive.install --force hex phx_new 1.7.0-rc.3 + mise exec -- mix local.hex --force + mise exec -- mix local.rebar --force + mise exec -- mix archive.install --force hex phx_new $phoenix_version ;; "PostgreSQL") sudo apt-get update sudo apt-get -y install linux-headers-generic build-essential libssl-dev libreadline-dev zlib1g-dev libcurl4-openssl-dev uuid-dev icu-devtools - - asdf plugin add postgres https://github.com/smashedtoatoms/asdf-postgres.git - asdf install postgres 15.1 - asdf global postgres 15.1 - asdf reshim postgres - - echo 'pg_ctl() { "$HOME/.asdf/shims/pg_ctl" "$@"; }' >>~/.profile - source ~/.zshrc >/dev/null 2>&1 - ;; - "Chrome") - sudo wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb - sudo apt install -y ./google-chrome-stable_current_amd64.deb - ;; - "Node.js") - asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git - asdf install nodejs 20.14.0 - asdf global nodejs 20.14.0 - asdf reshim nodejs 20.14.0 - ;; - "ChromeDriver") - source ~/.zshrc >/dev/null 2>&1 - npm install -g chromedriver - ;; - "Docker") - sudo apt-get update - sudo apt-get install -y \ - ca-certificates \ - curl \ - gnupg \ - lsb-release - sudo mkdir -p /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list >/dev/null - sudo apt-get update - sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + mise use -g -y postgres@$postgres_version ;; *) - echo "Invalid name argument on install" + printf "Invalid name argument on install: %s\n" "$1" + exit 1 ;; esac } -function maybe_install() { - if already_installed $1; then - echo "$1 is already installed. Skipping..." +maybe_install() { + if already_installed "$1"; then + printf "$1 is already installed. Skipping...\n" else - echo "Installing $1..." - if [[ $1 == "Homebrew" || $1 == "Erlang" ]]; then - echo "This might take a while." + printf "Installing $1...\n" + if [ "$1" = "Erlang" ]; then + printf "This might take a while.\n" fi - echo "" - install $1 + printf "\n" + install "$1" fi } -function add_env() { - echo "" - echo -e "${white}" - sleep 2 - maybe_install "Git" - - echo "" - echo -e "${white}" - sleep 2 - maybe_install "Zsh" +add_env() { + printf "\n" - echo -e "${white}" - sleep 2 - maybe_install "oh-my-zsh" - - echo -e "${white}" - sleep 2 - maybe_install "wget" - - echo -e "${white}" - sleep 2 - maybe_install "Homebrew" - - echo -e "${white}" - sleep 3 - maybe_install "asdf" + printf "${white}\n" + sleep 1.5 + maybe_install "mise" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "Erlang" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "Elixir" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "Phoenix" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "PostgreSQL" - if [[ "$1" =~ ^([yY][eE][sS]|[yY])$ ]]; then - echo -e "${white}" - sleep 3 - maybe_install "Chrome" - echo -e "${white}" - - sleep 1.5 - maybe_install "Node.js" - echo -e "${white}" - - sleep 2 - maybe_install "ChromeDriver" - echo -e "${white}" - - maybe_install "Docker" - echo -e "${white}" - fi - - echo -e "${white}" - echo -e "${cyan}${bold}phx.tools setup is complete!" - echo -e "${cyan}${bold}Please restart the terminal and type in the following command:" - echo -e "${cyan}${bold}mix phx.new" - echo -e "${white}" + printf "${white}\n" + printf "${cyan}${bold}phx.tools setup is complete!\n" + printf "${cyan}${bold}Please restart the terminal and type in the following command:\n" + printf "${cyan}${bold}mix phx.new\n" + printf "${white}\n" } phx_tools=" @@ -274,41 +177,36 @@ optimum=" ░╚════╝░╚═╝░░░░░░░░╚═╝░░░╚═╝╚═╝░░░░░╚═╝░╚═════╝░╚═╝░░░░░╚═╝╚═════╝░╚═╝░░╚═╝ " -echo -e "$phx_tools" - -echo -e "$by" - -echo -e "$optimum" +printf "%s\n" "$phx_tools" +printf "%s\n" "$by" +printf "%s\n" "$optimum" sleep 3 -echo "" +printf "\n" -echo -e "${bblue}${bold}Welcome to the phx.tools shell script for Linux-based OS." +printf "${bblue}${bold}Welcome to the phx.tools shell script for Linux-based OS.\n" sleep 3 -echo "" +printf "\n" -echo -e "${bblue}${bold}The following will be installed if not available already:" +printf "${bblue}${bold}The following will be installed if not available already:\n" -echo -e "${cyan}${bold}" +printf "${cyan}${bold}\n" -echo "1) Build dependencies" -echo "2) Zsh" -echo "3) Homebrew" -echo "4) asdf" -echo "5) Erlang" -echo "6) Elixir" -echo "7) Phoenix" -echo "8) PostgreSQL" +printf "1) Build dependencies\n" +printf "2) mise\n" +printf "3) Erlang\n" +printf "4) Elixir\n" +printf "5) Phoenix\n" +printf "6) PostgreSQL\n" -echo "" -echo -e "${white} ${bold}" +printf "\n" +printf "${white}${bold}\n" sleep 1 -# only true if user answer y/n is_yn() { case "$1" in [yY] | [yY][eE][sS]) @@ -326,54 +224,22 @@ is_yn() { answer='' while ! is_yn "$answer"; do - read -p "Do you want to continue? (y/n) " answer - echo "" + printf "Do you want to continue? (y/n) " + read -r answer + printf "\n" case "$answer" in [yY] | [yY][eE][sS]) - echo -e "${bblue}${bold}We can also install some optional tools:" - - echo -e "${cyan}${bold}" - - echo "1) Chrome" - echo "2) Node.js" - echo "3) ChromeDriver" - echo "4) Docker" - - echo -e "${white}" - echo -e "${white} ${bold}" - - optional="" - - while ! is_yn "$optional"; do - read -p "Do you want us to install those as well? (y/n) " optional - - if ! [[ "$optional" =~ ^([yY][eE][sS]|[yY]|[nN]|[nN][oO])$ ]]; then - echo "Please enter y or n" - echo "" - fi - done - - echo "" - - echo -e "${bblue}${bold}We're going to switch your default shell to Zsh even if it's not available yet, so you might see the following:" - - echo -e "${bblue}${bold}chsh: Warning: /bin/zsh does not exist" - - echo -e "${bblue}${bold}But don't worry. The installation will proceed as regular." - + printf "\n" sleep 3 - - sudo -S chsh -s '/bin/zsh' "${USER}" - - add_env "$optional" + add_env ;; [nN] | [nN][oO]) - echo "Thank you for your time" - echo "" + printf "Thank you for your time\n" + printf "\n" ;; *) - echo "Please enter y or n" - echo "" + printf "Please enter y or n\n" + printf "\n" ;; esac done diff --git a/priv/static/macOS.sh b/priv/static/macOS.sh index b11471295..2c8492998 100755 --- a/priv/static/macOS.sh +++ b/priv/static/macOS.sh @@ -1,4 +1,6 @@ -#! /bin/bash +#!/bin/sh + +set -eu # Make sure important variables exist if not already defined # @@ -12,8 +14,8 @@ HOME="${HOME:-$(getent passwd $USER 2>/dev/null | cut -d: -f6)}" # macOS does not have getent, but this works even if $HOME is unset HOME="${HOME:-$(eval echo ~$USER)}" -bold=$(tput bold) -normal=$(tput sgr0) +bold='\033[1m' +normal='\033[0m' red='\033[0;31m' blue='\033[0;34m' bblue='\033[1;34m' @@ -21,201 +23,150 @@ white='\033[0;37m' green='\033[0;32m' cyan='\033[0;36m' -function already_installed() { - case $1 in - "Xcode Command Line Tools") - which xcode-select >/dev/null +elixir_version=1.17.2-otp-27 +erlang_version=27.0.1 +phoenix_version=1.7.14 +postgres_version=15.1 + +case "${SHELL:-}" in +*/bash) + current_shell="bash" + config_file="$HOME/.bashrc" + ;; +*/zsh) + current_shell="zsh" + config_file="$HOME/.zshrc" + ;; +*) + printf "Unsupported shell: %s\n" "$SHELL" + exit 1 + ;; +esac + +already_installed() { + case "$1" in + "Elixir") + mise which elixir >/dev/null 2>&1 ;; - - "oh-my-zsh") - [ -d ~/.oh-my-zsh ] + "Erlang") + mise which erl >/dev/null 2>&1 ;; "Homebrew") which brew >/dev/null 2>&1 ;; - "asdf") - brew list | grep -q asdf - ;; - "Erlang") - command -v erl >/dev/null 2>&1 - ;; - "Elixir") - which elixir >/dev/null 2>&1 + "mise") + which mise >/dev/null 2>&1 ;; "Phoenix") mix phx.new --version >/dev/null 2>&1 ;; - "Node.js") - which node >/dev/null 2>&1 - ;; "PostgreSQL") - which pg_ctl >/dev/null 2>&1 - ;; - "Chrome") - brew list | grep -q google-chrome + mise which initdb >/dev/null 2>&1 ;; - "ChromeDriver") - brew list | grep -q chromedriver - ;; - "Docker") - which docker >/dev/null 2>&1 + "Xcode Command Line Tools") + which xcode-select >/dev/null 2>&1 ;; *) - echo "Invalid name argument on checking" + printf "Invalid name argument on checking: %s\n" "$1" + exit 1 ;; esac } -function install() { - case $1 in - "Xcode Command Line Tools") - xcode-select --install - ;; - "oh-my-zsh") - sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended - ;; - "Homebrew") - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - ;; - "asdf") - # Deps for asdf - brew install coreutils curl git - - brew install asdf && echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >>${ZDOTDIR:-~}/.zshrc +install() { + case "$1" in + "Elixir") + mise use -g -y elixir@$elixir_version ;; "Erlang") - # Deps for erlang brew install autoconf openssl@1.1 wxwidgets libxslt fop - - export KERL_CONFIGURE_OPTIONS="--without-javac --with-ssl=$(brew --prefix openssl@1.1)" - asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git - asdf install erlang 27.0 - asdf global erlang 27.0 - asdf reshim erlang 27.0 + if [ ! -f ~/.kerlrc ]; then + printf "KERL_CONFIGURE_OPTIONS=\"--with-ssl=$(brew --prefix openssl@1.1) --without-javac\"\n" >~/.kerlrc + fi + mise use -g -y erlang@$erlang_version ;; - "Elixir") - # Deps for elixir - brew install unzip + "mise") + curl https://mise.run | sh - asdf plugin add elixir https://github.com/asdf-vm/asdf-elixir.git - asdf install elixir 1.17.1-otp-27 - asdf global elixir 1.17.1-otp-27 - asdf reshim elixir 1.17.1-otp-27 + case $current_shell in + "bash") + echo 'eval "$(~/.local/bin/mise activate bash)"' >>$config_file + ;; + "zsh") + echo 'eval "$(~/.local/bin/mise activate zsh)"' >>$config_file + ;; + esac + + export PATH="$HOME/.local/bin:$PATH" ;; "Phoenix") - source ~/.zshrc >/dev/null 2>&1 - mix local.hex --force - mix archive.install --force hex phx_new 1.7.0-rc.3 - ;; - "Node.js") - asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git - asdf install nodejs 20.14.0 - asdf global nodejs 20.14.0 - asdf reshim nodejs 20.14.0 + mise exec -- mix local.hex --force + mise exec -- mix local.rebar --force + mise exec -- mix archive.install --force hex phx_new $phoenix_version ;; "PostgreSQL") - # Dependencies for PSQL brew install gcc readline zlib curl ossp-uuid - - asdf plugin add postgres https://github.com/smashedtoatoms/asdf-postgres.git - asdf install postgres 15.1 - asdf global postgres 15.1 - asdf reshim postgres - - echo 'pg_ctl() { "$HOME/.asdf/shims/pg_ctl" "$@"; }' >>~/.profile - source ~/.zshrc >/dev/null 2>&1 - ;; - "Chrome") - brew install google-chrome + mise use -g -y postgres@$postgres_version ;; - "ChromeDriver") - # Dependencies for chromedriver - brew install zip - - asdf plugin add chromedriver - asdf install chromedriver latest - asdf global chromedriver latest - asdf reshim chromedriver latest - ;; - "Docker") - brew install --cask docker + "Xcode Command Line Tools") + xcode-select --install ;; *) - echo "Invalid name argument on install" + printf "Invalid name argument on install: %s\n" "$1" + exit 1 ;; esac } -function maybe_install() { - if already_installed $1; then - echo "$1 is already installed. Skipping..." +maybe_install() { + if already_installed "$1"; then + printf "%s is already installed. Skipping...\n" "$1" else - echo "Installing $1..." - if [[ $1 == "Homebrew" || $1 == "Erlang" ]]; then - echo "This might take a while." + printf "Installing %s...\n" "$1" + if [ "$1" = "Homebrew" ] || [ "$1" = "Erlang" ]; then + printf "This might take a while.\n" fi - echo "" - install $1 + printf "\n" + install "$1" fi } -function add_env() { - echo "" - echo -e "${white}" - sleep 2 - maybe_install "xcode" +add_env() { + printf "\n" - echo -e "${white}" - sleep 2 - maybe_install "oh-my-zsh" + printf "${white}\n" + sleep 1.5 + maybe_install "Xcode Command Line Tools" - echo -e "${white}" - sleep 2 + printf "${white}\n" + sleep 1.5 maybe_install "Homebrew" - echo -e "${white}" - sleep 3 - maybe_install "asdf" + printf "${white}\n" + sleep 1.5 + maybe_install "mise" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "Erlang" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "Elixir" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "Phoenix" - echo -e "${white}" + printf "${white}\n" sleep 1.5 maybe_install "PostgreSQL" - if [[ "$1" =~ ^([yY][eE][sS]|[yY])$ ]]; then - echo -e "${white}" - sleep 3 - maybe_install "Chrome" - echo -e "${white}" - - sleep 1.5 - maybe_install "Node.js" - echo -e "${white}" - - sleep 2 - maybe_install "ChromeDriver" - echo -e "${white}" - - maybe_install "Docker" - echo -e "${white}" - fi - - echo -e "${white}" - echo -e "${cyan}${bold}phx.tools setup is complete!" - echo -e "${cyan}${bold}Please restart the terminal and type in the following command:" - echo -e "${cyan}${bold}mix phx.new" - echo -e "${white}" + printf "${white}\n" + printf "${cyan}${bold}phx.tools setup is complete!\n" + printf "${cyan}${bold}Please restart the terminal and type in the following command:\n" + printf "${cyan}${bold}mix phx.new\n" + printf "${white}\n" } phx_tools=" @@ -243,41 +194,37 @@ optimum=" ░╚════╝░╚═╝░░░░░░░░╚═╝░░░╚═╝╚═╝░░░░░╚═╝░╚═════╝░╚═╝░░░░░╚═╝╚═════╝░╚═╝░░╚═╝ " -echo -e "$phx_tools" - -echo -e "$by" - -echo -e "$optimum" +printf "%s\n" "$phx_tools" +printf "%s\n" "$by" +printf "%s\n" "$optimum" sleep 3 -echo "" +printf "\n" -echo -e "${bblue}${bold}Welcome to the phx.tools shell script for macOS." +printf "${bblue}${bold}Welcome to the phx.tools shell script for macOS.\n" sleep 3 -echo "" +printf "\n" -echo -e "${bblue}${bold}The following will be installed if not available already:" +printf "${bblue}${bold}The following will be installed if not available already:\n" -echo -e "${cyan}${bold}" +printf "${cyan}${bold}\n" -echo "1) Build dependencies" -echo "2) oh-my-zsh" -echo "3) Homebrew" -echo "4) asdf" -echo "5) Erlang" -echo "6) Elixir" -echo "7) Phoenix" -echo "8) PostgreSQL" +printf "1) Build dependencies\n" +printf "2) Homebrew\n" +printf "3) mise\n" +printf "4) Erlang\n" +printf "5) Elixir\n" +printf "6) Phoenix\n" +printf "7) PostgreSQL\n" -echo "" -echo -e "${white} ${bold}" +printf "\n" +printf "${white}${bold}\n" sleep 1 -# only true if user answer y/n is_yn() { case "$1" in [yY] | [yY][eE][sS]) @@ -295,54 +242,22 @@ is_yn() { answer='' while ! is_yn "$answer"; do - read -p "Do you want to continue? (y/n) " answer - echo "" + printf "Do you want to continue? (y/n) " + read -r answer + printf "\n" case "$answer" in [yY] | [yY][eE][sS]) - echo -e "${bblue}${bold}We can also install some optional tools:" - - echo -e "${cyan}${bold}" - - echo "1) Chrome" - echo "2) Node.js" - echo "3) ChromeDriver" - echo "4) Docker" - - echo -e "${white}" - echo -e "${white} ${bold}" - - optional="" - - while ! is_yn "$optional"; do - read -p "Do you want us to install those as well? (y/n) " optional - - if ! [[ "$optional" =~ ^([yY][eE][sS]|[yY]|[nN]|[nN][oO])$ ]]; then - echo "Please enter y or n" - echo "" - fi - done - - echo "" - - echo -e "${bblue}${bold}We're going to switch your default shell to Zsh even if it's not available yet, so you might see the following:" - - echo -e "${bblue}${bold}chsh: Warning: /bin/zsh does not exist" - - echo -e "${bblue}${bold}But don't worry. The installation will proceed as regular." - + printf "\n" sleep 3 - - sudo -S chsh -s '/bin/zsh' "${USER}" - - add_env "$optional" + add_env ;; [nN] | [nN][oO]) - echo "Thank you for your time" - echo "" + printf "Thank you for your time\n" + printf "\n" ;; *) - echo "Please enter y or n" - echo "" + printf "Please enter y or n\n" + printf "\n" ;; esac done diff --git a/test/scripts/Makefile b/test/scripts/Makefile index 508e67cf9..9948ccb59 100644 --- a/test/scripts/Makefile +++ b/test/scripts/Makefile @@ -1,6 +1,13 @@ +SHELL := $(SHELL) +current_shell := $(shell basename $(SHELL)) + +.ONESHELL: +SHELLFLAGS := -eu -c + serve: - initdb -D ~/pgdata -U postgres - pg_ctl start -D ~/pgdata - mix phx.new --no-install phx_tools_test - cd phx_tools_test && mix local.rebar --force && mix setup - cd phx_tools_test && elixir --erl '-detached' -S mix phx.server + mise exec -- initdb -D ~/pgdata -U postgres + mise exec -- pg_ctl start -D ~/pgdata + mise exec -- mix phx.new --no-install phx_tools_test + cd phx_tools_test + mise exec -- mix setup + mise exec -- elixir --erl '-detached' -S mix phx.server diff --git a/test/scripts/script.exp b/test/scripts/script.exp index c0eef5d82..00a74b3bf 100755 --- a/test/scripts/script.exp +++ b/test/scripts/script.exp @@ -7,6 +7,4 @@ spawn ./../../priv/static/$script match_max 100000 expect "Do you want to continue? (y/n) " send -- "y\r" -expect "Do you want us to install those as well? (y/n) " -send -- "y\r" expect eof From d2060f4e4b0f7b24fc7e62b75ebc85caed1287f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almir=20Saraj=C4=8Di=C4=87?= Date: Fri, 20 Sep 2024 10:24:51 +0200 Subject: [PATCH 2/6] Enable unattended setup --- .github/github_workflows.ex | 11 +++++++++++ .github/workflows/main.yml | 6 ++++++ .github/workflows/pr.yml | 6 ++++++ priv/static/Linux.sh | 10 ++++++++++ priv/static/macOS.sh | 10 ++++++++++ 5 files changed, 43 insertions(+) diff --git a/.github/github_workflows.ex b/.github/github_workflows.ex index 3d4dc1487..207b6957f 100644 --- a/.github/github_workflows.ex +++ b/.github/github_workflows.ex @@ -419,6 +419,17 @@ defmodule GithubWorkflows do ] ] ) ++ + if(os == "Linux", + do: [], + else: [ + [ + name: "Disable password prompt for macOS", + if: "steps.result_cache.outputs.cache-hit != 'true'", + run: + ~S + ] + ] + ) ++ [ [ name: "Install expect tool", diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 85d34e2a0..6dc8297ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -313,6 +313,9 @@ jobs: with: key: ${{ runner.os }}-bash-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} path: priv/static/macOS.sh + - name: Disable password prompt for macOS + if: steps.result_cache.outputs.cache-hit != 'true' + run: 'sudo sed -i "" "s/%admin ALL = (ALL) ALL/%admin ALL = (ALL) NOPASSWD: ALL/g" /etc/sudoers' - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: brew install expect @@ -391,6 +394,9 @@ jobs: - name: Install shell if: steps.result_cache.outputs.cache-hit != 'true' run: brew install zsh + - name: Disable password prompt for macOS + if: steps.result_cache.outputs.cache-hit != 'true' + run: 'sudo sed -i "" "s/%admin ALL = (ALL) ALL/%admin ALL = (ALL) NOPASSWD: ALL/g" /etc/sudoers' - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: brew install expect diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e20228977..a8c785e09 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -317,6 +317,9 @@ jobs: with: key: ${{ runner.os }}-bash-script-${{ hashFiles('test/scripts/script.exp') }}-${{ hashFiles('priv/static/macOS.sh') }} path: priv/static/macOS.sh + - name: Disable password prompt for macOS + if: steps.result_cache.outputs.cache-hit != 'true' + run: 'sudo sed -i "" "s/%admin ALL = (ALL) ALL/%admin ALL = (ALL) NOPASSWD: ALL/g" /etc/sudoers' - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: brew install expect @@ -395,6 +398,9 @@ jobs: - name: Install shell if: steps.result_cache.outputs.cache-hit != 'true' run: brew install zsh + - name: Disable password prompt for macOS + if: steps.result_cache.outputs.cache-hit != 'true' + run: 'sudo sed -i "" "s/%admin ALL = (ALL) ALL/%admin ALL = (ALL) NOPASSWD: ALL/g" /etc/sudoers' - name: Install expect tool if: steps.result_cache.outputs.cache-hit != 'true' run: brew install expect diff --git a/priv/static/Linux.sh b/priv/static/Linux.sh index 94bf71b42..6bab0d2f0 100755 --- a/priv/static/Linux.sh +++ b/priv/static/Linux.sh @@ -125,6 +125,16 @@ maybe_install() { add_env() { printf "\n" + # Ask for sudo password upfront + sudo -v + + # Keep sudo alive + while true; do + sudo -n true + sleep 60 + kill -0 "$$" || exit + done 2>/dev/null & + printf "${white}\n" sleep 1.5 maybe_install "mise" diff --git a/priv/static/macOS.sh b/priv/static/macOS.sh index 2c8492998..1f4f53647 100755 --- a/priv/static/macOS.sh +++ b/priv/static/macOS.sh @@ -134,6 +134,16 @@ maybe_install() { add_env() { printf "\n" + # Ask for sudo password upfront + sudo -v + + # Keep sudo alive + while true; do + sudo -n true + sleep 60 + kill -0 "$$" || exit + done 2>/dev/null & + printf "${white}\n" sleep 1.5 maybe_install "Xcode Command Line Tools" From 2f5936dfb0667074460f1109762b0415f13aa6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almir=20Saraj=C4=8Di=C4=87?= Date: Fri, 20 Sep 2024 11:17:09 +0200 Subject: [PATCH 3/6] Fix setup on a fresh Linux --- priv/static/Linux.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/priv/static/Linux.sh b/priv/static/Linux.sh index 6bab0d2f0..ea0bc6b76 100755 --- a/priv/static/Linux.sh +++ b/priv/static/Linux.sh @@ -51,6 +51,9 @@ already_installed() { "Erlang") mise which erl >/dev/null 2>&1 ;; + "git") + which git >/dev/null 2>&1 + ;; "mise") which mise >/dev/null 2>&1 ;; @@ -70,14 +73,23 @@ already_installed() { install() { case "$1" in "Elixir") + sudo apt-get update + sudo apt-get install -y unzip mise use -g -y elixir@$elixir_version ;; "Erlang") + sudo apt-get update + sudo apt-get install -y build-essential automake autoconf libssl-dev libncurses5-dev + if [ ! -f ~/.kerlrc ]; then printf "KERL_CONFIGURE_OPTIONS=\"--without-javac\"\n" >~/.kerlrc fi mise use -g -y erlang@$erlang_version ;; + "git") + sudo apt-get update + sudo apt-get -y install git + ;; "mise") curl https://mise.run | sh @@ -135,6 +147,10 @@ add_env() { kill -0 "$$" || exit done 2>/dev/null & + printf "${white}\n" + sleep 1.5 + maybe_install "git" + printf "${white}\n" sleep 1.5 maybe_install "mise" From b78be45c865b779fb943dd2c1881eddf5b84bedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almir=20Saraj=C4=8Di=C4=87?= Date: Fri, 20 Sep 2024 12:23:35 +0200 Subject: [PATCH 4/6] Fix setup on a fresh macOS --- priv/static/macOS.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/priv/static/macOS.sh b/priv/static/macOS.sh index 1f4f53647..8bb4e37e8 100755 --- a/priv/static/macOS.sh +++ b/priv/static/macOS.sh @@ -85,6 +85,9 @@ install() { fi mise use -g -y erlang@$erlang_version ;; + "Homebrew") + $SHELL -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + ;; "mise") curl https://mise.run | sh From 5fb89c184dcfdf2e1289bdcd2a265000350fbe59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almir=20Saraj=C4=8Di=C4=87?= Date: Fri, 20 Sep 2024 13:23:51 +0200 Subject: [PATCH 5/6] Fix Homebrew setup --- priv/static/macOS.sh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/priv/static/macOS.sh b/priv/static/macOS.sh index 8bb4e37e8..c33403d64 100755 --- a/priv/static/macOS.sh +++ b/priv/static/macOS.sh @@ -86,7 +86,22 @@ install() { mise use -g -y erlang@$erlang_version ;; "Homebrew") - $SHELL -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + UNAME_MACHINE="$(/usr/bin/uname -m)" + + if [[ "${UNAME_MACHINE}" == "arm64" ]]; then + ( + echo + echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' + ) >>$config_file + eval "$(/opt/homebrew/bin/brew shellenv)" + else + ( + echo + echo 'eval "$(/usr/local/bin/brew shellenv)"' + ) >>$config_file + eval "$(/usr/local/bin/brew shellenv)" + fi ;; "mise") curl https://mise.run | sh From f3b518cf9d1a48d41b3132f719b8e5b710802f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almir=20Saraj=C4=8Di=C4=87?= Date: Fri, 20 Sep 2024 15:12:58 +0200 Subject: [PATCH 6/6] Fix too many open files error on macOS https://github.com/erlang/otp/issues/8827 --- priv/static/macOS.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/priv/static/macOS.sh b/priv/static/macOS.sh index c33403d64..fb020836c 100755 --- a/priv/static/macOS.sh +++ b/priv/static/macOS.sh @@ -83,6 +83,7 @@ install() { if [ ! -f ~/.kerlrc ]; then printf "KERL_CONFIGURE_OPTIONS=\"--with-ssl=$(brew --prefix openssl@1.1) --without-javac\"\n" >~/.kerlrc fi + ulimit -n 1024 mise use -g -y erlang@$erlang_version ;; "Homebrew")