diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..fe2b2fa --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,61 @@ +name: Build release workflow + +on: + push: + tags: + - '*' + +jobs: + create_release: + runs-on: ubuntu-24.04 + name: Create github release + outputs: + upload_url: > + ${{ steps.get_release.outputs.upload_url || + steps.create_release.outputs.upload_url }} + steps: + - name: Try to Get Release + id: get_release + uses: zebra-lucky/actions-js-getRelease@0.0.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag: ${{ github.ref }} + - name: Create Release + id: create_release + if: ${{ !steps.get_release.outputs.upload_url }} + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + draft: false + prerelease: false + + build_with_pyinstaller: + needs: create_release + runs-on: ubuntu-24.04 + name: create PyInstaller build + steps: + - name: Set outputs for pkg_ver + id: set_vars + run: | + export JM_VERSION=${{ github.ref_name }} + echo "::set-output name=pkg_ver::$(echo $JM_VERSION)" + - name: Checkout + uses: actions/checkout@v1 + - name: build + env: + JM_VERSION: ${{ github.ref_name }} + run: | + ./contrib/build-linux/pyinstaller-build/build.sh + - name: Upload Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create_release.outputs.upload_url }} + asset_path: dist/joinmarket-clientserver-${{ github.ref_name}}.tgz + asset_name: joinmarket-clientserver-${{ github.ref_name}}.tgz + asset_content_type: application/octet-stream diff --git a/contrib/build-linux/pyinstaller-build/build.sh b/contrib/build-linux/pyinstaller-build/build.sh new file mode 100755 index 0000000..46460bd --- /dev/null +++ b/contrib/build-linux/pyinstaller-build/build.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +set -e + +PROJECT_ROOT="$(dirname "$(readlink -e "$0")")/../../.." +VENVPATH=$PROJECT_ROOT/jmvenv +JM_ROOT=$PROJECT_ROOT + +sudo apt-get install -y python3-dev python3-pip python3-venv git \ + build-essential automake pkg-config libtool libffi-dev libssl-dev + + +python3.12 -m venv $VENVPATH + + +. $VENVPATH/bin/activate + + +pip install .[gui] +pip install pyinstaller==6.14.2 + +# need to regenerate twisted/plugins/dropin.cache +python -c \ + 'from twisted.plugin import IPlugin, getPlugins; list(getPlugins(IPlugin))' + +rm -rf deps +mkdir -p deps +cd deps +git clone https://github.com/bitcoin-core/secp256k1.git +cd secp256k1 +git checkout v0.6.0 +./autogen.sh +./configure --prefix $VENVPATH --enable-module-recovery \ + --enable-experimental --enable-module-ecdh --enable-benchmark=no +make +make check +make install +cd ../.. + + +rm -rf libsodium +git clone https://github.com/jedisct1/libsodium.git +cd libsodium +git checkout 1.0.20-RELEASE +./autogen.sh +./configure --prefix $VENVPATH +make check +sudo make install +cd .. + +cp contrib/build-linux/pyinstaller-build/joinmarket-clientserver.spec . + +pyinstaller -y joinmarket-clientserver.spec + +ls -l dist/joinmarket-clientserver/ + +cd dist + +export JM_VERSION="${JM_VERSION}" + +mv joinmarket-clientserver joinmarket-clientserver-${JM_VERSION} + +tar -czvf joinmarket-clientserver-${JM_VERSION}.tgz \ + joinmarket-clientserver-${JM_VERSION} + +ls -l diff --git a/contrib/build-linux/pyinstaller-build/joinmarket-clientserver.spec b/contrib/build-linux/pyinstaller-build/joinmarket-clientserver.spec new file mode 100644 index 0000000..33b9d5d --- /dev/null +++ b/contrib/build-linux/pyinstaller-build/joinmarket-clientserver.spec @@ -0,0 +1,92 @@ +# -*- mode: python; coding: utf-8 -*- + +import itertools +import os +from pathlib import Path + + +PROJECT_ROOT = os.path.abspath('.') + + +binaries = [] +binaries += [(f'{PROJECT_ROOT}/jmvenv/lib/lib*', '.')] + + +datas = [] +datas += [(f'{PROJECT_ROOT}/jmvenv/lib/python3.12/site-packages/' + f'twisted/plugins/dropin.cache','twisted/plugins')] +datas += [(f'{PROJECT_ROOT}/jmvenv/lib/python3.12/site-packages/' + f'twisted/plugins/__init__.py', 'twisted/plugins')] +datas += [(f'{PROJECT_ROOT}/jmvenv/lib/python3.12/site-packages/' + f'twisted/plugins/txtorcon_endpoint_parser.py', 'twisted/plugins')] + + +scripts = [ + # 'scripts/add-utxo.py', + # 'scripts/bond-calculator.py', + # 'scripts/bumpfee.py', + # 'scripts/genwallet.py', + # 'scripts/jmwalletd.py', + # 'scripts/joinmarketd.py', + # 'scripts/joinmarket-qt.py', + # 'scripts/receive-payjoin.py', + # 'scripts/sendpayment.py', + # 'scripts/sendtomany.py', + 'scripts/start-dn.py', + # 'scripts/tumbler.py', + #'scripts/wallet-tool.py', + # 'scripts/yg-privacyenhanced.py', + #'scripts/yield-generator-basic.py', +] + + +hiddenimports = [ + 'chromalog.mark.helpers', + 'chromalog.mark.helpers.simple', + 'twisted.plugins', +# 'twisted.plugins.autobahn_endpoints', +# 'twisted.plugins.autobahn_twistd', + 'twisted.plugins.txtorcon_endpoint_parser', +] + + +a = {} +pyz = {} +exe = {} + + +for s in scripts: + a[s] = Analysis( + [s], + pathex=[], + binaries=binaries, + datas=datas, + hiddenimports=hiddenimports, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, + ) + + pyz[s] = PYZ(a[s].pure) + + exe[s] = EXE( + pyz[s], a[s].scripts, [], + name=Path(s).stem, + exclude_binaries=True, debug=False, bootloader_ignore_signals=False, + strip=False, upx=True, console=True, disable_windowed_traceback=False, + argv_emulation=False, target_arch=None, codesign_identity=None, + entitlements_file=None, + ) + +coll = COLLECT( + *list(exe.values()), + list(set(itertools.chain.from_iterable(b.binaries for b in a.values()))), + list(set(itertools.chain.from_iterable(d.datas for d in a.values()))), + strip=False, + upx=True, + upx_exclude=[], + name='joinmarket-clientserver', +)