Skip to content
Open
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
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Root task runner for YieldVault-RWA.
# Thin wrappers around the existing pnpm/cargo scripts so contributors have one
# entry point. Works with GNU make on Linux, macOS and Git Bash on Windows.

PNPM ?= pnpm

.DEFAULT_GOAL := help
.PHONY: help install test lint build format validate

help: ## List available targets
@echo "Usage: make <target>"
@echo ""
@awk 'BEGIN { FS = ":.*## " } /^[a-zA-Z_-]+:.*## / { printf " %-10s %s\n", $$1, $$2 }' $(MAKEFILE_LIST)

install: ## Install workspace dependencies (backend, frontend, packages)
$(PNPM) check:pnpm-version
$(PNPM) install

test: ## Run backend, frontend and root script tests
$(PNPM) test:all

lint: ## Lint backend and frontend with ESLint
$(PNPM) --filter backend lint
$(PNPM) --filter frontend lint

build: ## Build API schemas, backend and frontend
$(PNPM) build

format: ## Format backend sources (and Rust contracts when cargo is installed)
$(PNPM) --filter backend format
@if command -v cargo >/dev/null 2>&1; then cargo fmt --all; else echo "cargo not found, skipping cargo fmt"; fi

validate: ## Run repository convention and governance validators
$(PNPM) validate:contribution-standards
$(PNPM) validate:testing-strategy
$(PNPM) validate:sprint-and-triage
$(PNPM) validate:release-notes
$(PNPM) validate:nfr-baselines
$(PNPM) validate:codeowners
$(PNPM) validate:pr-template
$(PNPM) validate:renovate
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ For detailed setup instructions, prerequisites, validation steps, and troublesho

For a complete environment variable reference with defaults, required flags, and production recommendations, see **[Environment Variable Matrix](./docs/ENV_VARIABLE_MATRIX.md)**.

### Makefile Targets

The root `Makefile` wraps the existing pnpm scripts so common tasks have one entry point. Run `make` (or `make help`) to list them:

| Command | What it runs |
| --------------- | ---------------------------------------------------------------------------- |
| `make help` | Lists all targets (default goal) |
| `make install` | `pnpm check:pnpm-version` then `pnpm install` for the whole workspace |
| `make test` | `pnpm test:all` (backend Jest, frontend Vitest, root script tests) |
| `make lint` | ESLint for `backend` and `frontend` |
| `make build` | `pnpm build` (API schemas, backend, frontend) |
| `make format` | Prettier for `backend`, plus `cargo fmt --all` when `cargo` is installed |
| `make validate` | Contribution, testing-strategy, triage, release-notes, NFR, CODEOWNERS, PR template and Renovate validators |

The targets use GNU make and POSIX shell, so they run on Linux, macOS and Git Bash on Windows. Git Bash does not ship `make`; install it with `choco install make`, `scoop install make`, or `winget install ezwinports.make`. Set `PNPM` to override the pnpm binary, for example `make install PNPM="corepack pnpm"`.

## API Documentation

Generate contract and frontend API docs:
Expand Down
37 changes: 37 additions & 0 deletions scripts/makefile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { describe, it, expect } from 'vitest';
import { readFileSync, existsSync } from 'node:fs';
import { resolve } from 'node:path';

const rootDir = resolve(__dirname, '..');
const TARGETS = ['help', 'install', 'test', 'lint', 'build', 'format', 'validate'];

describe('Root Makefile', () => {
const makefilePath = resolve(rootDir, 'Makefile');

it('exists at the repository root', () => {
expect(existsSync(makefilePath)).toBe(true);
});

it('declares every target as phony and defaults to help', () => {
const makefile = readFileSync(makefilePath, 'utf8');
const phony = makefile.match(/^\.PHONY:(.*)$/m)?.[1].split(/\s+/) ?? [];
for (const target of TARGETS) {
expect(phony).toContain(target);
expect(makefile).toMatch(new RegExp(`^${target}:.*## `, 'm'));
}
expect(makefile).toMatch(/^\.DEFAULT_GOAL := help$/m);
});

it('uses tab-indented recipes and LF line endings', () => {
const makefile = readFileSync(makefilePath, 'utf8');
expect(makefile).not.toContain('\r');
expect(makefile).not.toMatch(/^ +(@|\$\(PNPM\))/m);
});

it('is documented in README.md', () => {
const readme = readFileSync(resolve(rootDir, 'README.md'), 'utf8');
for (const target of TARGETS) {
expect(readme).toContain(`make ${target}`);
}
});
});