# Forgejo Actions build + release for fold (port of .github/workflows/build.yml). # # Requires act_runner(s) registered on git.trevon.dev with label # `ubuntu-latest` (Linux). The macOS job is gated behind a manual # workflow_dispatch input because it needs a runner labelled `macos-latest` # (register one on a Mac, then run this workflow with "Build macOS packages" # checked — or change the gate to always-on). # # - push / PR: build (Meson+Conan, clang-19), test, coverage floor, smoke, # upload artifacts (Linux) # - workflow_dispatch + build_macos=true: macOS build (llvm@22) # - tag v*: build Linux (and macOS if enabled), create a Forgejo release, # attach tarballs # # Release tarball naming: fold---.tar.gz # os: linux | macos # arch: x86_64 | aarch64 name: build on: push: branches: [main, master] tags: ["v*"] pull_request: workflow_dispatch: inputs: build_macos: description: Build macOS packages (requires macos-latest runner) type: boolean default: false permissions: contents: read concurrency: group: build-${{ github.ref }} cancel-in-progress: true jobs: build-linux: runs-on: ubuntu-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - name: Install system deps (linux) run: | sudo apt-get update sudo apt-get install -y \ clang-19 \ llvm-19-dev \ libclang-19-dev \ libclang-cpp19-dev \ libz3-dev libsqlite3-dev \ meson ninja-build pkg-config cmake build-essential \ nlohmann-json3-dev \ libcli11-dev libspdlog-dev libfmt-dev { echo "CC=clang-19" echo "CXX=clang++-19" echo "LLVM_CONFIG=llvm-config-19" } >> "$GITHUB_ENV" - name: Set up Python (for Conan) uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.12" - name: Install Conan run: | python -m pip install --upgrade pip python -m pip install 'conan>=2,<3' conan profile detect --force - name: Install Rust frontend toolchains run: | set -euxo pipefail if ! command -v rustup >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain none # shellcheck disable=SC1091 . "$HOME/.cargo/env" fi rustup toolchain install nightly-2026-05-28 \ --component rustc-dev --component rustfmt --component llvm-tools-preview # A newer target nightly exercises Cargo/analyzer skew when available. # The validation artifact records an explicit skip if it is not newer. rustup toolchain install nightly-2026-07-28 rustup run nightly-2026-05-28 rustc -Vv rustup run nightly-2026-07-28 rustc -Vv echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Configure and compile through setup.sh run: ./setup.sh release - name: Test run: meson test -C build/release --print-errorlogs - name: Set up uv for coverage uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - name: Enforce reviewed coverage floor env: COVERAGE_MIN_LINE: "70" run: ./scripts/coverage.sh - name: Smoke run: | ./build/release/src/cli/fold --version ./build/release/src/cli/fold scan \ tests/fixtures/clones \ --std c++20 \ --detectors clone \ --format markdown --output fold-smoke.md \ --processes 1 head -30 fold-smoke.md - name: Generate quality report run: | ./build/release/src/cli/fold quality \ --skip-format --skip-tests --skip-policy --skip-diff-scan \ --out-dir quality-report - name: Package release tarball run: | set -euo pipefail VERSION="${GITHUB_REF_NAME#v}" [ -n "$VERSION" ] || VERSION="$(git describe --tags --always 2>/dev/null || echo dev)" case "$RUNNER_OS" in Linux) OS=linux ;; macOS) OS=macos ;; esac case "$(uname -m)" in x86_64) ARCH=x86_64 ;; arm64) ARCH=aarch64 ;; esac NAME="fold-${VERSION}-${OS}-${ARCH}" mkdir -p "dist/${NAME}" cp build/release/src/cli/fold "dist/${NAME}/fold" cp README.md "dist/${NAME}/" 2>/dev/null || true cp LICENSE "dist/${NAME}/" 2>/dev/null || true (cd dist && tar czf "${NAME}.tar.gz" "${NAME}") (cd dist && shasum -a 256 "${NAME}.tar.gz" > "SHA256SUMS-${NAME}.txt") ls -la dist/ - name: Upload smoke report if: always() uses: https://code.forgejo.org/forgejo/upload-artifact@16871d9e8cfcf27ff31822cac382bbb5450f1e1e # v4 with: name: smoke-${{ runner.os }} path: fold-smoke.md if-no-files-found: ignore - name: Upload quality report if: always() uses: https://code.forgejo.org/forgejo/upload-artifact@16871d9e8cfcf27ff31822cac382bbb5450f1e1e # v4 with: name: quality-${{ runner.os }} path: quality-report/ if-no-files-found: ignore - name: Upload Rust toolchain evidence if: always() uses: https://code.forgejo.org/forgejo/upload-artifact@16871d9e8cfcf27ff31822cac382bbb5450f1e1e # v4 with: name: rust-toolchain-${{ runner.os }} path: build/release/meson-logs/rust-toolchain-skew.json if-no-files-found: ignore - name: Upload package uses: https://code.forgejo.org/forgejo/upload-artifact@16871d9e8cfcf27ff31822cac382bbb5450f1e1e # v4 with: name: fold-${{ runner.os }}-${{ runner.arch }} path: dist/ if-no-files-found: error build-macos: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.build_macos == 'true' }} runs-on: macos-latest steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - name: Install system deps (macos) run: | brew update brew install llvm@22 z3 meson ninja pkg-config nlohmann-json cli11 spdlog echo "LLVM_CONFIG=$(brew --prefix llvm@22)/bin/llvm-config" >> "$GITHUB_ENV" echo "PKG_CONFIG_PATH=$(brew --prefix z3)/lib/pkgconfig:$(brew --prefix)/lib/pkgconfig" >> "$GITHUB_ENV" - name: Set up Python (for Conan) uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.12" - name: Install Conan run: | python -m pip install --upgrade pip python -m pip install 'conan>=2,<3' conan profile detect --force - name: Install Rust frontend toolchains run: | set -euxo pipefail if ! command -v rustup >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain none # shellcheck disable=SC1091 . "$HOME/.cargo/env" fi rustup toolchain install nightly-2026-05-28 \ --component rustc-dev --component rustfmt --component llvm-tools-preview rustup toolchain install nightly-2026-07-28 echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Configure and compile through setup.sh run: ./setup.sh release - name: Test run: meson test -C build/release --print-errorlogs - name: Smoke run: | ./build/release/src/cli/fold --version ./build/release/src/cli/fold scan \ tests/fixtures/clones \ --std c++20 \ --detectors clone \ --format markdown --output fold-smoke.md \ --processes 1 head -30 fold-smoke.md - name: Package release tarball run: | set -euo pipefail VERSION="${GITHUB_REF_NAME#v}" [ -n "$VERSION" ] || VERSION="$(git describe --tags --always 2>/dev/null || echo dev)" case "$RUNNER_OS" in Linux) OS=linux ;; macOS) OS=macos ;; esac case "$(uname -m)" in x86_64) ARCH=x86_64 ;; arm64) ARCH=aarch64 ;; esac NAME="fold-${VERSION}-${OS}-${ARCH}" mkdir -p "dist/${NAME}" cp build/release/src/cli/fold "dist/${NAME}/fold" cp README.md "dist/${NAME}/" 2>/dev/null || true cp LICENSE "dist/${NAME}/" 2>/dev/null || true (cd dist && tar czf "${NAME}.tar.gz" "${NAME}") (cd dist && shasum -a 256 "${NAME}.tar.gz" > "SHA256SUMS-${NAME}.txt") ls -la dist/ - uses: https://code.forgejo.org/forgejo/upload-artifact@16871d9e8cfcf27ff31822cac382bbb5450f1e1e # v4 with: name: fold-${{ runner.os }}-${{ runner.arch }} path: dist/ if-no-files-found: error release: if: startsWith(github.ref, 'refs/tags/') needs: [build-linux, build-macos] runs-on: ubuntu-latest permissions: contents: write steps: - uses: https://code.forgejo.org/forgejo/download-artifact@d8d0a99033603453ad2255e58720b460a0555e1e # v4 with: path: dist merge-multiple: true - name: Create Forgejo release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail TAG="${GITHUB_REF_NAME}" curl -fsS -X POST "https://git.trevon.dev/api/v1/repos/${GITHUB_REPOSITORY}/releases" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\",\"draft\":false,\"prerelease\":false}" \ > /tmp/release.json || { curl -fsS "https://git.trevon.dev/api/v1/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \ -H "Authorization: token ${GITHUB_TOKEN}" > /tmp/release.json } RELEASE_ID="$(python3 -c "import json;print(json.load(open('/tmp/release.json'))['id'])")" echo "release id: ${RELEASE_ID}" for f in dist/*.tar.gz; do [ -f "$f" ] || continue echo "uploading $(basename "$f")" curl -fsS -X POST "https://git.trevon.dev/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=$(basename "$f")" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary "@$f" done for f in dist/SHA256SUMS-*.txt; do [ -f "$f" ] || continue curl -fsS -X POST "https://git.trevon.dev/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=$(basename "$f")" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: text/plain" \ --data-binary "@$f" done echo "release ${TAG} ready"