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
92 changes: 92 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: CI

on:
push:
branches:
- main
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
check-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Check formatting
run: make check-format

check:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
toolchain: [stable, beta]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Install GNU sed (macOS)
if: runner.os == 'macOS'
run: brew install gnu-sed

- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: clippy

- uses: Swatinem/rust-cache@v2

- name: Check compilation
run: make check

- name: Lint
run: make lint

- name: Test
run: make test

check-trailing-whitespace:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Check trailing whitespace
run: make check-trailing-whitespace

check-format-md:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'

- name: Check markdown formatting
run: make check-format-md

generate-spec:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Install GNU sed (macOS)
if: runner.os == 'macOS'
run: brew install gnu-sed

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Generate specification
run: make generate-spec
2 changes: 1 addition & 1 deletion .github/workflows/releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
- uses: actions/checkout@v3
with:
persist-credentials: false

- uses: taiki-e/github-actions/install-rust@main
with:
toolchain: stable
Expand Down
11 changes: 11 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Build outputs
target/

# Generated files
*.lock

# Config files
*.toml

# Changelog
CHANGELOG.md
13 changes: 13 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "avoid",
"proseWrap": "always",
"endOfLine": "lf"
}
108 changes: 108 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
SED := $(shell command -v gsed 2>/dev/null)
ifeq ($(SED),)
$(error GNU sed (gsed) not found on macOS. \
Install with: brew install gnu-sed)
endif
else
SED := sed
endif

