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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v7
- name: Validate initial Cargo publication guards
run: node --test scripts/initial-publish-context.test.mjs

- name: Read supported specification revision
id: specification
shell: bash
Expand Down Expand Up @@ -140,6 +143,9 @@ jobs:
COMP_CWORD=3
_stack_completion
test "${COMPREPLY[*]}" = default_icons_path
- name: Verify crates.io source package
run: cargo +stable publish --dry-run -p stack-diagram-cli --locked

- name: Run canonical formatter suite
env:
STACK_SPECIFICATION_DIR: ${{ github.workspace }}/.stack-specification
Expand Down
123 changes: 123 additions & 0 deletions .github/workflows/initial-publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Initial crates.io publish

on:
workflow_dispatch:
inputs:
expected_sha:
description: Exact main commit whose CI has succeeded
required: true
type: string

permissions:
contents: read
actions: read

concurrency:
group: initial-crates-io-publish
cancel-in-progress: false

defaults:
run:
shell: bash

jobs:
publish:
runs-on: ubuntu-24.04
timeout-minutes: 15
env:
EXPECTED_SHA: ${{ inputs.expected_sha }}
steps:
- name: Reject unexpected dispatch context
run: |
test "$GITHUB_REPOSITORY" = stack-sh/cli
test "$GITHUB_REF" = refs/heads/main
[[ "$EXPECTED_SHA" =~ ^[0-9a-f]{40}$ ]]
test "$GITHUB_SHA" = "$EXPECTED_SHA"

- name: Check out the exact dispatch commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.sha }}
persist-credentials: false

- name: Install the minimum supported Rust toolchain
run: rustup toolchain install 1.85.0 --profile minimal

- name: Verify package identity and successful main CI
env:
GH_TOKEN: ${{ github.token }}
run: |
test "$(git rev-parse HEAD)" = "$EXPECTED_SHA"
cargo +1.85.0 metadata --no-deps --locked --format-version 1 > "$RUNNER_TEMP/package.json"
gh run list --repo stack-sh/cli --workflow ci.yaml --event push --branch main --commit "$EXPECTED_SHA" --limit 1 --json status,conclusion,headSha > "$RUNNER_TEMP/ci.json"
node scripts/initial-publish-context.mjs "$RUNNER_TEMP/package.json" "$RUNNER_TEMP/ci.json"

- name: Require an unpublished crate name
run: |
code=$(curl --silent --show-error --max-time 30 --user-agent 'stack-sh/cli initial publication (https://github.com/stack-sh/cli)' --output "$RUNNER_TEMP/crate-state.json" --write-out '%{http_code}' https://crates.io/api/v1/crates/stack-diagram-cli)
test "$code" = 404

- name: Verify the exact source package without credentials
run: cargo +1.85.0 publish --package stack-diagram-cli --registry crates-io --locked --dry-run

- name: Publish the initial crate
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_INITIAL_PUBLISH_TOKEN }}
run: |
test -n "$CARGO_REGISTRY_TOKEN"
cargo +1.85.0 publish --package stack-diagram-cli --registry crates-io --locked

verify-install:
needs: publish
name: Cargo install (${{ matrix.target }}, Rust ${{ matrix.rust }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 25
permissions:
contents: read
strategy:
fail-fast: false
matrix:
rust: ["1.85.0", stable]
target: [aarch64-apple-darwin, x86_64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-unknown-linux-gnu]
include:
- target: aarch64-apple-darwin
runner: macos-15
- target: x86_64-apple-darwin
runner: macos-15-intel
- target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm
- target: x86_64-unknown-linux-gnu
runner: ubuntu-24.04
steps:
- name: Check out smoke tests at the published source commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Install the selected Rust toolchain
env:
RUST_VERSION: ${{ matrix.rust }}
TARGET: ${{ matrix.target }}
run: |
rustup toolchain install "$RUST_VERSION" --profile minimal
rustc "+$RUST_VERSION" -vV | grep -F "host: $TARGET"
- name: Install only from crates.io into an isolated directory
env:
CARGO_HOME: ${{ runner.temp }}/cargo-registry-home
CARGO_TARGET_DIR: ${{ runner.temp }}/cargo-registry-target
RUST_VERSION: ${{ matrix.rust }}
run: cargo "+$RUST_VERSION" install stack-diagram-cli --version 0.5.1 --locked --registry crates-io --root "$RUNNER_TEMP/cargo-install"
- name: Verify commands, generated assets, and machine-readable output
env:
STACK_BINARY: ${{ runner.temp }}/cargo-install/bin/stack
TARGET: ${{ matrix.target }}
run: |
python3 - <<'PY'
import os
from pathlib import Path
from scripts.verify_release_binary import verify_architecture, verify_commands
binary = Path(os.environ["STACK_BINARY"])
verify_architecture(binary, os.environ["TARGET"])
verify_commands(binary, "0.5.1")
print("Verified registry-only Cargo installation and CLI commands")
PY
26 changes: 15 additions & 11 deletions Cargo.lock

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

20 changes: 14 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
[package]
name = "stack-cli"
version = "0.5.0"
name = "stack-diagram-cli"
version = "0.5.1"
edition = "2024"
rust-version = "1.85"
publish = false
publish = ["crates-io"]
homepage = "https://stack-diagram.com/"
documentation = "https://stack-diagram.com/docs/guide/getting-started"
keywords = ["stack", "diagram", "cli", "svg"]
categories = ["command-line-utilities", "visualization"]
include = ["/src/**", "/templates/**", "/catalogs/**", "/tests/fixtures/**", "/LICENSE", "/NOTICE", "/THIRD_PARTY_LICENSES.md", "/README.md", "/Cargo.lock"]
description = "Native command-line interface for Stack diagrams"
repository = "https://github.com/stack-sh/cli"
license = "Apache-2.0"
readme = "README.md"

[lib]
name = "stack_cli"

[[bin]]
name = "stack"
path = "src/main.rs"
Expand All @@ -19,9 +27,9 @@ serde = { version = "=1.0.229", features = ["derive"] }
serde_json = "=1.0.151"
serde_yaml_ng = "=0.10.0"
sha2 = "=0.11.0"
stack-compiler = { git = "https://github.com/stack-sh/compiler.git", rev = "84ab5663a7f7c5b7dc0b5e9e2f04c8894ed02820" }
stack-engine = { git = "https://github.com/stack-sh/engine.git", rev = "9af727aea79233b8389e0ed6fdbae7d3f388dc29" }
stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "7e208d6a3c90d255799f390a4e8b86248c73caee" }
stack-compiler = "=0.1.0"
stack-engine = "=0.7.0"
stack-theme = "=0.5.0"
ureq = { version = "=3.4.0", default-features = false, features = ["rustls"] }
zip = { version = "=6.0.0", default-features = false, features = ["deflate-flate2-zlib-rs"] }

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ stack fmt -
stack render arch.stack
stack render arch.stack -o arch.svg
stack render arch.stack --json
stack update --check
stack lsp
stack doctor
stack doctor --provider-pack .stack-icons
Expand Down Expand Up @@ -146,3 +145,7 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) before opening a change. Please report
## Licensing

