name: Build and Release on: push: tags: - "0.*" env: LINUX_TARGET: x86_64-unknown-linux-musl PGO_SITEMAP: https://riptide-pgo.blitzw.in/sitemaps/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" "$LLVM_BIN/llvm-profdata" --version rustc --version rustc -vV - name: Build instrumented binary shell: sh run: | set -eu rm -rf /tmp/riptide-pgo mkdir -p /tmp/riptide-pgo/profiles RUSTFLAGS=" -C target-feature=+crt-static -C profile-generate=/tmp/riptide-pgo/profiles " 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: Verify instrumented binary shell: sh run: | /tmp/riptide-pgo/riptide --help - name: Train PGO profile shell: sh env: LLVM_PROFILE_FILE: /tmp/riptide-pgo/profiles/%m-%p.profraw run: | set -eu SITEMAP_URL='https://riptide-pgo.blitzw.in/sitemaps/sitemap.xml' SITEMAP_URL_2='https://riptide-pgo.blitzw.in/sitemaps2/sitemap.xml' printf 'Training round 1 with sitemap: <%s>\n' "$SITEMAP_URL" timeout 10m \ /tmp/riptide-pgo/riptide \ --sitemap "$SITEMAP_URL" \ --output /tmp/pgo-urls.txt \ --scheme https \ --workers 16 \ --timeout-secs 30 test -s /tmp/pgo-urls.txt echo "Training round 1 input:" wc -l /tmp/pgo-urls.txt printf 'Training round 2 with sitemap: <%s>\n' "$SITEMAP_URL_2" timeout 10m \ /tmp/riptide-pgo/riptide \ --sitemap "$SITEMAP_URL_2" \ --output /tmp/pgo-urls-2.txt \ --scheme https \ --workers 16 \ --timeout-secs 30 test -s /tmp/pgo-urls-2.txt echo "Training round 2 input:" wc -l /tmp/pgo-urls-2.txt echo "Generated profiles:" find /tmp/riptide-pgo/profiles \ -name '*.profraw' \ -type f \ -print test -n "$( find /tmp/riptide-pgo/profiles \ -name '*.profraw' \ -type f \ -print -quit )" - name: Merge Round 1 of PGO profiles shell: sh run: | set -eu LLVM_PROFDATA="${{ steps.llvm.outputs.LLVM_BIN }}/llvm-profdata" "$LLVM_PROFDATA" merge \ -o /tmp/riptide-pgo.profdata \ /tmp/riptide-pgo/profiles/*.profraw test -s /tmp/riptide-pgo.profdata - name: Build finalized Linux binary shell: sh run: | set -eu 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 shell: sh 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 shell: sh run: | ./dist/riptide --help - name: Upload Linux binary uses: https://code.forgejo.org/forgejo/upload-artifact@v4 with: name: riptide-linux path: dist/riptide release: name: Create Forgejo release runs-on: self-hosted needs: - build-linux container: image: alpine:latest steps: - name: Install release tools run: | apk add --no-cache \ curl \ jq \ coreutils \ nodejs - name: Download Linux artifact uses: forgejo/download-artifact@v5 with: name: riptide-linux path: release - name: Calculate checksums id: checksum run: | LINUX_SHA="$(sha256sum release/riptide | awk '{print $1}')" echo "LINUX_SHA=$LINUX_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 }} 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"