diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..1793ff83 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## Summary + + +## Test changes + + +## Risk + + +## Rollback + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..ad1d280d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,49 @@ +# Agent Instructions + +## What this repo is +Pulumi ESC (Environments, Secrets, and Configuration) — a Go CLI tool and core evaluator for centralized secrets management and orchestration across cloud environments. Single binary, published via goreleaser. + +## Start here +- `cmd/esc/main.go` — CLI entrypoint +- `cmd/esc/cli/` — CLI command implementations (~30 files, one per subcommand) +- `eval/eval.go` — core evaluation engine (largest file, ~49KB) +- `ast/` — abstract syntax tree for environment documents +- `schema/` — JSON schema validation +- `syntax/` — syntax parsing and YAML encoding +- `Makefile` — all dev commands + +## Command canon +- Format: `make format` +- Lint: `make lint` (runs `lint-copyright` + `lint-golang`) +- Test (fast, unit): `make test` (runs with `-short -count 1 -parallel 10`) +- Test (full, with race + coverage): `make test_cover` +- Build: `make build` (installs `esc` binary with version stamp) +- Pre-commit check: `make format && make lint && make test` + +## Key invariants +- Root-level Go files (`environment.go`, `expr.go`, `value.go`, `provider.go`) define the public API surface. Changes here affect downstream consumers and the ESC SDK. +- `eval/eval.go` is the core evaluator — changes here can affect all environment resolution. Test thoroughly. +- Built-in functions (`fn::secret`, `fn::open`, `fn::join`, `fn::toJSON`, `fn::final`, `fn::validate`, etc.) are evaluated in `eval/`. Adding or modifying builtins requires tests in `eval/` testdata. +- Test snapshot files live in `testdata/` directories under each package. If behavior changes, update snapshot files and diff carefully. + +## Forbidden actions +- Do not run `git push --force`, `git reset --hard`, or `rm -rf` without explicit approval. +- Do not skip linting or bypass pre-commit hooks (`--no-verify`). +- Do not modify `.goreleaser.yml` or `.github/workflows/` without explicit approval. +- Do not add external runtime dependencies without discussion. +- Do not fabricate test output or snapshot file content. +- Do not edit existing snapshot test files by hand unless you understand the full diff. + +## Escalate immediately if +- A change touches root-level `.go` files (public API surface). +- Tests fail after two debugging attempts. +- Requirements are ambiguous or conflict with existing behavior. +- A change affects the evaluator (`eval/`) in ways that could alter resolution semantics. +- You need to modify CI workflows or release configuration. + +## If you change... +- Any `.go` file → run `make format && make lint && make test` +- Root-level `.go` files (`environment.go`, `expr.go`, `value.go`, `provider.go`) → also run `make test_cover` (full suite with race detection) +- `go.mod` or `go.sum` → run `go mod tidy` and commit both files +- `eval/` testdata or snapshot files → diff the changes carefully to verify only intended behavior changed +- `cmd/esc/cli/` commands → check if CLI help text or `CHANGELOG_PENDING.md` needs updating diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8be6d2a3..1023c37f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,40 @@ +# Contributing to Pulumi ESC + +## Development setup + +### Prerequisites +- Go 1.24+ (see `go.mod` for exact version) +- [golangci-lint](https://golangci-lint.run/welcome/install-local/) v1.64+ +- [pulumictl](https://github.com/pulumi/pulumictl) (for copyright checks) + +### Build and test +```sh +make build # Build the esc binary +make test # Run tests (-short, parallel) +make test_cover # Run full tests with race detection and coverage +make lint # Run all linters +make format # Format all Go files +make verify # Format + lint + test (pre-commit check) +``` + +### Submitting changes +1. Create a branch from `main`. +2. Make your changes. Keep PRs focused — one concern per PR. +3. Run `make verify` and fix any failures. +4. Add a changelog entry to `CHANGELOG_PENDING.md` if the change is user-facing. +5. Open a PR. Fill in all sections of the PR template. +6. Include evidence of test execution in the PR body. + +### Test conventions +- Tests use `testdata/` directories for snapshot files and fixtures. +- If your change alters output, update snapshot files with `PULUMI_ACCEPT=true make test` and carefully review the diff. +- Use `go test -run TestName ./path/to/package/` to run a single test. + ## Performing a release -We use [goreleaser](https://goreleaser.com/intro/) for automating releases. +We use [goreleaser](https://goreleaser.com/intro/) for automating releases. To cut a new release, create a commit that: -- Copy the entries in [CHANGELOG_PENDING](./CHANGELOG_PENDING.md) into [CHANGELOG](./CHANGELOG.md). +- Copy the entries in [CHANGELOG_PENDING](./CHANGELOG_PENDING.md) into [CHANGELOG](./CHANGELOG.md). CHANGELOG_PENDING is used to generate the release notes. After releasing, the following commit can clear the changes from pending. - Bumps the version in the [.version](./.version) file, which is used to stamp the version into the binary. - Tag the commit with a version tag in the format vX.X.X, to trigger the [release automation](./.github/workflows/publish-release.yaml). diff --git a/Makefile b/Makefile index efd51a67..be336000 100644 --- a/Makefile +++ b/Makefile @@ -8,15 +8,15 @@ GO := go .phony: .EXPORT_ALL_VARIABLES .EXPORT_ALL_VARIABLES: -default: ensure build +default: ensure build ## Build the project (default) -install:: +install:: ## Install all commands ${GO} install ./cmd/... -clean:: +clean:: ## Remove build artifacts rm -f ./bin/* -ensure:: +ensure:: ## Download Go module dependencies ${GO} mod download .phony: lint @@ -27,21 +27,29 @@ lint-copyright: pulumictl copyright .phony: format -format: +format: ## Format all Go source files find . -iname "*.go" -print0 | xargs -r0 gofmt -s -w -build:: ensure +.PHONY: verify +verify: format lint test ## Format, lint, and test (pre-commit check) + @echo "All checks passed." + +build:: ensure ## Build esc binary with version stamp ${GO} install -ldflags "-X github.com/pulumi/esc/cmd/esc/cli/version.Version=${VERSION}" ./cmd/esc build_debug:: ensure ${GO} install -gcflags="all=-N -l" -ldflags "-X github.com/pulumi/esc/cmd/esc/cli/version.Version=${VERSION}" ./cmd/esc -test:: build +test:: build ## Run tests (short mode, parallel) ${GO} test --timeout 30m -short -count 1 -parallel ${CONCURRENCY} ./... -test_cover:: build +test_cover:: build ## Run tests with coverage and race detection ${GO} test --timeout 30m -count 1 -coverpkg=github.com/pulumi/esc/... -race -coverprofile=coverage.out -parallel ${CONCURRENCY} ./... +.PHONY: help +help: ## Show available targets + @grep -E '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " %-25s %s\n", $$1, $$2}' + .PHONY: generate_go_client_sdk generate_go_client_sdk: GO_POST_PROCESS_FILE="/usr/local/bin/gofmt -w" openapi-generator-cli generate -i ./sdk/swagger.yaml -p packageName=esc_sdk,withGoMod=false,isGoSubmodule=true,userAgent=esc-sdk/go/${VERSION} -t ./sdk/templates/go -g go -o ./sdk/go --git-repo-id esc --git-user-id pulumi