Repository-authored work is licensed under the [Apache License 2.0](./LICENSE) for personal and commercial use. Runtime and build dependency licenses are recorded in [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md). Every published binary archive ships the applicable license and notice files described there.

## Cargo source package

The source package is named `stack-diagram-cli`; its binary remains `stack`. All Rust dependencies resolve from crates.io. Consult the [current installation guide](https://stack-diagram.com/docs/guide/getting-started) for verified releases and installation commands. A source change does not activate a distribution channel or replace existing release archives. Maintainers follow the [Cargo publication procedure](https://github.com/stack-sh/cli/blob/main/docs/cargo-releasing.md).
6 changes: 3 additions & 3 deletions THIRD_PARTY_LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Audit date: 2026-09-05

| Component | Version or revision | License | Source | Distribution note |
| --- | --- | --- | --- | --- |
| `stack-engine` / `stack-formatter` | `9af727aea79233b8389e0ed6fdbae7d3f388dc29` | Apache-2.0 | <https://github.com/stack-sh/engine> | Linked into the native binary; validates and renders caller-owned provider packs without bundling vendor assets. |
| `stack-compiler` | `84ab5663a7f7c5b7dc0b5e9e2f04c8894ed02820` | Apache-2.0 | <https://github.com/stack-sh/compiler> | Linked directly for protocol-neutral language intelligence and transitively through `stack-engine`; performs no runtime I/O. |
| `stack-theme` | `7e208d6a3c90d255799f390a4e8b86248c73caee` | Apache-2.0 | <https://github.com/stack-sh/theme> | Linked directly and through `stack-engine`; its 30 fallback and 12 explicit core SVGs are Stack-authored Apache-2.0 assets. It also provides the asset-free provider-pack contract and types. |
| `stack-engine` / `stack-formatter` | `0.7.0` / `0.1.0` (crates.io) | Apache-2.0 | <https://github.com/stack-sh/engine> | Linked into the native binary; validates and renders caller-owned provider packs without bundling vendor assets. |
| `stack-compiler` | `0.1.0 (crates.io)` | Apache-2.0 | <https://github.com/stack-sh/compiler> | Linked directly for protocol-neutral language intelligence and transitively through `stack-engine`; performs no runtime I/O. |
| `stack-theme` | `0.5.0 (crates.io)` | Apache-2.0 | <https://github.com/stack-sh/theme> | Linked directly and through `stack-engine`; its 30 fallback and 12 explicit core SVGs are Stack-authored Apache-2.0 assets. It also provides the asset-free provider-pack contract and types. |
| `roxmltree` | `0.21.1` | MIT OR Apache-2.0 | <https://github.com/RazrFalcon/roxmltree> | Parses untrusted local SVG into a read-only tree before allowlisted serialization. |
| `sha2`, `digest`, `block-buffer`, `crypto-common`, `hybrid-array`, `const-oid`, `typenum` | `0.11.0`, `0.11.3`, `0.12.1`, `0.2.2`, `0.4.14`, `0.10.2`, `1.20.1` | MIT OR Apache-2.0 | <https://github.com/RustCrypto> | Computes complete archive and per-asset SHA-256 identities. |
| `zip` | `6.0.0` | MIT | <https://github.com/zip-rs/zip2> | Reads audited, allowlisted entries from verified official ZIP archives. |
Expand Down
Loading