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
1 change: 1 addition & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[alias]
build-examples = "run --quiet -p xtask -- build-examples"
fmt-markdown = "run --quiet -p xtask -- fmt-markdown"
validate = "run --quiet -p xtask -- validate"
17 changes: 16 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Rust
uses: dtolnay/rust-toolchain@6255b92812bf51d292e488b61469267a391267f6 # stable
uses: dtolnay/rust-toolchain@3fc1e40d4c4ce3007de028907c886bc3996ce2ea # 1.96.0
with:
components: rustfmt

Expand All @@ -32,6 +32,21 @@ jobs:
- name: Verify Cargo.lock is up to date
run: cargo metadata --locked --format-version 1 > /dev/null

# `cargo validate markdown` installs the rumdl version pinned in
# xtask/src/markdown.rs into target/tools on first use.
- name: Cache Markdown tooling
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: target/tools
key: markdown-tools-${{ runner.os }}-${{ hashFiles('xtask/src/markdown.rs') }}

- name: Validate Markdown
run: |
if ! cargo validate markdown; then
echo "::error::Markdown formatting check failed. Run \`cargo fmt-markdown\` locally and commit the result."
exit 1
fi

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
Expand Down
32 changes: 32 additions & 0 deletions .rumdl.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Markdown formatting for human-authored docs. Run `cargo fmt-markdown` to
# rewrap; `cargo validate markdown` checks formatting in CI.

[global]
# Only enforce line wrapping and table alignment; other markdownlint-style
# rules are out of scope.
enable = ["MD013", "MD060"]
line-length = 80
cache = false
exclude = [
# Assembled from changelog fragments by the release tooling.
"CHANGELOG.md",
# Each nonempty line in a fragment is a separate changelog item, so
# fragments must not be wrapped.
"changelog/*/*.md",
]

[MD013]
reflow = true
# Rejoin and rewrap whole paragraphs so edited text can simply be reformatted.
reflow-mode = "normalize"
code-blocks = false
# Long inline code spans cannot be wrapped; do not flag lines they push past
# the limit.
code-spans = false
headings = false
# Tables are aligned by MD060 instead of wrapped.
tables = false

