Files

279 lines
7.1 KiB
YAML

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 <<EOF
{
"tag_name": "$TAG",
"name": "$TAG",
"body": "initial release\nriptide: static linux musl binary (x86_64).\n$LINUX_SHA riptide",
"draft": false,
"prerelease": false
}
EOF
curl -fsSL \
-X POST \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
"https://codeberg.org/api/v1/repos/$REPO/releases" \
--data-binary @release.json
- name: Get release ID
id: release
env:
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
REPO: ${{ github.repository }}
TAG: ${{ github.ref_name }}
run: |
RELEASE_ID="$(
curl -fsSL \
-H "Authorization: token $FORGEJO_TOKEN" \
"https://codeberg.org/api/v1/repos/$REPO/releases/tags/$TAG" |
jq -r '.id'
)"
test "$RELEASE_ID" != "null"
echo "id=$RELEASE_ID" >> "$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"