diff --git a/.forgejo/workflows/pgo-binary.txt b/.forgejo/workflows/pgo-binary.txt new file mode 100644 index 0000000..f88a4db --- /dev/null +++ b/.forgejo/workflows/pgo-binary.txt @@ -0,0 +1,318 @@ +name: Build and Release + +on: + push: + tags: + - "v*" + +permissions: + contents: write + +env: + LINUX_TARGET: x86_64-unknown-linux-musl + WINDOWS_TARGET: x86_64-pc-windows-gnu + PGO_SITEMAP: https://riptide-pgo.blitzw.in/sitemap.xml + +jobs: + build-linux: + name: Build Linux musl binary with PGO + runs-on: self-hosted + + container: + image: rust:alpine + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + apk add --no-cache \ + build-base \ + musl-dev \ + curl \ + file \ + binutils \ + coreutils + + - name: Install Rust targets and LLVM tools + run: | + rustup target add "$LINUX_TARGET" + rustup component add llvm-tools-preview + + - name: Locate LLVM tools + id: llvm + shell: sh + run: | + SYSROOT="$(rustc --print sysroot)" + HOST="$(rustc -vV | sed -n 's/^host: //p')" + LLVM_BIN="$SYSROOT/lib/rustlib/$HOST/bin" + + test -x "$LLVM_BIN/llvm-profdata" + + echo "LLVM_BIN=$LLVM_BIN" >> "$GITHUB_OUTPUT" + + - name: Build instrumented binary + shell: sh + run: | + rm -rf /tmp/riptide-pgo + mkdir -p /tmp/riptide-pgo + + RUSTFLAGS="\ + -C target-feature=+crt-static \ + -C profile-generate=/tmp/riptide-pgo \ + " cargo build \ + --release \ + --target "$LINUX_TARGET" + + cp \ + "target/$LINUX_TARGET/release/riptide" \ + /tmp/riptide-pgo/riptide + + chmod +x /tmp/riptide-pgo/riptide + + file /tmp/riptide-pgo/riptide + + - name: Train PGO profile + shell: sh + env: + LLVM_PROFILE_FILE: /tmp/riptide-pgo/%m-%p.profraw + run: | + timeout 10m \ + /tmp/riptide-pgo/riptide \ + --sitemap "$PGO_SITEMAP" \ + --output /tmp/pgo-urls.txt \ + --scheme https \ + --workers 16 \ + --timeout-secs 30 + + test -s /tmp/pgo-urls.txt + + echo "Training input produced:" + wc -l /tmp/pgo-urls.txt + + echo "Generated profiles:" + find /tmp/riptide-pgo -name '*.profraw' -type f -print + + - name: Merge PGO profiles + shell: sh + run: | + "${{ steps.llvm.outputs.LLVM_BIN }}/llvm-profdata" merge \ + -o /tmp/riptide-pgo.profdata \ + /tmp/riptide-pgo/*.profraw + + test -s /tmp/riptide-pgo.profdata + + - name: Build optimized Linux binary + shell: sh + run: | + RUSTFLAGS="\ + -C target-feature=+crt-static \ + -C profile-use=/tmp/riptide-pgo.profdata \ + " cargo build \ + --release \ + --target "$LINUX_TARGET" + + mkdir -p dist + + cp \ + "target/$LINUX_TARGET/release/riptide" \ + dist/riptide + + chmod +x dist/riptide + + - name: Verify Linux binary + shell: sh + run: | + file dist/riptide + + if readelf -l dist/riptide | grep -q 'INTERP'; then + echo "ERROR: riptide has a dynamic ELF interpreter" + exit 1 + fi + + echo "Static musl binary verified." + + - name: Smoke test + run: | + ./dist/riptide --help + + - name: Upload Linux binary + uses: actions/upload-artifact@v4 + with: + name: riptide-linux + path: dist/riptide + + build-windows: + name: Build Windows binary + runs-on: self-hosted + + container: + image: rust:alpine + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Windows cross-compiler + run: | + apk add --no-cache \ + mingw-w64-gcc \ + build-base \ + file + + - name: Install Rust target + run: | + rustup target add "$WINDOWS_TARGET" + + - name: Build Windows binary + shell: sh + run: | + cargo build \ + --release \ + --target "$WINDOWS_TARGET" + + mkdir -p dist + + cp \ + "target/$WINDOWS_TARGET/release/riptide.exe" \ + dist/riptide.exe + + - name: Verify Windows binary + shell: sh + run: | + file dist/riptide.exe + + - name: Smoke test + shell: sh + run: | + test -s dist/riptide.exe + + - name: Upload Windows binary + uses: actions/upload-artifact@v4 + with: + name: riptide-windows + path: dist/riptide.exe + + release: + name: Create Forgejo release + runs-on: self-hosted + needs: + - build-linux + - build-windows + + container: + image: alpine:latest + + steps: + - name: Install release tools + run: | + apk add --no-cache \ + curl \ + jq \ + coreutils + + - name: Download Linux artifact + uses: actions/download-artifact@v4 + with: + name: riptide-linux + path: release + + - name: Download Windows artifact + uses: actions/download-artifact@v4 + with: + name: riptide-windows + path: release + + - name: Make binaries executable + run: | + chmod 755 release/riptide + chmod 644 release/riptide.exe + + - name: Calculate checksums + id: checksum + shell: sh + run: | + LINUX_SHA="$(sha256sum release/riptide | awk '{print $1}')" + WINDOWS_SHA="$(sha256sum release/riptide.exe | awk '{print $1}')" + + printf '%s\n' "$LINUX_SHA" + printf '%s\n' "$WINDOWS_SHA" + + { + echo "LINUX_SHA=$LINUX_SHA" + echo "WINDOWS_SHA=$WINDOWS_SHA" + } >> "$GITHUB_OUTPUT" + + - name: Create release + shell: sh + env: + FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} + REPO: ${{ github.repository }} + TAG: ${{ github.ref_name }} + LINUX_SHA: ${{ steps.checksum.outputs.LINUX_SHA }} + WINDOWS_SHA: ${{ steps.checksum.outputs.WINDOWS_SHA }} + run: | + cat > release.json <