Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
dbe77b0
support docker images
adamspofford-dfinity Dec 8, 2025
a0bb0b4
error handling + windows
adamspofford-dfinity Dec 12, 2025
518050c
container preservation
adamspofford-dfinity Dec 12, 2025
8a8e9e5
.
adamspofford-dfinity Dec 13, 2025
e05cc00
windows
adamspofford-dfinity Dec 13, 2025
d0219ce
container args
adamspofford-dfinity Dec 13, 2025
68fb26c
remove special term
adamspofford-dfinity Dec 13, 2025
222f3ad
locate git bash
adamspofford-dfinity Dec 13, 2025
324bde4
Change default network to docker on windows
adamspofford-dfinity Jan 8, 2026
c602680
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 8, 2026
af95a26
new fields
adamspofford-dfinity Jan 8, 2026
df3c389
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 14, 2026
d525c30
include windows builds in CI
adamspofford-dfinity Jan 14, 2026
cfa5d56
Revert default network change
adamspofford-dfinity Jan 14, 2026
929a23e
Convert native networks to containers on windows
adamspofford-dfinity Jan 14, 2026
99d903f
Add ii config
adamspofford-dfinity Jan 14, 2026
af109f2
Wrap terminal output
adamspofford-dfinity Jan 15, 2026
633c780
use ctrl-break for process groups
adamspofford-dfinity Jan 15, 2026
c0f5349
quote filenames in templated sh calls
adamspofford-dfinity Jan 15, 2026
a7d87f3
dockerate start_network_with_flags
adamspofford-dfinity Jan 15, 2026
879fc4f
you can't override $HOME so use portable mode
adamspofford-dfinity Jan 15, 2026
3106c80
print port for all sources
adamspofford-dfinity Jan 15, 2026
bb153fe
remove unc prefix from expected path
adamspofford-dfinity Jan 15, 2026
5d7e2d2
windows stops use container id
adamspofford-dfinity Jan 15, 2026
3921a42
Add windows to e2e matrix
adamspofford-dfinity Jan 15, 2026
ca35070
detect with winreg instead of pathsearch
adamspofford-dfinity Jan 15, 2026
6161702
clean up
adamspofford-dfinity Jan 15, 2026
51cb0c5
Better message
adamspofford-dfinity Jan 15, 2026
76be34f
Quote unit tests as well
adamspofford-dfinity Jan 15, 2026
77298a4
Never use unprefixed bash because it may be wsl bash
adamspofford-dfinity Jan 15, 2026
e03517c
Cache before installing
adamspofford-dfinity Jan 15, 2026
482dba0
Add explicit arch to docker commands
adamspofford-dfinity Jan 16, 2026
61c68f8
Set up docker with tcp
adamspofford-dfinity Jan 16, 2026
bd47875
.
adamspofford-dfinity Jan 16, 2026
4a1b0b8
There's an action for this
adamspofford-dfinity Jan 16, 2026
6a2843f
Normalize lf
adamspofford-dfinity Jan 16, 2026
c63a16e
Add envvar for WSL2 docker path conversion
adamspofford-dfinity Jan 16, 2026
f23616d
Reproduce tcp check in stop
adamspofford-dfinity Jan 16, 2026
581be73
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 16, 2026
20232b9
Fix merged tests
adamspofford-dfinity Jan 16, 2026
c541ec0
Remove 8.3 names from cwd check
adamspofford-dfinity Jan 16, 2026
514f74e
Update to windows-2025 to remove the need for `wsl --update`
adamspofford-dfinity Jan 16, 2026
5e5c095
Shrink cache
adamspofford-dfinity Jan 16, 2026
cd03a85
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 17, 2026
88a9ac2
merge broke the build
adamspofford-dfinity Jan 17, 2026
2704201
Move status dir to dockerd host when in wsl mode
adamspofford-dfinity Jan 17, 2026
021dfd1
Always use wslpath
adamspofford-dfinity Jan 17, 2026
af82b6b
better msg
adamspofford-dfinity Jan 20, 2026
87850e2
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 20, 2026
33b0d00
Include DISTRO in WSLPATH
adamspofford-dfinity Jan 20, 2026
0a23849
Add polling fallback for file watching
adamspofford-dfinity Jan 20, 2026
f036f51
Remove vendored-openssl from the Windows build
adamspofford-dfinity Jan 20, 2026
7377125
Use version nonspecific name (cache loses the context)
adamspofford-dfinity Jan 20, 2026
7306c68
immediately poll
adamspofford-dfinity Jan 20, 2026
2679440
wsl sets a var already
adamspofford-dfinity Jan 20, 2026
5353e7b
Lock for a shorter duration
adamspofford-dfinity Jan 20, 2026
bca7031
fix manual flags check
adamspofford-dfinity Jan 21, 2026
4b574a2
Increase timeout to 5m
adamspofford-dfinity Jan 21, 2026
8c628d9
docs
adamspofford-dfinity Jan 21, 2026
c7dab56
Update dist
adamspofford-dfinity Jan 21, 2026
8a55ab6
remove unnecessary tmpdir handling
adamspofford-dfinity Jan 21, 2026
733e693
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 21, 2026
609e118
Apply suggestion
adamspofford-dfinity Jan 21, 2026
08a8eeb
Simplify conditional term output
adamspofford-dfinity Jan 21, 2026
6c94a2e
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 21, 2026
f3d8d10
Merge branch 'main' into spofford/windows
adamspofford-dfinity Jan 21, 2026
6d2de37
this is redundant (and wrong)
adamspofford-dfinity Jan 22, 2026
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
21 changes: 21 additions & 0 deletions .github/scripts/init-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# This sets up dockerd in a WSL2 container manually. You could probably do this locally if you wanted,
# but the primary purpose is that GitHub Actions' WSL2 runners aren't set up for hypervisor support,
# so Docker Desktop's automatic WSL2 integration doesn't work.
set -ex
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y docker.io
nohup dockerd -H tcp://127.0.0.1:2375 >/var/log/dockerd.log 2>&1 &
for i in $(seq 1 30); do
if docker -H tcp://127.0.0.1:2375 info >/dev/null 2>&1; then
echo Docker ready
{
echo DOCKER_HOST=tcp://127.0.0.1:2375
echo ICP_CLI_DOCKER_WSL2_DISTRO="$WSL_DISTRO_NAME"
} >> $GITHUB_ENV
exit 0
fi
sleep 1
done
cat /var/log/dockerd.log
exit 1
6 changes: 5 additions & 1 deletion .github/scripts/test-matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ def test_names():

