Skip to content

CI

CI #3474

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
schedule:
- cron: "0 4 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
env:
CARGO_TERM_COLOR: always
NIGHTLY_TOOLCHAIN: nightly-2025-11-30
jobs:
local-validation:
name: ${{ matrix.label }}
if: ${{ github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' }}
runs-on: ubuntu-latest
permissions:
contents: read
statuses: read
strategy:
fail-fast: false
matrix:
include:
- label: fmt
context: local/fmt
- label: biome
context: local/biome
- label: i18n
context: local/i18n
- label: zizmor
context: local/zizmor
- label: clippy
context: local/lint
- label: test
context: local/test
- label: macos-app
context: local/macos-app
- label: ios-app
context: local/ios-app
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Verify local status context
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
REQUIRED_CONTEXT: ${{ matrix.context }}
run: python3 scripts/check-local-status.py
changelog-guard:
name: Changelog Guard
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
- name: Block manual CHANGELOG.md edits
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: bash ./scripts/check-changelog-guard.sh "$BASE_SHA" "$HEAD_SHA"
zizmor:
name: Workflow Security
if: ${{ github.event_name != 'pull_request' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- uses: zizmorcore/zizmor-action@135698455da5c3b3e55f73f4419e481ab68cdd95 # v0.4.1
with:
advanced-security: false
online-audits: false
biome:
name: Biome
if: ${{ github.event_name != 'pull_request' }}
needs: zizmor
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- uses: biomejs/setup-biome@29711cbb52afee00eb13aeb30636592f9edc0088 # v2.7.0
with:
version: "2.4.6"
- run: biome ci crates/web/ui/src/ crates/web/ui/e2e/
- run: ./scripts/i18n-check.sh
fmt:
name: Format
if: ${{ github.event_name != 'pull_request' }}
needs: zizmor
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Check Rust file size limit
run: ./scripts/check-file-size.sh
- name: Check website install script sync
run: ./scripts/check-website-install-sync.sh
- name: Check install script package names match release workflow
run: ./scripts/check-install-package-names.sh
- name: Check install docs avoid stale asset URLs
run: ./scripts/check-install-docs.sh
- uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: ${{ env.NIGHTLY_TOOLCHAIN }}
components: rustfmt
- run: cargo fmt --all -- --check
rust-ci:
name: Rust CI (clippy + test)
if: ${{ github.event_name != 'pull_request' }}
needs: [fmt, biome]
runs-on: [self-hosted, Linux, X64]
permissions:
contents: read
container:
image: nvidia/cuda:12.4.1-devel-ubuntu22.04
env:
LD_LIBRARY_PATH: /usr/local/cuda/compat:/usr/local/nvidia/lib:/usr/local/nvidia/lib64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Clean up corrupted cargo config
run: rm -f ~/.cargo/config.toml
- name: Install build dependencies
run: bash ./scripts/install-linux-build-deps.sh
- uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: ${{ env.NIGHTLY_TOOLCHAIN }}
components: clippy
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
package-manager-cache: false
- name: Install QMD CLI
run: |
npm install -g @tobilu/qmd
qmd --version
- name: Initialize git repo in llama-cpp source to satisfy cmake
run: |
cargo fetch --locked
LLAMA_SRC=$(find ~/.cargo/registry/src -name "llama-cpp-sys-2-*" -type d 2>/dev/null | head -1)
if [ -n "$LLAMA_SRC" ] && [ ! -d "$LLAMA_SRC/.git" ]; then
cd "$LLAMA_SRC"
git init
git config user.email "ci@example.com"
git config user.name "CI"
git add -A
git commit -m "init" --allow-empty
git tag v0.0.0
fi
- name: Build Tailwind CSS
run: |
./scripts/download-tailwindcss-cli.sh tailwindcss-linux-x64
cd crates/web/ui && TAILWINDCSS=../../../tailwindcss-linux-x64 ./build.sh
- run: cargo clippy -Z unstable-options --workspace --all-features --all-targets --timings -- -D warnings
- name: Upload cargo timing reports
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: cargo-timings-rust-ci-${{ github.run_id }}-${{ github.run_attempt }}
path: target/cargo-timings/
if-no-files-found: ignore
- uses: taiki-e/install-action@f176c07a0a40cbfdd08ee9aa8bf1655701d11e69 # v2.67.25
with:
tool: cargo-nextest
- run: cargo nextest run --all-features --profile ci
- name: Upload test results
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: test-results-${{ github.run_id }}-${{ github.run_attempt }}
path: target/nextest/ci/junit.xml
if-no-files-found: ignore
sandbox-runtime-e2e:
name: Sandbox Runtime E2E
if: ${{ github.event_name != 'pull_request' }}
needs: [fmt, biome]
runs-on: ubuntu-latest
permissions:
contents: read
env:
MOLTIS_SANDBOX_RUNTIME_E2E: "1"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install runtime dependencies
run: |
sudo apt-get update
sudo apt-get install -y podman uidmap slirp4netns fuse-overlayfs
- name: Verify runtimes
run: |
docker --version
docker info
podman --version
podman info
- uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: ${{ env.NIGHTLY_TOOLCHAIN }}
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
shared-key: sandbox-runtime-e2e-v1
cache-all-crates: true
- name: Exercise Docker and Podman OCI file transfers
run: cargo test -p moltis-tools runtime_oci_file_transfers -- --nocapture
coverage:
name: Code Coverage
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Free disk space
run: |
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/share/boost
sudo apt-get clean
df -h /
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential clang libclang-dev pkg-config
- uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: ${{ env.NIGHTLY_TOOLCHAIN }}
components: llvm-tools-preview
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
package-manager-cache: false
- name: Install QMD CLI
run: |
npm install -g @tobilu/qmd
qmd --version
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
shared-key: coverage-v1
cache-all-crates: true
- name: Initialize git repo in llama-cpp source to satisfy cmake
run: |
cargo fetch --locked
LLAMA_SRC=$(find ~/.cargo/registry/src -name "llama-cpp-sys-2-*" -type d 2>/dev/null | head -1)
if [ -n "$LLAMA_SRC" ] && [ ! -d "$LLAMA_SRC/.git" ]; then
cd "$LLAMA_SRC"
git init
git config user.email "ci@example.com"
git config user.name "CI"
git add -A
git commit -m "init" --allow-empty
git tag v0.0.0
fi
- uses: taiki-e/install-action@f176c07a0a40cbfdd08ee9aa8bf1655701d11e69 # v2.67.25
with:
tool: cargo-llvm-cov
- name: Build Tailwind CSS
run: |
./scripts/download-tailwindcss-cli.sh tailwindcss-linux-x64
cd crates/web/ui && TAILWINDCSS=../../../tailwindcss-linux-x64 ./build.sh
- name: Generate coverage
run: cargo llvm-cov --workspace --exclude moltis-tools --exclude moltis-swift-bridge --lcov --output-path lcov.info
- name: Upload to Codecov
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
with:
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
e2e:
name: E2E Tests
if: ${{ github.event_name != 'pull_request' }}
needs: [fmt, biome]
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: stable
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
package-manager-cache: false
- name: Install npm dependencies
working-directory: crates/web/ui
run: npm ci
- name: Build Tailwind CSS
run: |
./scripts/download-tailwindcss-cli.sh tailwindcss-linux-x64
cd crates/web/ui && TAILWINDCSS=../../../tailwindcss-linux-x64 ./build.sh
- name: Build moltis binary
run: cargo build --bin moltis
- name: Install Playwright browsers
working-directory: crates/web/ui
run: npx playwright install --with-deps chromium
- name: Run E2E tests
working-directory: crates/web/ui
env:
CI: "true"
run: npx playwright test
- name: Upload test results
if: ${{ !cancelled() }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: e2e-test-results-${{ github.run_id }}-${{ github.run_attempt }}
path: |
crates/web/ui/playwright-report/
crates/web/ui/test-results/
if-no-files-found: ignore
retention-days: 14
macos-app:
name: macOS App
if: ${{ github.event_name != 'pull_request' }}
needs: [fmt, biome]
runs-on: macos-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: stable
targets: aarch64-apple-darwin,wasm32-wasip2
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
shared-key: macos-app-v1
cache-all-crates: true
- name: Install Swift build dependencies
run: brew install xcodegen cbindgen swiftlint
- name: Build Tailwind CSS
run: |
./scripts/download-tailwindcss-cli.sh tailwindcss-macos-arm64
cd crates/web/ui && TAILWINDCSS=../../../tailwindcss-macos-arm64 ./build.sh
- name: Build Swift bridge and generate Xcode project
env:
MOLTIS_SWIFT_BRIDGE_TARGETS: aarch64-apple-darwin
MOLTIS_SWIFT_BRIDGE_SKIP_WASM_PRECOMPILE: "1"
run: |
./scripts/build-swift-bridge.sh
./scripts/generate-swift-project.sh
- name: Lint Swift
run: ./scripts/lint-swift.sh
- name: Build macOS app
run: |
xcodebuild \
-project apps/macos/Moltis.xcodeproj \
-scheme Moltis \
-configuration Release \
-destination "platform=macOS" \
-derivedDataPath apps/macos/.derivedData-ci \
ARCHS=arm64 \
ONLY_ACTIVE_ARCH=YES \
build
ios-app:
name: iOS App
if: ${{ github.event_name != 'pull_request' }}
needs: [fmt, biome]
runs-on: macos-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: stable
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
shared-key: ios-app-v1
cache-all-crates: true
- name: Install xcodegen
run: brew install xcodegen
- name: Export GraphQL schema and generate project
run: |
cargo run -p moltis-schema-export -- apps/ios/GraphQL/Schema/schema.graphqls
./scripts/generate-ios-graphql.sh
./scripts/generate-ios-project.sh
- name: Build iOS app
run: |
xcodebuild \
-project apps/ios/Moltis.xcodeproj \
-scheme Moltis \
-configuration Debug \
-destination "generic/platform=iOS" \
CODE_SIGNING_ALLOWED=NO \
build
rust-full-targets:
name: Rust Full Targets (scheduled)
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
continue-on-error: true
needs: [fmt, biome]
runs-on: [self-hosted, Linux, X64]
permissions:
contents: read
container:
image: nvidia/cuda:12.4.1-devel-ubuntu22.04
env:
LD_LIBRARY_PATH: /usr/local/cuda/compat:/usr/local/nvidia/lib:/usr/local/nvidia/lib64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Clean up corrupted cargo config
run: rm -f ~/.cargo/config.toml
- name: Install build dependencies
run: bash ./scripts/install-linux-build-deps.sh
- uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # master
with:
toolchain: ${{ env.NIGHTLY_TOOLCHAIN }}
components: clippy
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
package-manager-cache: false
- name: Install QMD CLI
run: |
npm install -g @tobilu/qmd
qmd --version
- name: Initialize git repo in llama-cpp source to satisfy cmake
run: |
cargo fetch --locked
LLAMA_SRC=$(find ~/.cargo/registry/src -name "llama-cpp-sys-2-*" -type d 2>/dev/null | head -1)
if [ -n "$LLAMA_SRC" ] && [ ! -d "$LLAMA_SRC/.git" ]; then
cd "$LLAMA_SRC"
git init
git config user.email "ci@example.com"
git config user.name "CI"
git add -A
git commit -m "init" --allow-empty
git tag v0.0.0
fi
- name: Build Tailwind CSS
run: |
./scripts/download-tailwindcss-cli.sh tailwindcss-linux-x64
cd crates/web/ui && TAILWINDCSS=../../../tailwindcss-linux-x64 ./build.sh
- run: cargo clippy -Z unstable-options --workspace --all-features --all-targets --timings -- -D warnings
- name: Upload cargo timing reports
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: cargo-timings-rust-full-targets-${{ github.run_id }}-${{ github.run_attempt }}
path: target/cargo-timings/
if-no-files-found: ignore