[MD060]
enabled = true
style = "aligned"
45 changes: 27 additions & 18 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@
```

- Focused checks are appropriate while iterating, but do not push without the
full command passing. It covers Rust formatting and tests plus the checked-in
Python, TypeScript, Go, Java, and .NET sample projects.
full command passing. It covers Rust formatting and tests, Markdown
formatting, plus the checked-in Python, TypeScript, Go, Java, and .NET sample
projects.

```sh
cargo validate python
```

- When running Rust tests directly, pass the feature flag to test the "advanced" features:
- Human-authored Markdown is wrapped at 80 columns. After editing Markdown,
rewrap it with `cargo fmt-markdown` (configured in `.rumdl.toml`) rather than
wrapping by hand.

- When running Rust tests directly, pass the feature flag to test the "advanced"
features:

```sh
cargo test --all-features
Expand All @@ -28,11 +34,11 @@ When asked to create a stack of pull requests, use the
[`gh-stack`](https://github.com/github/gh-stack) GitHub CLI extension rather
than creating and linking the PRs manually.

- If `gh stack` is unavailable, install it with `gh extension install
github/gh-stack`.
- Initialize the stack from its trunk branch, normally with `gh stack init
--base main <bottom-branch>`, then add each successive layer from the current
top branch with `gh stack add <branch>`.
- If `gh stack` is unavailable, install it with
`gh extension install github/gh-stack`.
- Initialize the stack from its trunk branch, normally with
`gh stack init --base main <bottom-branch>`, then add each successive layer
from the current top branch with `gh stack add <branch>`.
- Commit each layer independently. Use `gh stack push` to publish every branch
and `gh stack submit` to create the PRs with the correct parent branches.
- Use `gh stack view` to inspect the stack. When the trunk or lower layers
Expand All @@ -44,9 +50,10 @@ github/gh-stack`.
- Never edit generated sample output directly. Change the authored input,
generator, or shared model as appropriate, then regenerate the affected
outputs with the generator.
- JSON Schema sample outputs: `cargo build-examples --format json-schema [--lang <language>]`.
- Advanced WIT sample outputs: `cargo build-examples --format wit [--lang <language>]
[<example>]`.
- JSON Schema sample outputs:
`cargo build-examples --format json-schema [--lang <language>]`.
- Advanced WIT sample outputs:
`cargo build-examples --format wit [--lang <language>] [<example>]`.
- Review regenerated diffs to ensure they are the intended consequence of the
source change.

Expand All @@ -67,17 +74,18 @@ github/gh-stack`.
- Keep JSON and JSON Schema concerns within the relevant JSON Schema parser,
planning, generator, and `src/json_schema/` components. Do not introduce JSON
knowledge into generic or unrelated modules.
- Put target-language policy and rendering decisions in that language's files
or modules (for example `src/generator/python.rs` and
- Put target-language policy and rendering decisions in that language's files or
modules (for example `src/generator/python.rs` and
`src/generator/json_schema/python.rs`). Shared code may represent language
neutral concepts, but must not encode one target's conventions.

### Planning

When planning a change, map each change onto one or more existing architectural component
such as parsing or specific passes. If the change requires adding a pass then explicitly
identify it as a new addition to the architecture. Each change should have a
justification for why it belongs where it is planned in the architecture.
When planning a change, map each change onto one or more existing architectural
component such as parsing or specific passes. If the change requires adding a
pass then explicitly identify it as a new addition to the architecture. Each
change should have a justification for why it belongs where it is planned in the
architecture.

## Documentation and public changes

Expand All @@ -93,7 +101,8 @@ justification for why it belongs where it is planned in the architecture.
- Choose a fun, whimsical lowercase kebab-case filename, such as
`moonwalking-marshmallow.md`. Keep entries concise, ideally a sentence or two.
Each nonempty line becomes one bullet; omit the leading `-`. Multiple items
from one PR can share a fragment, but unrelated PRs should have separate files.
from one PR can share a fragment, but unrelated PRs should have separate
files.
- `CHANGELOG.md` contains completed releases only. See `changelog/README.md`.

## Compatibility
Expand Down
46 changes: 24 additions & 22 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
# Contributing

Run `cargo validate` before pushing; it validates Rust and all five language
sample projects. Follow the generated sample guidance in [AGENTS.md](AGENTS.md).
Run `cargo validate` before pushing; it validates Rust, Markdown formatting, and
all five language sample projects. Run `cargo fmt-markdown` to rewrap Markdown
you have edited. Follow the generated sample guidance in [AGENTS.md](AGENTS.md).

## Running tests

`cargo test --all-features` runs the Rust-only suite, including parsing,
planning, CLI behavior, and generated-source assertions for every language.
It does not require Python, Node, Go, Java, or .NET tooling.
planning, CLI behavior, and generated-source assertions for every language. It
does not require Python, Node, Go, Java, or .NET tooling.

Use `cargo validate <language>` to validate one language: `rust`, `python`,
`typescript`, `go`, `java`, or `dotnet`. Each non-Rust stage checks generated
sample freshness, runs the sample projects' native checks, and exercises
generated-code regressions using the applicable compilers, formatters, and runtimes.
Go, Java, Python, and TypeScript validation also check JSON Schema conformance
cases, format and pattern corpora, and generated-output compilation probes.
generated-code regressions using the applicable compilers, formatters, and
runtimes. Go, Java, Python, and TypeScript validation also check JSON Schema
conformance cases, format and pattern corpora, and generated-output compilation
probes.

Toolchain tests are integration-test targets in the `nexgen-validation-tests`
package under `validation-tests/`. For focused debugging after dependencies are
Expand All @@ -34,11 +36,11 @@ Java, Python, and TypeScript. It requires all four toolchains and checks
acceptance, validation errors, and serialized values against expected results
and across backends. It also checks that declared divergences remain necessary.
These checks use unformatted generator output so formatters cannot hide syntax
defects. `cargo validate` runs all language stages followed by this cross-language
check.
defects. `cargo validate` runs all language stages followed by this
cross-language check.

Validation writes per-stage logs to `target/validate-logs/`. Use `--verbose`
to also see command output in the terminal.
Validation writes per-stage logs to `target/validate-logs/`. Use `--verbose` to
also see command output in the terminal.

Public-facing changes need a [changelog fragment](changelog/README.md).

Expand All @@ -51,18 +53,18 @@ python3 scripts/prepare_release.py 0.3.0
```

The script creates or resumes `chore/release-0.3.0`, updates the crate and
lockfile versions, verifies the lockfile, assembles a dated release section,
and consumes fragments. It regenerates samples, commits the release changes,
pushes, and opens or reuses the release PR. Empty releases are allowed.
`--date YYYY-MM-DD` overrides the release date.
Resuming a prepared release preserves its changelog and any later fragments.
Release PRs use the `skip-changelog` label because they consume existing entries.
lockfile versions, verifies the lockfile, assembles a dated release section, and
consumes fragments. It regenerates samples, commits the release changes, pushes,
and opens or reuses the release PR. Empty releases are allowed.
`--date YYYY-MM-DD` overrides the release date. Resuming a prepared release
preserves its changelog and any later fragments. Release PRs use the
`skip-changelog` label because they consume existing entries.

After merging, run the **Create Release** workflow from main. It uses the
shared tool to extract the completed changelog section for the draft GitHub
release, attaches binaries, and publishes the crate.
After merging, run the **Create Release** workflow from main. It uses the shared
tool to extract the completed changelog section for the draft GitHub release,
attaches binaries, and publishes the crate.

GitHub Actions checks out a pinned SDK Rust revision to build only the shared
changelog CLI for fragment validation and release-note extraction. Local release
preparation needs no SDK Rust checkout; Nexgen has no Core submodule.
Keep the tool pins in the changelog and Create Release workflows consistent.
preparation needs no SDK Rust checkout; Nexgen has no Core submodule. Keep the
tool pins in the changelog and Create Release workflows consistent.
Loading
Loading