name: build cli for all platforms on: push: tags: - '*' pull_request: branches: [ main, master ] permissions: contents: write jobs: build-all-for-all: runs-on: ubuntu-latest strategy: fail-fast: false matrix: goos: [linux, freebsd, windows] goarch: [amd64, arm64, riscv64] exclude: - goarch: arm64 goos: windows - goarch: riscv64 goos: windows - goarch: arm64 goos: freebsd - goarch: riscv64 goos: freebsd steps: - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v4 with: go-version: 'stable' - name: Install FUSE dependencies run: | sudo apt-get update sudo apt-get install -y libfuse-dev - name: Install cross-compilation tools for ARM64 if: matrix.goarch == 'arm64' && matrix.goos == 'linux' run: | sudo apt-get install -y gcc-aarch64-linux-gnu - name: Install cross-compilation tools for RISC-V if: matrix.goarch == 'riscv64' && matrix.goos == 'linux' run: | sudo apt-get install -y gcc-riscv64-linux-gnu - name: Install FreeBSD SDK if: matrix.goos == 'freebsd' run: | sudo apt-get update sudo apt-get install -y clang lld binutils-riscv64-unknown-elf 2>/dev/null || true mkdir -p /tmp/freebsd-sdk cd /tmp/freebsd-sdk # Determine download path based on architecture case "${{ matrix.goarch }}" in arm64) DLPATH="arm64" ;; riscv64) DLPATH="riscv" ;; *) DLPATH="amd64" ;; esac wget -q "https://download.freebsd.org/releases/${DLPATH}/14.3-RELEASE/base.txz" && tar -xf base.txz # Download and extract libfuse source mkdir -p libfuse && cd libfuse wget -q https://github.com/libfuse/libfuse/releases/download/fuse-2.9.9/fuse-2.9.9.tar.gz tar -xzf fuse-2.9.9.tar.gz --strip-components=1 mkdir -p /tmp/freebsd-sdk/usr/include cp include/fuse.h /tmp/freebsd-sdk/usr/include/ cp include/fuse_*.h /tmp/freebsd-sdk/usr/include/ 2>/dev/null || true cd /tmp/freebsd-sdk - name: Set cross-compiler id: set-cc run: | if [ "${{ matrix.goarch }}" = "arm64" ] && [ "${{ matrix.goos }}" = "linux" ]; then echo "CC=aarch64-linux-gnu-gcc" >> $GITHUB_ENV elif [ "${{ matrix.goarch }}" = "riscv64" ] && [ "${{ matrix.goos }}" = "linux" ]; then echo "CC=riscv64-linux-gnu-gcc" >> $GITHUB_ENV elif [ "${{ matrix.goos }}" = "freebsd" ]; then TRIPLE="x86_64-unknown-freebsd14.3" [ "${{ matrix.goarch }}" = "arm64" ] && TRIPLE="aarch64-unknown-freebsd14.3" [ "${{ matrix.goarch }}" = "riscv64" ] && TRIPLE="riscv64-unknown-freebsd14.3" echo "CC=clang --target=$TRIPLE --sysroot=/tmp/freebsd-sdk" >> $GITHUB_ENV echo "CGO_CFLAGS=-isystem /tmp/freebsd-sdk/usr/include --target=$TRIPLE" >> $GITHUB_ENV echo "CGO_LDFLAGS=-L/tmp/freebsd-sdk/usr/lib -L/tmp/freebsd-sdk/lib -L/tmp/freebsd-sdk/usr/lib64 --target=$TRIPLE" >> $GITHUB_ENV fi - name: Build binary env: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} CGO_ENABLED: ${{ matrix.goos == 'windows' && '0' || '1' }} run: | go build -ldflags "-X main.version=${{ github.ref_name }}" -o nak-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }} - name: Upload Release Asset if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v1 with: files: ./nak-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }} build-darwin: runs-on: macos-latest strategy: fail-fast: false matrix: goarch: [amd64, arm64] steps: - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v4 with: go-version: 'stable' - name: Install macFUSE run: brew install --cask macfuse - name: Build binary env: GOOS: darwin GOARCH: ${{ matrix.goarch }} CGO_ENABLED: '1' run: | go build -ldflags "-X main.version=${{ github.ref_name }}" -o nak-${{ github.ref_name }}-darwin-${{ matrix.goarch }} - name: Upload Release Asset if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v1 with: files: ./nak-${{ github.ref_name }}-darwin-${{ matrix.goarch }} smoke-test-linux-amd64: runs-on: ubuntu-latest needs: - build-all-for-all steps: - name: download and smoke test latest binary run: | set -eo pipefail # exit on error, and on pipe failures echo "downloading nak binary from releases" RELEASE_URL="https://api.github.com/repos/fiatjaf/nak/releases/latest" wget $(wget -q -O - ${RELEASE_URL} | jq -r '.assets[] | select(.name | contains("linux-amd64")) | .browser_download_url') -O nak -nv chmod +x nak echo "printing version..." ./nak --version # generate and manipulate keys echo "testing key operations..." SECRET_KEY=$(./nak key generate) PUBLIC_KEY=$(echo $SECRET_KEY | ./nak key public) echo "generated key pair: $SECRET_KEY => $PUBLIC_KEY" # create events echo "testing event creation..." ./nak event -c "hello world" HELLOWORLD=$(./nak event -c "hello world") echo " hello world again: $HELLOWORLD" ./nak event --ts "2 days ago" -c "event with timestamp" ./nak event -k 1 -t "t=test" -c "event with tag" # test NIP-19 encoding/decoding echo "testing NIP-19 encoding/decoding..." NSEC=$(echo $SECRET_KEY | ./nak encode nsec) echo "encoded nsec: $NSEC" ./nak encode npub 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 EVENT_ID="5ae731bbc7711f78513da14927c48cc7143a91e6cad0565fdc4d73b8967a7d59" NEVENT1=$(./nak encode nevent $EVENT_ID) echo "encoded nevent1: $NEVENT1" ./nak decode $NEVENT1 ./nak decode npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 # test event verification echo "testing event verification..." # create an event and verify it VERIFY_EVENT=$(./nak event -c "verify me") echo $VERIFY_EVENT | ./nak verify # test PoW echo "testing pow..." ./nak event -c "testing pow" --pow 8 # test NIP-49 key encryption/decryption echo "testing NIP-49 key encryption/decryption..." ENCRYPTED_KEY=$(./nak key encrypt $SECRET_KEY "testpassword") echo "encrypted key: ${ENCRYPTED_KEY: 0:20}..." DECRYPTED_KEY=$(./nak key decrypt $ENCRYPTED_KEY "testpassword") if [ "$DECRYPTED_KEY" != "$SECRET_KEY" ]; then echo "nip-49 encryption/decryption test failed!" exit 1 fi # test multi-value tags echo "testing multi-value tags..." ./nak event --ts "yesterday" -t "e=f59911b561c37c90b01e9e5c2557307380835c83399756f4d62d8167227e420a;wss://relay.example.com;root" -c "testing multi-value tags" # test relay operations (with a public relay) echo "testing publishing..." # publish a simple event to a public relay EVENT_JSON=$(./nak event --sec $SECRET_KEY -c "test from nak smoke test" nos.lol < /dev/null) EVENT_ID=$(echo $EVENT_JSON | jq -r .id) echo "published event ID: $EVENT_ID" # wait a moment for propagation sleep 2 # fetch the event we just published ./nak req -i $EVENT_ID nos.lol # test serving (just start and immediately kill) echo "testing serve command..." timeout 2s ./nak serve || true # test filesystem mount (just start and immediately kill) echo "testing fs mount command..." mkdir -p /tmp/nostr-mount timeout 2s ./nak fs --sec $SECRET_KEY /tmp/nostr-mount || true echo "all tests passed"