{
description = "Pack - A WebAssembly package runtime with extended WIT support for recursive types";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, flake-utils, rust-overlay }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
# Rust toolchain with WASM target
rustToolchain = pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rust-src" "rust-analyzer" ];
targets = [ "wasm32-unknown-unknown" ];
};
buildInputs = with pkgs; [
rustToolchain
pkg-config
openssl
] ++ lib.optionals stdenv.isDarwin [
darwin.apple_sdk.frameworks.Security
darwin.apple_sdk.frameworks.SystemConfiguration
];
nativeBuildInputs = with pkgs; [
rustToolchain
pkg-config
];
in
{
devShells.default = pkgs.mkShell {
inherit buildInputs nativeBuildInputs;
packages = with pkgs; [
cargo-watch
cargo-edit
cargo-expand
wasm-pack
wasmtime
gh
];
RUST_SRC_PATH = "${rustToolchain}/lib/rustlib/src/rust/library";
RUST_BACKTRACE = "1";
shellHook = ''
echo "Pack development environment"
echo "Rust: $(rustc --version)"
echo ""
echo "Commands:"
echo " cargo build - Build packr runtime"
echo " cargo test --workspace - Run all tests"
echo " cargo test -p packr-abi --features derive - Run derive tests"
echo " cargo clippy --workspace - Lint"
echo " nix run .#test - Run full test suite"
echo " nix run .#pr - Create PR from jj revision"
echo " nix run .#release -- patch - Bump version, create release PR"
'';
};
packages.default = pkgs.rustPlatform.buildRustPackage {
pname = "packr";
version = "0.5.1";
src = ./.;
cargoLock = {
lockFile = ./Cargo.lock;
};
inherit nativeBuildInputs buildInputs;
meta = with pkgs.lib; {
description = "A WebAssembly package runtime with extended WIT support for recursive types";
homepage = "https://github.com/colinrozzi/pack";
license = licenses.mit;
};
};
packages.packr = self.packages.${system}.default;
# Run full test suite (workspace + derive tests)
packages.test = pkgs.writeShellScriptBin "pack-test" ''
set -e
echo "Running workspace tests..."
cargo test --workspace
echo ""
echo "Running derive tests..."
cargo test -p packr-abi --features derive
echo ""
echo "All tests passed!"
'';
# Release: bump version and create a PR
# After merge, CI publishes to crates.io and creates the git tag
packages.release = pkgs.writeShellScriptBin "pack-release" ''
set -e
BUMP="''${1:-patch}"
CURRENT=$(${pkgs.gnugrep}/bin/grep -m1 '^version = ' Cargo.toml | ${pkgs.gnused}/bin/sed 's/version = "\(.*\)"/\1/')
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
case "$BUMP" in
patch) PATCH=$((PATCH + 1)) ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
[0-9]*.[0-9]*.[0-9]*) IFS='.' read -r MAJOR MINOR PATCH <<< "$BUMP" ;;
*) echo "Usage: nix run .#release -- [patch|minor|major|X.Y.Z]"; exit 1 ;;
esac
NEW="$MAJOR.$MINOR.$PATCH"
echo "Bumping $CURRENT -> $NEW"
# Update workspace version in root Cargo.toml
${pkgs.gnused}/bin/sed -i "0,/^version = \"$CURRENT\"/s//version = \"$NEW\"/" Cargo.toml
# Update workspace dependency versions. Match any prior version (not
# just $CURRENT) — historically these drifted from the package version
# (e.g. pinned at "0.5.1" while the package was at "0.5.5"), and a
# regex tied to $CURRENT silently skipped them.
${pkgs.gnused}/bin/sed -i -E "s/version = \"[^\"]+\", path = \"crates\//version = \"$NEW\", path = \"crates\//g" Cargo.toml
# Update flake.nix version
${pkgs.gnused}/bin/sed -i "s/version = \"$CURRENT\"/version = \"$NEW\"/" flake.nix
# Update Cargo.lock
cargo update --workspace 2>/dev/null || true
echo ""
echo "Updated to v$NEW"
echo ""
BRANCH="release-v$NEW"
if command -v jj &>/dev/null; then
jj describe -m "release v$NEW"
jj bookmark create "$BRANCH" -r @ 2>/dev/null || jj bookmark set "$BRANCH" -r @
jj git push --bookmark "$BRANCH" --allow-new
else
git checkout -b "$BRANCH"
git add -A
git commit -m "release v$NEW"
git push -u origin "$BRANCH"
fi
${pkgs.gh}/bin/gh pr create \
--title "release v$NEW" \
--body "Bump version to v$NEW. Merging will publish to crates.io and create a GitHub release." \
--base main \
--head "$BRANCH"
echo ""
echo "PR created. Merge to publish v$NEW to crates.io."
'';
# Create a PR from the current jj revision
packages.pr = pkgs.writeShellScriptBin "pack-pr" ''
set -e
DESCRIPTION=$(jj log -r @ --no-graph -T 'description' 2>/dev/null)
if [ -z "$DESCRIPTION" ] || [ "$DESCRIPTION" = "(no description set)" ]; then
echo "Error: Current revision has no description. Run: jj describe -m 'your change'"
exit 1
fi
TITLE=$(echo "$DESCRIPTION" | head -1)
BRANCH=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-' | ${pkgs.gnused}/bin/sed 's/--*/-/g; s/^-//; s/-$//' | head -c 50)
echo "Creating PR: $TITLE"
echo "Branch: $BRANCH"
echo ""
jj bookmark create "$BRANCH" -r @ 2>/dev/null || jj bookmark set "$BRANCH" -r @
jj git push --bookmark "$BRANCH" --allow-new
${pkgs.gh}/bin/gh pr create \
--title "$TITLE" \
--body "$DESCRIPTION" \
--base main \
--head "$BRANCH"
'';
}
);
}