name: ci
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --all-targets
- run: cargo test --all-targets -- --test-threads=1
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets -- -D warnings
demo-invite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: sudo apt-get update && sudo apt-get install -y jq
- run: cargo build --release --bin wire
- run: WIRE=./target/release/wire bash demo-invite.sh
demo-command:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --release --bin wire
- run: ./target/release/wire demo --json | tee /dev/stderr | grep -q '"ok":true'
demo-hotline:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: sudo apt-get update && sudo apt-get install -y jq
- run: cargo build --release --bin wire
- run: WIRE=./target/release/wire bash demo-hotline.sh
integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: sudo apt-get update && sudo apt-get install -y jq
- run: cargo build --release --bin wire
- run: WIRE=./target/release/wire tests/it/run-all.sh
docs-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: deprecated phrases (canonical surface drift)
run: |
set -e
FILES="README.md AGENTS.md INSTALL.md docs/integrations/*.md docs/AGENT_INTEGRATION.md"
fail=0
check() {
local pattern="$1"
local description="$2"
# Exclude lines inside Legacy sections (best-effort: grep -v on
# the line itself contains 'Legacy' marker; deeper context
# exclusion would need a real parser).
hits=$(grep -nE "$pattern" $FILES 2>/dev/null \
| grep -v -iE '(legacy|deprecated|removed|v1\.0 removes)' \
|| true)
if [ -n "$hits" ]; then
echo "::error::Deprecated phrase '$description' found in docs:"
echo "$hits"
fail=1
fi
}
# The shapes swift-harbor's audit (#145) called out:
check 'wire add [a-z][a-z-]*@' 'wire add <peer>@<relay> (use `wire dial`)'
check 'wire init <nick>' 'wire init <nick> (use `wire up`)'
check 'wire daemon start' 'wire daemon start (no subcommand; use `wire daemon`)'
check 'wire up <nick>@' 'wire up <nick>@<relay> (handle is DID-derived; use `wire up @<relay>`)'
check 'wire\.slancha\.ai' 'wire.slancha.ai (use wireup.net)'
check 'relay\.slancha\.ai' 'relay.slancha.ai (use wireup.net)'
if [ "$fail" -ne 0 ]; then
echo ""
echo "Lint failed: deprecated command phrase(s) drifted back into docs."
echo "Fix the lines above or move them under a 'Legacy' header if intentional."
exit 1
fi
echo "docs-lint: clean."
install-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: sudo apt-get update && sudo apt-get install -y jq
- run: cargo build --release --bin wire
- name: fresh-user smoke (offline, clean WIRE_HOME)
run: |
set -euo pipefail
sudo install -m 0755 target/release/wire /usr/local/bin/wire
export WIRE_HOME="$(mktemp -d)/home" WIRE_QUIET_AUTOSESSION=1
cd "$(mktemp -d)" # clean cwd — no repo, no existing state
wire --version
wire --help >/dev/null
wire whoami --json | jq -e '.initialized == false' # pre-init
# `wire up --no-local` creates the local identity but also tries to
# claim its DID-derived handle on the shared relay — that claim can
# 409 if the random persona is already taken (non-fatal). The real
# check is the local identity, so tolerate a nonzero exit and assert
# via whoami.
wire up --no-local || true
wire whoami --json | jq -e '.did | startswith("did:wire:")'
wire here >/dev/null
echo "install-smoke: fresh-user offline path OK"
- name: nuke smoke (dry-run changes nothing; --force resets; re-up works)
run: |
set -euo pipefail
export WIRE_HOME="$(mktemp -d)/home" WIRE_QUIET_AUTOSESSION=1
wire up --no-local || true
wire whoami --json | jq -e '.did | startswith("did:wire:")' # identity created
wire nuke --dry-run # lists, must change nothing
wire whoami --json | jq -e '.did | startswith("did:wire:")' # dry-run kept it
wire nuke --force --json | jq -e 'has("removed_paths")'
wire whoami --json | jq -e '.initialized == false' # state wiped
wire up --no-local || true # fresh again
wire whoami --json | jq -e '.did | startswith("did:wire:")'
echo "install-smoke: nuke + re-up OK"
install-smoke-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --release --bin wire
- name: fresh-user + nuke smoke (PowerShell)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true # native non-zero exit → throw
$wire = ".\target\release\wire.exe"
$env:WIRE_HOME = Join-Path $env:RUNNER_TEMP ("wh-" + [guid]::NewGuid().ToString("N"))
$env:WIRE_QUIET_AUTOSESSION = "1"
& $wire --version
& $wire --help | Out-Null
$pre = (& $wire whoami --json | ConvertFrom-Json)
if ($pre.initialized -ne $false) { throw "expected initialized:false pre-init" }
# `wire up --no-local` creates the local identity but also tries to
# claim its handle on the shared relay; that claim can 409 (handle
# already taken) which is non-fatal. Tolerate a nonzero exit and
# assert the real outcome (local DID) via whoami.
try { & $wire up --no-local } catch { Write-Host "wire up claim non-fatal: $_" }
$post = (& $wire whoami --json | ConvertFrom-Json)
if (-not $post.did.StartsWith("did:wire:")) { throw "expected a did:wire: DID" }
& $wire here | Out-Null
& $wire nuke --dry-run
$afterDry = (& $wire whoami --json | ConvertFrom-Json)
if (-not $afterDry.did.StartsWith("did:wire:")) { throw "dry-run must not wipe state" }
& $wire nuke --force --json | ConvertFrom-Json | Out-Null
$afterNuke = (& $wire whoami --json | ConvertFrom-Json)
if ($afterNuke.initialized -ne $false) { throw "nuke --force should wipe state" }
try { & $wire up --no-local } catch { Write-Host "wire up claim non-fatal: $_" }
$fresh = (& $wire whoami --json | ConvertFrom-Json)
if (-not $fresh.did.StartsWith("did:wire:")) { throw "re-up should recreate identity" }
Write-Host "install-smoke-windows: fresh-user + nuke OK"
install-script-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: sudo apt-get update && sudo apt-get install -y jq
- run: cargo build --release --bin wire
- name: install.sh from a clean machine, then fresh-user onboarding
run: |
set -euo pipefail
DIST="$(mktemp -d)"
# Resolve the SAME triple install.sh will request on this runner, so
# the served asset name matches (mirrors install.sh's Linux branch).
case "$(uname -m)" in
x86_64|amd64) triple="x86_64-unknown-linux-musl" ;;
aarch64|arm64) triple="aarch64-unknown-linux-musl" ;;
*) echo "unsupported arch $(uname -m)" >&2; exit 1 ;;
esac
cp target/release/wire "$DIST/wire-$triple"
( cd "$DIST" && sha256sum "wire-$triple" > "wire-$triple.sha256" )
# Serve over http so install.sh's curl exercises the real download +
# SHA-256-sibling verify path (not a file:// shortcut, which would let
# install.sh silently cargo-fall-back to the crates.io release).
# Background the subshell itself (not `& )` inside it) so $! captures
# the server PID — `& )` backgrounds within the subshell and leaves $!
# unset, which is fatal under `set -u`.
( cd "$DIST" && exec python3 -m http.server 8099 >/dev/null 2>&1 ) &
SRV=$!; trap 'kill "$SRV" 2>/dev/null || true' EXIT
for i in $(seq 1 20); do curl -fsS "http://127.0.0.1:8099/wire-$triple.sha256" -o /dev/null && break; sleep 0.5; done
PFX="$(mktemp -d)/bin"
WIRE_DIST_URL="http://127.0.0.1:8099" sh install.sh --prefix "$PFX"
test -x "$PFX/wire" # landed where --prefix said
"$PFX/wire" --version
export WIRE_HOME="$(mktemp -d)/home" WIRE_QUIET_AUTOSESSION=1
cd "$(mktemp -d)" # clean cwd, no repo
"$PFX/wire" whoami --json | jq -e '.initialized == false' # pre-init
# up --offline is PR-only — if install.sh had cargo-fallen-back to the
# crates.io release, this flag wouldn't exist, so it also proves the
# SERVED binary was the one installed.
"$PFX/wire" up --offline
"$PFX/wire" whoami --json | jq -e '.did | startswith("did:wire:")'
echo "install-script-smoke: install.sh + fresh onboarding OK"