diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0917c0e8e..eb06b5eab 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,4 +24,6 @@ jobs: restore-keys: | ${{ runner.os }}-connect-es-ci- - name: make - run: make ci && make checkdiff + run: make ci + - name: Check changed files + run: node scripts/gh-diffcheck.js diff --git a/Makefile b/Makefile index a8a525dc6..dbbcb0207 100644 --- a/Makefile +++ b/Makefile @@ -59,49 +59,41 @@ $(BIN)/node16: Makefile @touch $(@) $(BUILD)/protoc-gen-connect-es: node_modules tsconfig.base.json packages/protoc-gen-connect-es/tsconfig.json $(shell find packages/protoc-gen-connect-es/src -name '*.ts') - npm run -w packages/protoc-gen-connect-es clean npm run -w packages/protoc-gen-connect-es build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect: $(GEN)/connect node_modules packages/connect/package.json packages/connect/scripts/* tsconfig.base.json packages/connect/tsconfig.json $(shell find packages/connect/src -name '*.ts') packages/connect/*.js - npm run -w packages/connect clean npm run -w packages/connect build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect-node: $(BUILD)/connect $(BUILD)/connect-conformance packages/connect-node/tsconfig.json $(shell find packages/connect-node/src -name '*.ts') - npm run -w packages/connect-node clean npm run -w packages/connect-node build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect-fastify: $(BUILD)/connect $(BUILD)/connect-node packages/connect-fastify/tsconfig.json $(shell find packages/connect-fastify/src -name '*.ts') - npm run -w packages/connect-fastify clean npm run -w packages/connect-fastify build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect-express: $(BUILD)/connect $(BUILD)/connect-node packages/connect-express/tsconfig.json $(shell find packages/connect-express/src -name '*.ts') - npm run -w packages/connect-express clean npm run -w packages/connect-express build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect-next: $(BUILD)/connect $(BUILD)/connect-node packages/connect-next/tsconfig.json $(shell find packages/connect-next/src -name '*.ts') - npm run -w packages/connect-next clean npm run -w packages/connect-next build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect-web: $(GEN)/connect-web $(BUILD)/connect $(BUILD)/connect-conformance packages/connect-web/tsconfig.json $(shell find packages/connect-web/src -name '*.ts') - npm run -w packages/connect-web clean npm run -w packages/connect-web build @mkdir -p $(@D) @touch $(@) $(BUILD)/connect-conformance: $(GEN)/connect-conformance $(BUILD)/connect packages/connect-conformance/tsconfig.json $(shell find packages/connect-conformance/src -name '*.ts') - npm run -w packages/connect-conformance clean npm run -w packages/connect-conformance build @mkdir -p $(@D) @touch $(@) @@ -112,7 +104,6 @@ $(BUILD)/example: $(GEN)/example $(BUILD)/connect-web packages/example/tsconfig. @touch $(@) $(BUILD)/connect-migrate: packages/connect-migrate/package.json packages/connect-migrate/tsconfig.json $(shell find packages/connect-migrate/src -name '*.ts') - npm run -w packages/connect-migrate clean npm run -w packages/connect-migrate build @mkdir -p $(@D) @touch $(@) @@ -257,34 +248,3 @@ format: node_modules ## Format all files, adding license headers .PHONY: bench bench: node_modules $(GEN)/connect-web-bench $(BUILD)/connect-web ## Benchmark code size npm run -w packages/connect-web-bench bundle-size - -.PHONY: setversion -setversion: ## Set a new version in for the project, i.e. make setversion SET_VERSION=1.2.3 - node scripts/set-workspace-version.js $(SET_VERSION) - npm ci - $(MAKE) all - -# Recommended procedure: -# 1. Set a new version with the target `setversion` -# 2. Commit and push all changes -# 3. Login with `npm login` -# 4. Run this target, publishing to npmjs.com -# 5. Tag the release -.PHONY: release -release: all ## Release npm packages - @[ -z "$(shell git status --short)" ] || (echo "Uncommitted changes found." && exit 1); - npm publish \ - --workspace packages/connect \ - --workspace packages/connect-web \ - --workspace packages/connect-node \ - --workspace packages/connect-fastify \ - --workspace packages/connect-express \ - --workspace packages/connect-next \ - --workspace packages/protoc-gen-connect-es \ - --workspace packages/connect-migrate \ - -.PHONY: checkdiff -checkdiff: - @# Used in CI to verify that `make` does not produce a diff - test -z "$$(git status --porcelain | tee /dev/stderr)" - diff --git a/package.json b/package.json index 96153e107..ebbd5673c 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,13 @@ "./packages/connect-conformance", "./packages/connect-cloudflare" ], + "scripts": { + "clean": "git clean -Xdf", + "setversion": "node scripts/set-workspace-version.js", + "postsetversion": "npm run all", + "all": "make", + "release": "npm run all && node scripts/release.js" + }, "type": "module", "engineStrict": true, "engines": { diff --git a/packages/connect-conformance/package.json b/packages/connect-conformance/package.json index c4a62177a..0dd7e14ed 100644 --- a/packages/connect-conformance/package.json +++ b/packages/connect-conformance/package.json @@ -15,7 +15,8 @@ }, "scripts": { "generate": "buf generate buf.build/connectrpc/conformance:v1.0.2", - "clean": "rm -rf ./dist/*", + "postgenerate": "license-header src/gen", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm", "postbuild": "connectconformance --version", "build:cjs": "tsc --project tsconfig.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/src/package.json '{\"type\":\"commonjs\"}'", diff --git a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/client_compat_pb.ts b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/client_compat_pb.ts index 66fcbbb48..52a020e15 100644 --- a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/client_compat_pb.ts +++ b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/client_compat_pb.ts @@ -1,4 +1,4 @@ -// Copyright 2023-2024 The Connect Authors +// Copyright 2021-2024 The Connect Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/config_pb.ts b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/config_pb.ts index 7df98b1cb..fdc518fcb 100644 --- a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/config_pb.ts +++ b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/config_pb.ts @@ -1,4 +1,4 @@ -// Copyright 2023-2024 The Connect Authors +// Copyright 2021-2024 The Connect Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/server_compat_pb.ts b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/server_compat_pb.ts index 3c5035cb1..e56188206 100644 --- a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/server_compat_pb.ts +++ b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/server_compat_pb.ts @@ -1,4 +1,4 @@ -// Copyright 2023-2024 The Connect Authors +// Copyright 2021-2024 The Connect Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_connect.ts b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_connect.ts index 9c46f51b4..dddad87c3 100644 --- a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_connect.ts +++ b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_connect.ts @@ -1,4 +1,4 @@ -// Copyright 2023-2024 The Connect Authors +// Copyright 2021-2024 The Connect Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_pb.ts b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_pb.ts index 6d5b3513d..2968d6332 100644 --- a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_pb.ts +++ b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/service_pb.ts @@ -1,4 +1,4 @@ -// Copyright 2023-2024 The Connect Authors +// Copyright 2021-2024 The Connect Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/suite_pb.ts b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/suite_pb.ts index bef304b4d..923376e0f 100644 --- a/packages/connect-conformance/src/gen/connectrpc/conformance/v1/suite_pb.ts +++ b/packages/connect-conformance/src/gen/connectrpc/conformance/v1/suite_pb.ts @@ -1,4 +1,4 @@ -// Copyright 2023-2024 The Connect Authors +// Copyright 2021-2024 The Connect Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/connect-express/package.json b/packages/connect-express/package.json index 639c02b3f..c11f937f1 100644 --- a/packages/connect-express/package.json +++ b/packages/connect-express/package.json @@ -8,7 +8,7 @@ "directory": "packages/connect-express" }, "scripts": { - "clean": "rm -rf ./dist/*", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm", "build:cjs": "tsc --project tsconfig.build.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", "build:esm": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationDir ./dist/esm", diff --git a/packages/connect-fastify/package.json b/packages/connect-fastify/package.json index faa83e7ae..a788db74d 100644 --- a/packages/connect-fastify/package.json +++ b/packages/connect-fastify/package.json @@ -8,7 +8,7 @@ "directory": "packages/connect-fastify" }, "scripts": { - "clean": "rm -rf ./dist/*", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm", "build:cjs": "tsc --project tsconfig.build.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", "build:esm": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationDir ./dist/esm", diff --git a/packages/connect-migrate/package.json b/packages/connect-migrate/package.json index c681b8602..22607e251 100644 --- a/packages/connect-migrate/package.json +++ b/packages/connect-migrate/package.json @@ -13,7 +13,7 @@ "connect-migrate": "bin/connect-migrate" }, "scripts": { - "clean": "rm -rf ./dist/cjs/*", + "prebuild": "rm -rf ./dist/*", "build": "tsc --project tsconfig.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs", "test": "jasmine --config=jasmine.json", "build+test": "npm run build && npm run test" diff --git a/packages/connect-next/package.json b/packages/connect-next/package.json index 209fa1011..3d7ea8dea 100644 --- a/packages/connect-next/package.json +++ b/packages/connect-next/package.json @@ -8,7 +8,7 @@ "directory": "packages/connect-next" }, "scripts": { - "clean": "rm -rf ./dist/*", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm", "build:cjs": "tsc --project tsconfig.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", "build:esm": "tsc --project tsconfig.json --outDir ./dist/esm --declaration --declarationDir ./dist/esm", diff --git a/packages/connect-node/package.json b/packages/connect-node/package.json index 1433e5805..9dad50d8b 100644 --- a/packages/connect-node/package.json +++ b/packages/connect-node/package.json @@ -8,7 +8,7 @@ "directory": "packages/connect-node" }, "scripts": { - "clean": "rm -rf ./dist/*", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm", "build:cjs": "tsc --project tsconfig.build.json --module commonjs --moduleResolution node10 --verbatimModuleSyntax false --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", "build:esm": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationDir ./dist/esm", diff --git a/packages/connect-web-bench/package.json b/packages/connect-web-bench/package.json index 54dde5559..9ccde1a86 100644 --- a/packages/connect-web-bench/package.json +++ b/packages/connect-web-bench/package.json @@ -4,7 +4,7 @@ "scripts": { "bundle-size": "tsx src/report.ts", "generate": "buf generate", - "postgenerate": "license-header ." + "postgenerate": "license-header src/gen" }, "dependencies": { "@bufbuild/buf": "^1.36.0", diff --git a/packages/connect-web/package.json b/packages/connect-web/package.json index da38d954c..79da10b60 100644 --- a/packages/connect-web/package.json +++ b/packages/connect-web/package.json @@ -8,7 +8,7 @@ "directory": "packages/connect-web" }, "scripts": { - "clean": "rm -rf ./dist/*", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm", "build:cjs": "tsc --project tsconfig.build.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", "build:esm": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationDir ./dist/esm", @@ -23,6 +23,7 @@ "conformance:client:node:callback": "connectconformance --mode client --conf ./conformance/conformance-web-node.yaml -v --known-failing @./conformance/known-failing-callback-client.txt -- ./conformance/client.ts --browser node --useCallbackClient", "jasmine": "jasmine --config=jasmine.json", "generate": "buf generate --template browserstack/buf.gen.yaml", + "postgenerate": "license-header browserstack/gen", "karma:browserstack": "karma start browserstack/karma.browserstack.conf.cjs" }, "type": "module", diff --git a/packages/connect/package.json b/packages/connect/package.json index 1506a9786..a5003e6e3 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -9,8 +9,9 @@ "directory": "packages/connect" }, "scripts": { - "clean": "rm -rf ./dist/*", "generate": "buf generate", + "postgenerate": "license-header src/protocol-grpc/gen", + "prebuild": "rm -rf ./dist/*", "build": "npm run build:cjs && npm run build:esm && node scripts/update-user-agent.mjs", "build:cjs": "tsc --project tsconfig.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs --declaration --declarationDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", "build:esm": "tsc --project tsconfig.json --outDir ./dist/esm --declaration --declarationDir ./dist/esm", diff --git a/packages/connect/src/protocol-connect/transport.spec.ts b/packages/connect/src/protocol-connect/transport.spec.ts index 47069cbd1..1da286a82 100644 --- a/packages/connect/src/protocol-connect/transport.spec.ts +++ b/packages/connect/src/protocol-connect/transport.spec.ts @@ -384,6 +384,9 @@ describe("Connect transport", function () { } }); }); + // Special handling of set-cookie is available since Node.js v20.0.0, + // v18.14.1, v16.19.1, but not in headers-polyfill 3.1.2. + // Also see https://github.com/nodejs/undici/releases/tag/v5.19.0 if ("getSetCookie" in new Headers()) { describe("when there is support for set-cookie", function () { // eslint-disable-next-line @typescript-eslint/require-await diff --git a/packages/protoc-gen-connect-es/package.json b/packages/protoc-gen-connect-es/package.json index c71f012a6..f8d0d1e05 100644 --- a/packages/protoc-gen-connect-es/package.json +++ b/packages/protoc-gen-connect-es/package.json @@ -15,7 +15,7 @@ "node": ">=16.0.0" }, "scripts": { - "clean": "rm -rf ./dist/cjs/*", + "prebuild": "rm -rf ./dist/*", "build": "tsc --project tsconfig.json --module commonjs --verbatimModuleSyntax false --moduleResolution node10 --outDir ./dist/cjs" }, "preferUnplugged": true, diff --git a/scripts/gh-diffcheck.js b/scripts/gh-diffcheck.js new file mode 100644 index 000000000..03123c418 --- /dev/null +++ b/scripts/gh-diffcheck.js @@ -0,0 +1,36 @@ +// Copyright 2021-2024 The Connect Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { execSync } from "node:child_process"; + +if (gitUncommitted()) { + process.stdout.write( + "::error::Uncommitted changes found. Please make sure this branch is up to date, and run the command locally (for example `npx turbo format`). " + + "Verify the changes are what you want and commit them.\n", + ); + execSync("git --no-pager diff", { + stdio: "inherit", + }); + process.exit(1); +} + +/** + * @returns {boolean} + */ +function gitUncommitted() { + const out = execSync("git status --porcelain", { + encoding: "utf-8", + }); + return out.trim().length > 0; +} diff --git a/scripts/release.js b/scripts/release.js new file mode 100644 index 000000000..44ddbbb84 --- /dev/null +++ b/scripts/release.js @@ -0,0 +1,118 @@ +// Copyright 2021-2024 The Connect Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { readdirSync, readFileSync } from "fs"; +import { join } from "path"; +import { existsSync } from "node:fs"; +import { execSync } from "node:child_process"; + +/* + * Publish connect-es + * + * Recommended procedure: + * 1. Set a new version with `npm run setversion 1.2.3` + * 2. Commit and push all changes to a PR, wait for approval. + * 3. Login with `npm login` + * 4. Publish to npmjs.com with `npm run release` + * 5. Merge PR and create a release on GitHub + */ + +const tag = determinePublishTag(findWorkspaceVersion("packages")); +const uncommitted = gitUncommitted(); +if (uncommitted.length > 0) { + throw new Error("Uncommitted changes found: \n" + uncommitted); +} +npmPublish(); + +/** + * + */ +function npmPublish() { + const command = + `npm publish --tag ${tag}` + + " --workspace packages/connect" + + " --workspace packages/connect-web" + + " --workspace packages/connect-node" + + " --workspace packages/connect-fastify" + + " --workspace packages/connect-express" + + " --workspace packages/connect-next" + + " --workspace packages/connect-migrate" + + " --workspace packages/protoc-gen-connect-es"; + execSync(command, { + stdio: "inherit", + }); +} + +/** + * @returns {string} + */ +function gitUncommitted() { + const out = execSync("git status --short", { + encoding: "utf-8", + }); + if (out.trim().length === 0) { + return ""; + } + return out; +} + +/** + * @param {string} version + * @returns {string} + */ +function determinePublishTag(version) { + if (/^\d+\.\d+\.\d+$/.test(version)) { + return "latest"; + } else if (/^\d+\.\d+\.\d+-alpha.*$/.test(version)) { + return "alpha"; + } else if (/^\d+\.\d+\.\d+-beta.*$/.test(version)) { + return "beta"; + } else if (/^\d+\.\d+\.\d+-rc.*$/.test(version)) { + return "rc"; + } else { + throw new Error(`Unable to determine publish tag from version ${version}`); + } +} + +/** + * @param {string} packagesDir + * @returns {string} + */ +function findWorkspaceVersion(packagesDir) { + let version = undefined; + for (const entry of readdirSync(packagesDir, { withFileTypes: true })) { + if (!entry.isDirectory()) { + continue; + } + const path = join(packagesDir, entry.name, "package.json"); + if (existsSync(path)) { + const pkg = JSON.parse(readFileSync(path, "utf-8")); + if (pkg.private === true) { + continue; + } + if (!pkg.version) { + throw new Error(`${path} is missing "version"`); + } + if (version === undefined) { + version = pkg.version; + } else if (version !== pkg.version) { + throw new Error(`${path} has unexpected version ${pkg.version}`); + } + } + } + if (version === undefined) { + throw new Error(`unable to find workspace version`); + } + return version; +}