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
46 changes: 36 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,22 @@ jobs:
runner: ubuntu-latest
arch_tag: amd64
cache_suffix: cache-amd64
dockerfile: Dockerfile
- platform: linux/arm64
runner: ubuntu-22.04-arm
arch_tag: arm64
cache_suffix: cache-arm64
dockerfile: Dockerfile
- platform: linux/amd64
runner: ubuntu-latest
arch_tag: amd64-engine
cache_suffix: cache-amd64-engine
dockerfile: cloudengine.Dockerfile
- platform: linux/arm64
runner: ubuntu-22.04-arm
arch_tag: arm64-engine
cache_suffix: cache-arm64-engine
dockerfile: cloudengine.Dockerfile
steps:
- name: "Checkout code"
uses: actions/checkout@v4
Expand Down Expand Up @@ -138,6 +150,7 @@ jobs:
uses: docker/build-push-action@v6
with:
push: true
file: ${{ matrix.dockerfile }}
platforms: ${{ matrix.platform }}
tags: |
ghcr.io/${{ github.repository }}:${{ matrix.arch_tag }}
Expand All @@ -148,13 +161,32 @@ jobs:
BUILDKIT_INLINE_CACHE=1

docker-manifest:
name: "Create and push multi-arch manifest"
name: "Create and push multi-arch manifest (${{ matrix.variant }})"
if: ${{ github.ref_type == 'tag' }}
needs: docker-build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- variant: standard
amd64_tag: amd64
arm64_tag: arm64
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=${{ github.sha }},enable=true
type=raw,value=latest,enable=true
- variant: engine
amd64_tag: amd64-engine
arm64_tag: arm64-engine
tags: |
type=semver,pattern={{version}},suffix=-engine
type=raw,value=engine-beta,enable=true
steps:
- name: "Checkout code"
uses: actions/checkout@v4
Expand All @@ -167,13 +199,7 @@ jobs:
with:
images: |
ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=${{ github.sha }},enable=true
type=raw,value=latest,enable=${{ github.ref_type == 'tag' }}
tags: ${{ matrix.tags }}

- name: "Log in to GitHub Container Registry"
uses: docker/login-action@v3
Expand All @@ -187,5 +213,5 @@ jobs:
with:
tags: ${{ steps.meta.outputs.tags }}
sources: |
ghcr.io/${{ github.repository }}:amd64
ghcr.io/${{ github.repository }}:arm64
ghcr.io/${{ github.repository }}:${{ matrix.amd64_tag }}
ghcr.io/${{ github.repository }}:${{ matrix.arm64_tag }}
22 changes: 11 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ edition = "2024"
authors = ["DFINITY Stiftung <sdk@dfinity.org>"]
license = "Apache-2.0"

[features]
cloud-engine = []

