Skip to content

Latest commit

 

History

History
215 lines (144 loc) · 9.23 KB

CONTRIBUTING.md

File metadata and controls

215 lines (144 loc) · 9.23 KB

Contributing

Prerequisites

Native (recommended for active development)

The Aspire toolchain is bundled as a local dotnet tool — no workload install required.

dotnet tool restore

Docker (zero-install alternative)

If you only need to validate rendering or authoring changes, the Docker setup removes the .NET/Node prerequisite:

./dev.sh build            # build images (once, or after Dockerfile changes)
./dev.sh isolated-serve   # serve docs with hot reload at http://localhost:3000
./dev.sh test             # run the full unit-test suite

The same setup runs the assembled site and the codex. All three modes use the same verbs (<mode>-serve, <mode>-build, <mode>-watch, and <mode>-clone where the mode clones repositories):

Mode Serves URL Commands
isolated One docset (docs/) http://localhost:3000 isolated-serve, isolated-build
assembler Every repository under one navigation http://localhost:4000 assembler-clone, assembler-build, assembler-serve, assembler-watch
codex The codex portal http://localhost:4001 codex-clone, codex-build, codex-serve, codex-watch
./dev.sh assembler-clone    # clone the repositories (first run, needs network)
./dev.sh assembler-watch    # rebuild and reload on every source change

Notes for the assembler and codex modes:

  • They run from source in the tooling image, so local code changes apply without a publish.
  • Builds are static and the site is down while one runs. -watch rebuilds on each change to src/, config/, or docs/, then reloads open pages.
  • Clones and build output live in named volumes. ./dev.sh clean removes them.
  • The image has no ssh, so dev.sh clones over HTTPS. Private repositories need GITHUB_TOKEN or a logged-in gh.
  • The serve commands publish a fixed port and reject --port.
  • codex reads its config from CODEX_CONFIG (default config/codex.example.yml).
  • The assembler builds the API Explorer pages. Set FEATURE_ASSEMBLER_API_EXPLORER=false to skip them and build faster. After changing it, run ./dev.sh assembler-build --no-assume-build once, because the build stamp ignores environment variables.

Run ./dev.sh help for the full list of commands. Docker files live under build/dev/.

Validate the fully assembled documentation

dotnet aspire run

Will spin up all our services and clone and build all the documentation sets.

By default, private repositories are skipped, existing clones are reused, and the build is skipped when code/config/content is unchanged. To opt out of any default:

dotnet aspire run -- --no-skip-private-repositories  # include private repos (requires auth tokens)
dotnet aspire run -- --no-assume-cloned              # force a fresh clone
dotnet aspire run -- --no-assume-build               # force a full rebuild even if stamp matches

--skip-private-repositories (default) injects docs-builder's own docs into the navigation so you can validate new features without production credentials.

Our Integration Tests use these defaults to validate the assembler builds.

Tip: Install the Aspire skills plugin for day-to-day orchestration and monitoring support in Claude Code:

/plugin marketplace add microsoft/aspire-skills
/plugin install aspire@aspire-skills

Continuously build during development

Two watch loops are available depending on what you're working on:

Single-docset watch (authoring, templates, frontend)

./build.sh watch

Monitors code, Razor template files, and frontend assets for a single documentation set. Markdown files refresh via live reload without a recompile. Code or layout changes relaunch the server automatically. Web assets are rebuilt by vite build --watch in the background.

Full assembled-site watch (assembler, navigation, multi-repo)

./build.sh watchall

Runs dotnet watch on the Aspire AppHost. When you edit any .cs file the AppHost restarts, the assembler clone step is skipped (default-on --assume-cloned), and the build step consults the MVID stamp — if code actually changed it rebuilds; otherwise it skips in seconds. No live reload; the site comes back on port 4000 after each restart.

CLI reference maintenance

When you add or change CLI options in src/tooling/docs-builder/Commands/, regenerate the checked-in schema so CI and the published CLI reference stay in sync:

dotnet run --project src/tooling/docs-builder -- __schema > docs/cli-schema.json

Commit the updated docs/cli-schema.json with your code changes. CI compares the schema (ignoring the version field) and fails if it has drifted.

The schema drives auto-generated parameter tables and usage synopses on CLI reference pages. For behavior, workflows, and examples that the schema cannot express, also update supplemental files under docs/cli/ (see Writing supplemental content).

Working on non-trivial changes

Before starting implementation on anything non-trivial — a new directive, a CLI command, a change that touches more than one project — write a short plan first: a few paragraphs (in the PR description, a linked issue, or handed to an agent as a prompt) stating what's changing and an explicit definition of done. This isn't bureaucracy for its own sake: it's what lets a change be scoped to a single sitting/session instead of sprawling as the "actual" requirements get discovered mid-implementation. Trivial fixes (typos, one-line bug fixes, dependency bumps) don't need this.

Release Process

This section outlines the process for releasing a new version of this project.

Versioning

This project uses Semantic Versioning and its version is automatically determined by release-drafter based on the labels of the pull requests merged into the main branch.

See the release-drafter configuration for more details.

Git Hooks with Husky.Net

This repository uses Husky.Net to automatically format and validate code before commits.

What Gets Checked

Pre-commit hooks (run on staged files):

  • dotnet-lint - Checks C# formatting with curb (dotnet curb check .)
  • prettier - Formats TypeScript, JavaScript, CSS, and JSON files in src/Elastic.Documentation.Site/
  • typescript-check - Type checks TypeScript files with tsc --noEmit (only if TS files are staged)
  • eslint - Lints and fixes JavaScript/TypeScript files

Installation

Husky.Net is included as a dotnet tool. After cloning the repository, restore the tools:

dotnet tool restore

Then install the git hooks:

dotnet husky install

That's it! The hooks will now run automatically on every commit.

The pre-commit hook runs dotnet tool restore before curb, so a new worktree does not need a manual restore before the first commit. You still need dotnet husky install in that worktree so .husky/_/husky.sh exists.

Usage

Once installed, hooks run automatically when you commit:

git add .
git commit -m "your message"  # Pre-commit hooks run here

Note: If hooks modify files (prettier, eslint), the commit will fail so you can review the changes. Simply stage the changes and commit again:

git add -u
git commit -m "your message"

If the dotnet-lint hook fails, run dotnet curb format . to fix the formatting and commit the fixes.

Manual Execution

You can test hooks without committing:

# Run all pre-commit tasks
dotnet husky run --group pre-commit

# Test individual tasks
dotnet husky run --name dotnet-lint
dotnet husky run --name prettier
dotnet husky run --name typescript-check
dotnet husky run --name eslint

Configuration

Hook configuration is defined in .husky/task-runner.json. See the Husky.Net documentation for more details.

Creating a New Release

To create a new release trigger the release workflow on the main branch.

Every time a pull request is merged into the main branch, release-drafter will create a draft release or update the existing draft release in the Releases page.

To create a new release you need to publish the existing draft release created by release-drafter.

Important

Make sure the release-drafter workflow is finished before publishing the release.

Note

When a release is published, the create-major-tag workflow will force push a new major tag in the format vX where X is the major version of the release. For example, if the release is 1.2.3 was published, the workflow will force push a new tag v1 on the same commit.