# SPDX-License-Identifier: AGPL-3.0-or-later name: Tests on: pull_request: push: branches: - main permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: GHCR_REGISTRY: ghcr.io/${{ github.repository_owner }} CARGO_PROFILE_DEV_DEBUG: none CARGO_PROFILE_TEST_DEBUG: none CARGO_INCREMENTAL: '0' jobs: typecheck: runs-on: ubuntu-24.04 timeout-minutes: 25 env: FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" targets: wasm32-unknown-unknown - name: Restore ci helper id: ci-helper uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: target/debug/fluxer-ci key: >- fluxer-ci-bin-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }} - name: Build ci helper if: steps.ci-helper.outputs.cache-hit != 'true' run: cargo build --locked --package fluxer-ci - name: Save ci helper if: github.ref == 'refs/heads/main' && steps.ci-helper.outputs.cache-hit != 'true' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: target/debug/fluxer-ci key: >- fluxer-ci-bin-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }} - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Install dependencies run: | "$FLUXER_CI_BIN" ci --step install_dependencies - name: Run typecheck run: | "$FLUXER_CI_BIN" ci --step typecheck test: runs-on: ubuntu-24.04 timeout-minutes: 25 env: FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci PNPM_TEST_WORKSPACE_CONCURRENCY: '2' steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" targets: wasm32-unknown-unknown - name: Restore ci helper id: ci-helper uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: target/debug/fluxer-ci key: >- fluxer-ci-bin-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }} - name: Build ci helper if: steps.ci-helper.outputs.cache-hit != 'true' run: cargo build --locked --package fluxer-ci - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Install dependencies run: | "$FLUXER_CI_BIN" ci --step install_dependencies - name: Restore fluxer_app wasm artifacts id: app-wasm uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | fluxer_app/pkgs/libfluxcore fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts key: >- app-wasm-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs', 'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts', 'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock', 'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**', 'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml', 'packages/markdown_parser/rust/src/**') }} - name: Run tests run: | "$FLUXER_CI_BIN" ci --step test - name: Save fluxer_app wasm artifacts if: always() && github.ref == 'refs/heads/main' && steps.app-wasm.outputs.cache-hit != 'true' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | fluxer_app/pkgs/libfluxcore fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts key: >- app-wasm-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs', 'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts', 'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock', 'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**', 'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml', 'packages/markdown_parser/rust/src/**') }} rust: runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 45 steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" components: clippy, rustfmt - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Cache cargo uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | ~/.cargo/registry ~/.cargo/git target key: rust-${{ runner.os }}-${{ hashFiles('fluxer_media_proxy/tools/install-native-deps.sh') }}-${{ hashFiles('Cargo.lock') }} restore-keys: | rust-${{ runner.os }}-${{ hashFiles('fluxer_media_proxy/tools/install-native-deps.sh') }}- - name: Install cargo-deny run: cargo install cargo-deny --version 0.20.2 --locked - name: Check Rust dependencies run: cargo deny --locked check -D warnings - name: Check desktop native dependencies run: tools/ci/check-desktop-native-workspaces.sh dependencies - name: Cache native media dependencies uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: /opt/fluxer-native key: media-native-${{ runner.os }}-${{ hashFiles('fluxer_media_proxy/tools/install-native-deps.sh') }} - name: Install native dependencies run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ build-essential \ binutils \ clang \ cmake \ curl \ libaom-dev \ libavfilter-dev \ libclang-dev \ libcurl4-openssl-dev \ libdav1d-dev \ libde265-dev \ libfido2-dev \ libheif-dev \ liblcms2-dev \ libpipewire-0.3-dev \ libspa-0.2-dev \ libssl-dev \ libudev-dev \ libvips-dev \ libwebp-dev \ libyuv-dev \ meson \ nasm \ ninja-build \ pkg-config \ xz-utils \ yasm \ zlib1g-dev sudo fluxer_media_proxy/tools/install-native-deps.sh /opt/fluxer-native echo "PKG_CONFIG_PATH=/opt/fluxer-native/lib/pkgconfig:/opt/fluxer-native/lib64/pkgconfig" >> "$GITHUB_ENV" echo "LD_LIBRARY_PATH=/opt/fluxer-native/lib:/opt/fluxer-native/lib64" >> "$GITHUB_ENV" echo "/opt/fluxer-native/bin" >> "$GITHUB_PATH" - name: Install Node.js dependencies run: pnpm --filter fluxer_admin install - name: Check formatting run: cargo fmt --all -- --check - name: Check formatting (desktop native workspaces) run: tools/ci/check-desktop-native-workspaces.sh fmt - name: Clippy (warnings as errors) run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings - name: Clippy (desktop native workspaces on Linux, warnings as errors) run: tools/ci/check-desktop-native-workspaces.sh clippy - name: Verify the source-built ffmpeg CLI is on PATH run: | set -euo pipefail command -v ffmpeg test "$(command -v ffmpeg)" = /opt/fluxer-native/bin/ffmpeg ffmpeg -hide_banner -version - name: Run tests env: FLUXER_REQUIRE_MEDIA_FIXTURES: "1" run: cargo test --workspace --all-features --locked - name: Run desktop native workspace tests on Linux run: tools/ci/check-desktop-native-workspaces.sh test gateway: runs-on: ubuntu-24.04 timeout-minutes: 25 env: FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" - name: Cache cargo (gateway NIFs) uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with: workspaces: | fluxer_gateway/native/guild_member_list_oset_nif -> target fluxer_gateway/native/push_markdown_plaintext_nif -> target save-if: ${{ github.ref == 'refs/heads/main' }} - name: Restore ci helper id: ci-helper uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: target/debug/fluxer-ci key: >- fluxer-ci-bin-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }} - name: Build ci helper if: steps.ci-helper.outputs.cache-hit != 'true' run: cargo build --locked --package fluxer-ci - name: Set up Erlang uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124 with: otp-version: '28' rebar3-version: '3.27.0' - name: Restore rebar3 dependencies id: rebar3-cache uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | ~/.cache/rebar3 fluxer_gateway/_build !fluxer_gateway/_build/default/lib/fluxer_gateway/** !fluxer_gateway/_build/test/lib/fluxer_gateway/** key: >- rebar3-${{ runner.os }}-otp28-rebar3.27.0-${{ hashFiles('fluxer_gateway/rebar.lock', 'fluxer_gateway/rebar.config') }} restore-keys: | rebar3-${{ runner.os }}-otp28-rebar3.27.0- - name: Check formatting run: | "$FLUXER_CI_BIN" ci --step gateway_fmt - name: Compile run: | "$FLUXER_CI_BIN" ci --step gateway_compile - name: Run dialyzer run: | "$FLUXER_CI_BIN" ci --step gateway_dialyzer - name: Run eunit tests run: | "$FLUXER_CI_BIN" ci --step gateway_eunit - name: Save rebar3 dependencies if: always() && github.ref == 'refs/heads/main' && steps.rebar3-cache.outputs.cache-hit != 'true' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | ~/.cache/rebar3 fluxer_gateway/_build !fluxer_gateway/_build/default/lib/fluxer_gateway/** !fluxer_gateway/_build/test/lib/fluxer_gateway/** key: >- rebar3-${{ runner.os }}-otp28-rebar3.27.0-${{ hashFiles('fluxer_gateway/rebar.lock', 'fluxer_gateway/rebar.config') }} knip: runs-on: ubuntu-24.04 timeout-minutes: 25 env: FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" targets: wasm32-unknown-unknown - name: Restore ci helper id: ci-helper uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: target/debug/fluxer-ci key: >- fluxer-ci-bin-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }} - name: Build ci helper if: steps.ci-helper.outputs.cache-hit != 'true' run: cargo build --locked --package fluxer-ci - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Install dependencies run: | "$FLUXER_CI_BIN" ci --step install_dependencies - name: Restore fluxer_app wasm artifacts id: app-wasm uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | fluxer_app/pkgs/libfluxcore fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts key: >- app-wasm-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs', 'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts', 'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock', 'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**', 'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml', 'packages/markdown_parser/rust/src/**') }} - name: Run knip run: | "$FLUXER_CI_BIN" ci --step knip - name: Save fluxer_app wasm artifacts if: always() && github.ref == 'refs/heads/main' && steps.app-wasm.outputs.cache-hit != 'true' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | fluxer_app/pkgs/libfluxcore fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts key: >- app-wasm-${{ runner.os }}-1.98.1-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs', 'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts', 'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock', 'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**', 'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml', 'packages/markdown_parser/rust/src/**') }} lint: runs-on: ubuntu-24.04 timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Check formatting and lint run: pnpm exec biome ci . - name: Lint JSX for browser-translation safety run: pnpm exec eslint . --max-warnings 0 i18n: runs-on: ubuntu-24.04 timeout-minutes: 25 steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Compile locale catalogs run: pnpm i18n:compile - name: Check drift of compiled locale modules run: | if ! git diff --exit-code -- \ packages/errors/src/i18n/locales \ packages/errors/src/i18n/ErrorI18nTypes.generated.ts \ fluxer_api/pkgs/email/src/email_i18n/locales \ fluxer_api/pkgs/email/src/email_i18n/EmailI18nTypes.generated.ts \ fluxer_api/src/api/content_i18n/locales; then echo "::error::Compiled locale modules are outdated. Run 'pnpm i18n:compile' and commit the result. Translations belong in the weblate/ catalogs, not in the generated locales/ modules." exit 1 fi docs: runs-on: ubuntu-24.04 timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install pnpm uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: '26' cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile --filter fluxer_docs... - name: Verify documentation matches the live API run: pnpm --filter fluxer_docs verify - name: Build documentation run: pnpm --filter fluxer_docs build fonts: runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 with: python-version: "3.14" - name: Install font tooling run: python3 -m pip install -r tools/fonts/requirements.txt - name: Verify shipped fonts match the lockfile run: python3 tools/fonts/build_fonts.py --verify