[dependencies]
anyhow = { version = "1.0.100", features = ["backtrace"] }
camino = "1.2.2"
clap = { version = "4.5.53", features = ["derive", "env"] }
hex = "0.4.3"
ic_principal = "0.1.1"
notify = "8.2.0"
pocket-ic = { git = "https://github.com/dfinity/ic", rev = "781ef50bd6bfbcfac6769b55361d0624247009c1" }
pocket-ic = { git = "https://github.com/dfinity/ic", rev = "d17cf0bcd330e94f868cc7d19d0ac860cbe64198" }
reqwest = { version = "0.12.24", default-features = false, features = ["rustls-tls", "json"] }
semver = "1.0.27"
serde = { version = "1.0.228", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM rust:1.93.1-slim-trixie AS chef
FROM rust:1.94.0-slim-trixie AS chef
RUN apt-get update && apt-get install -y jq curl
WORKDIR /app
RUN cargo install cargo-chef --version 0.1.73 --locked
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,18 @@ When `--status-dir` is provided, the launcher writes a JSON status file (`status

The launcher handles `SIGINT` (Ctrl+C) and `SIGTERM` for graceful shutdown. It stops the PocketIC server and waits for it to exit before terminating.

### Experimental features

If the launcher is built with `--feature cloud-engine`, you can create subnets of type `cloud-engine`. The subnet admin is set to the anonymous principal. The `:cloudengine-beta` Docker tag is an alternative to the standard image with this feature enabled.

## Installing

`icp-cli-network-launcher` is typically installed automatically by icp-cli. It can be updated to the latest version with `icp network update`.

Binary downloads are also available on the [releases page](https://github.com/dfinity/icp-cli-network-launcher/releases).

A Docker image is published under the name `ghcr.io/dfinity/icp-cli-network-launcher`. The container port 4943 should be published for gateway access, and if a status dir is needed, mount it at `/app/status`.

## Development

### Prerequisites
Expand Down
22 changes: 22 additions & 0 deletions cloudengine.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM rust:1.94.0-slim-trixie AS chef
RUN apt-get update && apt-get install -y jq curl
WORKDIR /app
RUN cargo install cargo-chef --version 0.1.73 --locked
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN ./package.sh out -- --features=cloud-engine
FROM debian:trixie-slim AS runtime
RUN apt-get update && apt-get install -y ca-certificates
WORKDIR /app
COPY --from=builder /app/out ./
STOPSIGNAL SIGINT
EXPOSE 4942/tcp 4943/tcp
ENTRYPOINT ["/app/icp-cli-network-launcher", "--status-dir=/app/status", \
"--config-port", "4942", "--gateway-port", "4943", \
"--bind", "0.0.0.0", "--pocketic-config-bind", "0.0.0.0"]
CMD ["--nns", "--ii", "--subnet=application", "--subnet=cloud-engine"]
17 changes: 14 additions & 3 deletions package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,19 @@ case $(uname -m) in
aarch64*) arch="arm64";;
*) echo "Unsupported architecture $(uname -m)"; exit 1;;
esac

dir=
cargo_args=()
while (( $# )); do
case "$1" in
--) shift; cargo_args=("$@"); break;;
*) [[ -z "$dir" ]] && dir="$1" || die "too many arguments";;
esac
shift
done

maketarball=0
if [[ -z "$1" ]]; then
if [[ -z "$dir" ]]; then
maketarball=1
fi
tar=tar
Expand All @@ -44,8 +55,8 @@ else
[[ "$source" != "git+"* ]] || die "package.version is not patch but pocket-ic dependency is git"
fi
name="icp-cli-network-launcher-${arch}-${os}-v${v}"
outdir="${1-"dist/${name}"}"
cargo build --release
outdir="${dir:-"dist/${name}"}"
cargo build --release "${cargo_args[@]}"
mkdir -p "${outdir}"
cp "target/release/icp-cli-network-launcher" "${outdir}/"
if [[ -z "$icdate" ]]; then
Expand Down
28 changes: 26 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg_attr(not(feature = "cloud-engine"), allow(unused))]

use std::{
collections::HashSet,
fs,
Expand All @@ -14,7 +16,10 @@ use ic_principal::Principal;
use notify::{Event, RecursiveMode, Watcher, recommended_watcher};
use pocket_ic::{
PocketIcBuilder,
common::rest::{AutoProgressConfig, IcpFeatures, IcpFeaturesConfig, InstanceHttpGatewayConfig},
common::rest::{
AutoProgressConfig, ExtendedSubnetConfigSet, IcpFeatures, IcpFeaturesConfig,
InstanceHttpGatewayConfig, SubnetSpec,
},
};
use reqwest::Client;
use semver::{Version, VersionReq};
Expand Down Expand Up @@ -101,6 +106,8 @@ enum SubnetKind {
Fiduciary,
Nns,
Sns,
#[cfg(feature = "cloud-engine")]
CloudEngine,
}

#[tokio::main]
Expand Down Expand Up @@ -218,7 +225,22 @@ async fn main() -> anyhow::Result<()> {
drop(watcher);
// pocket-ic CLI setup ends here
// initial HTTP setup
let mut pic = PocketIcBuilder::new()
let mut base_subnets = ExtendedSubnetConfigSet::default();
#[cfg(feature = "cloud-engine")]
for _ in 0..subnet
.iter()
.filter(|s| matches!(s, SubnetKind::CloudEngine))
.count()
{
use pocket_ic::common::rest::CanisterCyclesCostSchedule;

base_subnets.cloud_engine.push(
SubnetSpec::default()
.with_subnet_admins(vec![Principal::anonymous()])
.with_cost_schedule(CanisterCyclesCostSchedule::Free),
);
}
let mut pic = PocketIcBuilder::new_with_config(base_subnets)
.with_server_url(
format!("http://127.0.0.1:{config_port}/")
.parse()
Expand Down Expand Up @@ -256,6 +278,8 @@ async fn main() -> anyhow::Result<()> {
SubnetKind::Fiduciary => pic = pic.with_fiduciary_subnet(),
SubnetKind::Nns => pic = pic.with_nns_subnet(),
SubnetKind::Sns => pic = pic.with_sns_subnet(),
#[cfg(feature = "cloud-engine")]
SubnetKind::CloudEngine => {} // handled above
}
}
}
Expand Down
Loading