From f25a9936af6cbc2f31f994e5ba299085b4d7b45a Mon Sep 17 00:00:00 2001 From: Jarvis Date: Wed, 20 May 2026 13:41:53 +0800 Subject: [PATCH 1/3] feat: release v0.1.0 --- .github/workflows/release.yml | 131 +++++++++++++++++++ .github/workflows/tests.yml | 37 +++++- rockspec/lua-resty-simdjson-0.1.0-1.rockspec | 37 ++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml create mode 100644 rockspec/lua-resty-simdjson-0.1.0-1.rockspec diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..db078e7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,131 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: "Release version, for example 0.1.0 or v0.1.0" + required: true + push: + branches: + - "main" + paths: + - "rockspec/**" + +permissions: + contents: write + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install Lua + uses: leafo/gh-actions-lua@v10 + with: + luaVersion: "5.1.5" + + - name: Install LuaRocks + uses: leafo/gh-actions-luarocks@v4 + with: + luarocksVersion: "3.11.1" + + - name: Install upload dependency + run: luarocks install dkjson + + - name: Extract release name + id: release_env + shell: bash + env: + HEAD_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + RELEASE_VERSION: ${{ inputs.version }} + run: | + semver_re="^v?([0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?)$" + if [ -n "$RELEASE_VERSION" ]; then + if [[ $RELEASE_VERSION =~ $semver_re ]]; then + version="${BASH_REMATCH[1]}" + else + echo "version input is not correct (expected: X.Y.Z[-prerelease])" + exit 1 + fi + else + title="${HEAD_COMMIT_MESSAGE%%$'\n'*}" + if [[ $title =~ ^(.*)\ \(#[0-9]+\)$ ]]; then + title="${BASH_REMATCH[1]}" + fi + title_re="^feat: release v?([0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?)$" + if [[ $title =~ $title_re ]]; then + version="${BASH_REMATCH[1]}" + else + echo "commit format is not correct (expected: feat: release vX.Y.Z[-prerelease])" + exit 1 + fi + fi + + echo "version=v${version}" >> $GITHUB_OUTPUT + echo "version_without_v=${version}" >> $GITHUB_OUTPUT + if [[ $version == *-* ]]; then + echo "is_prerelease=true" >> $GITHUB_OUTPUT + else + echo "is_prerelease=false" >> $GITHUB_OUTPUT + fi + + - name: Verify rockspec exists + id: verify_rockspec + shell: bash + env: + VERSION_WITHOUT_V: ${{ steps.release_env.outputs.version_without_v }} + run: | + rockspec_file="$(python3 - <<'PY' + import os + import re + from pathlib import Path + + version = os.environ["VERSION_WITHOUT_V"] + pattern = re.compile(r"^lua-resty-simdjson-" + re.escape(version) + r"-(\d+)\.rockspec$") + matches = [] + for path in Path("rockspec").glob("lua-resty-simdjson-" + version + "-*.rockspec"): + match = pattern.match(path.name) + if match: + matches.append((int(match.group(1)), str(path))) + if not matches: + raise SystemExit("rockspec file not found for version " + version) + print(max(matches)[1]) + PY + )" + echo "rockspec_file=${rockspec_file}" >> $GITHUB_OUTPUT + + - name: Validate LuaRocks token + shell: bash + env: + LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }} + run: | + if [ -z "$LUAROCKS_TOKEN" ]; then + echo "LUAROCKS_TOKEN secret is not configured" + exit 1 + fi + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.release_env.outputs.version }} + name: ${{ steps.release_env.outputs.version }} + draft: false + prerelease: ${{ steps.release_env.outputs.is_prerelease }} + + - name: Upload to LuaRocks + env: + LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }} + ROCKSPEC_FILE: ${{ steps.verify_rockspec.outputs.rockspec_file }} + shell: bash + run: | + mkdir -p "$HOME/.luarocks" + chmod 700 "$HOME/.luarocks" + lua -e 'local token = os.getenv("LUAROCKS_TOKEN"); assert(token and token ~= "", "missing LUAROCKS_TOKEN"); local f = assert(io.open(os.getenv("HOME") .. "/.luarocks/upload_config.lua", "w")); f:write(("key = %q\n"):format(token)); f:write("server = \"https://luarocks.org\"\nversion = \"1.0\"\n"); f:close()' + chmod 600 "$HOME/.luarocks/upload_config.lua" + luarocks upload "$ROCKSPEC_FILE" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c0328e3..5b93d59 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,7 +44,7 @@ jobs: - name: Install packages run: | sudo apt update - sudo apt-get install -qq -y wget cpanminus net-tools libpcre3-dev build-essential valgrind + sudo apt-get install -qq -y wget cpanminus net-tools libpcre3-dev build-essential valgrind luarocks if [ ! -e perl ]; then sudo cpanm --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1); cp -r /usr/local/share/perl/ .; else sudo cp -r perl /usr/local/share; fi - name: Download OpenResty @@ -67,6 +67,41 @@ jobs: openresty -V make test OPENRESTY_PREFIX=${BASE_PATH}/openresty DEBUG=true + - name: Validate LuaRocks package + run: | + export PATH=${BASE_PATH}/openresty/bin:$PATH + rm -rf /tmp/lua-resty-simdjson-rock + ROCKSPEC="$(python3 - <<'PY' + import re + from pathlib import Path + + pattern = re.compile(r"^lua-resty-simdjson-(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?-(\d+)\.rockspec$") + def prerelease_key(value): + if value is None: + return () + key = [] + for part in value.split("."): + if part.isdigit(): + key.append((0, int(part))) + else: + key.append((1, part)) + return tuple(key) + + matches = [] + for path in Path("rockspec").glob("lua-resty-simdjson-*.rockspec"): + match = pattern.match(path.name) + if match: + major, minor, patch, prerelease, revision = match.groups() + matches.append((int(major), int(minor), int(patch), prerelease is None, prerelease_key(prerelease), int(revision), str(path))) + if not matches: + raise SystemExit("no lua-resty-simdjson rockspec found") + print(max(matches)[-1]) + PY + )" + luarocks make "$ROCKSPEC" --tree /tmp/lua-resty-simdjson-rock + eval "$(luarocks path --tree /tmp/lua-resty-simdjson-rock)" + resty -e 'local simdjson = require("resty.simdjson"); local parser = assert(simdjson.new()); local obj = parser:decode("{\"a\":42}"); assert(obj.a == 42); assert(parser:encode(obj) == "{\"a\":42}")' + - name: Run Valgrind run: | export PATH=${BASE_PATH}/openresty/bin:$PATH diff --git a/rockspec/lua-resty-simdjson-0.1.0-1.rockspec b/rockspec/lua-resty-simdjson-0.1.0-1.rockspec new file mode 100644 index 0000000..fdb11b4 --- /dev/null +++ b/rockspec/lua-resty-simdjson-0.1.0-1.rockspec @@ -0,0 +1,37 @@ +package = "lua-resty-simdjson" +version = "0.1.0-1" +supported_platforms = { "linux", "macosx" } + +source = { + url = "git+https://github.com/api7/lua-resty-simdjson.git", + tag = "v0.1.0", +} + +description = { + summary = "Fast JSON encoder and decoder for OpenResty", + detailed = [[ + lua-resty-simdjson provides a LuaJIT FFI binding for simdjson. + It is optimized for decoding large JSON payloads in OpenResty while + keeping proxy path latency low through optional yielding. + ]], + homepage = "https://github.com/api7/lua-resty-simdjson", + license = "Apache-2.0", +} + +dependencies = { + "lua == 5.1", +} + +build = { + type = "command", + build_command = "make build", + install_command = [[ + set -e + mkdir -p "$(LUADIR)/resty/simdjson" "$(LIBDIR)" + cp lib/resty/simdjson/*.lua "$(LUADIR)/resty/simdjson/" + lib=libsimdjson_ffi.so + if [ ! -f "$lib" ]; then lib=libsimdjson_ffi.dylib; fi + if [ ! -f "$lib" ]; then echo "simdjson native library not found"; exit 1; fi + cp "$lib" "$(LIBDIR)/" + ]], +} From 0e139fd2a5a3be80d7d49080cfde1f1325209ef4 Mon Sep 17 00:00:00 2001 From: Jarvis Date: Wed, 20 May 2026 13:51:23 +0800 Subject: [PATCH 2/3] fix: avoid LuaRocks package name conflict --- .github/workflows/release.yml | 30 ++++++++++--------- .github/workflows/tests.yml | 12 ++++---- ... api7-lua-resty-simdjson-0.1.0-1.rockspec} | 4 ++- 3 files changed, 25 insertions(+), 21 deletions(-) rename rockspec/{lua-resty-simdjson-0.1.0-1.rockspec => api7-lua-resty-simdjson-0.1.0-1.rockspec} (93%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index db078e7..97e376f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,21 +17,22 @@ permissions: jobs: release: + if: "${{ github.event_name == 'workflow_dispatch' || startsWith(github.event.head_commit.message, 'feat: release ') }}" name: Release runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: persist-credentials: false - name: Install Lua - uses: leafo/gh-actions-lua@v10 + uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e with: luaVersion: "5.1.5" - name: Install LuaRocks - uses: leafo/gh-actions-luarocks@v4 + uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 with: luarocksVersion: "3.11.1" @@ -87,9 +88,9 @@ jobs: from pathlib import Path version = os.environ["VERSION_WITHOUT_V"] - pattern = re.compile(r"^lua-resty-simdjson-" + re.escape(version) + r"-(\d+)\.rockspec$") + pattern = re.compile(r"^api7-lua-resty-simdjson-" + re.escape(version) + r"-(\d+)\.rockspec$") matches = [] - for path in Path("rockspec").glob("lua-resty-simdjson-" + version + "-*.rockspec"): + for path in Path("rockspec").glob("api7-lua-resty-simdjson-" + version + "-*.rockspec"): match = pattern.match(path.name) if match: matches.append((int(match.group(1)), str(path))) @@ -110,14 +111,6 @@ jobs: exit 1 fi - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ steps.release_env.outputs.version }} - name: ${{ steps.release_env.outputs.version }} - draft: false - prerelease: ${{ steps.release_env.outputs.is_prerelease }} - - name: Upload to LuaRocks env: LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }} @@ -126,6 +119,15 @@ jobs: run: | mkdir -p "$HOME/.luarocks" chmod 700 "$HOME/.luarocks" - lua -e 'local token = os.getenv("LUAROCKS_TOKEN"); assert(token and token ~= "", "missing LUAROCKS_TOKEN"); local f = assert(io.open(os.getenv("HOME") .. "/.luarocks/upload_config.lua", "w")); f:write(("key = %q\n"):format(token)); f:write("server = \"https://luarocks.org\"\nversion = \"1.0\"\n"); f:close()' + touch "$HOME/.luarocks/upload_config.lua" chmod 600 "$HOME/.luarocks/upload_config.lua" + lua -e 'local token = os.getenv("LUAROCKS_TOKEN"); assert(token and token ~= "", "missing LUAROCKS_TOKEN"); local f = assert(io.open(os.getenv("HOME") .. "/.luarocks/upload_config.lua", "w")); assert(f:write(("key = %q\n"):format(token))); assert(f:write("server = \"https://luarocks.org\"\nversion = \"1.0\"\n")); assert(f:close())' luarocks upload "$ROCKSPEC_FILE" + + - name: Create Release + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 + with: + tag_name: ${{ steps.release_env.outputs.version }} + name: ${{ steps.release_env.outputs.version }} + draft: false + prerelease: ${{ steps.release_env.outputs.is_prerelease }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5b93d59..0bac405 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,7 +44,7 @@ jobs: - name: Install packages run: | sudo apt update - sudo apt-get install -qq -y wget cpanminus net-tools libpcre3-dev build-essential valgrind luarocks + sudo apt-get install -qq -y wget cpanminus net-tools libpcre3-dev build-essential valgrind lua5.1 liblua5.1-0-dev luarocks if [ ! -e perl ]; then sudo cpanm --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1); cp -r /usr/local/share/perl/ .; else sudo cp -r perl /usr/local/share; fi - name: Download OpenResty @@ -75,7 +75,7 @@ jobs: import re from pathlib import Path - pattern = re.compile(r"^lua-resty-simdjson-(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?-(\d+)\.rockspec$") + pattern = re.compile(r"^api7-lua-resty-simdjson-(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?-(\d+)\.rockspec$") def prerelease_key(value): if value is None: return () @@ -88,18 +88,18 @@ jobs: return tuple(key) matches = [] - for path in Path("rockspec").glob("lua-resty-simdjson-*.rockspec"): + for path in Path("rockspec").glob("api7-lua-resty-simdjson-*.rockspec"): match = pattern.match(path.name) if match: major, minor, patch, prerelease, revision = match.groups() matches.append((int(major), int(minor), int(patch), prerelease is None, prerelease_key(prerelease), int(revision), str(path))) if not matches: - raise SystemExit("no lua-resty-simdjson rockspec found") + raise SystemExit("no api7-lua-resty-simdjson rockspec found") print(max(matches)[-1]) PY )" - luarocks make "$ROCKSPEC" --tree /tmp/lua-resty-simdjson-rock - eval "$(luarocks path --tree /tmp/lua-resty-simdjson-rock)" + luarocks --lua-version=5.1 make "$ROCKSPEC" --tree /tmp/lua-resty-simdjson-rock + eval "$(luarocks --lua-version=5.1 path --tree /tmp/lua-resty-simdjson-rock)" resty -e 'local simdjson = require("resty.simdjson"); local parser = assert(simdjson.new()); local obj = parser:decode("{\"a\":42}"); assert(obj.a == 42); assert(parser:encode(obj) == "{\"a\":42}")' - name: Run Valgrind diff --git a/rockspec/lua-resty-simdjson-0.1.0-1.rockspec b/rockspec/api7-lua-resty-simdjson-0.1.0-1.rockspec similarity index 93% rename from rockspec/lua-resty-simdjson-0.1.0-1.rockspec rename to rockspec/api7-lua-resty-simdjson-0.1.0-1.rockspec index fdb11b4..5873cb8 100644 --- a/rockspec/lua-resty-simdjson-0.1.0-1.rockspec +++ b/rockspec/api7-lua-resty-simdjson-0.1.0-1.rockspec @@ -1,4 +1,4 @@ -package = "lua-resty-simdjson" +package = "api7-lua-resty-simdjson" version = "0.1.0-1" supported_platforms = { "linux", "macosx" } @@ -20,6 +20,8 @@ description = { dependencies = { "lua == 5.1", + "lua-cjson", + "lua-resty-core", } build = { From 419762b86ff2c0a30f5cacc3fd4439a1fa50a72c Mon Sep 17 00:00:00 2001 From: Jarvis Date: Wed, 20 May 2026 13:57:46 +0800 Subject: [PATCH 3/3] fix: create release before LuaRocks upload --- .github/workflows/release.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 97e376f..ebf23ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -111,6 +111,14 @@ jobs: exit 1 fi + - name: Create Release + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 + with: + tag_name: ${{ steps.release_env.outputs.version }} + name: ${{ steps.release_env.outputs.version }} + draft: false + prerelease: ${{ steps.release_env.outputs.is_prerelease }} + - name: Upload to LuaRocks env: LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }} @@ -123,11 +131,3 @@ jobs: chmod 600 "$HOME/.luarocks/upload_config.lua" lua -e 'local token = os.getenv("LUAROCKS_TOKEN"); assert(token and token ~= "", "missing LUAROCKS_TOKEN"); local f = assert(io.open(os.getenv("HOME") .. "/.luarocks/upload_config.lua", "w")); assert(f:write(("key = %q\n"):format(token))); assert(f:write("server = \"https://luarocks.org\"\nversion = \"1.0\"\n")); assert(f:close())' luarocks upload "$ROCKSPEC_FILE" - - - name: Create Release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 - with: - tag_name: ${{ steps.release_env.outputs.version }} - name: ${{ steps.release_env.outputs.version }} - draft: false - prerelease: ${{ steps.release_env.outputs.is_prerelease }}