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
199 changes: 199 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
name: Native install packages

# Build the native OS install packages (#503) — the Windows .msi, macOS .pkg, and Ubuntu .deb —
# that ARE the install architecture (the dig-installer just fetches + runs them). Each package
# installs the binary, registers the OS service `net.dignetwork.dig-node`, the chia:// scheme
# handler (→ `dig-node open`), and the restrictive machine-wide state dir (#501).
#
# * pull_request → BUILD all three (validation only; no publish), so a broken package definition
# is caught on the PR (release.yml is tag/main-only and does not build packages).
# * push tag v* → build all three AND attach them to the GitHub Release. The Ubuntu .deb is a
# release ASSET (apt.dig.net's deploy ingests upstream GitHub release .debs to build the signed
# apt repo — no push needed; the .deb name + control metadata are apt-correct + stable).
on:
pull_request:
paths:
- "packaging/**"
- "src/**"
- "crates/**"
- "Cargo.toml"
- "Cargo.lock"
- ".github/workflows/package.yml"
push:
tags:
- "v*"
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: "0"
CARGO_PROFILE_RELEASE_DEBUG: "0"

jobs:
# ---- Ubuntu .deb ----------------------------------------------------------
deb:
name: build .deb (linux-x64)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Rust
run: |
rustup toolchain install stable
rustup default stable
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-pkg-deb-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-pkg-deb-
- name: Resolve version
id: ver
run: |
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then V="${GITHUB_REF_NAME#v}"; else
V="$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"(.*)".*/\1/')"; fi
echo "v=$V" >> "$GITHUB_OUTPUT"
- name: Build release binary
run: cargo build --release --locked --bin dig-node
- name: Build .deb
run: bash packaging/linux/build-deb.sh target/release/dig-node "${{ steps.ver.outputs.v }}" amd64 dist
- name: Validate .deb metadata
run: |
dpkg-deb --info dist/*.deb
dpkg-deb --contents dist/*.deb
- uses: actions/upload-artifact@v4
with:
name: dig-node-deb
path: dist/*.deb
if-no-files-found: error

# ---- macOS .pkg (universal) ----------------------------------------------
pkg:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +35 to +75
name: build .pkg (macos-universal)
runs-on: macos-14
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Rust + targets
run: |
rustup toolchain install stable
rustup default stable
rustup target add aarch64-apple-darwin x86_64-apple-darwin
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-pkg-mac-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-pkg-mac-
- name: Resolve version
id: ver
run: |
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then V="${GITHUB_REF_NAME#v}"; else
V="$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"(.*)".*/\1/')"; fi
echo "v=$V" >> "$GITHUB_OUTPUT"
- name: Build both arches + lipo a universal binary
run: |
cargo build --release --locked --target aarch64-apple-darwin --bin dig-node
cargo build --release --locked --target x86_64-apple-darwin --bin dig-node
mkdir -p dist
lipo -create -output dist/dig-node \
target/aarch64-apple-darwin/release/dig-node \
target/x86_64-apple-darwin/release/dig-node
lipo -info dist/dig-node
- name: Build .pkg
run: bash packaging/macos/build-pkg.sh dist/dig-node "${{ steps.ver.outputs.v }}" dist
- uses: actions/upload-artifact@v4
with:
name: dig-node-pkg
path: dist/*.pkg
if-no-files-found: error

# ---- Windows .msi ---------------------------------------------------------
msi:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +76 to +120
name: build .msi (windows-x64)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Rust
shell: bash
run: |
rustup toolchain install stable
rustup default stable
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-pkg-msi-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-pkg-msi-
- name: Resolve version
id: ver
shell: bash
run: |
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then V="${GITHUB_REF_NAME#v}"; else
V="$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"(.*)".*/\1/')"; fi
echo "v=$V" >> "$GITHUB_OUTPUT"
- name: Build release binary
run: cargo build --release --locked --bin dig-node
- name: Install WiX
shell: bash
run: |
# Pin WiX v5.0.2 — the last release BEFORE the v6+ Open Source Maintenance Fee (OSMF)
# EULA gate (WIX7015), which cannot be accepted non-interactively in CI. The .wxs uses the
# v4 schema namespace, which v5 supports. Pin the extension to the SAME version so the
# WixToolset.Util.wixext major matches the toolset (a mismatched ext major fails to load).
dotnet tool install --global wix --version 5.0.2
wix extension add -g WixToolset.Util.wixext/5.0.2
- name: Build .msi
shell: bash
run: |
mkdir -p dist
wix build packaging/windows/dig-node.wxs \
-ext WixToolset.Util.wixext \
-arch x64 \
-d Version="${{ steps.ver.outputs.v }}" \
-d BinDir="target/release" \
-o "dist/dig-node-${{ steps.ver.outputs.v }}-windows-x64.msi"
- uses: actions/upload-artifact@v4
with:
name: dig-node-msi
path: dist/*.msi
if-no-files-found: error

# ---- Attach to the GitHub Release (tags only) -----------------------------
publish:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +121 to +176
name: Attach packages to the release
needs: [deb, pkg, msi]
if: github.ref_type == 'tag'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
- name: Flatten
run: |
mkdir -p release
find artifacts -type f \( -name '*.deb' -o -name '*.pkg' -o -name '*.msi' \) -exec cp {} release/ \;
ls -la release
- name: Attach to release
uses: softprops/action-gh-release@v2
with:
files: release/*
# Do NOT regenerate notes — release.yml (the binary release) owns the notes; this job
# only appends the native-package assets to the same tag's release.
generate_release_notes: false
fail_on_unmatched_files: true
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ edition = "2021"
# (`[workspace.package].version`), so it MUST be set here for a release to fire
# (§3.6). The library crates (dig-node-core/dig-runtime/dig-wallet) keep their own
# independent versions — only the released binary tracks the workspace version.
version = "0.27.0"
version = "0.28.0"

# Release hardening, matching digstore: keep integer-overflow checks ON in release.
# The node parses untrusted serialized input and does offset/length arithmetic over
Expand Down
41 changes: 41 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,47 @@ out to both listeners (§4.1).

9.6. **Uninstall.** `uninstall` performs a best-effort `stop` first, then removes the registration.

### 9.7. Native install packages (#503)

The canonical end-user install path is a NATIVE OS PACKAGE built by this repo's CI (`package.yml`),
published as GitHub Release assets on each `vX.Y.Z` tag. The `dig-installer` simply fetches + runs
the right package; it does not re-implement service registration. Each package installs the binary,
registers the OS service, registers the `chia://` scheme handler (→ `dig-node open`, §8.5), creates
the machine-wide state dir (§7.3a), and sets the `dig.local` → `127.0.0.2` hosts entry (via the
idempotent, no-shell `dig-node ensure-hosts`, §8.1). The `dig-node install`/`uninstall` CLI (§9.1)
remains for manual/dev use.

- **Windows `.msi`** (WiX; `dig-node-<ver>-windows-x64.msi`). Installs `dig-node.exe` under
`%ProgramFiles%\DIG Network\dig-node\`; `ServiceInstall`+`ServiceControl` register
`net.dignetwork.dig-node` (DisplayName **"DIG NETWORK: NODE"**) running `dig-node.exe run-service`
as LocalSystem, auto-start, STARTED on install, STOPPED+REMOVED on uninstall; creates
`C:\ProgramData\DigNode` with a **restrictive DACL — inheritance broken, only SYSTEM +
Administrators (never Users)** so the token is not world-readable (§7.3a; dig-node leaves a
pre-existing dir's ACL intact); registers `chia://` under `HKLM\Software\Classes\chia`
(`shell\open\command` = `"…\dig-node.exe" open "%1"`); appends the install dir to the system PATH;
runs `dig-node ensure-hosts` as a deferred (SYSTEM) custom action. A stable `UpgradeCode` +
`MajorUpgrade` give clean in-place upgrades.
- **macOS `.pkg`** (`dig-node-<ver>-macos.pkg`, universal arm64+x86_64). Installs `dig-node` to
`/usr/local/bin`; a LaunchDaemon `/Library/LaunchDaemons/net.dignetwork.dig-node.plist`
(`RunAtLoad`+`KeepAlive`, `run` with `DIG_NODE_RUN_CONTEXT=service`); a tiny AppleScript app
(`/Applications/DIG Network.app`, `CFBundleURLTypes` for the `chia` scheme) forwards URL opens to
`dig-node open`; `postinstall` creates the restrictive state dir, `launchctl bootstrap`s the
daemon, and registers the handler with LaunchServices.
- **Ubuntu `.deb`** (`dig-node_<ver>_amd64.deb`; `Package: dig-node`, `Depends: libc6`). Installs
`/usr/bin/dig-node`; a systemd system unit `net.dignetwork.dig-node.service` (auto-start,
`Restart=on-failure`, `DIG_NODE_RUN_CONTEXT=service`); a `.desktop` with
`MimeType=x-scheme-handler/chia` registered as the system default handler; `postinst` creates
`/var/lib/dig-node` (root-owned `0700`), the hosts entry, and enables+starts the unit; `prerm`
stops+disables it. The filename + control metadata are **apt-correct + stable** so apt.dig.net
ingests the Release asset to build its signed apt repo (the repo is GPG-signed by apt.dig.net; the
`.deb` itself needs no code-signing cert).
- **Scheme registration scope.** All three register the DIG-specific **`chia://`** scheme. The
`urn:dig:chia:` textual form is accepted by `dig-node open` (§8.5) but is NOT registered as a
global OS handler — doing so would hijack the entire `urn:` scheme (every URN on the machine).
- **Unix service identity.** The systemd/launchd services run as **root**, so `/var/lib/dig-node`
and `/Library/Application Support/DigNode` are root-owned `0700` and a non-root operator drives
control with `sudo dig-node pair` (the remedy the CLI prints, §7.3a).

---

## 10. Error-code catalogue (JSON-RPC wire)
Expand Down
Loading
Loading