include = []
for test in test_names():
# Ubuntu: run everything
# Ubuntu/Windows: run everything
include.append({
"test": test,
"os": "ubuntu-22.04"
})
include.append({
"test": test,
"os": "windows-2025"
})

# macOS: only run selected tests
if test in MACOS_TESTS:
Expand Down
39 changes: 30 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ env:
CARGO_NET_RETRY: 10
# Use the local .curlrc
CURL_HOME: .
# Disable incremental compilation
CARGO_INCREMENTAL: 0
# These variables should be shared with WSL
WSLENV: CARGO_INCREMENTAL:CURL_HOME/p:CARGO_NET_RETRY:GITHUB_ENV/p:GITHUB_OUTPUT/p

defaults:
run:
shell: bash

jobs:
discover:
Expand All @@ -30,15 +38,11 @@ jobs:
matrix:
# Make the os matrix match .github/scripts/test-matrix.py so that
# we optimize caching
os: [ubuntu-22.04, macos-15]
os: [ubuntu-22.04, macos-15, windows-2025]

steps:
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0

- name: Setup image (Linux)
if: ${{ contains(matrix.os, 'ubuntu') }}
run: ./.github/scripts/provision-linux-build.sh

- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
Expand All @@ -50,6 +54,10 @@ jobs:
target/
key: ${{ matrix.os }}-cargo-${{ hashFiles('rust-toolchain.toml') }}-${{ hashFiles('**/Cargo.lock') }}

- name: Setup image (Linux)
if: ${{ contains(matrix.os, 'ubuntu') }}
run: ./.github/scripts/provision-linux-build.sh

