|
| 1 | +name: build |
| 2 | + |
| 3 | +# Builds GhostFS (normal + cybersec binaries) and packages them into a |
| 4 | +# single .deb — "ghostfs" — which: |
| 5 | +# 1. installs the ghostfs / ghostfs-cybersec binaries + admin tooling + |
| 6 | +# initramfs early-boot hooks, and |
| 7 | +# 2. assumes Calamares is ALREADY installed on the target system, and |
| 8 | +# patches its configuration so the graphical installer offers ONLY |
| 9 | +# GhostFS as a root filesystem (no ext4/btrfs/xfs choice). |
| 10 | +# |
| 11 | +# This workflow does NOT install anything on the runner beyond build |
| 12 | +# dependencies — it produces a .deb artifact for you to install elsewhere |
| 13 | +# (`sudo apt install ./ghostfs_<version>_amd64.deb`, or `sudo dpkg -i` + |
| 14 | +# `sudo apt -f install` for dependency resolution). |
| 15 | + |
| 16 | +on: |
| 17 | + push: |
| 18 | + branches: [ main ] |
| 19 | + paths: |
| 20 | + - 'source-code/**' |
| 21 | + - 'Cargo.toml' |
| 22 | + - 'scripts/**' |
| 23 | + - 'calamares/**' |
| 24 | + - 'packaging/**' |
| 25 | + - '.github/workflows/build.yml' |
| 26 | + tags: |
| 27 | + - 'v*' |
| 28 | + pull_request: |
| 29 | + branches: [ main ] |
| 30 | + workflow_dispatch: {} |
| 31 | + |
| 32 | +env: |
| 33 | + CARGO_TERM_COLOR: always |
| 34 | + PKG_VERSION: 0.3.0 |
| 35 | + |
| 36 | +jobs: |
| 37 | + build-deb: |
| 38 | + runs-on: ubuntu-latest |
| 39 | + steps: |
| 40 | + - name: Checkout |
| 41 | + uses: actions/checkout@v4 |
| 42 | + |
| 43 | + - name: Install Rust toolchain |
| 44 | + uses: dtolnay/rust-action@stable |
| 45 | + continue-on-error: true |
| 46 | + |
| 47 | + - name: Install Rust toolchain (fallback, pinned) |
| 48 | + uses: actions-rs/toolchain@v1 |
| 49 | + with: |
| 50 | + toolchain: stable |
| 51 | + profile: minimal |
| 52 | + override: true |
| 53 | + |
| 54 | + - name: Cache cargo registry + build artifacts |
| 55 | + uses: actions/cache@v4 |
| 56 | + with: |
| 57 | + path: | |
| 58 | + ~/.cargo/registry |
| 59 | + ~/.cargo/git |
| 60 | + target |
| 61 | + key: ${{ runner.os }}-cargo-ghostfs-${{ hashFiles('**/Cargo.lock', '**/Cargo.toml') }} |
| 62 | + restore-keys: | |
| 63 | + ${{ runner.os }}-cargo-ghostfs- |
| 64 | +
|
| 65 | + - name: Install system build dependencies |
| 66 | + run: | |
| 67 | + sudo apt-get update |
| 68 | + sudo apt-get install -y --no-install-recommends \ |
| 69 | + build-essential pkg-config \ |
| 70 | + libfuse3-dev libfuse-dev \ |
| 71 | + libssl-dev \ |
| 72 | + protobuf-compiler \ |
| 73 | + dpkg-dev fakeroot \ |
| 74 | + python3 python3-yaml |
| 75 | +
|
| 76 | + - name: Show toolchain versions |
| 77 | + run: | |
| 78 | + rustc --version |
| 79 | + cargo --version |
| 80 | + dpkg-deb --version |
| 81 | +
|
| 82 | + # ── Build binaries ────────────────────────────────────────────────────── |
| 83 | + # Two separate binaries, per Makefile / build.hl convention: |
| 84 | + # normal — encryption optional (--encryption flag at mkfs time) |
| 85 | + # cybersec — encryption always on, MAC/IDS/forensics/canary active |
| 86 | + - name: cargo build (normal) |
| 87 | + working-directory: . |
| 88 | + run: | |
| 89 | + cargo build --release --no-default-features \ |
| 90 | + --features normal,zstd,lz4 |
| 91 | +
|
| 92 | + - name: Stash normal binary |
| 93 | + run: | |
| 94 | + mkdir -p dist |
| 95 | + cp target/release/ghostfs dist/ghostfs-normal |
| 96 | +
|
| 97 | + - name: cargo build (cybersec) |
| 98 | + run: | |
| 99 | + cargo build --release --no-default-features \ |
| 100 | + --features cybersec,zstd,lz4 |
| 101 | +
|
| 102 | + - name: Stash cybersec binary |
| 103 | + run: | |
| 104 | + cp target/release/ghostfs dist/ghostfs-cybersec |
| 105 | +
|
| 106 | + - name: cargo test (best-effort — repo currently has no test suite) |
| 107 | + run: cargo test --release --no-default-features --features cybersec,zstd,lz4 || \ |
| 108 | + echo "::warning::No tests ran (or tests failed) — see README 'testowanie' section. Not blocking the build." |
| 109 | + |
| 110 | + # ── Assemble the .deb payload tree ─────────────────────────────────────── |
| 111 | + - name: Assemble packaging tree |
| 112 | + run: | |
| 113 | + set -eux |
| 114 | + PKGROOT="$(mktemp -d)/ghostfs" |
| 115 | + mkdir -p "$PKGROOT" |
| 116 | + cp -r packaging/deb/. "$PKGROOT/" |
| 117 | +
|
| 118 | + # Binaries |
| 119 | + install -Dm755 dist/ghostfs-normal "$PKGROOT/usr/local/bin/ghostfs" |
| 120 | + install -Dm755 dist/ghostfs-cybersec "$PKGROOT/usr/local/bin/ghostfs-cybersec" |
| 121 | +
|
| 122 | + # Admin / mount helper scripts |
| 123 | + install -Dm755 scripts/ghostfs-admin.sh "$PKGROOT/usr/local/bin/ghostfs-admin.sh" |
| 124 | + install -Dm755 scripts/mount.ghostfs "$PKGROOT/sbin/mount.ghostfs" |
| 125 | +
|
| 126 | + # initramfs hooks |
| 127 | + install -Dm755 scripts/ghostfs-initramfs-hook "$PKGROOT/etc/initramfs-tools/hooks/ghostfs" |
| 128 | + install -Dm755 scripts/ghostfs-mount-initramfs "$PKGROOT/etc/initramfs-tools/scripts/local-top/ghostfs-mount" |
| 129 | +
|
| 130 | + # Calamares job modules |
| 131 | + mkdir -p "$PKGROOT/usr/lib/calamares/modules" |
| 132 | + cp -r calamares/modules/ghostfs-mkfs "$PKGROOT/usr/lib/calamares/modules/" |
| 133 | + cp -r calamares/modules/ghostfs-mount "$PKGROOT/usr/lib/calamares/modules/" |
| 134 | + cp -r calamares/modules/ghostfs-umount "$PKGROOT/usr/lib/calamares/modules/" |
| 135 | + chmod 755 "$PKGROOT"/usr/lib/calamares/modules/*/*.py |
| 136 | +
|
| 137 | + # Calamares config: static ghostfs-mkfs.conf installed directly; |
| 138 | + # settings.conf + partition.conf patch shipped as docs and applied |
| 139 | + # by postinst via calamares-patch.py (so we can revert on removal). |
| 140 | + install -Dm644 calamares/config/ghostfs-mkfs.conf \ |
| 141 | + "$PKGROOT/etc/calamares/modules/ghostfs-mkfs.conf" |
| 142 | + install -Dm644 calamares/config/settings.conf.ghostfs \ |
| 143 | + "$PKGROOT/usr/share/doc/ghostfs/settings.conf.ghostfs" |
| 144 | + install -Dm644 calamares/config/partition.conf.ghostfs-patch.yaml \ |
| 145 | + "$PKGROOT/usr/share/doc/ghostfs/partition.conf.ghostfs-patch.yaml" |
| 146 | +
|
| 147 | + # Docs |
| 148 | + install -Dm644 README.md "$PKGROOT/usr/share/doc/ghostfs/README.md" |
| 149 | + install -Dm644 LICENSE "$PKGROOT/usr/share/doc/ghostfs/copyright" |
| 150 | +
|
| 151 | + # Fill in Installed-Size (KB) — dpkg-deb doesn't require it but |
| 152 | + # apt/dpkg -l output is nicer with it present. |
| 153 | + SIZE_KB=$(du -sk "$PKGROOT" | cut -f1) |
| 154 | + sed -i "/^Description:/i Installed-Size: ${SIZE_KB}" "$PKGROOT/DEBIAN/control" |
| 155 | +
|
| 156 | + chmod 755 "$PKGROOT/DEBIAN/postinst" "$PKGROOT/DEBIAN/postrm" |
| 157 | + echo "PKGROOT=$PKGROOT" >> "$GITHUB_ENV" |
| 158 | +
|
| 159 | + - name: Determine package version |
| 160 | + run: | |
| 161 | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then |
| 162 | + VERSION="${GITHUB_REF#refs/tags/v}" |
| 163 | + else |
| 164 | + VERSION="${PKG_VERSION}+git$(date -u +%Y%m%d).${GITHUB_SHA::8}" |
| 165 | + fi |
| 166 | + sed -i "s/^Version: .*/Version: ${VERSION}/" "$PKGROOT/DEBIAN/control" |
| 167 | + echo "DEB_VERSION=${VERSION}" >> "$GITHUB_ENV" |
| 168 | +
|
| 169 | + - name: Lint control file |
| 170 | + run: | |
| 171 | + cat "$PKGROOT/DEBIAN/control" |
| 172 | + dpkg-deb --build --root-owner-group --nocheck "$PKGROOT" /tmp/lint-check.deb |
| 173 | + dpkg-deb --info /tmp/lint-check.deb |
| 174 | + rm -f /tmp/lint-check.deb |
| 175 | +
|
| 176 | + # ── Build the .deb ──────────────────────────────────────────────────────── |
| 177 | + - name: Build .deb |
| 178 | + run: | |
| 179 | + set -eux |
| 180 | + mkdir -p out |
| 181 | + DEB_FILE="out/ghostfs_${DEB_VERSION}_amd64.deb" |
| 182 | + fakeroot dpkg-deb --build --root-owner-group "$PKGROOT" "$DEB_FILE" |
| 183 | + dpkg-deb --info "$DEB_FILE" |
| 184 | + dpkg-deb --contents "$DEB_FILE" |
| 185 | +
|
| 186 | + - name: Verify package with lintian (non-blocking) |
| 187 | + run: | |
| 188 | + sudo apt-get install -y --no-install-recommends lintian || true |
| 189 | + lintian out/*.deb || echo "::warning::lintian reported issues (non-blocking)" |
| 190 | +
|
| 191 | + - name: Upload .deb artifact |
| 192 | + uses: actions/upload-artifact@v4 |
| 193 | + with: |
| 194 | + name: ghostfs-deb-${{ env.DEB_VERSION }} |
| 195 | + path: out/*.deb |
| 196 | + if-no-files-found: error |
| 197 | + |
| 198 | + - name: Create GitHub Release (tags only) |
| 199 | + if: startsWith(github.ref, 'refs/tags/v') |
| 200 | + uses: softprops/action-gh-release@v2 |
| 201 | + with: |
| 202 | + files: out/*.deb |
| 203 | + generate_release_notes: true |
| 204 | + |
| 205 | + install-smoke-test: |
| 206 | + needs: build-deb |
| 207 | + runs-on: ubuntu-latest |
| 208 | + # Sanity-checks that the .deb installs cleanly against a stub Calamares |
| 209 | + # package (real Calamares is heavy/GUI-oriented and not worth pulling |
| 210 | + # into CI just to check our postinst/postrm patch logic runs and |
| 211 | + # reverts without crashing). |
| 212 | + steps: |
| 213 | + - name: Checkout |
| 214 | + uses: actions/checkout@v4 |
| 215 | + |
| 216 | + - name: Download built .deb |
| 217 | + uses: actions/download-artifact@v4 |
| 218 | + with: |
| 219 | + pattern: ghostfs-deb-* |
| 220 | + path: out |
| 221 | + merge-multiple: true |
| 222 | + |
| 223 | + - name: Install build deps for stub package |
| 224 | + run: sudo apt-get update && sudo apt-get install -y dpkg-dev fakeroot python3-yaml |
| 225 | + |
| 226 | + - name: Build a stub 'calamares' package so Depends resolves |
| 227 | + run: | |
| 228 | + set -eux |
| 229 | + STUB="$(mktemp -d)/calamares-stub" |
| 230 | + mkdir -p "$STUB/DEBIAN" "$STUB/etc/calamares/modules" |
| 231 | + cat > "$STUB/DEBIAN/control" <<EOF |
| 232 | + Package: calamares |
| 233 | + Version: 3.2.0-stub |
| 234 | + Section: admin |
| 235 | + Priority: optional |
| 236 | + Architecture: amd64 |
| 237 | + Maintainer: CI Stub <ci@example.invalid> |
| 238 | + Description: Stub calamares package for CI smoke-testing ghostfs's postinst |
| 239 | + EOF |
| 240 | + cat > "$STUB/etc/calamares/settings.conf" <<'EOF' |
| 241 | + # stub original settings.conf |
| 242 | + modules-search: [ local ] |
| 243 | + sequence: |
| 244 | + - show: [ welcome, partition, summary ] |
| 245 | + - exec: [ partition, unpackfs, bootloader ] |
| 246 | + - show: [ finished ] |
| 247 | + EOF |
| 248 | + cat > "$STUB/etc/calamares/modules/partition.conf" <<'EOF' |
| 249 | + availableFileSystemTypes: [ ext4, btrfs, xfs ] |
| 250 | + defaultFileSystemType: ext4 |
| 251 | + EOF |
| 252 | + fakeroot dpkg-deb --build --root-owner-group "$STUB" /tmp/calamares-stub.deb |
| 253 | + sudo dpkg -i /tmp/calamares-stub.deb |
| 254 | +
|
| 255 | + - name: Install ghostfs .deb |
| 256 | + run: | |
| 257 | + sudo apt-get install -y ./out/*.deb || sudo dpkg -i ./out/*.deb |
| 258 | + sudo apt-get -f install -y || true |
| 259 | +
|
| 260 | + - name: Verify GhostFS-only patch was applied |
| 261 | + run: | |
| 262 | + echo "--- partition.conf after install ---" |
| 263 | + cat /etc/calamares/modules/partition.conf |
| 264 | + grep -q "^- ghostfs$" /etc/calamares/modules/partition.conf || \ |
| 265 | + grep -q "ghostfs" /etc/calamares/modules/partition.conf |
| 266 | + grep -q "defaultFileSystemType: ghostfs" /etc/calamares/modules/partition.conf |
| 267 | + test -f /etc/calamares/modules/partition.conf.ghostfs-orig |
| 268 | + test -f /etc/calamares/settings.conf.ghostfs-orig |
| 269 | + grep -q "ghostfs-mkfs" /etc/calamares/settings.conf |
| 270 | + echo "OK: Calamares now GhostFS-only" |
| 271 | +
|
| 272 | + - name: Verify mount.ghostfs and binaries were installed |
| 273 | + run: | |
| 274 | + test -x /sbin/mount.ghostfs |
| 275 | + test -x /usr/local/bin/ghostfs |
| 276 | + test -x /usr/local/bin/ghostfs-cybersec |
| 277 | + /usr/local/bin/ghostfs --help |
| 278 | +
|
| 279 | + - name: Remove ghostfs and verify Calamares config was restored |
| 280 | + run: | |
| 281 | + sudo apt-get remove -y ghostfs |
| 282 | + echo "--- partition.conf after removal ---" |
| 283 | + cat /etc/calamares/modules/partition.conf |
| 284 | + grep -q "ext4" /etc/calamares/modules/partition.conf |
| 285 | + ! test -f /etc/calamares/modules/partition.conf.ghostfs-orig |
| 286 | + echo "OK: original Calamares config restored on removal" |
0 commit comments