diff --git a/.github/workflows/launchpad_ppa.yml b/.github/workflows/launchpad_ppa.yml index 55d0884b..0e61fa88 100644 --- a/.github/workflows/launchpad_ppa.yml +++ b/.github/workflows/launchpad_ppa.yml @@ -8,9 +8,9 @@ on: description: 'Release tag to upload to PPA (e.g. v0.5.0). Empty = latest release' required: false distributions: - description: 'Target distributions (comma-separated: jammy,noble,oracular)' + description: 'Target distributions (comma-separated: jammy,noble,resolute)' required: false - default: 'jammy,noble' + default: 'jammy,noble,resolute' permissions: contents: read @@ -23,7 +23,7 @@ jobs: strategy: fail-fast: false matrix: - distro: [jammy, noble, oracular] + distro: [jammy, noble, resolute] steps: - name: Checkout code @@ -55,10 +55,17 @@ jobs: env: GH_TOKEN: ${{ github.token }} + - name: Check out release tag + if: steps.check_distro.outputs.should_run == 'true' + uses: actions/checkout@v4 + with: + ref: ${{ steps.get_tag.outputs.tag }} + fetch-depth: 0 + - name: Update debian/changelog from release if: steps.check_distro.outputs.should_run == 'true' run: | - sudo apt-get update && sudo apt-get install -y curl + sudo apt-get update && sudo apt-get install -y curl jq bash ./debian/update-changelog.sh \ -d ${{ matrix.distro }} \ -p lablup/backend-ai \ @@ -81,45 +88,28 @@ jobs: dpkg-dev \ build-essential - # ─────────────────────────────────────────────────────────────── - # NEW Step 5.5: Install Rust toolchain 1.75 (to produce lockfile v3) - # ─────────────────────────────────────────────────────────────── - - name: Install Rust 1.75 (for lockfile v3 & vendor) + - name: Install Rust 1.85 for vendoring if: steps.check_distro.outputs.should_run == 'true' - uses: dtolnay/rust-toolchain@1.75.0 + uses: dtolnay/rust-toolchain@1.85.1 - # ─────────────────────────────────────────────────────────────── - # NEW Step 5.6: Generate Cargo.lock (v3) with Cargo 1.75 - # ─────────────────────────────────────────────────────────────── - - name: Generate lockfile v3 (Cargo 1.75) + - name: Validate lockfile with Rust 1.85 if: steps.check_distro.outputs.should_run == 'true' run: | - # Ensure we create a lockfile compatible with jammy's cargo (v3) - rm -f Cargo.lock - cargo generate-lockfile - # Safety check: lockfile must be version = 3 (1.75 writes v3) + cargo --version + rustc --version + cargo metadata --format-version 1 --locked --no-deps > /dev/null awk '/^version = /{print; found=1} END{ if(!found) exit 1 }' Cargo.lock - if ! grep -q '^version = 3' Cargo.lock; then - echo "ERROR: Cargo.lock is not v3 (jammy-compatible)." - exit 1 - fi - # ─────────────────────────────────────────────────────────────── - # NEW Step 5.7: Vendor dependencies & write .cargo/config.toml - # ─────────────────────────────────────────────────────────────── - - name: Vendor Rust dependencies (offline build on Launchpad) + - name: Vendor Rust dependencies for offline Launchpad build if: steps.check_distro.outputs.should_run == 'true' run: | + rm -rf vendor .cargo mkdir -p .cargo - # Create vendor directory and config - cargo vendor vendor > .cargo/config.toml - # Ensure config has replace-with vendored-sources + cargo vendor --locked vendor > .cargo/config.toml grep -q 'replace-with = "vendored-sources"' .cargo/config.toml grep -q '\[source.vendored-sources\]' .cargo/config.toml grep -q '^directory = "vendor"$' .cargo/config.toml - # Quick sanity: no network is needed for build now - echo "Vendoring done. Files:" - ls -lah vendor | head -n 50 + test -d vendor - name: Prepare package version if: steps.check_distro.outputs.should_run == 'true' @@ -170,17 +160,14 @@ jobs: - name: Build source package if: steps.check_distro.outputs.should_run == 'true' run: | - # Clean any build artifacts rm -f bssh rm -rf target/ - # Ensure Architecture field is 'any' + test -d vendor + test -f .cargo/config.toml sed -i 's/Architecture: .*/Architecture: any/' debian/control chmod +x debian/rules export GNUPGHOME=/home/runner/.gnupg - # IMPORTANT: vendor/ and .cargo/config.toml are already present in the tree - # dpkg-buildpackage -S -sa will include them into the source tarball - if [ -n "${{ secrets.GPG_PASSPHRASE }}" ]; then echo "Building and signing source package with passphrase..." cat > /tmp/gpg-sign.sh << 'EOSCRIPT' @@ -216,4 +203,4 @@ jobs: dput backend-ai-ppa "$CHANGES_FILE" echo "✅ Successfully uploaded to PPA" echo "📦 Version: $FULL_PACKAGE_VERSION" - echo "📦 Package will be available at: https://launchpad.net/~lablup/+archive/ubuntu/backend-ai" \ No newline at end of file + echo "📦 Package will be available at: https://launchpad.net/~lablup/+archive/ubuntu/backend-ai" diff --git a/debian/README.packaging b/debian/README.packaging index a95bca5e..4c3d1470 100644 --- a/debian/README.packaging +++ b/debian/README.packaging @@ -9,37 +9,36 @@ Launchpad build environments do NOT have internet access. This means: - The build must use system-provided packages only ### Build Dependencies -The following packages are required and must be available in the Ubuntu repository: -- `rustc (>= 1.82)` - Rust compiler (requires 1.82 or newer for Rust edition 2024) -- `cargo (>= 0.82)` - Rust package manager +The following packages are required and must be available to Launchpad through the Ubuntu archive or a configured dependency PPA: +- `rustc-1.85` or `rustc (>= 1.85)` - Rust compiler (Rust edition 2024 requires Rust 1.85+) +- `cargo-1.85` or `cargo (>= 1.85)` - Rust package manager - `pkg-config` - For finding system libraries -- `libssl-dev` - OpenSSL development files - `cmake` - Build system ### Rust Version Requirements -This project requires Rust 1.75 or newer. This means: -- Ubuntu 22.04 (Jammy): May need a newer Rust version from backports -- Ubuntu 23.10 (Noble): Should have 1.75+ -- Ubuntu 24.10 (Oracular): Should have 1.75+ +This project requires Rust 1.85 or newer because it uses Rust edition 2024. This means: +- Ubuntu 22.04 (Jammy): requires a versioned Rust 1.85 toolchain from the PPA itself or a dependent PPA +- Ubuntu 24.04 (Noble): requires a versioned Rust 1.85 toolchain from the PPA itself or a dependent PPA +- Ubuntu 26.04 (Resolute): can use the archive's default Rust toolchain If building for older Ubuntu versions, you may need to: -1. Use a PPA that provides newer Rust versions -2. Limit support to distributions with Rust 1.75+ +1. Add a Launchpad PPA dependency that provides `rustc-1.85` and `cargo-1.85` +2. Limit support to distributions with Rust 1.85+ ### Build Process -1. The debian/rules file uses system-provided rustc and cargo -2. A temporary HOME directory is created for cargo's cache -3. The project is built with `cargo build --release --locked` -4. The binary is installed to /usr/bin/bssh +1. GitHub Actions vendors crates into `vendor/` and generates `.cargo/config.toml` +2. The `debian/rules` file requires Rust/Cargo 1.85+ and enables offline cargo mode +3. Launchpad builds the project with `cargo build --release --frozen --workspace` +4. The binary is installed to `/usr/bin/bssh` ### Troubleshooting Build Failures If the build fails on Launchpad: 1. Check the build log for the exact error 2. Common issues: - Missing build dependencies: Add them to debian/control - - Rust version incompatibility: Ensure Rust 1.75+ is available - - Network access attempts: Remove any code that downloads dependencies - - Permission issues: Ensure proper file permissions in debian/rules + - Rust version incompatibility: Ensure Rust 1.85+ is available + - Missing PPA dependency: Jammy/Noble need access to `rustc-1.85` and `cargo-1.85` + - Missing vendored crates: Ensure `vendor/` and `.cargo/config.toml` are included in the source package - Cargo registry access: The build will fail if it tries to download crates ### Automatic Version Incrementing @@ -50,4 +49,4 @@ The packaging scripts support automatic version incrementing to avoid conflicts 3. **GitHub Actions**: Automatically uses version incrementing when uploading to PPA Version format: `{version}-1~{distro}{revision}` -- Example: `0.7.2-1~noble1` → `0.7.2-1~noble2` → `0.7.2-1~noble3` \ No newline at end of file +- Example: `0.7.2-1~noble1` → `0.7.2-1~noble2` → `0.7.2-1~noble3` diff --git a/debian/control b/debian/control index 7204afb0..6496751a 100644 --- a/debian/control +++ b/debian/control @@ -4,8 +4,8 @@ Priority: optional Maintainer: Jeongkyu Shin Build-Depends: debhelper-compat (= 13), build-essential, - rustc (>= 1.75), - cargo (>= 0.75), + rustc-1.85 | rustc (>= 1.85), + cargo-1.85 | cargo (>= 1.85), pkg-config, cmake Standards-Version: 4.6.2 @@ -35,4 +35,4 @@ Description: Broadcast SSH - Parallel command execution across cluster nodes * Real-time progress tracking and output streaming * XDG Base Directory specification compliance . - Developed and maintained as part of the Backend.AI project. \ No newline at end of file + Developed and maintained as part of the Backend.AI project. diff --git a/debian/control.source b/debian/control.source index e6adf38d..313798d4 100644 --- a/debian/control.source +++ b/debian/control.source @@ -3,8 +3,8 @@ Section: utils Priority: optional Maintainer: Jeongkyu Shin Build-Depends: debhelper-compat (= 13), - rustc (>= 1.75), - cargo (>= 0.75), + rustc-1.85 | rustc (>= 1.85), + cargo-1.85 | cargo (>= 1.85), pkg-config, cmake, build-essential @@ -35,4 +35,4 @@ Description: Broadcast SSH - Parallel command execution across cluster nodes * Real-time progress tracking and output streaming * XDG Base Directory specification compliance . - Developed and maintained as part of the Backend.AI project. \ No newline at end of file + Developed and maintained as part of the Backend.AI project. diff --git a/debian/prepare-source-package.sh b/debian/prepare-source-package.sh index 84195704..69659e8c 100755 --- a/debian/prepare-source-package.sh +++ b/debian/prepare-source-package.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -# This script prepares the source package for Launchpad PPA upload -# It switches from binary-based packaging to source-based packaging +# This script prepares the source package for Launchpad PPA upload. +# It vendors Rust dependencies so Launchpad can build offline. echo "Preparing source package for Launchpad..." @@ -12,30 +12,21 @@ if [ ! -f "Cargo.toml" ]; then exit 1 fi -# Backup original files -cp debian/control debian/control.binary -cp debian/rules debian/rules.binary - -# Use source-based packaging files +# Ensure source-package rules are active cp debian/control.source debian/control cp debian/rules.source debian/rules - -# Make rules executable chmod +x debian/rules # Vendor Rust dependencies for offline build echo "Vendoring Rust dependencies..." -cargo vendor debian/vendor - -# Create cargo config to use vendored dependencies +rm -rf vendor .cargo mkdir -p .cargo -cat > .cargo/config.toml << 'EOF' -[source.crates-io] -replace-with = "vendored-sources" +cargo vendor --locked vendor > .cargo/config.toml -[source.vendored-sources] -directory = "debian/vendor" -EOF +if ! grep -q '^directory = "vendor"$' .cargo/config.toml; then + echo "Error: cargo vendor did not generate the expected source replacement config" + exit 1 +fi echo "Source package preparation complete!" -echo "The package will now build from source on Launchpad" \ No newline at end of file +echo "The package will now build from source on Launchpad" diff --git a/debian/rules b/debian/rules index 834e8aa1..2af6975f 100755 --- a/debian/rules +++ b/debian/rules @@ -3,41 +3,46 @@ # Enable all hardening options export DEB_BUILD_MAINT_OPTIONS = hardening=+all -# Set HOME for cargo (Launchpad builds need this) -export HOME = /tmp/build-home +# Keep cargo state inside the build tree. +export HOME = $(CURDIR)/debian/home export CARGO_HOME = $(HOME)/.cargo +export CARGO_TARGET_DIR = $(CURDIR)/target +export CARGO_NET_OFFLINE = true + +RUSTC := $(shell if command -v rustc-1.85 >/dev/null 2>&1; then printf '%s' rustc-1.85; else printf '%s' rustc; fi) +CARGO := $(shell if command -v cargo-1.85 >/dev/null 2>&1; then printf '%s' cargo-1.85; else printf '%s' cargo; fi) %: dh $@ override_dh_auto_configure: - # Create temporary home directory for cargo mkdir -p $(CARGO_HOME) - # Verify rust toolchain is available - rustc --version - cargo --version + test -d vendor + test -f .cargo/config.toml + $(RUSTC) --version + $(CARGO) --version + rustc_version=$$($(RUSTC) --version | awk '{print $$2}'); \ + cargo_version=$$($(CARGO) --version | awk '{print $$2}'); \ + dpkg --compare-versions "$$rustc_version" ge 1.85 || { \ + echo "rustc 1.85+ is required for Rust edition 2024 (found $$rustc_version)"; \ + exit 1; \ + }; \ + dpkg --compare-versions "$$cargo_version" ge 1.85 || { \ + echo "cargo 1.85+ is required for Rust edition 2024 (found $$cargo_version)"; \ + exit 1; \ + } override_dh_auto_build: - # If Cargo.lock is lockfile v4, regenerate with Cargo 1.75 (produces v3) - if grep -q '^version = 4' Cargo.lock 2>/dev/null; then \ - rm -f Cargo.lock; \ - cargo generate-lockfile; \ - fi - # Build the project with cargo - cargo build --release --locked - + $(CARGO) build --release --frozen --workspace + override_dh_auto_install: - # Install the compiled binary install -D -m 0755 target/release/bssh debian/bssh/usr/bin/bssh override_dh_auto_test: - # Skip tests to save build time on Launchpad @echo "Skipping tests for PPA build" override_dh_auto_clean: - # Don't run dh_auto_clean as it requires cargo to be installed - # Just clean the build artifacts manually rm -rf target/ $(HOME) override_dh_builddeb: - dh_builddeb --destdir=../ \ No newline at end of file + dh_builddeb --destdir=../ diff --git a/debian/rules.launchpad b/debian/rules.launchpad index 7dd8504e..2af6975f 100644 --- a/debian/rules.launchpad +++ b/debian/rules.launchpad @@ -3,43 +3,46 @@ # Enable all hardening options export DEB_BUILD_MAINT_OPTIONS = hardening=+all -# Rust/Cargo specific settings -export CARGO_HOME = $(CURDIR)/debian/cargo +# Keep cargo state inside the build tree. +export HOME = $(CURDIR)/debian/home +export CARGO_HOME = $(HOME)/.cargo export CARGO_TARGET_DIR = $(CURDIR)/target +export CARGO_NET_OFFLINE = true + +RUSTC := $(shell if command -v rustc-1.85 >/dev/null 2>&1; then printf '%s' rustc-1.85; else printf '%s' rustc; fi) +CARGO := $(shell if command -v cargo-1.85 >/dev/null 2>&1; then printf '%s' cargo-1.85; else printf '%s' cargo; fi) %: dh $@ override_dh_auto_configure: - # Install Rust if not present (Launchpad builders may not have it) - if ! command -v rustc >/dev/null 2>&1; then \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal; \ - . $(HOME)/.cargo/env; \ - fi - # Ensure we have the stable toolchain - $(HOME)/.cargo/bin/rustup default stable || rustup default stable + mkdir -p $(CARGO_HOME) + test -d vendor + test -f .cargo/config.toml + $(RUSTC) --version + $(CARGO) --version + rustc_version=$$($(RUSTC) --version | awk '{print $$2}'); \ + cargo_version=$$($(CARGO) --version | awk '{print $$2}'); \ + dpkg --compare-versions "$$rustc_version" ge 1.85 || { \ + echo "rustc 1.85+ is required for Rust edition 2024 (found $$rustc_version)"; \ + exit 1; \ + }; \ + dpkg --compare-versions "$$cargo_version" ge 1.85 || { \ + echo "cargo 1.85+ is required for Rust edition 2024 (found $$cargo_version)"; \ + exit 1; \ + } override_dh_auto_build: - # If Cargo.lock is lockfile v4, regenerate with Cargo 1.75 (produces v3) - if grep -q '^version = 4' Cargo.lock 2>/dev/null; then \ - rm -f Cargo.lock; \ - cargo generate-lockfile; \ - fi - # Build the project with cargo - cargo build --release --locked + $(CARGO) build --release --frozen --workspace override_dh_auto_install: - # Install the compiled binary install -D -m 0755 target/release/bssh debian/bssh/usr/bin/bssh override_dh_auto_test: - # Run tests - PATH="$(HOME)/.cargo/bin:$(PATH)" cargo test --release --locked || true + @echo "Skipping tests for PPA build" override_dh_auto_clean: - # Clean cargo build artifacts - rm -rf $(CARGO_TARGET_DIR) $(CARGO_HOME) - dh_auto_clean + rm -rf target/ $(HOME) override_dh_builddeb: - dh_builddeb --destdir=../ \ No newline at end of file + dh_builddeb --destdir=../ diff --git a/debian/rules.launchpad-simple b/debian/rules.launchpad-simple index 69d0fba6..2af6975f 100644 --- a/debian/rules.launchpad-simple +++ b/debian/rules.launchpad-simple @@ -3,38 +3,46 @@ # Enable all hardening options export DEB_BUILD_MAINT_OPTIONS = hardening=+all -# Ensure we have HOME set for cargo -export HOME = /tmp/build-home +# Keep cargo state inside the build tree. +export HOME = $(CURDIR)/debian/home export CARGO_HOME = $(HOME)/.cargo -export PATH := $(CARGO_HOME)/bin:$(PATH) +export CARGO_TARGET_DIR = $(CURDIR)/target +export CARGO_NET_OFFLINE = true + +RUSTC := $(shell if command -v rustc-1.85 >/dev/null 2>&1; then printf '%s' rustc-1.85; else printf '%s' rustc; fi) +CARGO := $(shell if command -v cargo-1.85 >/dev/null 2>&1; then printf '%s' cargo-1.85; else printf '%s' cargo; fi) %: dh $@ override_dh_auto_configure: - # Create temporary home directory - mkdir -p $(HOME) - # Install Rust toolchain - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable - # Verify installation - $(CARGO_HOME)/bin/rustc --version - $(CARGO_HOME)/bin/cargo --version + mkdir -p $(CARGO_HOME) + test -d vendor + test -f .cargo/config.toml + $(RUSTC) --version + $(CARGO) --version + rustc_version=$$($(RUSTC) --version | awk '{print $$2}'); \ + cargo_version=$$($(CARGO) --version | awk '{print $$2}'); \ + dpkg --compare-versions "$$rustc_version" ge 1.85 || { \ + echo "rustc 1.85+ is required for Rust edition 2024 (found $$rustc_version)"; \ + exit 1; \ + }; \ + dpkg --compare-versions "$$cargo_version" ge 1.85 || { \ + echo "cargo 1.85+ is required for Rust edition 2024 (found $$cargo_version)"; \ + exit 1; \ + } override_dh_auto_build: - # Build the project - $(CARGO_HOME)/bin/cargo build --release --locked + $(CARGO) build --release --frozen --workspace override_dh_auto_install: - # Install the compiled binary install -D -m 0755 target/release/bssh debian/bssh/usr/bin/bssh override_dh_auto_test: - # Skip tests to save build time on Launchpad @echo "Skipping tests for PPA build" override_dh_auto_clean: rm -rf target/ $(HOME) - dh_auto_clean override_dh_builddeb: - dh_builddeb --destdir=../ \ No newline at end of file + dh_builddeb --destdir=../ diff --git a/debian/rules.source b/debian/rules.source index 1cf51c68..75f2bebd 100644 --- a/debian/rules.source +++ b/debian/rules.source @@ -3,22 +3,46 @@ # Enable all hardening options export DEB_BUILD_MAINT_OPTIONS = hardening=+all -# Use vendored dependencies for offline builds -export CARGO_HOME = $(CURDIR)/debian/cargo +# Use vendored dependencies for offline builds. +export HOME = $(CURDIR)/debian/home +export CARGO_HOME = $(HOME)/.cargo export CARGO_TARGET_DIR = $(CURDIR)/target +export CARGO_NET_OFFLINE = true + +RUSTC := $(shell if command -v rustc-1.85 >/dev/null 2>&1; then printf '%s' rustc-1.85; else printf '%s' rustc; fi) +CARGO := $(shell if command -v cargo-1.85 >/dev/null 2>&1; then printf '%s' cargo-1.85; else printf '%s' cargo; fi) %: - dh $@ --buildsystem=cargo + dh $@ + +override_dh_auto_configure: + mkdir -p $(CARGO_HOME) + test -d vendor + test -f .cargo/config.toml + $(RUSTC) --version + $(CARGO) --version + rustc_version=$$($(RUSTC) --version | awk '{print $$2}'); \ + cargo_version=$$($(CARGO) --version | awk '{print $$2}'); \ + dpkg --compare-versions "$$rustc_version" ge 1.85 || { \ + echo "rustc 1.85+ is required for Rust edition 2024 (found $$rustc_version)"; \ + exit 1; \ + }; \ + dpkg --compare-versions "$$cargo_version" ge 1.85 || { \ + echo "cargo 1.85+ is required for Rust edition 2024 (found $$cargo_version)"; \ + exit 1; \ + } override_dh_auto_build: - dh_auto_build -- --release --locked + $(CARGO) build --release --frozen --workspace override_dh_auto_install: - # Install the compiled binary install -D -m 0755 target/release/bssh debian/bssh/usr/bin/bssh override_dh_auto_test: - dh_auto_test -- --release + @echo "Skipping tests for PPA build" + +override_dh_auto_clean: + rm -rf target/ $(HOME) override_dh_builddeb: - dh_builddeb --destdir=../ \ No newline at end of file + dh_builddeb --destdir=../ diff --git a/debian/source/include-binaries b/debian/source/include-binaries index ae776faf..22d0d82f 100644 --- a/debian/source/include-binaries +++ b/debian/source/include-binaries @@ -1 +1 @@ -debian/vendor \ No newline at end of file +vendor