- uses: t1m0thyj/unlock-keyring@e481cdc8833d4417a58f40734e8f197183317047
if: ${{ contains(matrix.os, 'ubuntu') }}

Expand All @@ -68,10 +76,6 @@ jobs:
steps:
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0

- name: Setup image (Linux)
if: ${{ contains(matrix.os, 'ubuntu') }}
run: ./.github/scripts/provision-linux-build.sh

- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
Expand All @@ -83,6 +87,21 @@ jobs:
target/
key: ${{ matrix.os }}-cargo-${{ hashFiles('rust-toolchain.toml') }}-${{ hashFiles('**/Cargo.lock') }}

- name: Setup image (Linux)
if: ${{ contains(matrix.os, 'ubuntu') }}
run: ./.github/scripts/provision-linux-build.sh

- name: Setup WSL2 (Windows)
if: ${{ contains(matrix.os, 'windows') }}
uses: Vampire/setup-wsl@6a8db447be7ed35f2f499c02c6e60ff77ef11278 # v6.0.0
with:
distribution: Ubuntu-22.04

- name: Setup Docker in WSL2 (Windows)
if: ${{ contains(matrix.os, 'windows') }}
run: .github/scripts/init-docker.sh
shell: wsl-bash_Ubuntu-22.04 {0}

- uses: t1m0thyj/unlock-keyring@e481cdc8833d4417a58f40734e8f197183317047
if: ${{ contains(matrix.os, 'ubuntu') }}

Expand All @@ -105,6 +124,7 @@ jobs:
- name: install network launcher
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: ${{ !contains(matrix.os, 'windows') }}
run: |
VERSION=v11.0.0
OS=""
Expand Down Expand Up @@ -142,6 +162,7 @@ jobs:
echo "ICP_CLI_NETWORK_LAUNCHER_PATH=$DEST/icp-cli-network-launcher" >> "$GITHUB_ENV"

- name: Run ${{ matrix.test }}
# the macos runners do not support Docker
run: cargo test --test ${{ matrix.test }} -- ${{ contains(matrix.os, 'macos') && '--skip :docker:' || '' }}

aggregate:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased

* feat: Release for Windows
* feat: Add safety controls for `--set-controller` and `--remove-controller`
* Warn and prompt for confirmation when removing yourself from controllers
* Add `-f/--force` flag to skip confirmation prompts
Expand Down
32 changes: 32 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ tracing = "0.1.41"
tracing-subscriber = "0.3.20"
url = "2.5.4"
uuid = { version = "1.16.0", features = ["serde", "v4"] }
winreg = "0.55"
wslpath2 = "0.1"
zeroize = "1.8.1"

