diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 9f41624..7111896 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -5,17 +5,20 @@ env: OTP_VERSION: OTP-26.2.5.9_diode WXWIDGETS_REPO: https://github.com/wxWidgets/wxWidgets.git WXWIDGETS_VERSION: v3.2.6 - ELIXIR_VERSION: 1.16.3 + ELIXIR_VERSION: 1.19.5 ELIXIR_VARIANT: -otp-26 DOCKER_BUILDKIT: 0 jobs: - windows: + # wxWidgets + OTP compile alone can approach GitHub's 360m/job limit; splitting gives toolchain + Mix two budgets. + windows-toolchain: runs-on: windows-latest - timeout-minutes: 90 + timeout-minutes: 360 defaults: run: shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" name: Build Erlang/OTP (Windows) steps: - name: Restore Windows Cache @@ -23,34 +26,71 @@ jobs: id: win32-cache with: path: "c:\\opt\\otp.exe" - key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }} - + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + - uses: Vampire/setup-wsl@v2 if: steps.win32-cache.outputs.cache-hit != 'true' with: - distribution: Ubuntu-18.04 + distribution: Ubuntu-22.04 - name: Install WSL dependencies if: steps.win32-cache.outputs.cache-hit != 'true' - run: apt update && apt install -y g++-mingw-w64 gcc-mingw-w64 make autoconf unzip + run: | + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + for attempt in 1 2 3 4 5; do + if apt-get update && apt-get install -y g++-mingw-w64 gcc-mingw-w64 make autoconf unzip; then + break + fi + echo "apt-get failed (attempt $attempt), retrying in 45s..." >&2 + sleep 45 + if [ "$attempt" -eq 5 ]; then + echo "apt-get install failed after 5 attempts" >&2 + exit 1 + fi + done - - name: Install openssl + - name: Install openssl and NSIS (Windows) if: steps.win32-cache.outputs.cache-hit != 'true' shell: cmd run: | - choco install openssl --version=1.1.1.2100 - IF EXIST "c:\\Program Files\\OpenSSL-Win64" (move "c:\\Program Files\\OpenSSL-Win64" "c:\\OpenSSL-Win64") ELSE (move "c:\\Program Files\\OpenSSL" "c:\\OpenSSL-Win64") - + choco install openssl --version=1.1.1.2100 -y + choco install nsis -y + if exist "C:\\Program Files\\OpenSSL-Win64" ( + xcopy "C:\\Program Files\\OpenSSL-Win64" "C:\\OpenSSL-Win64\\" /E /I /H /Y /Q + ) else if exist "C:\\Program Files\\OpenSSL" ( + xcopy "C:\\Program Files\\OpenSSL" "C:\\OpenSSL-Win64\\" /E /I /H /Y /Q + ) + + - name: Wire Windows NSIS into WSL PATH + if: steps.win32-cache.outputs.cache-hit != 'true' + run: | + NSIS="/mnt/c/Program Files (x86)/NSIS/makensis.exe" + if [ ! -f "$NSIS" ]; then + NSIS="/mnt/c/Program Files/NSIS/makensis.exe" + fi + if [ ! -f "$NSIS" ]; then + echo "Windows NSIS makensis.exe not found after choco install" >&2 + exit 1 + fi + install -d /usr/local/bin + printf '%s\n' '#!/bin/sh' "exec \"$NSIS\" \"\$@\"" > /usr/local/bin/makensis.exe + chmod +x /usr/local/bin/makensis.exe + - name: Download wxWidgets if: steps.win32-cache.outputs.cache-hit != 'true' run: | - git clone ${{ env.WXWIDGETS_REPO }} + set -euo pipefail + cd "${GITHUB_WORKSPACE}" + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + git config --global http.postBuffer 524288000 + git clone --depth 1 --branch ${{ env.WXWIDGETS_VERSION }} --single-branch ${{ env.WXWIDGETS_REPO }} wxWidgets cd wxWidgets - git checkout ${{ env.WXWIDGETS_VERSION }} - git submodule update --init + git submodule update --init --depth 1 sed -i -r -e 's/wxUSE_POSTSCRIPT +0/wxUSE_POSTSCRIPT 1/' include/wx/msw/setup.h - sed -i -r -e 's/wxUSE_WEBVIEW_EDGE +0/wxUSE_WEBVIEW_EDGE 1/' include/wx/msw/setup.h - sed -i -r -e 's/WXWIN_COMPATIBILITY_3_0 +0/WXWIN_COMPATIBILITY_3_0 1/' include/wx/msw/setup.h + sed -i -r -e 's/wxUSE_WEBVIEW_EDGE +0/wxUSE_WEBVIEW_EDGE 1/' include/wx/msw/setup.h + sed -i -r -e 's/WXWIN_COMPATIBILITY_3_0 +0/WXWIN_COMPATIBILITY_3_0 1/' include/wx/msw/setup.h - name: Install WebView2 if: steps.win32-cache.outputs.cache-hit != 'true' @@ -77,15 +117,16 @@ jobs: - name: Compile Erlang if: steps.win32-cache.outputs.cache-hit != 'true' run: | - git clone ${{ env.OTP_GITHUB_URL }} + set -euo pipefail + cd "${GITHUB_WORKSPACE}" + git clone --depth 1 --branch ${{ env.OTP_VERSION }} --single-branch ${{ env.OTP_GITHUB_URL }} otp cd otp - git checkout ${{ env.OTP_VERSION }} export ERL_TOP=`pwd` export MAKEFLAGS=-j$(($(nproc) + 2)) export ERLC_USE_SERVER=true export ERTS_SKIP_DEPEND=true eval `./otp_build env_win32 x64` - ./otp_build all -a + ./otp_build all -a cp /mnt/c/opt/local64/pgm/wxWidgets-3.x.x/3rdparty/webview2/runtimes/win-x64/native/WebView2Loader.dll $ERL_TOP/release/win32/erts-*/bin/ ./otp_build installer_win32 export NAME=`ls release/win32/otp*.exe` @@ -96,8 +137,39 @@ jobs: uses: actions/cache/save@v3 with: path: "c:\\opt\\otp.exe" - key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }} - + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + # mix deps.get vs deps.compile each need up to 360m on Windows when caches are cold. + windows-mix-deps: + runs-on: windows-latest + needs: windows-toolchain + timeout-minutes: 360 + defaults: + run: + shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" + name: Build Windows Mix deps (fetch) + steps: + - name: Restore Windows Cache + uses: actions/cache/restore@v3 + id: win32-cache + with: + path: "c:\\opt\\otp.exe" + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + - name: Verify OTP installer exists + shell: cmd + run: | + if not exist "C:\opt\otp.exe" ( + echo Missing C:\opt\otp.exe - toolchain job should have restored or built it. >&2 + exit /b 1 + ) + + - name: Install NSIS for installer step + shell: cmd + run: choco install nsis -y + - name: Run Erlang installer shell: cmd run: C:\\opt\\otp.exe /S @@ -119,40 +191,709 @@ jobs: shell: msys2 {0} run: | echo export PATH=\"\$PATH:/c/Program\ Files\ \(x86\)/NSIS\" >> $HOME/.bashrc - + - name: Install Elixir shell: msys2 {0} run: | cd $HOME - git clone https://github.com/elixir-lang/elixir.git + git clone --depth 1 --branch v${{ env.ELIXIR_VERSION }} --single-branch https://github.com/elixir-lang/elixir.git cd elixir - git checkout v${{ env.ELIXIR_VERSION }} - make + make echo export PATH=\"\$PATH:$HOME/elixir/bin\" >> $HOME/.bashrc - - - uses: actions/checkout@v1 + + - uses: actions/checkout@v4 + with: + lfs: false + fetch-depth: 1 + + - name: Restore Mix / Hex cache + id: mix-cache + uses: actions/cache/restore@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} - name: "Get dependencies" + if: steps.mix-cache.outputs.cache-hit != 'true' shell: msys2 {0} run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export HEX_HTTP_CONCURRENCY=16 + export GIT_TERMINAL_PROMPT=0 + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + mkdir -p "$MIX_HOME" "$HEX_HOME" mix local.hex --force mix local.rebar --force - mix deps.get + MIX_ENV=prod mix deps.get --only prod + + - name: Save Mix / Hex cache + if: steps.mix-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} + + + windows-deps-compile: + runs-on: windows-latest + needs: windows-mix-deps + timeout-minutes: 360 + defaults: + run: + shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" + name: Build Windows deps compile (prod) + steps: + - name: Restore Windows Cache + uses: actions/cache/restore@v3 + id: win32-cache + with: + path: "c:\\opt\\otp.exe" + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + - name: Verify OTP installer exists + shell: cmd + run: | + if not exist "C:\opt\otp.exe" ( + echo Missing C:\opt\otp.exe - toolchain job should have restored or built it. >&2 + exit /b 1 + ) + + - name: Install NSIS for installer step + shell: cmd + run: choco install nsis -y + + - name: Run Erlang installer + shell: cmd + run: C:\\opt\\otp.exe /S + + - name: "Install msys2" + uses: msys2/setup-msys2@v2 + with: + install: pacman-mirrors pkg-config base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-go upx mingw-w64-x86_64-dlfcn unzip git tar mingw-w64-x86_64-nodejs mingw-w64-x86_64-imagemagick mingw-w64-x86_64-osslsigncode autoconf automake libtool gettext-devel gettext + update: true + + - name: Locate Erlang + shell: msys2 {0} + run: | + ERTS=`find /c/Program\ Files/[Ee]rl* -type d -name "erts-*" -not -path "*lib*"` + echo $ERTS + echo export PATH=\"\$PATH:$ERTS/bin\" > $HOME/.bashrc + + - name: Locate NSIS + shell: msys2 {0} + run: | + echo export PATH=\"\$PATH:/c/Program\ Files\ \(x86\)/NSIS\" >> $HOME/.bashrc + + - name: Install Elixir + shell: msys2 {0} + run: | + cd $HOME + git clone --depth 1 --branch v${{ env.ELIXIR_VERSION }} --single-branch https://github.com/elixir-lang/elixir.git + cd elixir + make + echo export PATH=\"\$PATH:$HOME/elixir/bin\" >> $HOME/.bashrc + + - uses: actions/checkout@v4 + with: + lfs: false + fetch-depth: 1 + + - name: Restore Mix / Hex cache + id: mix-cache + uses: actions/cache/restore@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} + + - uses: actions/setup-node@v4 + with: + node-version: '22' - name: "npm install" + shell: cmd + working-directory: assets + run: npm install + + # Elixir is installed under MSYS $HOME; MSVC deps.compile needs a cmd-accessible path (exqlite uses MSVC/cl). + - name: Export Elixir bin path for MSVC deps compile shell: msys2 {0} + run: echo "ELIXIR_BIN_WIN=$(cygpath -aw "$HOME/elixir/bin")" >> "$GITHUB_ENV" + + # Erlang/OTP Windows installer is MSVC-built; NIFs must not use MSYS2 gcc against OTP headers (see exqlite guides/windows.md). + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Compile prod dependencies (Mix only) + env: + MIX_ENV: prod + # Elixir 1.19+: parallel deps compile processes (native/NIF); MSVC tools coexist with MSYS make/nmake. + MIX_OS_DEPS_COMPILE_PARTITION_COUNT: "4" + shell: cmd run: | - cd assets && npm install + set "MIX_HOME=%GITHUB_WORKSPACE%\.ci_mix_home" + set "HEX_HOME=%GITHUB_WORKSPACE%\.ci_hex_home" + set "PATH=C:\Program Files\Erlang OTP\bin;%ELIXIR_BIN_WIN%;%PATH%" + cd /d "%GITHUB_WORKSPACE%" + mix deps.compile - - name: "Build Release" + - name: Save Windows deps compile cache + uses: actions/cache/save@v4 + with: + path: _build/prod + key: windows-mix-deps-compile-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + windows-compile: + runs-on: windows-latest + needs: windows-deps-compile + timeout-minutes: 360 + defaults: + run: + shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" + name: Build Windows compile (prod) + steps: + - name: Restore Windows Cache + uses: actions/cache/restore@v3 + id: win32-cache + with: + path: "c:\\opt\\otp.exe" + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + - name: Verify OTP installer exists + shell: cmd + run: | + if not exist "C:\opt\otp.exe" ( + echo Missing C:\opt\otp.exe - toolchain job should have restored or built it. >&2 + exit /b 1 + ) + + - name: Install NSIS for installer step + shell: cmd + run: choco install nsis -y + + - name: Run Erlang installer + shell: cmd + run: C:\\opt\\otp.exe /S + + - name: "Install msys2" + uses: msys2/setup-msys2@v2 + with: + install: pacman-mirrors pkg-config base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-go upx mingw-w64-x86_64-dlfcn unzip git tar mingw-w64-x86_64-nodejs mingw-w64-x86_64-imagemagick mingw-w64-x86_64-osslsigncode autoconf automake libtool gettext-devel gettext + update: true + + - name: Locate Erlang + shell: msys2 {0} + run: | + ERTS=`find /c/Program\ Files/[Ee]rl* -type d -name "erts-*" -not -path "*lib*"` + echo $ERTS + echo export PATH=\"\$PATH:$ERTS/bin\" > $HOME/.bashrc + + - name: Locate NSIS + shell: msys2 {0} + run: | + echo export PATH=\"\$PATH:/c/Program\ Files\ \(x86\)/NSIS\" >> $HOME/.bashrc + + - name: Install Elixir + shell: msys2 {0} + run: | + cd $HOME + git clone --depth 1 --branch v${{ env.ELIXIR_VERSION }} --single-branch https://github.com/elixir-lang/elixir.git + cd elixir + make + echo export PATH=\"\$PATH:$HOME/elixir/bin\" >> $HOME/.bashrc + + - uses: actions/checkout@v4 + with: + lfs: false + fetch-depth: 1 + + - name: Restore Mix / Hex cache + id: mix-cache + uses: actions/cache/restore@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} + + - name: "Get dependencies" + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export HEX_HTTP_CONCURRENCY=8 + export GIT_TERMINAL_PROMPT=0 + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + mkdir -p "$MIX_HOME" "$HEX_HOME" + mix local.hex --force + mix local.rebar --force + MIX_ENV=prod mix deps.get --only prod + + # MSYS2's bundled npm can segfault (exit 139); use the Actions Node toolchain + cmd.exe. + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: "npm install" + shell: cmd + working-directory: assets + run: npm install + + - name: Restore Windows deps compile output + uses: actions/cache/restore@v4 + id: deps-compile-cache + with: + path: _build/prod + key: windows-mix-deps-compile-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + - name: Verify deps compile output + shell: msys2 {0} + run: | + set -euo pipefail + test -d "$GITHUB_WORKSPACE/_build/prod/lib" || { echo "Missing deps-compiled _build/prod from deps job." >&2; exit 1; } + + - name: Compile prod application (Mix only) + env: + MAKE: make + REBAR_TARGET_ARCH_WORDSIZE: 64 + REBAR_TARGET_ARCH: x86_64-w64-mingw32 + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export MIX_ENV=prod + mix compile + + - name: Save Windows Mix compile cache + uses: actions/cache/save@v4 + with: + path: _build/prod + key: windows-job-compile-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + windows-assets: + runs-on: windows-latest + needs: windows-compile + timeout-minutes: 360 + defaults: + run: + shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" + name: Build Windows assets + steps: + - name: Restore Windows Cache + uses: actions/cache/restore@v3 + id: win32-cache + with: + path: "c:\\opt\\otp.exe" + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + - name: Verify OTP installer exists + shell: cmd + run: | + if not exist "C:\opt\otp.exe" ( + echo Missing C:\opt\otp.exe - toolchain job should have restored or built it. >&2 + exit /b 1 + ) + + - name: Install NSIS for installer step + shell: cmd + run: choco install nsis -y + + - name: Run Erlang installer + shell: cmd + run: C:\\opt\\otp.exe /S + + - name: "Install msys2" + uses: msys2/setup-msys2@v2 + with: + install: pacman-mirrors pkg-config base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-go upx mingw-w64-x86_64-dlfcn unzip git tar mingw-w64-x86_64-nodejs mingw-w64-x86_64-imagemagick mingw-w64-x86_64-osslsigncode autoconf automake libtool gettext-devel gettext + update: true + + - name: Locate Erlang + shell: msys2 {0} + run: | + ERTS=`find /c/Program\ Files/[Ee]rl* -type d -name "erts-*" -not -path "*lib*"` + echo $ERTS + echo export PATH=\"\$PATH:$ERTS/bin\" > $HOME/.bashrc + + - name: Locate NSIS + shell: msys2 {0} + run: | + echo export PATH=\"\$PATH:/c/Program\ Files\ \(x86\)/NSIS\" >> $HOME/.bashrc + + - name: Install Elixir + shell: msys2 {0} + run: | + cd $HOME + git clone --depth 1 --branch v${{ env.ELIXIR_VERSION }} --single-branch https://github.com/elixir-lang/elixir.git + cd elixir + make + echo export PATH=\"\$PATH:$HOME/elixir/bin\" >> $HOME/.bashrc + + - uses: actions/checkout@v4 + with: + lfs: false + fetch-depth: 1 + + - name: Restore Mix / Hex cache + id: mix-cache + uses: actions/cache/restore@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} + + - name: "Get dependencies" + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export HEX_HTTP_CONCURRENCY=8 + export GIT_TERMINAL_PROMPT=0 + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + mkdir -p "$MIX_HOME" "$HEX_HOME" + mix local.hex --force + mix local.rebar --force + MIX_ENV=prod mix deps.get --only prod + + # MSYS2's bundled npm can segfault (exit 139); use the Actions Node toolchain + cmd.exe. + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: "npm install" + shell: cmd + working-directory: assets + run: npm install + + - name: Restore Windows Mix compile output + uses: actions/cache/restore@v4 + id: compile-job-cache + with: + path: _build/prod + key: windows-job-compile-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + - name: Verify compile output + shell: msys2 {0} + run: | + set -euo pipefail + test -d "$GITHUB_WORKSPACE/_build/prod/lib" || { echo "Missing compiled _build/prod from compile job." >&2; exit 1; } + + - name: Digest Phoenix assets env: MAKE: make - REBAR_TARGET_ARCH_WORDSIZE: 64 + REBAR_TARGET_ARCH_WORDSIZE: 64 REBAR_TARGET_ARCH: x86_64-w64-mingw32 - WIN32_KEY_PASS: ${{ secrets.WIN32_KEY_PASS }} shell: msys2 {0} run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export MIX_ENV=prod mix assets.deploy + + - name: Save Windows compile + assets cache + uses: actions/cache/save@v4 + with: + path: | + _build/prod + priv/static + key: windows-job-assets-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + windows-assemble: + runs-on: windows-latest + needs: windows-assets + timeout-minutes: 360 + defaults: + run: + shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" + name: Build Windows release (assemble) + steps: + - name: Restore Windows Cache + uses: actions/cache/restore@v3 + id: win32-cache + with: + path: "c:\\opt\\otp.exe" + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + - name: Verify OTP installer exists + shell: cmd + run: | + if not exist "C:\opt\otp.exe" ( + echo Missing C:\opt\otp.exe - toolchain job should have restored or built it. >&2 + exit /b 1 + ) + + - name: Install NSIS for installer step + shell: cmd + run: choco install nsis -y + + - name: Run Erlang installer + shell: cmd + run: C:\\opt\\otp.exe /S + + - name: "Install msys2" + uses: msys2/setup-msys2@v2 + with: + install: pacman-mirrors pkg-config base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-go upx mingw-w64-x86_64-dlfcn unzip git tar mingw-w64-x86_64-nodejs mingw-w64-x86_64-imagemagick mingw-w64-x86_64-osslsigncode autoconf automake libtool gettext-devel gettext + update: true + + - name: Locate Erlang + shell: msys2 {0} + run: | + ERTS=`find /c/Program\ Files/[Ee]rl* -type d -name "erts-*" -not -path "*lib*"` + echo $ERTS + echo export PATH=\"\$PATH:$ERTS/bin\" > $HOME/.bashrc + + - name: Locate NSIS + shell: msys2 {0} + run: | + echo export PATH=\"\$PATH:/c/Program\ Files\ \(x86\)/NSIS\" >> $HOME/.bashrc + + - name: Install Elixir + shell: msys2 {0} + run: | + cd $HOME + git clone --depth 1 --branch v${{ env.ELIXIR_VERSION }} --single-branch https://github.com/elixir-lang/elixir.git + cd elixir + make + echo export PATH=\"\$PATH:$HOME/elixir/bin\" >> $HOME/.bashrc + + - uses: actions/checkout@v4 + with: + lfs: false + fetch-depth: 1 + + - name: Restore Mix / Hex cache + id: mix-cache + uses: actions/cache/restore@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} + + - name: "Get dependencies" + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export HEX_HTTP_CONCURRENCY=8 + export GIT_TERMINAL_PROMPT=0 + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + mkdir -p "$MIX_HOME" "$HEX_HOME" + mix local.hex --force + mix local.rebar --force + MIX_ENV=prod mix deps.get --only prod + + # MSYS2's bundled npm can segfault (exit 139); use the Actions Node toolchain + cmd.exe. + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: "npm install" + shell: cmd + working-directory: assets + run: npm install + + - name: Restore Windows compile + assets output + uses: actions/cache/restore@v4 + id: compile-cache + with: + path: | + _build/prod + priv/static + key: windows-job-assets-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + - name: Verify compile + assets output from prior job + shell: msys2 {0} + run: | + set -euo pipefail + test -d "$GITHUB_WORKSPACE/_build/prod/lib" || { echo "Missing compiled _build/prod — assets job must run first." >&2; exit 1; } + + - name: Assemble prod release (no NSIS yet) + env: + MAKE: make + REBAR_TARGET_ARCH_WORDSIZE: 64 + REBAR_TARGET_ARCH: x86_64-w64-mingw32 + DESKTOP_CI_RELEASE_PHASE: assemble + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export MIX_ENV=prod + mix release default_release --overwrite + + - name: Save Windows prod _build cache + uses: actions/cache/save@v4 + with: + path: _build/prod + key: windows-prod-assemble-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + windows-package: + runs-on: windows-latest + needs: windows-assemble + timeout-minutes: 360 + defaults: + run: + shell: wsl-bash {0} + env: + GIT_LFS_SKIP_SMUDGE: "1" + name: Build Windows installer + steps: + - name: Restore Windows Cache + uses: actions/cache/restore@v3 + id: win32-cache + with: + path: "c:\\opt\\otp.exe" + key: win32-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-v4 + + - name: Verify OTP installer exists + shell: cmd + run: | + if not exist "C:\opt\otp.exe" ( + echo Missing C:\opt\otp.exe - toolchain job should have restored or built it. >&2 + exit /b 1 + ) + + - name: Install NSIS for installer step + shell: cmd + run: choco install nsis -y + + - name: Run Erlang installer + shell: cmd + run: C:\\opt\\otp.exe /S + + - name: "Install msys2" + uses: msys2/setup-msys2@v2 + with: + install: pacman-mirrors pkg-config base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-go upx mingw-w64-x86_64-dlfcn unzip git tar mingw-w64-x86_64-nodejs mingw-w64-x86_64-imagemagick mingw-w64-x86_64-osslsigncode autoconf automake libtool gettext-devel gettext + update: true + + - name: Locate Erlang + shell: msys2 {0} + run: | + ERTS=`find /c/Program\ Files/[Ee]rl* -type d -name "erts-*" -not -path "*lib*"` + echo $ERTS + echo export PATH=\"\$PATH:$ERTS/bin\" > $HOME/.bashrc + + - name: Locate NSIS + shell: msys2 {0} + run: | + echo export PATH=\"\$PATH:/c/Program\ Files\ \(x86\)/NSIS\" >> $HOME/.bashrc + + - name: Install Elixir + shell: msys2 {0} + run: | + cd $HOME + git clone --depth 1 --branch v${{ env.ELIXIR_VERSION }} --single-branch https://github.com/elixir-lang/elixir.git + cd elixir + make + echo export PATH=\"\$PATH:$HOME/elixir/bin\" >> $HOME/.bashrc + + - uses: actions/checkout@v4 + with: + lfs: false + fetch-depth: 1 + + - name: Restore Mix / Hex cache + id: mix-cache + uses: actions/cache/restore@v4 + with: + path: | + deps + .ci_mix_home + .ci_hex_home + key: windows-mix-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }} + + - name: "Get dependencies" + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export HEX_HTTP_CONCURRENCY=8 + export GIT_TERMINAL_PROMPT=0 + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + mkdir -p "$MIX_HOME" "$HEX_HOME" + mix local.hex --force + mix local.rebar --force + MIX_ENV=prod mix deps.get --only prod + + - name: Restore Windows prod _build + id: prod-build + uses: actions/cache/restore@v4 + with: + path: _build/prod + key: windows-prod-assemble-${{ hashFiles('mix.lock') }}-elixir-${{ env.ELIXIR_VERSION }}-v1 + + - name: Verify prod build from assemble job + shell: msys2 {0} + run: | + set -euo pipefail + test -d "$GITHUB_WORKSPACE/_build/prod" || { echo "Missing _build/prod after cache restore" >&2; exit 1; } + test -d "$GITHUB_WORKSPACE/_build/prod/rel" || { echo "Missing release output — assemble job must complete first." >&2; exit 1; } + + # MSYS2's bundled npm can segfault (exit 139); use the Actions Node toolchain + cmd.exe. + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: "npm install" + shell: cmd + working-directory: assets + run: npm install + + # If WIN32_KEY_PASS is set to "" (missing secret), desktop_deployment still + # attempts signing and osslsigncode misparses -pass, breaking -n "The ...". + # Only export the variable when the secret is non-empty so CI skips signing. + - name: Export WIN32_KEY_PASS for code signing (optional) + if: ${{ secrets.WIN32_KEY_PASS != '' }} + run: echo "WIN32_KEY_PASS=${{ secrets.WIN32_KEY_PASS }}" >> "$GITHUB_ENV" + + - name: "Build Release" + env: + MAKE: make + REBAR_TARGET_ARCH_WORDSIZE: 64 + REBAR_TARGET_ARCH: x86_64-w64-mingw32 + shell: msys2 {0} + run: | + set -euo pipefail + export MIX_HOME="$GITHUB_WORKSPACE/.ci_mix_home" + export HEX_HOME="$GITHUB_WORKSPACE/.ci_hex_home" + export MIX_ENV=prod mix desktop.installer - name: Archive Installer @@ -163,49 +904,78 @@ jobs: _build/prod/*.exe macos: - runs-on: macos-13 + runs-on: macos-15 steps: + # asdf v0.19+ is a Go binary from Homebrew; the old git clone + ~/.asdf/asdf.sh flow is invalid. + - name: Install asdf (Homebrew) + run: | + brew install asdf + echo "$(brew --prefix asdf)/bin" >> "$GITHUB_PATH" + - name: macOS Cache uses: actions/cache@v3 id: macos-cache with: path: /Users/runner/.asdf - key: macos-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }} + key: macos15-wxwidgets-${{ env.WXWIDGETS_VERSION }}-otp-${{ env.OTP_VERSION }}-png-tiff-sys-asdf-brew-kerl-cxx - name: "Install brew deps" if: steps.macos-cache.outputs.cache-hit != 'true' run: | - brew install binutils coreutils wget automake autoconf libtool + brew install binutils coreutils wget automake autoconf libtool libpng libtiff - name: "Installing wxWidgets" if: steps.macos-cache.outputs.cache-hit != 'true' run: | - mkdir ~/projects && cd ~/projects - git clone ${{ env.WXWIDGETS_REPO }} - cd wxWidgets; - git checkout ${{ env.WXWIDGETS_VERSION }} - git submodule update --init - ./configure --prefix=/usr/local/wxWidgets --enable-webview --enable-compat30 --disable-shared + set -euo pipefail + mkdir -p ~/projects && cd ~/projects + git config --global http.lowSpeedLimit 500 + git config --global http.lowSpeedTime 120 + git config --global http.postBuffer 524288000 + for attempt in 1 2 3 4 5; do + rm -rf wxWidgets + if git clone --depth 1 --branch ${{ env.WXWIDGETS_VERSION }} ${{ env.WXWIDGETS_REPO }} wxWidgets; then + break + fi + echo "git clone wxWidgets failed (attempt $attempt), retrying..." >&2 + if [ "$attempt" -eq 5 ]; then + echo "git clone wxWidgets failed after 5 attempts" >&2 + exit 1 + fi + sleep $((attempt * 25)) + done + cd wxWidgets + git submodule update --init --depth 1 + LIBPNG_PREFIX="$(brew --prefix libpng)" + LIBTIFF_PREFIX="$(brew --prefix libtiff)" + export CPPFLAGS="-I${LIBPNG_PREFIX}/include -I${LIBTIFF_PREFIX}/include ${CPPFLAGS:-}" + export LDFLAGS="-L${LIBPNG_PREFIX}/lib -L${LIBTIFF_PREFIX}/lib ${LDFLAGS:-}" + export PKG_CONFIG_PATH="${LIBPNG_PREFIX}/lib/pkgconfig:${LIBTIFF_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH:-}" + # Bundled libpng can hit fp.h issues on recent Xcode; use Homebrew libpng/libtiff (keg-only paths above). + ./configure --prefix=/usr/local/wxWidgets --enable-webview --enable-compat30 --disable-shared \ + --with-libpng=sys --with-libtiff=sys make -j8 - name: "Installing Erlang" if: steps.macos-cache.outputs.cache-hit != 'true' run: | - git clone https://github.com/asdf-vm/asdf.git ~/.asdf - . $HOME/.asdf/asdf.sh + set -euo pipefail + export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH" asdf plugin add erlang asdf plugin add elixir asdf plugin add nodejs - echo "erlang ref:${{ env.OTP_VERSION }}" >> .tool-versions - echo "elixir ${{ env.ELIXIR_VERSION }}${{ env.ELIXIR_VARIANT }}" >> .tool-versions - echo "nodejs v18.7.0" >> .tool-versions - export KERL_CONFIGURE_OPTIONS="--enable-parallel-configure --with-wxdir=`echo ~/projects/wxWidgets` --disable-jit --without-javac --disable-debug CXX='gcc -std=c++11'" + echo "erlang ref:${{ env.OTP_VERSION }}" >> ~/.tool-versions + echo "elixir ${{ env.ELIXIR_VERSION }}${{ env.ELIXIR_VARIANT }}" >> ~/.tool-versions + echo "nodejs v18.7.0" >> ~/.tool-versions + # Do not use CXX='gcc -std=c++11' — kerl splits that into CXX=gcc plus a stray -std=c++11 configure arg. + export KERL_CONFIGURE_OPTIONS="--enable-parallel-configure --with-wxdir=$HOME/projects/wxWidgets --disable-jit --without-javac --disable-debug CXX=clang++" asdf install - uses: actions/checkout@v1 - name: "Compile and Lint" run: | - . $HOME/.asdf/asdf.sh + set -euo pipefail + export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH" echo "erlang ref:${{ env.OTP_VERSION }}" > .tool-versions echo "elixir ${{ env.ELIXIR_VERSION }}${{ env.ELIXIR_VARIANT }}" >> .tool-versions echo "nodejs v18.7.0" >> .tool-versions @@ -216,10 +986,11 @@ jobs: cd assets && npm install - name: "Build Release" - env: - MACOS_PEM: ${{ secrets.MACOS_PEM }} run: | - . $HOME/.asdf/asdf.sh + set -euo pipefail + export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH" + # Do not set MACOS_PEM here: if the secret is set but not a valid Developer ID PEM, + # create_keychain maybe still runs the full path and fails import (CI cannot code-sign). mix desktop.create_keychain maybe export MACOS_KEYCHAIN="$HOME/Library/Keychains/macos-build.keychain" export LD_LIBRARY_PATH="$HOME/projects/wxWidgets/lib/" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90c8b0c..5e53513 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: - name: Setup elixir uses: erlef/setup-beam@v1 with: - elixir-version: "1.16.3" + elixir-version: "1.19.5" otp-version: "26.2.5.9" - uses: actions/checkout@v5 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6aa6535 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,40 @@ +# AGENTS.md + +## Cursor Cloud specific instructions + +### Overview + +This is a desktop TodoApp built with Elixir, Phoenix LiveView, and the `elixir-desktop` library. It renders UI via a native wxWidgets webview backed by a local Phoenix server on `127.0.0.1:30979`. Data is stored in SQLite under the app config directory (`~/.config/todo/database.sq3` on Unix-like systems; see `TodoApp.config_dir/0` in `lib/todo_app.ex`). + +### Running the app + +```bash +. "$HOME/.asdf/asdf.sh" && cd /workspace && DISPLAY=:1 iex -S mix +``` + +The web UI is accessible at http://127.0.0.1:30979/ in a browser (useful for testing without needing the native window). + +### Key commands + +| Task | Command | +|------|---------| +| Install deps | `mix deps.get` | +| Compile | `mix compile` | +| Lint | `mix lint` | +| Tests | `mix test` | +| Asset build | `MIX_ENV=prod mix assets.deploy` | +| Run app (dev) | Same as [Running the app](#running-the-app): load asdf, set `DISPLAY`, then `iex -S mix` | + +`MIX_ENV=prod mix assets.deploy` minifies and digests static assets for production releases. In development, esbuild and dart_sass run as Mix watchers when you start the app with `iex -S mix` (see `mix.exs` `asset_apps/1`). + +### Non-obvious notes + +- **No external services required.** This is a fully self-contained desktop app — no Postgres, Redis, Docker containers, or external APIs. +- **DBus/EGL warnings are expected** in headless/cloud environments. The app logs errors about DBus (desktop notifications) and EGL (GPU acceleration) but these do not affect functionality. +- **wxWidgets is required** for the desktop window. In headless environments, ensure `DISPLAY=:1` is set and an X server (Xvfb) is running. +- **Version management uses asdf** with `.tool-versions` pinning Erlang 28.4.3, Elixir 1.19.5, and Node.js 22.19.0. GitHub Actions (for example `.github/workflows/ci.yml`) still pins older Elixir/OTP for the default CI job; treat that file as the source of truth for CI, not `.tool-versions`. +- **The `mix lint` alias** runs `compile --warnings-as-errors`, `format --check-formatted`, and `credo --ignore design`. Run it with the default Mix environment (`dev`); Credo is only a dev/test dependency, so `MIX_ENV=prod mix lint` will fail on the Credo step. +- **Git LFS:** `*.a` files under `rel/android/` are tracked with Git LFS. After cloning, if those libraries look like small text files instead of archives, run `git lfs pull` before Android-related builds. +- **No test files exist** in the project currently — `mix test` compiles in the test environment but reports "There are no tests to run". +- **Assets** are built via esbuild (JS) and dart_sass (SCSS), both downloaded automatically by Mix on first run. Run `npm install` in `assets/` before `mix assets.deploy` if you have not yet (see the root `README.md`). +- **Android sample** lives under `rel/android/` (separate Gradle project). It uses a pinned Erlang/Elixir pair for the embedded runtime that can differ from the desktop `.tool-versions`; read `rel/android/README.md` before building an APK. diff --git a/lib/todo_app.ex b/lib/todo_app.ex index 6b28b68..0420307 100644 --- a/lib/todo_app.ex +++ b/lib/todo_app.ex @@ -2,7 +2,7 @@ defmodule TodoApp do @moduledoc """ TodoApp Application. This module takes care of the the boot. Because the TodoApp is a standalone desktop application there is - initial Database initialization needed when the SQlite database is + initial Database initialization needed when the SQLite database is not yet existing. This is done during start() by calling `TodoApp.Repo.initialize()`. diff --git a/mix.exs b/mix.exs index 1512534..6928676 100644 --- a/mix.exs +++ b/mix.exs @@ -16,11 +16,7 @@ defmodule Todo.MixProject do releases: [ default_release: [ applications: [runtime_tools: :permanent, ssl: :permanent], - steps: [ - # &Desktop.Deployment.prepare_release/1, - :assemble, - &Desktop.Deployment.generate_installer/1 - ] + steps: release_steps() ] ] ] @@ -32,6 +28,30 @@ defmodule Todo.MixProject do ] end + # Desktop installers are only produced for desktop targets. Mobile releases + # (e.g. MIX_TARGET=android for the APK) must stop at :assemble; the + # installer step invokes tooling that is not available on CI and is not used + # for embedded zip packaging. + defp release_steps do + case Mix.target() do + target when target in [:android, :ios] -> + [:assemble] + + _ -> + # CI can assemble in one Windows job and run NSIS packaging in the next (separate 360m budget). + case System.get_env("DESKTOP_CI_RELEASE_PHASE") do + "assemble" -> + [:assemble] + + _ -> + [ + :assemble, + &Desktop.Deployment.generate_installer/1 + ] + end + end + end + # Specifies which paths to compile per environment. defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] @@ -90,8 +110,11 @@ defmodule Todo.MixProject do deps_list = [ # {:desktop, path: "../desktop"}, # {:desktop, "~> 1.5"}, - {:desktop, github: "elixir-desktop/desktop"}, - {:desktop_deployment, github: "elixir-desktop/deployment"}, + # Pinned SHAs for reproducible CI. Do not add :depth with :ref — Android CI uses Elixir 1.17, where Mix forbids that pair. + {:desktop, + github: "elixir-desktop/desktop", ref: "0966857094b6ceaec6789fae65b74478bfc8be19"}, + {:desktop_deployment, + github: "elixir-desktop/deployment", ref: "c5c09864693121acb7e6de0f8f3253937ed2e07c"}, {:igniter, "~> 0.6"}, # {:desktop_deployment, path: "../deployment", runtime: false}, @@ -100,7 +123,10 @@ defmodule Todo.MixProject do {:phoenix_ecto, "~> 4.5"}, {:ecto_sqlite3, "~> 0.22.0"}, # Pinned to the same version as the android runtime binary nifs. - {:exqlite, github: "elixir-desktop/exqlite", override: true}, + {:exqlite, + github: "elixir-desktop/exqlite", + ref: "1caf1f42395fff8a68ac5a509f7294090a6f6f0d", + override: true}, {:phoenix_html, "~> 4.1"}, {:phoenix_live_dashboard, "~> 0.8.3"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, diff --git a/mix.lock b/mix.lock index 5d22ab3..db0f7e7 100644 --- a/mix.lock +++ b/mix.lock @@ -10,8 +10,8 @@ "dbus": {:hex, :dbus, "0.8.0", "7c800681f35d909c199265e55a8ee4aea9ebe4acccce77a0740f89f29cc57648", [:make], [], "hexpm", "a9784f2d9717ffa1f74169144a226c39633ac0d9c7fe8cb3594aeb89c827cca5"}, "debouncer": {:hex, :debouncer, "0.1.13", "af5906b231c196943ac8386b5b5f45a2f36d54a8bcd7e1b29eef2671de33d287", [:mix], [], "hexpm", "a14f57420c7d4a287f8f08e715fc8759b5d28dcd1032f9585d57c45d22123382"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, - "desktop": {:git, "https://github.com/elixir-desktop/desktop.git", "0966857094b6ceaec6789fae65b74478bfc8be19", []}, - "desktop_deployment": {:git, "https://github.com/elixir-desktop/deployment.git", "c5c09864693121acb7e6de0f8f3253937ed2e07c", []}, + "desktop": {:git, "https://github.com/elixir-desktop/desktop.git", "0966857094b6ceaec6789fae65b74478bfc8be19", [ref: "0966857094b6ceaec6789fae65b74478bfc8be19"]}, + "desktop_deployment": {:git, "https://github.com/elixir-desktop/deployment.git", "c5c09864693121acb7e6de0f8f3253937ed2e07c", [ref: "c5c09864693121acb7e6de0f8f3253937ed2e07c"]}, "dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"}, "ecto": {:hex, :ecto, "3.13.5", "9d4a69700183f33bf97208294768e561f5c7f1ecf417e0fa1006e4a91713a834", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df9efebf70cf94142739ba357499661ef5dbb559ef902b68ea1f3c1fabce36de"}, "ecto_sql": {:hex, :ecto_sql, "3.13.4", "b6e9d07557ddba62508a9ce4a484989a5bb5e9a048ae0e695f6d93f095c25d60", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2b38cf0749ca4d1c5a8bcbff79bbe15446861ca12a61f9fba604486cb6b62a14"}, @@ -21,7 +21,7 @@ "ex_dbus": {:hex, :ex_dbus, "0.1.4", "053df83d45b27ba0b9b6ef55a47253922069a3ace12a2a7dd30d3aff58301e17", [:mix], [{:dbus, "~> 0.8.0", [hex: :dbus, repo: "hexpm", optional: false]}, {:saxy, "~> 1.4.0", [hex: :saxy, repo: "hexpm", optional: false]}], "hexpm", "d8baeaf465eab57b70a47b70e29fdfef6eb09ba110fc37176eebe6ac7874d6d5"}, "ex_sni": {:hex, :ex_sni, "0.2.9", "81f9421035dd3edb6d69f1a4dd5f53c7071b41628130d32ba5ab7bb4bfdc2da0", [:mix], [{:debouncer, "~> 0.1", [hex: :debouncer, repo: "hexpm", optional: false]}, {:ex_dbus, "~> 0.1", [hex: :ex_dbus, repo: "hexpm", optional: false]}, {:saxy, "~> 1.4.0", [hex: :saxy, repo: "hexpm", optional: false]}], "hexpm", "921d67d913765ed20ea8354fd1798dabc957bf66990a6842d6aaa7cd5ee5bc06"}, "expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"}, - "exqlite": {:git, "https://github.com/elixir-desktop/exqlite.git", "1caf1f42395fff8a68ac5a509f7294090a6f6f0d", []}, + "exqlite": {:git, "https://github.com/elixir-desktop/exqlite.git", "1caf1f42395fff8a68ac5a509f7294090a6f6f0d", [ref: "1caf1f42395fff8a68ac5a509f7294090a6f6f0d"]}, "file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"}, "finch": {:hex, :finch, "0.21.0", "b1c3b2d48af02d0c66d2a9ebfb5622be5c5ecd62937cf79a88a7f98d48a8290c", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "87dc6e169794cb2570f75841a19da99cfde834249568f2a5b121b809588a4377"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, diff --git a/rel/android/app/run_mix b/rel/android/app/run_mix index 2cf3c6b..5d8696b 100755 --- a/rel/android/app/run_mix +++ b/rel/android/app/run_mix @@ -71,6 +71,7 @@ if [ ! -d "assets/node_modules" ]; then (cd assets && npm install) fi +mkdir -p "$(dirname "$APP_FILE")" rm -f "$APP_FILE" mix assets.deploy diff --git a/scripts/Dockerfile b/scripts/Dockerfile index 5ea974a..55f2bec 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -52,7 +52,8 @@ ARG ELIXIR_VARIANT ENV ELIXIR_VARIANT=${ELIXIR_VARIANT:-"-otp-26"} ENV ASDF_DIR=/root/.asdf -RUN git clone https://github.com/asdf-vm/asdf.git ${ASDF_DIR} && \ +# asdf v0.19+ dropped asdf.sh (Go rewrite); pin v0.18.x for Docker RUN sourcing. +RUN git clone https://github.com/asdf-vm/asdf.git ${ASDF_DIR} --branch v0.18.1 --depth 1 && \ . ${ASDF_DIR}/asdf.sh && \ asdf plugin add elixir && \ echo "elixir ${ELIXIR_VERSION}${ELIXIR_VARIANT}" >> .tool-versions && \ diff --git a/scripts/Dockerfile.cef b/scripts/Dockerfile.cef index 7276ed9..b8f2197 100644 --- a/scripts/Dockerfile.cef +++ b/scripts/Dockerfile.cef @@ -50,7 +50,7 @@ RUN cd ~/projects/wxWidgets && \ ENV OTP_VERSION=25.3.2.6 ENV ELIXIR_VERSION=1.13.4 ENV ASDF_DIR=/root/.asdf -RUN git clone https://github.com/asdf-vm/asdf.git ${ASDF_DIR} && \ +RUN git clone https://github.com/asdf-vm/asdf.git ${ASDF_DIR} --branch v0.18.1 --depth 1 && \ . ${ASDF_DIR}/asdf.sh && \ asdf plugin add erlang && \ asdf plugin add elixir && \ diff --git a/scripts/Dockerfile.raspbian b/scripts/Dockerfile.raspbian index 16e9223..af16a1e 100644 --- a/scripts/Dockerfile.raspbian +++ b/scripts/Dockerfile.raspbian @@ -36,7 +36,7 @@ RUN cd ~/projects/wxWidgets && \ ENV OTP_VERSION=25.3.2.6 ENV ELIXIR_VERSION=1.13.4 ENV ASDF_DIR=/root/.asdf -RUN git clone https://github.com/asdf-vm/asdf.git ${ASDF_DIR} && \ +RUN git clone https://github.com/asdf-vm/asdf.git ${ASDF_DIR} --branch v0.18.1 --depth 1 && \ . ${ASDF_DIR}/asdf.sh && \ asdf plugin add erlang && \ asdf plugin add elixir && \