Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 24 additions & 37 deletions .github/workflows/launchpad_ppa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
distro: [jammy, noble, oracular]
distro: [jammy, noble, resolute]

steps:
- name: Checkout code
Expand Down Expand Up @@ -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 \
Expand All @@ -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'
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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"
echo "📦 Package will be available at: https://launchpad.net/~lablup/+archive/ubuntu/backend-ai"
35 changes: 17 additions & 18 deletions debian/README.packaging
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`
- Example: `0.7.2-1~noble1` → `0.7.2-1~noble2` → `0.7.2-1~noble3`
6 changes: 3 additions & 3 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Priority: optional
Maintainer: Jeongkyu Shin <inureyes@gmail.com>
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
Expand Down Expand Up @@ -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.
Developed and maintained as part of the Backend.AI project.
6 changes: 3 additions & 3 deletions debian/control.source
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Section: utils
Priority: optional
Maintainer: Jeongkyu Shin <inureyes@gmail.com>
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
Expand Down Expand Up @@ -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.
Developed and maintained as part of the Backend.AI project.
29 changes: 10 additions & 19 deletions debian/prepare-source-package.sh
Original file line number Diff line number Diff line change
@@ -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..."

Expand All @@ -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"
echo "The package will now build from source on Launchpad"
43 changes: 24 additions & 19 deletions debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -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=../
dh_builddeb --destdir=../
Loading
Loading