[workspace.dependencies.reqwest]
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ The [`examples/`](examples/) directory contains example projects to help you get
- **Rust canisters** — [Rust](https://rustup.rs/) and `rustup target add wasm32-unknown-unknown`
- **Motoko canisters** — [mops](https://cli.mops.one/) and `mops toolchain init`

**Other dependencies:**
- Docker — always required on Windows (with WSL2), and some projects may require it on other platforms.

## Getting Help

- **[Documentation](docs/index.md)** — Guides, concepts, and reference
Expand All @@ -69,12 +72,13 @@ Contributions are welcome! See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for gu
- Rust 1.88.0+ ([rustup.rs](https://rustup.rs/))
- Platform dependencies:

| Platform | Install |
|----------|---------|
| macOS | `xcode-select --install` |
| Ubuntu/Debian | `sudo apt install build-essential pkg-config libssl-dev` |
| Fedora/RHEL | `sudo dnf install gcc pkg-config openssl-devel` |
| Arch Linux | `sudo pacman -S base-devel openssl` |
| Platform | Install |
|---------------|----------------------------------------------------------------------------------------------------------|
| macOS | `xcode-select --install` |
| Ubuntu/Debian | `sudo apt install build-essential pkg-config libssl-dev` |
| Fedora/RHEL | `sudo dnf install gcc pkg-config openssl-devel` |
| Arch Linux | `sudo pacman -S base-devel openssl` |
| Windows | VS build tools (see [Rustup's guide](https://rust-lang.github.io/rustup/installation/windows-msvc.html)) |

### Build and Test

Expand Down
13 changes: 11 additions & 2 deletions crates/icp-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ byte-unit.workspace = true
camino-tempfile.workspace = true
candid_parser = { workspace = true, features = ["assist"] }
candid.workspace = true
cargo-generate = { version = "0.23.7", features = ["vendored-openssl"] }
cargo-generate = { version = "0.23.7" }
clap-markdown.workspace = true
clap.workspace = true
console.workspace = true
dialoguer.workspace = true
dunce.workspace = true
elliptic-curve.workspace = true
futures.workspace = true
hex.workspace = true
Expand Down Expand Up @@ -52,27 +53,35 @@ sec1.workspace = true
serde_json.workspace = true
serde_yaml.workspace = true
serde.workspace = true
shellwords.workspace = true
snafu.workspace = true
sysinfo.workspace = true
tiny-bip39.workspace = true
tokio.workspace = true
tracing-subscriber.workspace = true
tracing.workspace = true
url.workspace = true
wslpath2.workspace = true

[target.'cfg(unix)'.dependencies]
cargo-generate = { version = "0.23.7", features = ["vendored-openssl"] }

[dev-dependencies]
assert_cmd = "2"
camino-tempfile = "1"
indoc.workspace = true
icp = { workspace = true }
nix = { version = "0.30.1", features = ["process", "signal"] }
predicates = "3"
rand.workspace = true
send_ctrlc = "0.6"
serde_yaml.workspace = true
serial_test = { version = "3.2.0", features = ["file_locks"] }
test-tag = "0.1"
uuid.workspace = true

[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.30.1", features = ["process", "signal"] }

[lints]
workspace = true

Expand Down
5 changes: 2 additions & 3 deletions crates/icp-cli/src/commands/canister/settings/update.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use anyhow::bail;
use byte_unit::{Byte, Unit};
use clap::{ArgAction, Args};
use console::Term;
use dialoguer::Confirm;
use ic_agent::Identity;
use ic_agent::export::Principal;
use ic_management_canister_types::{CanisterStatusResult, EnvironmentVariable, LogVisibility};
use icp::ProjectLoadError;
use icp::context::{CanisterSelection, Context};
use icp::context::{CanisterSelection, Context, TermWriter};
use std::collections::{HashMap, HashSet};
use std::io::Write;

Expand Down Expand Up @@ -452,7 +451,7 @@ fn get_environment_variables(
}

fn maybe_warn_on_env_vars_change(
mut term: &Term,
mut term: &TermWriter,
configured_settings: &icp::canister::Settings,
environment_variables_opt: &EnvironmentVariableOpt,
) -> Result<(), anyhow::Error> {
Expand Down
44 changes: 1 addition & 43 deletions crates/icp-cli/src/logging.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,11 @@
use std::io::Write;
#[cfg(unix)]
use std::os::fd::{AsRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawHandle, RawHandle};

use tracing::{Level, Subscriber, debug};
use tracing::{Level, Subscriber};
use tracing_subscriber::{
Layer,
filter::{Filtered, Targets},
fmt::format,
registry::LookupSpan,
};

#[derive(Debug)]
pub(crate) struct TermWriter<W> {
pub(crate) debug: bool,
pub(crate) writer: Box<W>,
}

impl<W: Write> Write for TermWriter<W> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
if !self.debug {
self.writer.write(buf)?;
}
debug!("{}", String::from_utf8_lossy(buf).trim());
Ok(buf.len())
}

fn flush(&mut self) -> std::io::Result<()> {
if !self.debug {
self.writer.flush()?;
}
Ok(())
}
}

#[cfg(unix)]
impl<W: AsRawFd> AsRawFd for TermWriter<W> {
fn as_raw_fd(&self) -> RawFd {
self.writer.as_raw_fd()
}
}
#[cfg(windows)]
impl<W: AsRawHandle> AsRawHandle for TermWriter<W> {
fn as_raw_handle(&self) -> RawHandle {
self.writer.as_raw_handle()
}
}

type DebugLayer<S> = Filtered<
tracing_subscriber::fmt::Layer<S, format::DefaultFields, format::Format<format::Full, ()>>,
Targets,
Expand Down
Loading