docs: add sponsors to README (#1225) #217
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Nightly Release | |
| on: | |
| push: | |
| branches: | |
| - master | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| nightly: | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: "1.26.2" | |
| - name: Set up Zig | |
| uses: goto-bus-stop/setup-zig@v2 | |
| - name: Set up libpcsclite for Linux cross-compilation | |
| run: | | |
| PCSC_DIR="$RUNNER_TEMP/pcsclite" | |
| mkdir -p "$PCSC_DIR/include" "$PCSC_DIR/lib/pkgconfig" | |
| # Download pcsc-lite headers from upstream | |
| PCSC_URL="https://raw.githubusercontent.com/LudovicRousseau/PCSC/master/src/PCSC" | |
| for header in winscard.h wintypes.h; do | |
| curl -fsSL "$PCSC_URL/$header" -o "$PCSC_DIR/include/$header" | |
| done | |
| # pcsclite.h is generated from pcsclite.h.in — download and substitute the version placeholder | |
| curl -fsSL "$PCSC_URL/pcsclite.h.in" -o "$PCSC_DIR/include/pcsclite.h" | |
| sed -i '' 's/@VERSION@/1.9.0/' "$PCSC_DIR/include/pcsclite.h" | |
| # Build stub library — the real libpcsclite is loaded at runtime on the user's system, | |
| # but the linker needs symbols to resolve during cross-compilation. | |
| cat > "$RUNNER_TEMP/pcsclite_stub.c" << 'STUB' | |
| #include <stddef.h> | |
| typedef long LONG; | |
| typedef unsigned long DWORD; | |
| typedef void *LPCVOID; | |
| typedef char *LPSTR; | |
| typedef const char *LPCSTR; | |
| typedef unsigned char *LPBYTE; | |
| typedef unsigned char BYTE; | |
| typedef LONG SCARDCONTEXT; | |
| typedef LONG SCARDHANDLE; | |
| typedef struct { DWORD dwProtocol; DWORD cbPciLength; } SCARD_IO_REQUEST; | |
| typedef struct { LPCSTR szReader; DWORD dwCurrentState; DWORD dwEventState; DWORD cbAtr; unsigned char rgbAtr[36]; void *pvUserData; } SCARD_READERSTATE; | |
| LONG SCardEstablishContext(DWORD s, LPCVOID r1, LPCVOID r2, SCARDCONTEXT *c) { return 0; } | |
| LONG SCardReleaseContext(SCARDCONTEXT c) { return 0; } | |
| LONG SCardIsValidContext(SCARDCONTEXT c) { return 0; } | |
| LONG SCardCancel(SCARDCONTEXT c) { return 0; } | |
| LONG SCardConnect(SCARDCONTEXT c, LPCSTR r, DWORD s, DWORD p, SCARDHANDLE *h, DWORD *ap) { return 0; } | |
| LONG SCardReconnect(SCARDHANDLE h, DWORD s, DWORD p, DWORD d, DWORD *ap) { return 0; } | |
| LONG SCardDisconnect(SCARDHANDLE h, DWORD d) { return 0; } | |
| LONG SCardBeginTransaction(SCARDHANDLE h) { return 0; } | |
| LONG SCardEndTransaction(SCARDHANDLE h, DWORD d) { return 0; } | |
| LONG SCardStatus(SCARDHANDLE h, LPSTR r, DWORD *rl, DWORD *s, DWORD *p, LPBYTE a, DWORD *al) { return 0; } | |
| LONG SCardTransmit(SCARDHANDLE h, const SCARD_IO_REQUEST *si, const BYTE *s, DWORD sl, SCARD_IO_REQUEST *ri, BYTE *r, DWORD *rl) { return 0; } | |
| LONG SCardControl(SCARDHANDLE h, DWORD c, LPCVOID i, DWORD il, void *o, DWORD ol, DWORD *br) { return 0; } | |
| LONG SCardGetAttrib(SCARDHANDLE h, DWORD a, LPBYTE b, DWORD *bl) { return 0; } | |
| LONG SCardSetAttrib(SCARDHANDLE h, DWORD a, const BYTE *b, DWORD bl) { return 0; } | |
| LONG SCardListReaders(SCARDCONTEXT c, LPCSTR g, LPSTR r, DWORD *rl) { return 0; } | |
| LONG SCardListReaderGroups(SCARDCONTEXT c, LPSTR g, DWORD *gl) { return 0; } | |
| LONG SCardGetStatusChange(SCARDCONTEXT c, DWORD t, SCARD_READERSTATE *s, DWORD n) { return 0; } | |
| LONG SCardFreeMemory(SCARDCONTEXT c, LPCVOID m) { return 0; } | |
| const char *pcsc_stringify_error(LONG e) { return "stub"; } | |
| STUB | |
| zig cc -c -target x86_64-linux-musl -o "$RUNNER_TEMP/pcsclite_stub_amd64.o" "$RUNNER_TEMP/pcsclite_stub.c" | |
| zig cc -c -target aarch64-linux-musl -o "$RUNNER_TEMP/pcsclite_stub_arm64.o" "$RUNNER_TEMP/pcsclite_stub.c" | |
| mkdir -p "$PCSC_DIR/lib/amd64" "$PCSC_DIR/lib/arm64" | |
| ar rcs "$PCSC_DIR/lib/amd64/libpcsclite.a" "$RUNNER_TEMP/pcsclite_stub_amd64.o" | |
| ar rcs "$PCSC_DIR/lib/arm64/libpcsclite.a" "$RUNNER_TEMP/pcsclite_stub_arm64.o" | |
| # Create pkg-config file — Libs will be overridden per-arch via CGO_LDFLAGS in goreleaser | |
| cat > "$PCSC_DIR/lib/pkgconfig/libpcsclite.pc" << EOF | |
| Name: libpcsclite | |
| Description: PC/SC Lite | |
| Version: 1.9.0 | |
| Cflags: -I$PCSC_DIR/include | |
| Libs: -L$PCSC_DIR/lib/amd64 -lpcsclite | |
| EOF | |
| echo "PKG_CONFIG_PATH=$PCSC_DIR/lib/pkgconfig" >> $GITHUB_ENV | |
| echo "PCSC_DIR=$PCSC_DIR" >> $GITHUB_ENV | |
| - name: Get macOS SDK path | |
| id: macos_sdk | |
| run: echo "path=$(xcrun --show-sdk-path)" >> $GITHUB_OUTPUT | |
| - name: Build with GoReleaser (snapshot) | |
| uses: goreleaser/goreleaser-action@v7 | |
| with: | |
| version: latest | |
| args: release --snapshot --clean --config .goreleaser.nightly.yml | |
| env: | |
| SDK_PATH: ${{ steps.macos_sdk.outputs.path }} | |
| - name: Delete existing nightly release | |
| env: | |
| GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} | |
| run: | | |
| gh release delete nightlyv0 --yes --cleanup-tag || true | |
| - name: Create nightly release | |
| env: | |
| GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} | |
| run: | | |
| SHORT_SHA="$(git rev-parse --short HEAD)" | |
| LATEST_TAG="$(git describe --tags --abbrev=0 --exclude='nightlyv*' --exclude='preview*' 2>/dev/null || echo '')" | |
| NOTES_FILE="$RUNNER_TEMP/release_notes.md" | |
| { | |
| echo "> [!WARNING]" | |
| echo "> This is an automated nightly build from the latest \`master\` commit (\`$SHORT_SHA\`). It may be unstable — use stable releases for production." | |
| echo "" | |
| echo "### Install" | |
| echo "" | |
| echo '- **Homebrew:** `brew install floatpane/matcha/matcha-nightly`' | |
| echo '- **Snapcraft:** `snap install matcha --beta`' | |
| if [ -n "$LATEST_TAG" ]; then | |
| echo "" | |
| echo "### Changes since $LATEST_TAG" | |
| echo "" | |
| git log --pretty=format:"- %s (%h)" "$LATEST_TAG..HEAD" | |
| echo "" | |
| fi | |
| } > "$NOTES_FILE" | |
| gh release create nightlyv0 dist/*.tar.gz dist/*.zip dist/checksums.txt \ | |
| --title "Nightly Build ($SHORT_SHA)" \ | |
| --notes-file "$NOTES_FILE" \ | |
| --prerelease \ | |
| --target master | |
| - name: Update Homebrew tap | |
| env: | |
| GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} | |
| run: | | |
| VERSION="nightly-$(git rev-parse --short HEAD)" | |
| DARWIN_AMD64_SHA=$(shasum -a 256 dist/matcha_nightly_darwin_amd64.tar.gz | cut -d ' ' -f 1) | |
| DARWIN_ARM64_SHA=$(shasum -a 256 dist/matcha_nightly_darwin_arm64.tar.gz | cut -d ' ' -f 1) | |
| LINUX_AMD64_SHA=$(shasum -a 256 dist/matcha_nightly_linux_amd64.tar.gz | cut -d ' ' -f 1) | |
| LINUX_ARM64_SHA=$(shasum -a 256 dist/matcha_nightly_linux_arm64.tar.gz | cut -d ' ' -f 1) | |
| BASE_URL="https://github.com/floatpane/matcha/releases/download/nightlyv0" | |
| cat > /tmp/matcha-nightly.rb << EOF | |
| class MatchaNightly < Formula | |
| desc "A beautiful and functional email client for your terminal (nightly)" | |
| homepage "https://matcha.floatpane.com" | |
| version "$VERSION" | |
| on_macos do | |
| if Hardware::CPU.intel? | |
| url "$BASE_URL/matcha_nightly_darwin_amd64.tar.gz" | |
| sha256 "$DARWIN_AMD64_SHA" | |
| else | |
| url "$BASE_URL/matcha_nightly_darwin_arm64.tar.gz" | |
| sha256 "$DARWIN_ARM64_SHA" | |
| end | |
| end | |
| on_linux do | |
| if Hardware::CPU.intel? | |
| url "$BASE_URL/matcha_nightly_linux_amd64.tar.gz" | |
| sha256 "$LINUX_AMD64_SHA" | |
| else | |
| url "$BASE_URL/matcha_nightly_linux_arm64.tar.gz" | |
| sha256 "$LINUX_ARM64_SHA" | |
| end | |
| end | |
| def install | |
| bin.install "matcha" | |
| end | |
| test do | |
| system "#{bin}/matcha", "--version" | |
| end | |
| end | |
| EOF | |
| # Clone the tap repo and push the nightly formula | |
| git clone "https://x-access-token:${GH_TOKEN}@github.com/floatpane/homebrew-matcha.git" /tmp/homebrew-matcha | |
| cp /tmp/matcha-nightly.rb /tmp/homebrew-matcha/matcha-nightly.rb | |
| cd /tmp/homebrew-matcha | |
| git config user.name "goreleaserbot" | |
| git config user.email "bot@goreleaser.com" | |
| git add matcha-nightly.rb | |
| git diff --cached --quiet || (git commit -m "Update matcha-nightly to $VERSION" && git push) | |
| snapcraft: | |
| runs-on: ${{ matrix.runner }} | |
| needs: nightly | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: amd64 | |
| runner: ubuntu-latest | |
| - arch: arm64 | |
| runner: ubuntu-24.04-arm | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Snapcraft and LXD | |
| run: | | |
| sudo snap install snapcraft --classic | |
| sudo snap install lxd | |
| sudo lxd init --auto | |
| sudo iptables -P FORWARD ACCEPT | |
| sudo usermod -aG lxd $USER | |
| - name: Build snap | |
| run: | | |
| touch .nightly | |
| sg lxd -c 'snapcraft pack --use-lxd --build-for=${{ matrix.arch }}' | |
| - name: Upload snap | |
| env: | |
| SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} | |
| run: snapcraft upload --release=beta *.snap |