diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..503ed76f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,39 @@ +# Repository Guidelines + +This repository hosts Temporal SDK feature examples in multiple languages. Follow these rules when modifying code or adding new features. + +## Running and Building +- Build the CLI with `go build -o temporal-features` (or use `go run .`). It requires Go, JDK 11+, Node 16+, uv, .NET 7+, and PHP 8.1+ to run the features. +- Run features with `temporal-features run --lang LANG [--version VERSION] [PATTERN...]`. Use `temporal-features prepare` to prebuild a project, and `build-image` to create docker images. +- History files live under `features//history/history...json`. Generate history with `--generate-history` only when developing a new feature or when a version intentionally changes history. +- Always test changes to a given language by running `go run . run --lang `. If adding a new feature test, test that feature specifically by running `go run . run --lang ` where `` is the path to the feature directory inside of `features/`. + +## Writing Features +- Each feature lives under `features/` in its own directory. Keep code short and clear and avoid unnecessary assertions. +- File naming conventions: + - Go: `feature.go` with optional version-specific files like `feature_pre1.11.0.go`. + - Java: `feature.java` + - TypeScript: `feature.ts` (workflow and non-workflow code may share this file). + - Python: `feature.py` +- Add a `README.md` to every feature directory with a short title and explanation. +- Bug regression tests belong under `features/bugs/`. Favor including as many languages as possible for non-bug features and feel free to extract helpers since backward compatibility is not a concern. + +## Formatting and Linting +- **TypeScript**: Format with Prettier and lint with ESLint using `npm run format` and `npm run lint`, you must ensure type checking passes with `npm run build`. +- **Python**: Install tools with `uv tool install poethepoet` and `uv sync`. Format with `poe format` and lint with `poe lint` which runs Ruff and mypy. +- **Go**: Run `go fmt ./...` before committing. +- **Java**: Ensure the project builds with `./gradlew assemble` and autoformat with `./gradlew spotlessApply`. +- **C#**: Builds treat warnings as errors. `.editorconfig` disables warning `CS1998`. + +These conventions help keep the examples consistent across languages and ensure CI passes. + +## Understanding SDK capabilities +Agents should use the docs.temporal.io website, as well as github.com to learn about the capabilities and the API specifics of each langauge SDK. + +* Go - https://github.com/temporalio/sdk-go and https://docs.temporal.io/develop/go/ +* Java - https://github.com/temporalio/sdk-java and https://docs.temporal.io/develop/java/ +* TypeScript - https://github.com/temporalio/sdk-typescript and https://docs.temporal.io/develop/typescript/ +* Python - https://github.com/temporalio/sdk-python and https://docs.temporal.io/develop/python/ +* .NET / C# - https://github.com/temporalio/sdk-dotnet and https://docs.temporal.io/develop/dotnet/ +* Ruby - https://github.com/temporalio/sdk-ruby and https://docs.temporal.io/develop/ruby/ +* PHP - https://github.com/temporalio/sdk-php and https://docs.temporal.io/develop/php/ diff --git a/cmd/run_python.go b/cmd/run_python.go index 0de450db..9b003720 100644 --- a/cmd/run_python.go +++ b/cmd/run_python.go @@ -19,6 +19,7 @@ func (p *Preparer) BuildPythonProgram(ctx context.Context) (sdkbuild.Program, er // Get version from pyproject.toml if not present version := p.config.Version + versionFromPyProj := "" if version == "" { b, err := os.ReadFile(filepath.Join(p.rootDir, "pyproject.toml")) if err != nil { @@ -26,7 +27,7 @@ func (p *Preparer) BuildPythonProgram(ctx context.Context) (sdkbuild.Program, er } for _, line := range strings.Split(string(b), "\n") { line = strings.TrimSpace(line) - if strings.HasPrefix(line, "temporalio = ") { + if strings.Contains(line, "temporalio") { version = line[strings.Index(line, `"`)+1 : strings.LastIndex(line, `"`)] break } @@ -34,12 +35,14 @@ func (p *Preparer) BuildPythonProgram(ctx context.Context) (sdkbuild.Program, er if version == "" { return nil, fmt.Errorf("version not found in pyproject.toml") } + versionFromPyProj = version } prog, err := sdkbuild.BuildPythonProgram(ctx, sdkbuild.BuildPythonProgramOptions{ - BaseDir: p.rootDir, - DirName: p.config.DirName, - Version: version, + BaseDir: p.rootDir, + DirName: p.config.DirName, + Version: version, + VersionFromPyProj: versionFromPyProj, }) if err != nil { return nil, fmt.Errorf("failed preparing: %w", err) diff --git a/package-lock.json b/package-lock.json index f0e72e84..fc49cfd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,12 @@ "dependencies": { "@grpc/grpc-js": "^1.12.4", "@protobuf-ts/protoc": "^2.8.1", - "@temporalio/activity": "^1.11.8", - "@temporalio/client": "^1.11.8", - "@temporalio/common": "^1.11.8", - "@temporalio/proto": "^1.11.8", - "@temporalio/worker": "^1.11.8", - "@temporalio/workflow": "^1.11.8", + "@temporalio/activity": "^1.12.1", + "@temporalio/client": "^1.12.1", + "@temporalio/common": "^1.12.1", + "@temporalio/proto": "^1.12.1", + "@temporalio/worker": "^1.12.1", + "@temporalio/workflow": "^1.12.1", "commander": "^8.3.0", "ms": "^3.0.0-canary.1", "proto3-json-serializer": "^1.1.1", @@ -647,39 +647,48 @@ "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" }, "node_modules/@temporalio/activity": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/activity/-/activity-1.11.8.tgz", - "integrity": "sha512-XWjj/EL0YiKsnh0W4W5kBm+Xp1jhpUEaQMGA25+BxKEYBn8qJ+mLQOwuqWn6punS9a6bvnT7P/pUlnhjPxH6KQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/activity/-/activity-1.12.1.tgz", + "integrity": "sha512-EPPIR5J0A6OxWTr5HGyeM2Lwh3US8S73N3ZFelCPaJwOq2Fh7qrLiwYp2wCwGYhhYI9Xppo3xE45MWUxayBa3Q==", "license": "MIT", "dependencies": { - "@temporalio/common": "1.11.8", + "@temporalio/common": "1.12.1", "abort-controller": "^3.0.0" + }, + "engines": { + "node": ">= 18.0.0" } }, "node_modules/@temporalio/client": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/client/-/client-1.11.8.tgz", - "integrity": "sha512-UpiU+awykWYjQSSJH5NLY5Id/uDdiD9yz5oaardv1YF80rMN7U1Q6W9lgPEbg/b62qOv3Mia1+fE5hrav7ying==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/client/-/client-1.12.1.tgz", + "integrity": "sha512-m89isGb6I4BBeCbhkvXbpjeRZZUa3E2R06J/I+t2JWgv0Tg+PoNPusvU9UBd6LN7f7AetsQvAZKU6eQHyWxSEA==", "license": "MIT", "dependencies": { - "@grpc/grpc-js": "^1.10.7", - "@temporalio/common": "1.11.8", - "@temporalio/proto": "1.11.8", + "@grpc/grpc-js": "^1.12.4", + "@temporalio/common": "1.12.1", + "@temporalio/proto": "1.12.1", "abort-controller": "^3.0.0", "long": "^5.2.3", "uuid": "^9.0.1" + }, + "engines": { + "node": ">= 18.0.0" } }, "node_modules/@temporalio/common": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/common/-/common-1.11.8.tgz", - "integrity": "sha512-hB+TSB/P2Vm8chYyZGcKALdywGvcBSqzSUzFG1lOm/JPDh2d4uK6lvE2S8OneEndlJSdzE++d2Mt5B+iKe2ytA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/common/-/common-1.12.1.tgz", + "integrity": "sha512-gMVNYh49qGNFPKN22BPXtQlgvcD8rxUoP0QO0ePeaz9TyHG6+3TURGhc8xybJA7zHnpfW8TH8XHMWJIMzCPxtg==", "license": "MIT", "dependencies": { - "@temporalio/proto": "1.11.8", + "@temporalio/proto": "1.12.1", "long": "^5.2.3", "ms": "^3.0.0-canary.1", "proto3-json-serializer": "^2.0.0" + }, + "engines": { + "node": ">= 18.0.0" } }, "node_modules/@temporalio/common/node_modules/proto3-json-serializer": { @@ -694,16 +703,20 @@ } }, "node_modules/@temporalio/core-bridge": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/core-bridge/-/core-bridge-1.11.8.tgz", - "integrity": "sha512-s1EkihwUHGIOylF31UFnsnntZmVqcKEgVTu8UvAf/J/br4jhs+nEO/mBFexqrzSWnraJhpq9UnzTNAklNHFVKg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/core-bridge/-/core-bridge-1.12.1.tgz", + "integrity": "sha512-JOLavcVhzLf4QDK7S/SAZjTbbtiYRoZoJCvJsl6T9s6MJFyeT1ih+4jeAN3UUmhLvaP++sqEuFSfRVJ0ZFoFNA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@temporalio/common": "1.11.8", + "@grpc/grpc-js": "^1.12.4", + "@temporalio/common": "1.12.1", "arg": "^5.0.2", "cargo-cp-artifact": "^0.1.8", "which": "^4.0.0" + }, + "engines": { + "node": ">= 18.0.0" } }, "node_modules/@temporalio/core-bridge/node_modules/isexe": { @@ -731,31 +744,36 @@ } }, "node_modules/@temporalio/proto": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/proto/-/proto-1.11.8.tgz", - "integrity": "sha512-L6QsIAq3PrnQpARAcqLCe4xMpbkpBEvA/9FQGddpzCESvViUOUAIHPwckL1DokYPedEAt19C+uuBGVBMCNx7vw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/proto/-/proto-1.12.1.tgz", + "integrity": "sha512-hW5jvxBuoKdh3CwbGT/AQoPMFoGG8xcPcHRMCTta/HZGFHRDibbr0aDfPS6ke7oYtcpWF0A8d6jRAHEXyPUvUQ==", "license": "MIT", "dependencies": { "long": "^5.2.3", "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">= 18.0.0" } }, "node_modules/@temporalio/worker": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/worker/-/worker-1.11.8.tgz", - "integrity": "sha512-KNUEw8khhFoVLhOy93j9EkA6KfKtOVn7N7+c4kn9AM7QXkcxe73+1AUwNKgFYKZph4i6I26NBxs7MPrgh3GKxQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/worker/-/worker-1.12.1.tgz", + "integrity": "sha512-jI3UxPAVbuM2MJO0c27iNV59KNHgAlx6yoJOpcE+jdGAmoN52MHdSt3qedrWtWINgZDbZg9dPC8KoDbXr9kP6g==", "license": "MIT", "dependencies": { + "@grpc/grpc-js": "^1.12.4", "@swc/core": "^1.3.102", - "@temporalio/activity": "1.11.8", - "@temporalio/client": "1.11.8", - "@temporalio/common": "1.11.8", - "@temporalio/core-bridge": "1.11.8", - "@temporalio/proto": "1.11.8", - "@temporalio/workflow": "1.11.8", + "@temporalio/activity": "1.12.1", + "@temporalio/client": "1.12.1", + "@temporalio/common": "1.12.1", + "@temporalio/core-bridge": "1.12.1", + "@temporalio/proto": "1.12.1", + "@temporalio/workflow": "1.12.1", "abort-controller": "^3.0.0", "heap-js": "^2.3.0", "memfs": "^4.6.0", + "protobufjs": "^7.2.5", "rxjs": "^7.8.1", "source-map": "^0.7.4", "source-map-loader": "^4.0.2", @@ -765,7 +783,7 @@ "webpack": "^5.94.0" }, "engines": { - "node": ">= 16.0.0" + "node": ">= 18.0.0" } }, "node_modules/@temporalio/worker/node_modules/supports-color": { @@ -783,13 +801,16 @@ } }, "node_modules/@temporalio/workflow": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/workflow/-/workflow-1.11.8.tgz", - "integrity": "sha512-gJy5Rr4WQCejdWskluHY/C20om0Yvx7/cLl9KHCweTyDLRfTu2VtMJRS8LPFQkKzoHBbLaqzPo2XdHh/u4JQoA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/workflow/-/workflow-1.12.1.tgz", + "integrity": "sha512-r2d2tzEf6zJENewZMku1ge53QO52ZTN8bJXp8zzerPYyMx9Iqhg3Ck1ckrdpxpDw9gxBYZsRbwS2vpiq53ZKRQ==", "license": "MIT", "dependencies": { - "@temporalio/common": "1.11.8", - "@temporalio/proto": "1.11.8" + "@temporalio/common": "1.12.1", + "@temporalio/proto": "1.12.1" + }, + "engines": { + "node": ">= 18.0.0" } }, "node_modules/@tsconfig/node10": { @@ -4187,33 +4208,33 @@ "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" }, "@temporalio/activity": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/activity/-/activity-1.11.8.tgz", - "integrity": "sha512-XWjj/EL0YiKsnh0W4W5kBm+Xp1jhpUEaQMGA25+BxKEYBn8qJ+mLQOwuqWn6punS9a6bvnT7P/pUlnhjPxH6KQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/activity/-/activity-1.12.1.tgz", + "integrity": "sha512-EPPIR5J0A6OxWTr5HGyeM2Lwh3US8S73N3ZFelCPaJwOq2Fh7qrLiwYp2wCwGYhhYI9Xppo3xE45MWUxayBa3Q==", "requires": { - "@temporalio/common": "1.11.8", + "@temporalio/common": "1.12.1", "abort-controller": "^3.0.0" } }, "@temporalio/client": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/client/-/client-1.11.8.tgz", - "integrity": "sha512-UpiU+awykWYjQSSJH5NLY5Id/uDdiD9yz5oaardv1YF80rMN7U1Q6W9lgPEbg/b62qOv3Mia1+fE5hrav7ying==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/client/-/client-1.12.1.tgz", + "integrity": "sha512-m89isGb6I4BBeCbhkvXbpjeRZZUa3E2R06J/I+t2JWgv0Tg+PoNPusvU9UBd6LN7f7AetsQvAZKU6eQHyWxSEA==", "requires": { - "@grpc/grpc-js": "^1.10.7", - "@temporalio/common": "1.11.8", - "@temporalio/proto": "1.11.8", + "@grpc/grpc-js": "^1.12.4", + "@temporalio/common": "1.12.1", + "@temporalio/proto": "1.12.1", "abort-controller": "^3.0.0", "long": "^5.2.3", "uuid": "^9.0.1" } }, "@temporalio/common": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/common/-/common-1.11.8.tgz", - "integrity": "sha512-hB+TSB/P2Vm8chYyZGcKALdywGvcBSqzSUzFG1lOm/JPDh2d4uK6lvE2S8OneEndlJSdzE++d2Mt5B+iKe2ytA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/common/-/common-1.12.1.tgz", + "integrity": "sha512-gMVNYh49qGNFPKN22BPXtQlgvcD8rxUoP0QO0ePeaz9TyHG6+3TURGhc8xybJA7zHnpfW8TH8XHMWJIMzCPxtg==", "requires": { - "@temporalio/proto": "1.11.8", + "@temporalio/proto": "1.12.1", "long": "^5.2.3", "ms": "^3.0.0-canary.1", "proto3-json-serializer": "^2.0.0" @@ -4230,11 +4251,12 @@ } }, "@temporalio/core-bridge": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/core-bridge/-/core-bridge-1.11.8.tgz", - "integrity": "sha512-s1EkihwUHGIOylF31UFnsnntZmVqcKEgVTu8UvAf/J/br4jhs+nEO/mBFexqrzSWnraJhpq9UnzTNAklNHFVKg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/core-bridge/-/core-bridge-1.12.1.tgz", + "integrity": "sha512-JOLavcVhzLf4QDK7S/SAZjTbbtiYRoZoJCvJsl6T9s6MJFyeT1ih+4jeAN3UUmhLvaP++sqEuFSfRVJ0ZFoFNA==", "requires": { - "@temporalio/common": "1.11.8", + "@grpc/grpc-js": "^1.12.4", + "@temporalio/common": "1.12.1", "arg": "^5.0.2", "cargo-cp-artifact": "^0.1.8", "which": "^4.0.0" @@ -4256,29 +4278,31 @@ } }, "@temporalio/proto": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/proto/-/proto-1.11.8.tgz", - "integrity": "sha512-L6QsIAq3PrnQpARAcqLCe4xMpbkpBEvA/9FQGddpzCESvViUOUAIHPwckL1DokYPedEAt19C+uuBGVBMCNx7vw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/proto/-/proto-1.12.1.tgz", + "integrity": "sha512-hW5jvxBuoKdh3CwbGT/AQoPMFoGG8xcPcHRMCTta/HZGFHRDibbr0aDfPS6ke7oYtcpWF0A8d6jRAHEXyPUvUQ==", "requires": { "long": "^5.2.3", "protobufjs": "^7.2.5" } }, "@temporalio/worker": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/worker/-/worker-1.11.8.tgz", - "integrity": "sha512-KNUEw8khhFoVLhOy93j9EkA6KfKtOVn7N7+c4kn9AM7QXkcxe73+1AUwNKgFYKZph4i6I26NBxs7MPrgh3GKxQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/worker/-/worker-1.12.1.tgz", + "integrity": "sha512-jI3UxPAVbuM2MJO0c27iNV59KNHgAlx6yoJOpcE+jdGAmoN52MHdSt3qedrWtWINgZDbZg9dPC8KoDbXr9kP6g==", "requires": { + "@grpc/grpc-js": "^1.12.4", "@swc/core": "^1.3.102", - "@temporalio/activity": "1.11.8", - "@temporalio/client": "1.11.8", - "@temporalio/common": "1.11.8", - "@temporalio/core-bridge": "1.11.8", - "@temporalio/proto": "1.11.8", - "@temporalio/workflow": "1.11.8", + "@temporalio/activity": "1.12.1", + "@temporalio/client": "1.12.1", + "@temporalio/common": "1.12.1", + "@temporalio/core-bridge": "1.12.1", + "@temporalio/proto": "1.12.1", + "@temporalio/workflow": "1.12.1", "abort-controller": "^3.0.0", "heap-js": "^2.3.0", "memfs": "^4.6.0", + "protobufjs": "^7.2.5", "rxjs": "^7.8.1", "source-map": "^0.7.4", "source-map-loader": "^4.0.2", @@ -4299,12 +4323,12 @@ } }, "@temporalio/workflow": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@temporalio/workflow/-/workflow-1.11.8.tgz", - "integrity": "sha512-gJy5Rr4WQCejdWskluHY/C20om0Yvx7/cLl9KHCweTyDLRfTu2VtMJRS8LPFQkKzoHBbLaqzPo2XdHh/u4JQoA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@temporalio/workflow/-/workflow-1.12.1.tgz", + "integrity": "sha512-r2d2tzEf6zJENewZMku1ge53QO52ZTN8bJXp8zzerPYyMx9Iqhg3Ck1ckrdpxpDw9gxBYZsRbwS2vpiq53ZKRQ==", "requires": { - "@temporalio/common": "1.11.8", - "@temporalio/proto": "1.11.8" + "@temporalio/common": "1.12.1", + "@temporalio/proto": "1.12.1" } }, "@tsconfig/node10": { diff --git a/package.json b/package.json index 25b3cc1d..a521f981 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,12 @@ "dependencies": { "@grpc/grpc-js": "^1.12.4", "@protobuf-ts/protoc": "^2.8.1", - "@temporalio/activity": "^1.11.8", - "@temporalio/client": "^1.11.8", - "@temporalio/common": "^1.11.8", - "@temporalio/proto": "^1.11.8", - "@temporalio/worker": "^1.11.8", - "@temporalio/workflow": "^1.11.8", + "@temporalio/activity": "^1.12.1", + "@temporalio/client": "^1.12.1", + "@temporalio/common": "^1.12.1", + "@temporalio/proto": "^1.12.1", + "@temporalio/worker": "^1.12.1", + "@temporalio/workflow": "^1.12.1", "protobufjs": "7.5.1", "commander": "^8.3.0", "ms": "^3.0.0-canary.1", diff --git a/sdkbuild/python.go b/sdkbuild/python.go index 04e216f5..2c6a1e69 100644 --- a/sdkbuild/python.go +++ b/sdkbuild/python.go @@ -19,6 +19,9 @@ type BuildPythonProgramOptions struct { // a single wheel in the dist directory. Otherwise it is a specific version // (with leading "v" is trimmed if present). Version string + // If specified, takes precedence over Version. Is a PEP 508 requirement string, like + // `temporalio>=1.13.0,<2`. + VersionFromPyProj string // If present, this directory is expected to exist beneath base dir. Otherwise // a temporary dir is created. DirName string @@ -89,7 +92,9 @@ requires-python = "~=3.9" return nil, fmt.Errorf("failed writing pyproject.toml: %w", err) } - if strings.ContainsAny(options.Version, `/\`) { + if options.VersionFromPyProj != "" { + executeCommand("uv", "add", options.VersionFromPyProj) + } else if strings.ContainsAny(options.Version, `/\`) { // It's a path; install from wheel wheel, err := getWheel(ctx, options.Version) if err != nil {