name: Docs on: push: branches: - main pull_request: branches: - main schedule: - cron: "0 2 * * *" jobs: build: name: Build website artifacts runs-on: ubuntu-latest steps: - name: Checkout uutils.github.io Repository uses: actions/checkout@v6 with: repository: uutils/uutils.github.io path: './uutils.github.io' fetch-depth: 0 - name: Checkout Coreutils Repository uses: actions/checkout@v6 with: repository: uutils/coreutils path: './coreutils' fetch-depth: 0 - name: Checkout Coreutils L10n Repository uses: actions/checkout@v6 with: repository: uutils/coreutils-l10n path: './coreutils-l10n' fetch-depth: 0 - name: Checkout Findutils Repository uses: actions/checkout@v6 with: repository: uutils/findutils path: './findutils' fetch-depth: 0 - name: Checkout Grep Repository uses: actions/checkout@v6 with: repository: uutils/grep path: './grep' fetch-depth: 0 - name: Install `rust` toolchain uses: dtolnay/rust-toolchain@stable with: targets: wasm32-wasip1 - name: Install system deps run: | sudo apt update sudo apt install libacl1-dev libselinux1-dev libsystemd-dev pip install babel - name: Install necessary tools (mdbook and mdbook-toc) uses: taiki-e/install-action@v2 with: tool: mdbook@0.5.0,mdbook-toc@0.15.3 - name: Copy l10n locales into coreutils run: | # Only copy locales into utilities that already exist in coreutils # Exclude en-US.ftl to preserve the coreutils English originals for util_dir in coreutils-l10n/src/uu/*/; do util=$(basename "$util_dir") if [ -d "coreutils/src/uu/$util/locales" ]; then for ftl in "$util_dir"/locales/*.ftl; do [ -f "$ftl" ] || continue [ "$(basename "$ftl")" = "en-US.ftl" ] && continue cp "$ftl" "coreutils/src/uu/$util/locales/" done fi done # Copy uucore l10n files, excluding en-US.ftl if [ -d "coreutils-l10n/src/uucore/locales" ]; then for ftl in coreutils-l10n/src/uucore/locales/*.ftl; do [ -f "$ftl" ] || continue [ "$(basename "$ftl")" = "en-US.ftl" ] && continue cp "$ftl" "coreutils/src/uucore/locales/" done fi - name: Patch mdbook theme with language selector run: | uutils.github.io/scripts/patch-mdbook-theme.sh coreutils/docs coreutils-l10n - name: Build Coreutils Docs run: | cd coreutils # Download and repack tldr zip: uudoc expects pages/common/ prefix curl -sfL https://github.com/tldr-pages/tldr/releases/download/v2.3/tldr-pages.zip -o /tmp/tldr-raw.zip || true if [ -f /tmp/tldr-raw.zip ]; then mkdir -p /tmp/tldr-repack/pages cd /tmp/tldr-repack && unzip -o /tmp/tldr-raw.zip -d pages/ > /dev/null zip -r "$OLDPWD/docs/tldr.zip" pages/ > /dev/null cd "$OLDPWD" fi cargo run --bin uudoc --all-features cd docs # Remove deprecated 'multilingual' field unsupported by newer mdbook sed -i '/^multilingual/d' book.toml # Strip the legacy FA4 `fa` class from uudoc-generated platform icons # so mdbook 0.5's Font Awesome parser picks up the `fa-brands` family # instead of defaulting to `regular` and warning about linux/windows/apple. find src/utils -name '*.md' -exec sed -i 's|class="fa fa-brands |class="fa-brands |g' {} + mdbook build - name: Build Coreutils Docs (translations) run: | uutils.github.io/scripts/build-docs-l10n.sh coreutils - name: Build Findutils Docs run: | cd findutils/docs # Remove deprecated 'multilingual' field unsupported by newer mdbook sed -i '/^multilingual/d' book.toml mdbook build - name: Build uutils WASM binary run: | cd coreutils # Build the multicall binary for WASI target # Use --no-default-features to avoid platform-specific dependencies cargo build --release --target wasm32-wasip1 -p coreutils --no-default-features --features feat_wasm if [ -f target/wasm32-wasip1/release/coreutils.wasm ]; then mkdir -p ../uutils.github.io/static/wasm cp target/wasm32-wasip1/release/coreutils.wasm ../uutils.github.io/static/wasm/uutils.wasm # Optimize WASM size if wasm-opt is available if command -v wasm-opt &> /dev/null; then wasm-opt -Oz ../uutils.github.io/static/wasm/uutils.wasm -o ../uutils.github.io/static/wasm/uutils.wasm fi echo "WASM binary size: $(du -h ../uutils.github.io/static/wasm/uutils.wasm | cut -f1)" # Generate the list of available locales from .ftl files locales=$(find src/uu/*/locales src/uucore/locales -name '*.ftl' 2>/dev/null \ | sed 's|.*/||; s|\.ftl$||' | sort -u | paste -sd, -) echo "const WASM_LOCALES = [$(echo "$locales" | sed 's/[^,]*/\"&\"/g')];" \ > ../uutils.github.io/static/wasm/locales.js echo "Available locales: $locales" # Generate the list of available commands from the feat_wasm feature # in Cargo.toml so the playground stays in sync with the WASM build. # HIDDEN_CMDS: utilities that ship in the binary but we don't want to # advertise in the playground (e.g. `yes` produces infinite output # that just spams the terminal). HIDDEN_CMDS='^(false|true|yes)$' commands=$(sed -n '/^feat_wasm = \[/,/^\]/p' Cargo.toml \ | grep -oE '"[a-zA-Z0-9_]+"' | tr -d '"' \ | sort -u | grep -vE "$HIDDEN_CMDS" | paste -sd, -) echo "const WASM_COMMANDS = [$(echo "$commands" | sed 's/[^,]*/\"&\"/g')];" \ > ../uutils.github.io/static/wasm/commands.js echo "Available commands: $commands" # Record the coreutils commit used to build the WASM binary commit_hash=$(git rev-parse HEAD) commit_short=$(git rev-parse --short HEAD) commit_date=$(git show -s --format=%cI HEAD) # Record the uutils.github.io commit the site was built from site_hash=$(git -C ../uutils.github.io rev-parse HEAD) site_short=$(git -C ../uutils.github.io rev-parse --short HEAD) site_date=$(git -C ../uutils.github.io show -s --format=%cI HEAD) { echo "const UUTILS_WASM_VERSION = {" echo " commit: \"${commit_hash}\"," echo " short: \"${commit_short}\"," echo " date: \"${commit_date}\"" echo "};" echo "const SITE_VERSION = {" echo " commit: \"${site_hash}\"," echo " short: \"${site_short}\"," echo " date: \"${site_date}\"" echo "};" } > ../uutils.github.io/static/wasm/version.js echo "uutils WASM build: ${commit_short} (${commit_date})" echo "site build: ${site_short} (${site_date})" fi - name: Build grep WASM binary run: | # uutils grep is a standalone binary (not part of the coreutils # multicall) and depends on the Oniguruma C library (onig_sys), so the # WASM build needs a WASI sysroot to compile the bundled C sources. WASI_SDK_VERSION=25 WASI_SDK_DIR="wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux" curl -sL "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/${WASI_SDK_DIR}.tar.gz" | tar xz export WASI_SDK_PATH="$PWD/${WASI_SDK_DIR}" export CC_wasm32_wasip1="$WASI_SDK_PATH/bin/clang" export CFLAGS_wasm32_wasip1="--sysroot=$WASI_SDK_PATH/share/wasi-sysroot" cd grep cargo build --release --target wasm32-wasip1 --bin grep if [ -f target/wasm32-wasip1/release/grep.wasm ]; then mkdir -p ../uutils.github.io/static/wasm cp target/wasm32-wasip1/release/grep.wasm ../uutils.github.io/static/wasm/grep.wasm # Optimize WASM size if wasm-opt is available if command -v wasm-opt &> /dev/null; then wasm-opt -Oz ../uutils.github.io/static/wasm/grep.wasm -o ../uutils.github.io/static/wasm/grep.wasm fi echo "grep WASM binary size: $(du -h ../uutils.github.io/static/wasm/grep.wasm | cut -f1)" # Advertise grep in the playground's command list. grep ships as its # own WASM module, so it isn't picked up by the coreutils feat_wasm # scan above; append it to the generated list here. commands_js=../uutils.github.io/static/wasm/commands.js if [ -f "$commands_js" ]; then existing=$(sed -n 's/^const WASM_COMMANDS = \[\(.*\)\];$/\1/p' "$commands_js") echo "const WASM_COMMANDS = [${existing}, \"grep\"];" > "$commands_js" else echo 'const WASM_COMMANDS = ["grep"];' > "$commands_js" fi # Record the grep commit used to build its WASM module so the # playground can show it alongside the coreutils build. grep_hash=$(git rev-parse HEAD) grep_short=$(git rev-parse --short HEAD) grep_date=$(git show -s --format=%cI HEAD) { echo "const UUTILS_GREP_VERSION = {" echo " commit: \"${grep_hash}\"," echo " short: \"${grep_short}\"," echo " date: \"${grep_date}\"" echo "};" } >> ../uutils.github.io/static/wasm/version.js echo "grep WASM build: ${grep_short} (${grep_date})" fi - name: Run Zola uses: shalzz/zola-deploy-action@v0.22.1 env: BUILD_DIR: uutils.github.io BUILD_ONLY: true - name: Collect results into `public` folder run: | cp -r uutils.github.io/public public cp -r coreutils/docs/book public/coreutils/docs cp -r findutils/docs/book public/findutils/docs # Copy translated docs to /coreutils/docs-{lang}/ for lang_dir in coreutils/docs/book-*/; do [ -d "$lang_dir" ] || continue lang=$(basename "$lang_dir" | sed 's/^book-//') cp -r "$lang_dir" "public/coreutils/docs-${lang}" done - name: Run playground JS tests run: | npm install puppeteer@24 node uutils.github.io/scripts/run-tests.js --dir public --port 8080 - name: Remove test files from deploy output run: rm -f public/js/wasm-terminal.test.html - name: Upload artifact for checking the output uses: actions/upload-artifact@v7 with: path: ./public - name: Upload artifact for pages uses: actions/upload-pages-artifact@v5 with: path: ./public # dev-docs: # name: generate the dev doc # runs-on: ubuntu-latest # steps: # - name: Checkout repository # uses: actions/checkout@v4 # with: # repository: uutils/coreutils # path: './coreutils' # fetch-depth: 0 # - name: Install `rust` toolchain # uses: actions-rs/toolchain@v1 # with: # toolchain: stable # default: true # profile: minimal # - name: Build dev documentation # run: | # cd coreutils # cargo doc --no-deps --all-features --workspace # - name: Deploy Docs # uses: peaceiris/actions-gh-pages@v3 # with: # github_token: ${{ secrets.GITHUB_TOKEN }} # publish_dir: ./coreutils/target/doc # destination_dir: coreutils/dev/ # build-report: # name: generate the build report # runs-on: ubuntu-latest # steps: # - name: Checkout repository # uses: actions/checkout@v4 # with: # repository: uutils/coreutils # path: './coreutils' # fetch-depth: 0 # - name: Install `rust` toolchain # uses: actions-rs/toolchain@v1 # with: # toolchain: nightly # default: true # profile: minimal # - name: Build report # run: | # cd coreutils # cargo +nightly build --timings=html -Zunstable-options # - name: Deploy build report # uses: peaceiris/actions-gh-pages@v3 # with: # github_token: ${{ secrets.GITHUB_TOKEN }} # publish_dir: ./coreutils/target/cargo-timings/ # destination_dir: cargo-timings/ # Deployment job deploy: permissions: contents: read pages: write id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'schedule' steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v5