name: Build and Release on: push: tags: - "0.*" 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: Install node run: | apk add --no-cache \ nodejs - 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 target 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 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 - name: Train PGO profile 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:" wc -l /tmp/pgo-urls.txt echo "Generated profiles:" find /tmp/riptide-pgo -name '*.profraw' -type f -print - name: Merge PGO profiles 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 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 static binary run: | file dist/riptide if readelf -l dist/riptide | grep -q 'INTERP'; then echo "ERROR: binary has a dynamic ELF interpreter" exit 1 fi - 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: Install Windows cross compiler and node run: | apk add --no-cache \ mingw-w64-gcc \ build-base \ file \ nodejs - name: Checkout repository uses: actions/checkout@v4 - name: Install Rust target run: | rustup target add "$WINDOWS_TARGET" - name: Build Windows binary run: | cargo build \ --release \ --target "$WINDOWS_TARGET" mkdir -p dist cp \ "target/$WINDOWS_TARGET/release/riptide.exe" \ dist/riptide.exe - name: Verify Windows binary run: | file 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 \ nodejs - 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: Calculate checksums id: checksum run: | LINUX_SHA="$(sha256sum release/riptide | awk '{print $1}')" WINDOWS_SHA="$(sha256sum release/riptide.exe | awk '{print $1}')" echo "LINUX_SHA=$LINUX_SHA" >> "$GITHUB_OUTPUT" echo "WINDOWS_SHA=$WINDOWS_SHA" >> "$GITHUB_OUTPUT" - name: Create Forgejo release 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 <> "$GITHUB_OUTPUT" - name: Upload Linux binary env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} REPO: ${{ github.repository }} RELEASE_ID: ${{ steps.release.outputs.id }} run: | curl -fsSL \ -X POST \ -H "Authorization: token $FORGEJO_TOKEN" \ -H "Content-Type: application/octet-stream" \ --data-binary @release/riptide \ "https://codeberg.org/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=riptide" - name: Upload Windows binary env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} REPO: ${{ github.repository }} RELEASE_ID: ${{ steps.release.outputs.id }} run: | curl -fsSL \ -X POST \ -H "Authorization: token $FORGEJO_TOKEN" \ -H "Content-Type: application/octet-stream" \ --data-binary @release/riptide.exe \ "https://codeberg.org/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=riptide.exe"