From 51d8fa12da99dada44fec28d9bc3dad9beac64a7 Mon Sep 17 00:00:00 2001 From: Zeping Bu Date: Sun, 13 Sep 2026 20:57:08 +0800 Subject: [PATCH 1/3] build: introduce rockspec and a LuaRocks release workflow Set up a release toolchain modeled on api7/lua-resty-ldap: - rockspec/api7-lua-resty-websocket-local-0.rockspec: for local dev installs (source = file://.). - rockspec/api7-lua-resty-websocket-master-0.rockspec: tracks the master branch, used by 'make dev' to pull in runtime dependencies. - rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec: the first versioned release, pointing at the not-yet-created v0.1.0 tag. The package is published as 'api7-lua-resty-websocket' rather than 'lua-resty-websocket': that name is already registered on LuaRocks by an unrelated account (uploader 'Invizory'), the same constraint that led Kong to publish their own fork as 'lua-resty-websocket-kong'. Makefile gains 'dev', 'test', and 'help' targets, matching lua-resty-ldap's. .github/workflows/release.yml triggers on pushes to master that touch rockspec/**, parses the head commit message for 'feat: release vX.Y.Z', cuts a GitHub release at that tag, and uploads the matching rockspec to LuaRocks via 'luarocks upload' (needs a LUAROCKS_TOKEN secret). ci.yml gets a 'luarocks make --local' step to catch a broken rockspec before merge. README.markdown's Installation section now mentions the LuaRocks package name. --- .github/workflows/ci.yml | 5 ++ .github/workflows/release.yml | 55 +++++++++++++++++++ Makefile | 30 +++++----- README.markdown | 6 ++ .../api7-lua-resty-websocket-0.1.0-0.rockspec | 31 +++++++++++ .../api7-lua-resty-websocket-local-0.rockspec | 30 ++++++++++ ...api7-lua-resty-websocket-master-0.rockspec | 31 +++++++++++ 7 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec create mode 100644 rockspec/api7-lua-resty-websocket-local-0.rockspec create mode 100644 rockspec/api7-lua-resty-websocket-master-0.rockspec diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e69163..b56db48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,13 @@ jobs: ca-certificates \ cpanminus \ git \ + lua5.1 \ + luarocks \ wget + - name: Validate rockspec + run: luarocks make rockspec/api7-lua-resty-websocket-local-0.rockspec --local --tree /tmp/rockspec-check + - name: Build and test env: CC: gcc diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..9c89e81 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Release + +on: + push: + branches: + - master + paths: + - 'rockspec/**' + +permissions: + contents: write + +jobs: + release: + name: Release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Lua + uses: leafo/gh-actions-lua@v8 + + - name: Install Luarocks + uses: leafo/gh-actions-luarocks@v4 + + - name: Extract release version + id: release_env + shell: bash + run: | + title="${{ github.event.head_commit.message }}" + re="^feat: release v?(\S+)" + if [[ "$title" =~ $re ]]; then + echo "version=v${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" + echo "version_without_v=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" + else + echo "head commit message does not match 'feat: release vX.Y.Z'" >&2 + exit 1 + fi + + - name: Create GitHub release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${{ steps.release_env.outputs.version }}" \ + --title "${{ steps.release_env.outputs.version }}" \ + --notes "Release ${{ steps.release_env.outputs.version }}" + + - name: Upload to LuaRocks + env: + LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }} + run: | + luarocks install dkjson + luarocks upload "rockspec/api7-lua-resty-websocket-${{ steps.release_env.outputs.version_without_v }}-0.rockspec" --api-key="$LUAROCKS_TOKEN" diff --git a/Makefile b/Makefile index 8a4a9ea..04033b5 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,16 @@ -OPENRESTY_PREFIX=/usr/local/openresty +### dev: Install runtime dependencies locally +.PHONY: dev +dev: + luarocks install rockspec/api7-lua-resty-websocket-master-0.rockspec --only-deps --local -PREFIX ?= /usr/local -LUA_INCLUDE_DIR ?= $(PREFIX)/include -LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) -INSTALL ?= install - -.PHONY: all test install - -all: ; - -install: all - $(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty/websocket - $(INSTALL) lib/resty/websocket/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty/websocket/ - -test: all - PATH=$(OPENRESTY_PREFIX)/nginx/sbin:$$PATH prove -I../test-nginx/lib -r t +### test: Run the test suite +.PHONY: test +test: + prove -I. -r t/ +### help: Show Makefile rules +.PHONY: help +help: + @echo Makefile rules: + @echo + @grep -E '^### [-A-Za-z0-9_]+:' Makefile | sed 's/###/ /' diff --git a/README.markdown b/README.markdown index 5fc6ee8..d899a28 100644 --- a/README.markdown +++ b/README.markdown @@ -629,6 +629,12 @@ each request. Installation ============ +This fork is published to LuaRocks as `api7-lua-resty-websocket` (the `lua-resty-websocket` package name is already held by an unrelated LuaRocks account, hence the different name): + +```shell +luarocks install api7-lua-resty-websocket +``` + It is recommended to use the latest [OpenResty bundle](http://openresty.org) directly where this library is bundled and enabled by default. At least OpenResty 1.4.2.9 is required. And you need to enable LuaJIT when building your OpenResty bundle by passing the `--with-luajit` option to its `./configure` script. No extra Nginx configuration is required. diff --git a/rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec b/rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec new file mode 100644 index 0000000..1a2dcb1 --- /dev/null +++ b/rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec @@ -0,0 +1,31 @@ +package = "api7-lua-resty-websocket" +version = "0.1.0-0" +source = { + url = "git+https://github.com/api7/lua-resty-websocket", + tag = "v0.1.0", +} + +description = { + summary = "Lua WebSocket implementation for the ngx_lua module", + detailed = [[ + api7-lua-resty-websocket is api7's fork of the OpenResty WebSocket + library. It implements WebSocket server and client libraries based + on the ngx_lua module, taking advantage of ngx_lua's cosocket API + for fully nonblocking behavior. It also carries a WebSocket reverse + proxy module ported from Kong/lua-resty-websocket-proxy. + ]], + homepage = "https://github.com/api7/lua-resty-websocket", + license = "2-clause BSD", +} + +dependencies = {} + +build = { + type = "builtin", + modules = { + ["resty.websocket.client"] = "lib/resty/websocket/client.lua", + ["resty.websocket.server"] = "lib/resty/websocket/server.lua", + ["resty.websocket.protocol"] = "lib/resty/websocket/protocol.lua", + ["resty.websocket.proxy"] = "lib/resty/websocket/proxy.lua", + } +} diff --git a/rockspec/api7-lua-resty-websocket-local-0.rockspec b/rockspec/api7-lua-resty-websocket-local-0.rockspec new file mode 100644 index 0000000..59be2ac --- /dev/null +++ b/rockspec/api7-lua-resty-websocket-local-0.rockspec @@ -0,0 +1,30 @@ +package = "api7-lua-resty-websocket" +version = "local-0" +source = { + url = "file://." +} + +description = { + summary = "Lua WebSocket implementation for the ngx_lua module", + detailed = [[ + api7-lua-resty-websocket is api7's fork of the OpenResty WebSocket + library. It implements WebSocket server and client libraries based + on the ngx_lua module, taking advantage of ngx_lua's cosocket API + for fully nonblocking behavior. It also carries a WebSocket reverse + proxy module ported from Kong/lua-resty-websocket-proxy. + ]], + homepage = "https://github.com/api7/lua-resty-websocket", + license = "2-clause BSD", +} + +dependencies = {} + +build = { + type = "builtin", + modules = { + ["resty.websocket.client"] = "lib/resty/websocket/client.lua", + ["resty.websocket.server"] = "lib/resty/websocket/server.lua", + ["resty.websocket.protocol"] = "lib/resty/websocket/protocol.lua", + ["resty.websocket.proxy"] = "lib/resty/websocket/proxy.lua", + } +} diff --git a/rockspec/api7-lua-resty-websocket-master-0.rockspec b/rockspec/api7-lua-resty-websocket-master-0.rockspec new file mode 100644 index 0000000..53cc93d --- /dev/null +++ b/rockspec/api7-lua-resty-websocket-master-0.rockspec @@ -0,0 +1,31 @@ +package = "api7-lua-resty-websocket" +version = "master-0" +source = { + url = "git://github.com/api7/lua-resty-websocket", + branch = "master", +} + +description = { + summary = "Lua WebSocket implementation for the ngx_lua module", + detailed = [[ + api7-lua-resty-websocket is api7's fork of the OpenResty WebSocket + library. It implements WebSocket server and client libraries based + on the ngx_lua module, taking advantage of ngx_lua's cosocket API + for fully nonblocking behavior. It also carries a WebSocket reverse + proxy module ported from Kong/lua-resty-websocket-proxy. + ]], + homepage = "https://github.com/api7/lua-resty-websocket", + license = "2-clause BSD", +} + +dependencies = {} + +build = { + type = "builtin", + modules = { + ["resty.websocket.client"] = "lib/resty/websocket/client.lua", + ["resty.websocket.server"] = "lib/resty/websocket/server.lua", + ["resty.websocket.protocol"] = "lib/resty/websocket/protocol.lua", + ["resty.websocket.proxy"] = "lib/resty/websocket/proxy.lua", + } +} From 705d10570c3834dd7cb01cfdcffa18f557d3e543 Mon Sep 17 00:00:00 2001 From: Zeping Bu Date: Sun, 13 Sep 2026 21:17:27 +0800 Subject: [PATCH 2/3] fix: address CodeRabbit findings on the release workflow - Guard the release job with an 'if:' condition on the commit message prefix, so an ordinary commit touching rockspec/** (like this one) shows as skipped instead of a failed run. - Route the commit message and extracted version/version_without_v through step 'env:' instead of interpolating the '${{ }}' expressions directly into 'run:' scripts. The commit message is attacker- controlled (anyone who can push a commit controls its message); with direct interpolation, shell metacharacters in it would execute in a job that also holds GITHUB_TOKEN and LUAROCKS_TOKEN. Also tighten the version regex to a specific character set so the extracted version itself can't carry shell metacharacters into later steps. - rockspec/api7-lua-resty-websocket-master-0.rockspec: use git+https instead of git://, which GitHub stopped serving unencrypted in 2022. - Makefile: 'make test' now puts a locally built ./work/nginx/sbin ahead of PATH, matching what ci.yml already exports before running the suite; without it, Test::Nginx::Socket::Lua can't find nginx when a contributor builds it locally instead of installing a system package. --- .github/workflows/release.yml | 28 ++++++++++++++----- Makefile | 2 +- ...api7-lua-resty-websocket-master-0.rockspec | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9c89e81..9386b2e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,10 @@ jobs: release: name: Release runs-on: ubuntu-latest + # only run for a commit whose message starts with "feat: release vX.Y.Z"; + # anything else touching rockspec/** (typo fixes, this workflow itself, + # etc.) should not show up as a failed run + if: "startsWith(github.event.head_commit.message, 'feat: release v')" steps: - name: Checkout code @@ -28,10 +32,20 @@ jobs: - name: Extract release version id: release_env shell: bash + env: + # route the commit message through the environment instead of + # interpolating it into the script source: it's attacker-controlled + # (anyone who can push a commit controls its message) and directly + # templating it into `run:` would let shell metacharacters in the + # message execute arbitrary commands in this job, which also holds + # GITHUB_TOKEN and LUAROCKS_TOKEN + TITLE: ${{ github.event.head_commit.message }} run: | - title="${{ github.event.head_commit.message }}" - re="^feat: release v?(\S+)" - if [[ "$title" =~ $re ]]; then + # keep the captured version to a safe character set (this is still + # attacker-controlled input up to this point) before it's used in + # later steps' `run:` blocks + re="^feat: release v?([0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?)" + if [[ "$TITLE" =~ $re ]]; then echo "version=v${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" echo "version_without_v=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" else @@ -42,14 +56,14 @@ jobs: - name: Create GitHub release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ steps.release_env.outputs.version }} run: | - gh release create "${{ steps.release_env.outputs.version }}" \ - --title "${{ steps.release_env.outputs.version }}" \ - --notes "Release ${{ steps.release_env.outputs.version }}" + gh release create "$VERSION" --title "$VERSION" --notes "Release $VERSION" - name: Upload to LuaRocks env: LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }} + VERSION_WITHOUT_V: ${{ steps.release_env.outputs.version_without_v }} run: | luarocks install dkjson - luarocks upload "rockspec/api7-lua-resty-websocket-${{ steps.release_env.outputs.version_without_v }}-0.rockspec" --api-key="$LUAROCKS_TOKEN" + luarocks upload "rockspec/api7-lua-resty-websocket-${VERSION_WITHOUT_V}-0.rockspec" --api-key="$LUAROCKS_TOKEN" diff --git a/Makefile b/Makefile index 04033b5..b651eba 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ dev: ### test: Run the test suite .PHONY: test test: - prove -I. -r t/ + PATH="$(PWD)/work/nginx/sbin:$$PATH" prove -I. -r t/ ### help: Show Makefile rules .PHONY: help diff --git a/rockspec/api7-lua-resty-websocket-master-0.rockspec b/rockspec/api7-lua-resty-websocket-master-0.rockspec index 53cc93d..97478f9 100644 --- a/rockspec/api7-lua-resty-websocket-master-0.rockspec +++ b/rockspec/api7-lua-resty-websocket-master-0.rockspec @@ -1,7 +1,7 @@ package = "api7-lua-resty-websocket" version = "master-0" source = { - url = "git://github.com/api7/lua-resty-websocket", + url = "git+https://github.com/api7/lua-resty-websocket", branch = "master", } From d5b1d3c4a63d5fa2d5788f73d182703edff073c8 Mon Sep 17 00:00:00 2001 From: Zeping Bu Date: Sun, 13 Sep 2026 21:35:49 +0800 Subject: [PATCH 3/3] build: drop the v0.1.0 rockspec from this PR The first versioned rockspec belongs with the PR that actually cuts the v0.1.0 release, not with the toolchain setup itself; it'll be added there instead. --- .../api7-lua-resty-websocket-0.1.0-0.rockspec | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec diff --git a/rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec b/rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec deleted file mode 100644 index 1a2dcb1..0000000 --- a/rockspec/api7-lua-resty-websocket-0.1.0-0.rockspec +++ /dev/null @@ -1,31 +0,0 @@ -package = "api7-lua-resty-websocket" -version = "0.1.0-0" -source = { - url = "git+https://github.com/api7/lua-resty-websocket", - tag = "v0.1.0", -} - -description = { - summary = "Lua WebSocket implementation for the ngx_lua module", - detailed = [[ - api7-lua-resty-websocket is api7's fork of the OpenResty WebSocket - library. It implements WebSocket server and client libraries based - on the ngx_lua module, taking advantage of ngx_lua's cosocket API - for fully nonblocking behavior. It also carries a WebSocket reverse - proxy module ported from Kong/lua-resty-websocket-proxy. - ]], - homepage = "https://github.com/api7/lua-resty-websocket", - license = "2-clause BSD", -} - -dependencies = {} - -build = { - type = "builtin", - modules = { - ["resty.websocket.client"] = "lib/resty/websocket/client.lua", - ["resty.websocket.server"] = "lib/resty/websocket/server.lua", - ["resty.websocket.protocol"] = "lib/resty/websocket/protocol.lua", - ["resty.websocket.proxy"] = "lib/resty/websocket/proxy.lua", - } -}