.PHONY: help
help: ## Ask for help!
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; \
{printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: build
build: ## Build the project in debug mode
cargo build

.PHONY: build-release
build-release: ## Build the project in release mode
cargo build --release

.PHONY: check
check: ## Check code for compilation errors
cargo check

.PHONY: check-format
check-format: ## Check code formatting
cargo fmt -- --check

.PHONY: format
format: ## Format code
cargo fmt

.PHONY: lint
lint: ## Run linter
cargo clippy -- -D warnings

.PHONY: test
test: ## Run tests
cargo test

.PHONY: clean
clean: ## Clean build artifacts
cargo clean

.PHONY: generate-spec
generate-spec: ## Generate the specification
cargo run -- spec build

.PHONY: setup
setup: ## Setup development environment
rustup component add clippy rustfmt

.PHONY: check-outdated
check-outdated: ## Check for outdated dependencies
cargo outdated || true

.PHONY: check-format-md
check-format-md: ## Check markdown formatting
npx prettier --check "**/*.md"

.PHONY: format-md
format-md: ## Format markdown files
npx prettier --write "**/*.md"

.PHONY: check-format-yaml
check-format-yaml: ## Check YAML formatting
npx prettier --check "**/*.yaml" "**/*.yml"

.PHONY: format-yaml
format-yaml: ## Format YAML files
npx prettier --write "**/*.yaml" "**/*.yml"

.PHONY: fix-trailing-whitespace
fix-trailing-whitespace: ## Remove trailing whitespaces from all files
@echo "Removing trailing whitespaces from all files..."
@find . -type f \( \
-name "*.rs" -o -name "*.toml" -o -name "*.md" \
-o -name "*.yaml" -o -name "*.yml" \) \
-not -path "./target/*" \
-not -path "./.git/*" \
-exec sh -c \
'echo "Processing: $$1"; $(SED) -i -e "s/[[:space:]]*$$//" "$$1"' \
_ {} \; && \
echo "Trailing whitespaces removed."

.PHONY: check-trailing-whitespace
check-trailing-whitespace: ## Check for trailing whitespaces in source files
@echo "Checking for trailing whitespaces..."
@files_with_trailing_ws=$$(find . -type f \( \
-name "*.rs" -o -name "*.toml" -o -name "*.md" \
-o -name "*.yaml" -o -name "*.yml" \) \
-not -path "./target/*" \
-not -path "./.git/*" \
-exec grep -l '[[:space:]]$$' {} + 2>/dev/null || true); \
if [ -n "$$files_with_trailing_ws" ]; then \
echo "Files with trailing whitespaces found:"; \
echo "$$files_with_trailing_ws" | sed 's/^/ /'; \
echo ""; \
echo "Run 'make fix-trailing-whitespace' to fix automatically."; \
exit 1; \
else \
echo "No trailing whitespaces found."; \
fi
66 changes: 42 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
# Cargo spec   ![](https://img.shields.io/crates/v/cargo-spec.svg)

This is a tool to turn your code into a specification.
It is language agnostic, but you need Cargo (which you can install via [Rustup](https://rustup.rs/)) to use it.
To see it in action, just look at the code in this codebase, as well as [the spec it produced](https://mimoo.github.io/cargo-specification/).
You can read more about the concepts behind it in the blogpost [The code is the specification: introducing cargo-spec](https://cryptologie.net/article/553/the-code-is-the-specification-introducing-cargo-spec/).
This is a tool to turn your code into a specification. It is language agnostic,
but you need Cargo (which you can install via [Rustup](https://rustup.rs/)) to
use it. To see it in action, just look at the code in this codebase, as well as
[the spec it produced](https://mimoo.github.io/cargo-specification/). You can
read more about the concepts behind it in the blogpost
[The code is the specification: introducing cargo-spec](https://cryptologie.net/article/553/the-code-is-the-specification-introducing-cargo-spec/).

## Usage

**initialize**. To start your specification, you need two files: a [`Specification.toml`](#configuration) configuration file and a template containing your specification written in [markdown](https://daringfireball.net/projects/markdown/).
You can create these in your current directory via `cargo spec new <NAME>`, or on a given path via `cargo spec init <PATH>`:
**initialize**. To start your specification, you need two files: a
[`Specification.toml`](#configuration) configuration file and a template
containing your specification written in
[markdown](https://daringfireball.net/projects/markdown/). You can create these
in your current directory via `cargo spec new <NAME>`, or on a given path via
`cargo spec init <PATH>`:

```console
$ cargo install cargo-spec
Expand All @@ -18,7 +24,9 @@ Created new specification as Specification.toml and specification_template.md
You can now run `cargo spec build` to create the specification file
```

**build**. Building your specification will convert your template into the desired format (markdown by default), at some path (`specification.md` by default):
**build**. Building your specification will convert your template into the
desired format (markdown by default), at some path (`specification.md` by
default):

```console
$ cargo spec build
Expand All @@ -36,14 +44,18 @@ $ cargo spec watch

## How to write a specification?

cargo-spec's philosophy stems from the fact that most protocols often come from a reference implementation. That reference implementation tends to change, and as you want your spec to be up to date you will want to keep parts of the spec as close to the code as possible.
cargo-spec's philosophy stems from the fact that most protocols often come from
a reference implementation. That reference implementation tends to change, and
as you want your spec to be up to date you will want to keep parts of the spec
as close to the code as possible.

cargo-spec allows you to write your specification as a markdown file, and extract special "spec comments" from your code to fill in sections of your spec.
cargo-spec allows you to write your specification as a markdown file, and
extract special "spec comments" from your code to fill in sections of your spec.

### Configuration

To run cargo-spec, you need a `Specification.toml` file.
Although you can specify a different filename via the `--specification-path` option.
To run cargo-spec, you need a `Specification.toml` file. Although you can
specify a different filename via the `--specification-path` option.

```toml
[specification]
Expand All @@ -65,8 +77,10 @@ abstract_modules = "@/src/module.rs" # you can also use absolute paths (you need

### Template

A template is simply a markdown file that contains placeholders. The path of the template must be specified in the `Specification.toml` file.
By default the `cargo spec new <NAME>` (or `cargo spec init <PATH>`) command will use `specification_template.md` as template.
A template is simply a markdown file that contains placeholders. The path of the
template must be specified in the `Specification.toml` file. By default the
`cargo spec new <NAME>` (or `cargo spec init <PATH>`) command will use
`specification_template.md` as template.

```markdown
# Consensus specification
Expand All @@ -84,8 +98,8 @@ Here's the consensus spec

### Spec comments in your code

Cargo-spec recognizes comments starting with the tilde `~`.
For example, in rust:
Cargo-spec recognizes comments starting with the tilde `~`. For example, in
rust:

```rust
//~ some specification text
Expand All @@ -103,7 +117,10 @@ or in OCaml:
(*~ some spec *)
```

> While cargo-spec is language-agnostic, it does not support all type of comments. [Post an issue](https://github.com/mimoo/cargo-specification/issues/new) if it does not work for the language you're using.
> While cargo-spec is language-agnostic, it does not support all type of
> comments.
> [Post an issue](https://github.com/mimoo/cargo-specification/issues/new) if it
> does not work for the language you're using.

## Nested lists

Expand All @@ -123,8 +140,8 @@ instead, simply add `~` at the start of your spec comment to add indentation:

## Importing code

You can import blocks of code by surrounding them with `//~ spec:startcode` and `//~ spec:endcode`:

You can import blocks of code by surrounding them with `//~ spec:startcode` and
`//~ spec:endcode`:

```rust
//~ spec:startcode
Expand All @@ -137,8 +154,8 @@ struct SomeStruct {

## Continuous Integration

You'll most likely want to enforce that PRs contains up-to-date specification files checked-in.
You can do this for example with this Github Action:
You'll most likely want to enforce that PRs contains up-to-date specification
files checked-in. You can do this for example with this Github Action:

```yml
name: Check specifications
Expand All @@ -151,7 +168,6 @@ jobs:
runs-on: ubuntu-latest
name: Enforce up-to-date specification files
steps:

- name: Checkout PR
uses: actions/checkout@v2

Expand All @@ -168,9 +184,11 @@ jobs:

## Projects making use of cargo-spec

* [cargo-spec]() ([spec](https://mimoo.github.io/cargo-specification/))
* [kimchi](https://github.com/o1-labs/proof-systems/blob/master/book/specifications/README.md) ([spec](https://o1-labs.github.io/proof-systems/specs/kimchi.html))
- [cargo-spec]() ([spec](https://mimoo.github.io/cargo-specification/))
- [kimchi](https://github.com/o1-labs/proof-systems/blob/master/book/specifications/README.md)
([spec](https://o1-labs.github.io/proof-systems/specs/kimchi.html))

## License

The Cargo spec Project is dual-licensed under Apache 2.0 and MIT terms. See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.
The Cargo spec Project is dual-licensed under Apache 2.0 and MIT terms. See
[LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.
Loading